diff --git a/.eslintrc.js b/.eslintrc.js index 85e9ec47f58..fb9d445ee54 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -230,13 +230,19 @@ module.exports = { './packages/desktop-client/src/components/UpdateNotification.*', './packages/desktop-client/src/components/accounts/Header.*', './packages/desktop-client/src/components/alerts.*', + './packages/desktop-client/src/components/budget/BudgetCategories.*', + './packages/desktop-client/src/components/budget/BudgetTotals.*', + './packages/desktop-client/src/components/budget/ExpenseGroup.*', + './packages/desktop-client/src/components/budget/IncomeGroup.*', './packages/desktop-client/src/components/budget/MobileBudget.*', './packages/desktop-client/src/components/budget/MobileBudgetTable.*', './packages/desktop-client/src/components/budget/MobileTable.*', './packages/desktop-client/src/components/budget/MonthCountSelector.*', './packages/desktop-client/src/components/budget/MonthPicker.*', + './packages/desktop-client/src/components/budget/RenderMonths.*', + './packages/desktop-client/src/components/budget/SidebarCategory.*', + './packages/desktop-client/src/components/budget/SidebarGroup.*', './packages/desktop-client/src/components/budget/constants.*', - './packages/desktop-client/src/components/budget/misc.*', './packages/desktop-client/src/components/budget/report/BudgetSummary.*', './packages/desktop-client/src/components/budget/report/components.*', './packages/desktop-client/src/components/budget/rollover/BudgetSummary.*', diff --git a/packages/crdt/jest.config.js b/packages/crdt/jest.config.js index a3b8912d852..0a6a68f0762 100644 --- a/packages/crdt/jest.config.js +++ b/packages/crdt/jest.config.js @@ -1,4 +1,6 @@ module.exports = { - preset: 'ts-jest/presets/js-with-ts-esm', testEnvironment: 'node', + transform: { + '^.+\\.(t|j)sx?$': '@swc/jest', + }, }; diff --git a/packages/crdt/package.json b/packages/crdt/package.json index 4e7f3967605..010f8b89c40 100644 --- a/packages/crdt/package.json +++ b/packages/crdt/package.json @@ -20,10 +20,11 @@ "uuid": "^9.0.0" }, "devDependencies": { + "@swc/core": "^1.3.82", + "@swc/jest": "^0.2.29", "@types/jest": "^27.5.0", "@types/uuid": "^9.0.2", "jest": "^27.0.0", - "ts-jest": "^27.0.0", "ts-protoc-gen": "^0.15.0", "typescript": "^5.0.2" } diff --git a/packages/desktop-client/.swcrc b/packages/desktop-client/.swcrc new file mode 100644 index 00000000000..f5997017d1e --- /dev/null +++ b/packages/desktop-client/.swcrc @@ -0,0 +1,15 @@ +{ + "jsc": { + "target": "es2022", + "transform": { + "react": { + "runtime": "automatic" + } + }, + "externalHelpers": true, + "parser": { + "syntax": "typescript", + "tsx": true + } + } +} diff --git a/packages/desktop-client/config-overrides.js b/packages/desktop-client/config-overrides.js deleted file mode 100644 index 5fe0dd3301b..00000000000 --- a/packages/desktop-client/config-overrides.js +++ /dev/null @@ -1,77 +0,0 @@ -const path = require('path'); - -const chokidar = require('chokidar'); -const { - addWebpackPlugin, - addWebpackResolve, - babelInclude, - override, - overrideDevServer, -} = require('customize-cra'); -const { IgnorePlugin } = require('webpack'); -const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); - -if (process.env.CI) { - process.env.DISABLE_ESLINT_PLUGIN = 'true'; -} - -// Forward Netlify env variables -if (process.env.REVIEW_ID) { - process.env.REACT_APP_REVIEW_ID = process.env.REVIEW_ID; -} - -module.exports = { - webpack: override( - babelInclude([path.resolve('src'), path.resolve('../loot-core')]), - addWebpackResolve({ - extensions: [ - ...(process.env.IS_GENERIC_BROWSER - ? ['.browser.js', '.browser.ts', '.browser.tsx'] - : []), - '.web.js', - '.web.ts', - '.web.tsx', - '.js', - '.ts', - '.tsx', - ], - }), - addWebpackPlugin( - new BundleAnalyzerPlugin({ - analyzerMode: 'disabled', - generateStatsFile: true, - }), - ), - // Pikaday throws a warning if Moment.js is not installed however it doesn't - // actually require it to be installed. As we don't use Moment.js ourselves - // then we can just silence this warning. - addWebpackPlugin( - new IgnorePlugin({ - contextRegExp: /pikaday$/, - resourceRegExp: /moment$/, - }), - ), - ), - devServer: overrideDevServer(config => { - return { - ...config, - onBeforeSetupMiddleware(server) { - chokidar - .watch([ - path.resolve('../loot-core/lib-dist/*.js'), - path.resolve('../loot-core/lib-dist/browser/*.js'), - ]) - .on('all', function () { - for (const ws of server.webSocketServer.clients) { - ws.send(JSON.stringify({ type: 'static-changed' })); - } - }); - }, - headers: { - ...config.headers, - 'Cross-Origin-Opener-Policy': 'same-origin', - 'Cross-Origin-Embedder-Policy': 'require-corp', - }, - }; - }), -}; diff --git a/packages/desktop-client/craco.config.ts b/packages/desktop-client/craco.config.ts new file mode 100644 index 00000000000..42a428979a2 --- /dev/null +++ b/packages/desktop-client/craco.config.ts @@ -0,0 +1,116 @@ +const path = require('path'); + +const { + loaderByName, + removeLoaders, + addAfterLoader, + addPlugins, +} = require('@craco/craco'); +const chokidar = require('chokidar'); +const TerserPlugin = require('terser-webpack-plugin'); +const { IgnorePlugin } = require('webpack'); +const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); + +if (process.env.CI) { + process.env.DISABLE_ESLINT_PLUGIN = 'true'; +} + +// Forward Netlify env variables +if (process.env.REVIEW_ID) { + process.env.REACT_APP_REVIEW_ID = process.env.REVIEW_ID; +} + +module.exports = { + webpack: { + configure: (webpackConfig, { env, paths }) => { + webpackConfig.mode = + process.env.NODE_ENV === 'development' ? 'development' : 'production'; + + // swc-loader + addAfterLoader(webpackConfig, loaderByName('babel-loader'), { + test: /\.m?[tj]sx?$/, + exclude: /node_modules/, + loader: require.resolve('swc-loader'), + }); + + // remove the babel loaders + removeLoaders(webpackConfig, loaderByName('babel-loader')); + + addPlugins(webpackConfig, [ + new BundleAnalyzerPlugin({ + analyzerMode: 'disabled', + generateStatsFile: true, + }), + // Pikaday throws a warning if Moment.js is not installed however it doesn't + // actually require it to be installed. As we don't use Moment.js ourselves + // then we can just silence this warning. + new IgnorePlugin({ + contextRegExp: /pikaday$/, + resourceRegExp: /moment$/, + }), + ]); + + webpackConfig.resolve.extensions = [ + '.web.js', + '.web.jsx', + '.web.ts', + '.web.tsx', + '.js', + '.jsx', + '.ts', + '.tsx', + ...webpackConfig.resolve.extensions, + ]; + + if (process.env.IS_GENERIC_BROWSER) { + webpackConfig.resolve.extensions = [ + '.browser.js', + '.browser.jsx', + '.browser.ts', + '.browser.tsx', + ...webpackConfig.resolve.extensions, + ]; + } + + webpackConfig.optimization = { + ...webpackConfig.optimization, + minimize: + process.env.CI === 'true' || process.env.NODE_ENV !== 'development', + minimizer: [ + new TerserPlugin({ + minify: TerserPlugin.swcMinify, + // `terserOptions` options will be passed to `swc` (`@swc/core`) + // Link to options - https://swc.rs/docs/config-js-minify + terserOptions: { + compress: false, + mangle: true, + }, + }), + ], + }; + + return webpackConfig; + }, + }, + devServer: (devServerConfig, { env, paths, proxy, allowedHost }) => { + devServerConfig.onBeforeSetupMiddleware = server => { + chokidar + .watch([ + path.resolve('../loot-core/lib-dist/*.js'), + path.resolve('../loot-core/lib-dist/browser/*.js'), + ]) + .on('all', function () { + for (const ws of server.webSocketServer.clients) { + ws.send(JSON.stringify({ type: 'static-changed' })); + } + }); + }; + devServerConfig.headers = { + ...devServerConfig.headers, + 'Cross-Origin-Opener-Policy': 'same-origin', + 'Cross-Origin-Embedder-Policy': 'require-corp', + }; + + return devServerConfig; + }, +}; diff --git a/packages/desktop-client/e2e/budget.test.js-snapshots/Budget-renders-the-summary-information-available-funds-overspent-budgeted-and-for-next-month-1-chromium-linux.png b/packages/desktop-client/e2e/budget.test.js-snapshots/Budget-renders-the-summary-information-available-funds-overspent-budgeted-and-for-next-month-1-chromium-linux.png index 00e539fa3f0..097b1beda3b 100644 Binary files a/packages/desktop-client/e2e/budget.test.js-snapshots/Budget-renders-the-summary-information-available-funds-overspent-budgeted-and-for-next-month-1-chromium-linux.png and b/packages/desktop-client/e2e/budget.test.js-snapshots/Budget-renders-the-summary-information-available-funds-overspent-budgeted-and-for-next-month-1-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/budget.test.js-snapshots/Budget-transfer-funds-to-another-category-1-chromium-linux.png b/packages/desktop-client/e2e/budget.test.js-snapshots/Budget-transfer-funds-to-another-category-1-chromium-linux.png index 89fdb85d24b..d96f3ce3035 100644 Binary files a/packages/desktop-client/e2e/budget.test.js-snapshots/Budget-transfer-funds-to-another-category-1-chromium-linux.png and b/packages/desktop-client/e2e/budget.test.js-snapshots/Budget-transfer-funds-to-another-category-1-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-the-accounts-page-and-asserts-on-balances-1-chromium-linux.png b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-the-accounts-page-and-asserts-on-balances-1-chromium-linux.png index 207a3d53444..900a67f119f 100644 Binary files a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-the-accounts-page-and-asserts-on-balances-1-chromium-linux.png and b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-opens-the-accounts-page-and-asserts-on-balances-1-chromium-linux.png differ diff --git a/packages/desktop-client/package.json b/packages/desktop-client/package.json index b9e88815bf7..ffa3681012b 100644 --- a/packages/desktop-client/package.json +++ b/packages/desktop-client/package.json @@ -6,6 +6,8 @@ "build" ], "devDependencies": { + "@craco/craco": "^7.1.0", + "@craco/types": "^7.1.0", "@juggle/resize-observer": "^3.1.2", "@playwright/test": "^1.37.1", "@reach/listbox": "^0.18.0", @@ -15,6 +17,8 @@ "@react-stately/collections": "^3.10.0", "@react-stately/list": "^3.9.1", "@svgr/cli": "^8.0.1", + "@swc/core": "^1.3.82", + "@swc/helpers": "^0.5.1", "@testing-library/react": "14.0.0", "@testing-library/user-event": "14.4.3", "@types/react": "^18.2.0", @@ -26,7 +30,6 @@ "@types/webpack-bundle-analyzer": "^4.6.0", "chokidar": "^3.5.3", "cross-env": "^7.0.3", - "customize-cra": "^1.0.0", "date-fns": "^2.29.3", "debounce": "^1.2.0", "downshift": "7.6.0", @@ -40,7 +43,6 @@ "memoize-one": "^6.0.0", "pikaday": "1.8.0", "react": "18.2.0", - "react-app-rewired": "^2.2.1", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-dom": "18.2.0", @@ -57,25 +59,22 @@ "redux-thunk": "^2.3.0", "remark-gfm": "^3.0.1", "sass": "^1.63.6", + "swc-loader": "^0.2.3", + "terser-webpack-plugin": "^5.3.9", "uuid": "^9.0.0", "victory": "^36.6.8", - "webpack-bundle-analyzer": "^4.9.0", + "webpack-bundle-analyzer": "^4.9.1", "xml2js": "^0.6.2" }, "scripts": { - "start": "cross-env PORT=3001 react-app-rewired start", + "start": "cross-env PORT=3001 craco start", "start:browser": "cross-env ./bin/watch-browser", "watch": "cross-env BROWSER=none yarn start", - "build": "cross-env INLINE_RUNTIME_CHUNK=false react-app-rewired build", + "build": "cross-env INLINE_RUNTIME_CHUNK=false craco build", "build:browser": "cross-env ./bin/build-browser", "generate:icons": "rm src/icons/*/*.js; cd src/icons && svgr --expand-props start --ext js -d . .", - "test": "react-app-rewired test", + "test": "craco test", "e2e": "npx playwright test --browser=chromium", "vrt": "cross-env VRT=true npx playwright test --browser=chromium" - }, - "jest": { - "setupFilesAfterEnv": [ - "/src/setupTests.js" - ] } } diff --git a/packages/desktop-client/src/components/AppBackground.tsx b/packages/desktop-client/src/components/AppBackground.tsx index 1af44ea58b3..b23e84af6ab 100644 --- a/packages/desktop-client/src/components/AppBackground.tsx +++ b/packages/desktop-client/src/components/AppBackground.tsx @@ -21,7 +21,7 @@ function AppBackground({ initializing, loadingText }: AppBackgroundProps) { {(loadingText != null || initializing) && ( {loadingText} diff --git a/packages/desktop-client/src/components/NotesButton.tsx b/packages/desktop-client/src/components/NotesButton.tsx index e49c57c43da..ac46eed8bb4 100644 --- a/packages/desktop-client/src/components/NotesButton.tsx +++ b/packages/desktop-client/src/components/NotesButton.tsx @@ -109,13 +109,13 @@ function NotesTooltip({ {editable ? (