diff --git a/packages/backend/eslint.config.js b/packages/backend/eslint.config.js index 02985d776b..56a49fb2fc 100644 --- a/packages/backend/eslint.config.js +++ b/packages/backend/eslint.config.js @@ -182,5 +182,8 @@ export default [ tsconfigRootDir: import.meta.dirname, }, }, + rules: { + 'import/no-default-export': 'off', + }, }, ]; diff --git a/packages/backend/jest.config.e2e.ts b/packages/backend/jest.config.e2e.ts index 004b7812e1..0c921e4286 100644 --- a/packages/backend/jest.config.e2e.ts +++ b/packages/backend/jest.config.e2e.ts @@ -8,7 +8,7 @@ import base from './jest.config.ts'; export default { ...base, globalSetup: "/built-test/entry.js", - setupFilesAfterEnv: ["/test/jest.setup.ts"], + setupFilesAfterEnv: ["/test/jest.setup.e2e.ts"], // All imported modules in your tests should be mocked automatically // automock: false, diff --git a/packages/backend/jest.config.unit.ts b/packages/backend/jest.config.unit.ts index bbad35a806..4787a85817 100644 --- a/packages/backend/jest.config.unit.ts +++ b/packages/backend/jest.config.unit.ts @@ -7,6 +7,7 @@ import base from './jest.config.ts'; export default { ...base, + globalSetup: '/test/jest.setup.unit.ts', testMatch: [ "/test/unit/**/*.ts", "/src/**/*.test.ts", diff --git a/packages/backend/package.json b/packages/backend/package.json index d00b4c1a51..949d60b053 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -242,13 +242,14 @@ "execa": "9.6.0", "fkill": "9.0.0", "jest": "30.1.3", + "jest-environment-node": "30.2.0", "jest-mock": "30.0.5", "nodemon": "3.1.10", "pid-port": "2.0.0", "simple-oauth2": "5.1.0", + "supertest": "7.1.4", "ts-jest": "29.4.4", "ts-node": "10.9.2", - "typescript": "5.9.2", - "supertest": "7.1.4" + "typescript": "5.9.2" } } diff --git a/packages/backend/src/boot/entry.ts b/packages/backend/src/boot/entry.ts index bbe6a57383..6bad70cf59 100644 --- a/packages/backend/src/boot/entry.ts +++ b/packages/backend/src/boot/entry.ts @@ -13,6 +13,7 @@ import { inspect } from 'node:util'; import chalk from 'chalk'; import Xev from 'xev'; import Logger from '@/logger.js'; +import { prepEnv } from '@/boot/prepEnv.js'; import { envOption } from '../env.js'; import { masterMain } from './master.js'; import { workerMain } from './worker.js'; @@ -22,8 +23,7 @@ import 'reflect-metadata'; process.title = `Misskey (${cluster.isPrimary ? 'master' : 'worker'})`; -Error.stackTraceLimit = Infinity; -EventEmitter.defaultMaxListeners = 128; +prepEnv(); const logger = new Logger('core', 'cyan'); const clusterLogger = logger.createSubLogger('cluster', 'orange'); diff --git a/packages/backend/src/boot/prepEnv.ts b/packages/backend/src/boot/prepEnv.ts new file mode 100644 index 0000000000..b8367ae22c --- /dev/null +++ b/packages/backend/src/boot/prepEnv.ts @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { EventEmitter } from 'node:events'; + +/** + * Configures Node.JS global runtime options for values appropriate for Sharkey. + */ +export function prepEnv() { + // Increase maximum stack trace length. + // This helps diagnose infinite recursion bugs. + Error.stackTraceLimit = Infinity; + + // Avoid warnings like "11 message listeners added to [Commander]. MaxListeners is 10." + // This is expected due to use of NestJS lifecycle hooks. + EventEmitter.defaultMaxListeners = 128; +} diff --git a/packages/backend/test/jest.setup.ts b/packages/backend/test/jest.setup.e2e.ts similarity index 100% rename from packages/backend/test/jest.setup.ts rename to packages/backend/test/jest.setup.e2e.ts diff --git a/packages/backend/test/jest.setup.unit.ts b/packages/backend/test/jest.setup.unit.ts new file mode 100644 index 0000000000..da3f715d8a --- /dev/null +++ b/packages/backend/test/jest.setup.unit.ts @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +// Need to reference the built file +import { prepEnv } from '../built/boot/prepEnv.js'; + +/** + * Applies the Sharkey environment details into the test environment. + * https://jestjs.io/docs/configuration#globalsetup-string + */ +export default function setup() { + // Make sure tests run in the Sharkey environment. + prepEnv(); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1620083ec8..b3d3c84103 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -565,6 +565,9 @@ importers: jest: specifier: 30.1.3 version: 30.1.3(@types/node@22.18.1)(esbuild-register@3.6.0(esbuild@0.25.10))(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.2.130)(@types/node@22.18.1)(typescript@5.9.2)) + jest-environment-node: + specifier: 30.2.0 + version: 30.2.0 jest-mock: specifier: 30.0.5 version: 30.0.5 @@ -582,7 +585,7 @@ importers: version: 7.1.4 ts-jest: specifier: 29.4.4 - version: 29.4.4(@babel/core@7.28.4)(@jest/transform@30.1.2)(@jest/types@30.0.5)(babel-jest@30.1.2(@babel/core@7.28.4))(esbuild@0.25.10)(jest-util@30.0.5)(jest@30.1.3(@types/node@22.18.1)(esbuild-register@3.6.0(esbuild@0.25.10))(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.2.130)(@types/node@22.18.1)(typescript@5.9.2)))(typescript@5.9.2) + version: 29.4.4(@babel/core@7.28.4)(@jest/transform@30.1.2)(@jest/types@30.2.0)(babel-jest@30.1.2(@babel/core@7.28.4))(esbuild@0.25.10)(jest-util@30.2.0)(jest@30.1.3(@types/node@22.18.1)(esbuild-register@3.6.0(esbuild@0.25.10))(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.2.130)(@types/node@22.18.1)(typescript@5.9.2)))(typescript@5.9.2) ts-node: specifier: 10.9.2 version: 10.9.2(@swc/core@1.13.5)(@swc/wasm@1.2.130)(@types/node@22.18.1)(typescript@5.9.2) @@ -1317,7 +1320,7 @@ importers: version: 30.1.0 ts-jest: specifier: 29.4.4 - version: 29.4.4(@babel/core@7.28.4)(@jest/transform@30.1.2)(@jest/types@30.0.5)(babel-jest@30.1.2(@babel/core@7.28.4))(esbuild@0.25.10)(jest-util@30.0.5)(jest@30.1.3(@types/node@22.18.1)(esbuild-register@3.6.0(esbuild@0.25.10))(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.2.130)(@types/node@22.18.1)(typescript@5.9.2)))(typescript@5.9.2) + version: 29.4.4(@babel/core@7.28.4)(@jest/transform@30.1.2)(@jest/types@30.2.0)(babel-jest@30.1.2(@babel/core@7.28.4))(esbuild@0.25.10)(jest-util@30.2.0)(jest@30.1.3(@types/node@22.18.1)(esbuild-register@3.6.0(esbuild@0.25.10))(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.2.130)(@types/node@22.18.1)(typescript@5.9.2)))(typescript@5.9.2) ts-node: specifier: 10.9.2 version: 10.9.2(@swc/core@1.13.5)(@swc/wasm@1.2.130)(@types/node@22.18.1)(typescript@5.9.2) @@ -1415,7 +1418,7 @@ importers: version: 2.0.0 ts-jest: specifier: 29.4.4 - version: 29.4.4(@babel/core@7.28.4)(@jest/transform@30.1.2)(@jest/types@30.0.5)(babel-jest@30.1.2(@babel/core@7.28.4))(esbuild@0.25.10)(jest-util@30.0.5)(jest@30.1.3(@types/node@22.18.1)(esbuild-register@3.6.0(esbuild@0.25.10))(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.2.130)(@types/node@22.18.1)(typescript@5.9.2)))(typescript@5.9.2) + version: 29.4.4(@babel/core@7.28.4)(@jest/transform@30.1.2)(@jest/types@30.2.0)(babel-jest@30.1.2(@babel/core@7.28.4))(esbuild@0.25.10)(jest-util@30.2.0)(jest@30.1.3(@types/node@22.18.1)(esbuild-register@3.6.0(esbuild@0.25.10))(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.2.130)(@types/node@22.18.1)(typescript@5.9.2)))(typescript@5.9.2) ts-node: specifier: 10.9.2 version: 10.9.2(@swc/core@1.13.5)(@swc/wasm@1.2.130)(@types/node@22.18.1)(typescript@5.9.2) @@ -2531,6 +2534,10 @@ packages: resolution: {integrity: sha512-N8t1Ytw4/mr9uN28OnVf0SYE2dGhaIxOVYcwsf9IInBKjvofAjbFRvedvBBlyTYk2knbJTiEjEJ2PyyDIBnd9w==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/environment@30.2.0': + resolution: {integrity: sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/expect-utils@30.1.2': resolution: {integrity: sha512-HXy1qT/bfdjCv7iC336ExbqqYtZvljrV8odNdso7dWK9bSeHtLlvwWWC3YSybSPL03Gg5rug6WLCZAZFH72m0A==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -2543,6 +2550,10 @@ packages: resolution: {integrity: sha512-Beljfv9AYkr9K+ETX9tvV61rJTY706BhBUtiaepQHeEGfe0DbpvUA5Z3fomwc5Xkhns6NWrcFDZn+72fLieUnA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/fake-timers@30.2.0': + resolution: {integrity: sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/get-type@30.1.0': resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -2596,6 +2607,10 @@ packages: resolution: {integrity: sha512-aREYa3aku9SSnea4aX6bhKn4bgv3AXkgijoQgbYV3yvbiGt6z+MQ85+6mIhx9DsKW2BuB/cLR/A+tcMThx+KLQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/types@30.2.0': + resolution: {integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@joshwooding/vite-plugin-react-docgen-typescript@0.6.1': resolution: {integrity: sha512-J4BaTocTOYFkMHIra1JDWrMWpNmBl4EkplIwHEsV8aeUOtdWjwSnln9U7twjMFTAEB7mptNtSKyVi1Y2W9sDJw==} peerDependencies: @@ -7326,6 +7341,10 @@ packages: resolution: {integrity: sha512-w8qBiXtqGWJ9xpJIA98M0EIoq079GOQRQUyse5qg1plShUCQ0Ek1VTTcczqKrn3f24TFAgFtT+4q3aOXvjbsuA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-environment-node@30.2.0: + resolution: {integrity: sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-fetch-mock@3.0.3: resolution: {integrity: sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==} @@ -7349,10 +7368,18 @@ packages: resolution: {integrity: sha512-HizKDGG98cYkWmaLUHChq4iN+oCENohQLb7Z5guBPumYs+/etonmNFlg1Ps6yN9LTPyZn+M+b/9BbnHx3WTMDg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-message-util@30.2.0: + resolution: {integrity: sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-mock@30.0.5: resolution: {integrity: sha512-Od7TyasAAQX/6S+QCbN6vZoWOMwlTtzzGuxJku1GhGanAjz9y+QsQkpScDmETvdc9aSXyJ/Op4rhpMYBWW91wQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-mock@30.2.0: + resolution: {integrity: sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-pnp-resolver@1.2.3: resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} engines: {node: '>=6'} @@ -7390,10 +7417,18 @@ packages: resolution: {integrity: sha512-pvyPWssDZR0FlfMxCBoc0tvM8iUEskaRFALUtGQYzVEAqisAztmy+R8LnU14KT4XA0H/a5HMVTXat1jLne010g==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-util@30.2.0: + resolution: {integrity: sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-validate@30.1.0: resolution: {integrity: sha512-7P3ZlCFW/vhfQ8pE7zW6Oi4EzvuB4sgR72Q1INfW9m0FGo0GADYlPwIkf4CyPq7wq85g+kPMtPOHNAdWHeBOaA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-validate@30.2.0: + resolution: {integrity: sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-watcher@30.1.3: resolution: {integrity: sha512-6jQUZCP1BTL2gvG9E4YF06Ytq4yMb4If6YoQGRR6PpjtqOXSP3sKe2kqwB6SQ+H9DezOfZaSLnmka1NtGm3fCQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -8840,6 +8875,10 @@ packages: resolution: {integrity: sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + pretty-format@30.2.0: + resolution: {integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + pretty-ms@9.3.0: resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} engines: {node: '>=18'} @@ -12221,6 +12260,13 @@ snapshots: '@types/node': 22.18.1 jest-mock: 30.0.5 + '@jest/environment@30.2.0': + dependencies: + '@jest/fake-timers': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 22.18.1 + jest-mock: 30.2.0 + '@jest/expect-utils@30.1.2': dependencies: '@jest/get-type': 30.1.0 @@ -12241,6 +12287,15 @@ snapshots: jest-mock: 30.0.5 jest-util: 30.0.5 + '@jest/fake-timers@30.2.0': + dependencies: + '@jest/types': 30.2.0 + '@sinonjs/fake-timers': 13.0.5 + '@types/node': 22.18.1 + jest-message-util: 30.2.0 + jest-mock: 30.2.0 + jest-util: 30.2.0 + '@jest/get-type@30.1.0': {} '@jest/globals@30.1.2': @@ -12350,6 +12405,16 @@ snapshots: '@types/yargs': 17.0.33 chalk: 4.1.2 + '@jest/types@30.2.0': + dependencies: + '@jest/pattern': 30.0.1 + '@jest/schemas': 30.0.5 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.18.1 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + '@joshwooding/vite-plugin-react-docgen-typescript@0.6.1(typescript@5.9.2)(vite@7.1.7(@types/node@22.18.1)(sass@1.93.2)(terser@5.44.0)(tsx@4.20.5))': dependencies: glob: 10.4.5 @@ -17989,6 +18054,16 @@ snapshots: jest-util: 30.0.5 jest-validate: 30.1.0 + jest-environment-node@30.2.0: + dependencies: + '@jest/environment': 30.2.0 + '@jest/fake-timers': 30.2.0 + '@jest/types': 30.2.0 + '@types/node': 22.18.1 + jest-mock: 30.2.0 + jest-util: 30.2.0 + jest-validate: 30.2.0 + jest-fetch-mock@3.0.3(encoding@0.1.13): dependencies: cross-fetch: 3.2.0(encoding@0.1.13) @@ -18037,12 +18112,30 @@ snapshots: slash: 3.0.0 stack-utils: 2.0.6 + jest-message-util@30.2.0: + dependencies: + '@babel/code-frame': 7.27.1 + '@jest/types': 30.2.0 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 30.2.0 + slash: 3.0.0 + stack-utils: 2.0.6 + jest-mock@30.0.5: dependencies: '@jest/types': 30.0.5 '@types/node': 22.18.1 jest-util: 30.0.5 + jest-mock@30.2.0: + dependencies: + '@jest/types': 30.2.0 + '@types/node': 22.18.1 + jest-util: 30.2.0 + jest-pnp-resolver@1.2.3(jest-resolve@30.1.3): optionalDependencies: jest-resolve: 30.1.3 @@ -18156,6 +18249,15 @@ snapshots: graceful-fs: 4.2.11 picomatch: 4.0.3 + jest-util@30.2.0: + dependencies: + '@jest/types': 30.2.0 + '@types/node': 22.18.1 + chalk: 4.1.2 + ci-info: 4.3.0 + graceful-fs: 4.2.11 + picomatch: 4.0.3 + jest-validate@30.1.0: dependencies: '@jest/get-type': 30.1.0 @@ -18165,6 +18267,15 @@ snapshots: leven: 3.1.0 pretty-format: 30.0.5 + jest-validate@30.2.0: + dependencies: + '@jest/get-type': 30.1.0 + '@jest/types': 30.2.0 + camelcase: 6.3.0 + chalk: 4.1.2 + leven: 3.1.0 + pretty-format: 30.2.0 + jest-watcher@30.1.3: dependencies: '@jest/test-result': 30.1.3 @@ -19802,6 +19913,12 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.3.1 + pretty-format@30.2.0: + dependencies: + '@jest/schemas': 30.0.5 + ansi-styles: 5.2.0 + react-is: 18.3.1 + pretty-ms@9.3.0: dependencies: parse-ms: 4.0.0 @@ -21178,7 +21295,7 @@ snapshots: ts-dedent@2.2.0: {} - ts-jest@29.4.4(@babel/core@7.28.4)(@jest/transform@30.1.2)(@jest/types@30.0.5)(babel-jest@30.1.2(@babel/core@7.28.4))(esbuild@0.25.10)(jest-util@30.0.5)(jest@30.1.3(@types/node@22.18.1)(esbuild-register@3.6.0(esbuild@0.25.10))(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.2.130)(@types/node@22.18.1)(typescript@5.9.2)))(typescript@5.9.2): + ts-jest@29.4.4(@babel/core@7.28.4)(@jest/transform@30.1.2)(@jest/types@30.2.0)(babel-jest@30.1.2(@babel/core@7.28.4))(esbuild@0.25.10)(jest-util@30.2.0)(jest@30.1.3(@types/node@22.18.1)(esbuild-register@3.6.0(esbuild@0.25.10))(ts-node@10.9.2(@swc/core@1.13.5)(@swc/wasm@1.2.130)(@types/node@22.18.1)(typescript@5.9.2)))(typescript@5.9.2): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 @@ -21194,10 +21311,10 @@ snapshots: optionalDependencies: '@babel/core': 7.28.4 '@jest/transform': 30.1.2 - '@jest/types': 30.0.5 + '@jest/types': 30.2.0 babel-jest: 30.1.2(@babel/core@7.28.4) esbuild: 0.25.10 - jest-util: 30.0.5 + jest-util: 30.2.0 ts-map@1.0.3: {}