diff --git a/eslint.config.js b/eslint.config.js index bc9dd841b..5830ca0f7 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,4 +1,5 @@ import nxEslintPlugin from '@nx/eslint-plugin'; +import jestExtendedPlugin from 'eslint-plugin-jest-extended'; import jsoncParser from 'jsonc-eslint-parser'; import tseslint from 'typescript-eslint'; import node from '@code-pushup/eslint-config/node.js'; @@ -84,6 +85,7 @@ export default tseslint.config( }, { files: ['**/*.test.ts', '**/*.spec.ts'], + plugins: { 'jest-extended': jestExtendedPlugin }, rules: { 'vitest/consistent-test-filename': [ 'warn', @@ -91,6 +93,11 @@ export default tseslint.config( pattern: String.raw`.*\.(bench|type|unit|int|e2e)\.test\.[tj]sx?$`, }, ], + 'jest-extended/prefer-to-be-array': 'warn', + 'jest-extended/prefer-to-be-false': 'warn', + 'jest-extended/prefer-to-be-object': 'warn', + 'jest-extended/prefer-to-be-true': 'warn', + 'jest-extended/prefer-to-have-been-called-once': 'warn', }, }, { diff --git a/package-lock.json b/package-lock.json index 364f46e21..6781508e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -76,6 +76,7 @@ "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-functional": "^7.1.0", "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jest-extended": "^3.0.0", "eslint-plugin-jest-formatting": "^3.1.0", "eslint-plugin-n": "^17.15.0", "eslint-plugin-promise": "^7.2.1", @@ -86,6 +87,7 @@ "globals": "^15.13.0", "husky": "^8.0.0", "inquirer": "^9.3.7", + "jest-extended": "^6.0.0", "jsdom": "~24.0.0", "jsonc-eslint-parser": "^2.4.0", "knip": "^5.33.3", @@ -14764,6 +14766,22 @@ "strip-bom": "^3.0.0" } }, + "node_modules/eslint-plugin-jest-extended": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest-extended/-/eslint-plugin-jest-extended-3.0.0.tgz", + "integrity": "sha512-G/nPzMUJ7gJyFwB8ThjELAJyxGhYc9EvJu2w9iNhKkroQ0yYQ3q5YdMoLVjWTawexl+M9j+jhOdd9shpCvsbYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "engines": { + "node": "^16.10.0 || ^18.12.0 || >=20.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, "node_modules/eslint-plugin-jest-formatting": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/eslint-plugin-jest-formatting/-/eslint-plugin-jest-formatting-3.1.0.tgz", @@ -18949,6 +18967,31 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-extended": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-6.0.0.tgz", + "integrity": "sha512-SM249N/q33YQ9XE8E06qZSnFuuV4GQFx7WrrmIj4wQUAP43jAo6budLT482jdBhf8ASwUiEEfJNjej0UusYs5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-diff": "^29.0.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || ^22.11.0 || >=23.0.0" + }, + "peerDependencies": { + "jest": ">=27.2.5", + "typescript": ">=5.0.0" + }, + "peerDependenciesMeta": { + "jest": { + "optional": true + }, + "typescript": { + "optional": false + } + } + }, "node_modules/jest-get-type": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", diff --git a/package.json b/package.json index 7a931e94e..45317b2f2 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-functional": "^7.1.0", "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jest-extended": "^3.0.0", "eslint-plugin-jest-formatting": "^3.1.0", "eslint-plugin-n": "^17.15.0", "eslint-plugin-promise": "^7.2.1", @@ -99,6 +100,7 @@ "globals": "^15.13.0", "husky": "^8.0.0", "inquirer": "^9.3.7", + "jest-extended": "^6.0.0", "jsdom": "~24.0.0", "jsonc-eslint-parser": "^2.4.0", "knip": "^5.33.3", diff --git a/packages/ci/src/lib/issues.unit.test.ts b/packages/ci/src/lib/issues.unit.test.ts index 806202ca5..6fd512707 100644 --- a/packages/ci/src/lib/issues.unit.test.ts +++ b/packages/ci/src/lib/issues.unit.test.ts @@ -31,7 +31,7 @@ describe('issues comparison', () => { }, }, ), - ).toBe(true); + ).toBeTrue(); }); it('should not match issues from different audits', () => { @@ -63,7 +63,7 @@ describe('issues comparison', () => { }, }, ), - ).toBe(false); + ).toBeFalse(); }); it('should match issues based on adjusted line', () => { @@ -97,7 +97,7 @@ describe('issues comparison', () => { }, }, ), - ).toBe(true); + ).toBeTrue(); }); it('should match issues from renamed files', () => { @@ -124,7 +124,7 @@ describe('issues comparison', () => { }, }, ), - ).toBe(true); + ).toBeTrue(); }); it('should match issues based on adjusted line range', () => { @@ -165,7 +165,7 @@ describe('issues comparison', () => { }, }, ), - ).toBe(true); + ).toBeTrue(); }); }); diff --git a/packages/ci/src/lib/monorepo/handlers/npm.unit.test.ts b/packages/ci/src/lib/monorepo/handlers/npm.unit.test.ts index 45b36c1cb..1cff90eb9 100644 --- a/packages/ci/src/lib/monorepo/handlers/npm.unit.test.ts +++ b/packages/ci/src/lib/monorepo/handlers/npm.unit.test.ts @@ -30,7 +30,7 @@ describe('npmHandler', () => { }, MEMFS_VOLUME, ); - await expect(npmHandler.isConfigured(options)).resolves.toBe(true); + await expect(npmHandler.isConfigured(options)).resolves.toBeTrue(); }); it('should NOT detect NPM workspaces when "workspaces" not set in package.json', async () => { @@ -41,7 +41,7 @@ describe('npmHandler', () => { }, MEMFS_VOLUME, ); - await expect(npmHandler.isConfigured(options)).resolves.toBe(false); + await expect(npmHandler.isConfigured(options)).resolves.toBeFalse(); }); it("should NOT detect NPM workspaces when package-lock.json doesn't exist", async () => { @@ -55,7 +55,7 @@ describe('npmHandler', () => { }, MEMFS_VOLUME, ); - await expect(npmHandler.isConfigured(options)).resolves.toBe(false); + await expect(npmHandler.isConfigured(options)).resolves.toBeFalse(); }); }); diff --git a/packages/ci/src/lib/monorepo/handlers/nx.unit.test.ts b/packages/ci/src/lib/monorepo/handlers/nx.unit.test.ts index 4ad65905c..e610b1638 100644 --- a/packages/ci/src/lib/monorepo/handlers/nx.unit.test.ts +++ b/packages/ci/src/lib/monorepo/handlers/nx.unit.test.ts @@ -24,7 +24,7 @@ describe('nxHandler', () => { stdout: 'NX Report complete - copy this into the issue template', } as utils.ProcessResult); - await expect(nxHandler.isConfigured(options)).resolves.toBe(true); + await expect(nxHandler.isConfigured(options)).resolves.toBeTrue(); }); it("should NOT detect Nx when nx.json doesn't exist", async () => { @@ -33,7 +33,7 @@ describe('nxHandler', () => { code: 0, } as utils.ProcessResult); - await expect(nxHandler.isConfigured(options)).resolves.toBe(false); + await expect(nxHandler.isConfigured(options)).resolves.toBeFalse(); }); it('should NOT detect Nx when `nx report` fails with non-zero exit code', async () => { @@ -43,7 +43,7 @@ describe('nxHandler', () => { stderr: 'Error: ValueExpected in nx.json', } as utils.ProcessResult); - await expect(nxHandler.isConfigured(options)).resolves.toBe(false); + await expect(nxHandler.isConfigured(options)).resolves.toBeFalse(); }); }); diff --git a/packages/ci/src/lib/monorepo/handlers/pnpm.unit.test.ts b/packages/ci/src/lib/monorepo/handlers/pnpm.unit.test.ts index 75c42538f..386d62aaa 100644 --- a/packages/ci/src/lib/monorepo/handlers/pnpm.unit.test.ts +++ b/packages/ci/src/lib/monorepo/handlers/pnpm.unit.test.ts @@ -28,7 +28,7 @@ describe('pnpmHandler', () => { }, MEMFS_VOLUME, ); - await expect(pnpmHandler.isConfigured(options)).resolves.toBe(true); + await expect(pnpmHandler.isConfigured(options)).resolves.toBeTrue(); }); it("should NOT detect PNPM workspace when pnpm-workspace.yaml doesn't exist", async () => { @@ -39,7 +39,7 @@ describe('pnpmHandler', () => { }, MEMFS_VOLUME, ); - await expect(pnpmHandler.isConfigured(options)).resolves.toBe(false); + await expect(pnpmHandler.isConfigured(options)).resolves.toBeFalse(); }); it("should NOT detect PNPM workspace when root package.json doesn't exist", async () => { @@ -52,7 +52,7 @@ describe('pnpmHandler', () => { }, MEMFS_VOLUME, ); - await expect(pnpmHandler.isConfigured(options)).resolves.toBe(false); + await expect(pnpmHandler.isConfigured(options)).resolves.toBeFalse(); }); }); diff --git a/packages/ci/src/lib/monorepo/handlers/turbo.unit.test.ts b/packages/ci/src/lib/monorepo/handlers/turbo.unit.test.ts index e4a590b3a..c4d397883 100644 --- a/packages/ci/src/lib/monorepo/handlers/turbo.unit.test.ts +++ b/packages/ci/src/lib/monorepo/handlers/turbo.unit.test.ts @@ -37,7 +37,7 @@ describe('turboHandler', () => { }, MEMFS_VOLUME, ); - await expect(turboHandler.isConfigured(options)).resolves.toBe(true); + await expect(turboHandler.isConfigured(options)).resolves.toBeTrue(); }); it("should NOT detect Turborepo when turbo.json doesn't exist", async () => { @@ -48,7 +48,7 @@ describe('turboHandler', () => { }, MEMFS_VOLUME, ); - await expect(turboHandler.isConfigured(options)).resolves.toBe(false); + await expect(turboHandler.isConfigured(options)).resolves.toBeFalse(); }); it("should NOT detect Turborepo when turbo.json doesn't include code-pushup task", async () => { @@ -72,7 +72,7 @@ describe('turboHandler', () => { }, MEMFS_VOLUME, ); - await expect(turboHandler.isConfigured(options)).resolves.toBe(false); + await expect(turboHandler.isConfigured(options)).resolves.toBeFalse(); }); }); diff --git a/packages/ci/src/lib/monorepo/handlers/yarn.unit.test.ts b/packages/ci/src/lib/monorepo/handlers/yarn.unit.test.ts index 1963b7917..a846af3c4 100644 --- a/packages/ci/src/lib/monorepo/handlers/yarn.unit.test.ts +++ b/packages/ci/src/lib/monorepo/handlers/yarn.unit.test.ts @@ -32,7 +32,7 @@ describe('yarnHandler', () => { }, MEMFS_VOLUME, ); - await expect(yarnHandler.isConfigured(options)).resolves.toBe(true); + await expect(yarnHandler.isConfigured(options)).resolves.toBeTrue(); }); it('should NOT detect Yarn workspaces when "workspaces" not set in package.json', async () => { @@ -43,7 +43,7 @@ describe('yarnHandler', () => { }, MEMFS_VOLUME, ); - await expect(yarnHandler.isConfigured(options)).resolves.toBe(false); + await expect(yarnHandler.isConfigured(options)).resolves.toBeFalse(); }); it("should NOT detect Yarn workspaces when yarn.lock doesn't exist", async () => { @@ -57,7 +57,7 @@ describe('yarnHandler', () => { }, MEMFS_VOLUME, ); - await expect(yarnHandler.isConfigured(options)).resolves.toBe(false); + await expect(yarnHandler.isConfigured(options)).resolves.toBeFalse(); }); }); diff --git a/packages/ci/src/lib/monorepo/packages.unit.test.ts b/packages/ci/src/lib/monorepo/packages.unit.test.ts index 2677c6b0d..b7024e953 100644 --- a/packages/ci/src/lib/monorepo/packages.unit.test.ts +++ b/packages/ci/src/lib/monorepo/packages.unit.test.ts @@ -228,7 +228,7 @@ describe('hasWorkspacesEnabled', () => { { 'package.json': pkgJsonContent({ name: 'example', private: true }) }, MEMFS_VOLUME, ); - await expect(hasWorkspacesEnabled(MEMFS_VOLUME)).resolves.toBe(false); + await expect(hasWorkspacesEnabled(MEMFS_VOLUME)).resolves.toBeFalse(); }); it('should identify as NOT enabled if `"private": true` missing in root package.json', async () => { @@ -241,7 +241,7 @@ describe('hasWorkspacesEnabled', () => { }, MEMFS_VOLUME, ); - await expect(hasWorkspacesEnabled(MEMFS_VOLUME)).resolves.toBe(false); + await expect(hasWorkspacesEnabled(MEMFS_VOLUME)).resolves.toBeFalse(); }); it('should identify as enabled if private and workspaces array set in root package.json', async () => { @@ -254,7 +254,7 @@ describe('hasWorkspacesEnabled', () => { }, MEMFS_VOLUME, ); - await expect(hasWorkspacesEnabled(MEMFS_VOLUME)).resolves.toBe(true); + await expect(hasWorkspacesEnabled(MEMFS_VOLUME)).resolves.toBeTrue(); }); it('should identify as enabled if private and workspaces object set in root package.json', async () => { @@ -270,7 +270,7 @@ describe('hasWorkspacesEnabled', () => { }, MEMFS_VOLUME, ); - await expect(hasWorkspacesEnabled(MEMFS_VOLUME)).resolves.toBe(true); + await expect(hasWorkspacesEnabled(MEMFS_VOLUME)).resolves.toBeTrue(); }); }); @@ -313,25 +313,25 @@ describe('hasScript', () => { { scripts: { 'code-pushup': 'code-pushup --no-progress' } }, 'code-pushup', ), - ).toBe(true); + ).toBeTrue(); }); it('should return false if script not in package.json "scripts"', () => { - expect(hasScript({}, 'code-pushup')).toBe(false); + expect(hasScript({}, 'code-pushup')).toBeFalse(); }); }); describe('hasDependency', () => { it('should return true if package name in "dependencies"', () => { - expect(hasDependency({ dependencies: { react: '^19.0.0' } }, 'react')).toBe( - true, - ); + expect( + hasDependency({ dependencies: { react: '^19.0.0' } }, 'react'), + ).toBeTrue(); }); it('should return true if package name in "devDependencies"', () => { - expect(hasDependency({ devDependencies: { nx: '20.1.3' } }, 'nx')).toBe( - true, - ); + expect( + hasDependency({ devDependencies: { nx: '20.1.3' } }, 'nx'), + ).toBeTrue(); }); it('should return false if package name is neither in "dependencies" nor "devDependencies"', () => { @@ -343,7 +343,7 @@ describe('hasDependency', () => { }, 'svelte', ), - ).toBe(false); + ).toBeFalse(); }); }); @@ -353,7 +353,7 @@ describe('hasCodePushUpDependency', () => { hasCodePushUpDependency({ devDependencies: { '@code-pushup/cli': '^0.55.0' }, }), - ).toBe(true); + ).toBeTrue(); }); it('should return true if @code-pushup/cli in "dependencies"', () => { @@ -361,7 +361,7 @@ describe('hasCodePushUpDependency', () => { hasCodePushUpDependency({ dependencies: { '@code-pushup/cli': 'latest' }, }), - ).toBe(true); + ).toBeTrue(); }); it('should return false if @code-pushup/cli is neither in "dependencies" nor "devDependencies"', () => { @@ -372,6 +372,6 @@ describe('hasCodePushUpDependency', () => { '@code-pushup/utils': 'latest', }, }), - ).toBe(false); + ).toBeFalse(); }); }); diff --git a/packages/ci/tsconfig.test.json b/packages/ci/tsconfig.test.json index 4c2574da1..6eaa057c7 100644 --- a/packages/ci/tsconfig.test.json +++ b/packages/ci/tsconfig.test.json @@ -18,6 +18,7 @@ "src/**/*.test.tsx", "src/**/*.test.js", "src/**/*.test.jsx", - "src/**/*.d.ts" + "src/**/*.d.ts", + "../../testing/test-setup/src/vitest.d.ts" ] } diff --git a/packages/ci/vitest.unit.config.ts b/packages/ci/vitest.unit.config.ts index e6dcce6bd..a7b37b3fd 100644 --- a/packages/ci/vitest.unit.config.ts +++ b/packages/ci/vitest.unit.config.ts @@ -26,6 +26,7 @@ export default defineConfig({ '../../testing/test-setup/src/lib/git.mock.ts', '../../testing/test-setup/src/lib/console.mock.ts', '../../testing/test-setup/src/lib/reset.mocks.ts', + '../../testing/test-setup/src/lib/extend/jest-extended.matcher.ts', ], }, }); diff --git a/packages/core/src/lib/collect-and-persist.unit.test.ts b/packages/core/src/lib/collect-and-persist.unit.test.ts index 1ecb5c5fe..3a7ee4d43 100644 --- a/packages/core/src/lib/collect-and-persist.unit.test.ts +++ b/packages/core/src/lib/collect-and-persist.unit.test.ts @@ -49,7 +49,7 @@ describe('collectAndPersistReports', () => { it('should call collect and persistReport with correct parameters in non-verbose mode', async () => { const sortedScoredReport = sortReport(scoreReport(MINIMAL_REPORT_MOCK)); - expect(isVerbose()).toBe(false); + expect(isVerbose()).toBeFalse(); const nonVerboseConfig: CollectAndPersistReportsOptions = { ...MINIMAL_CONFIG_MOCK, diff --git a/packages/core/src/lib/merge-diffs.unit.test.ts b/packages/core/src/lib/merge-diffs.unit.test.ts index 97b8cb163..ef529e1dc 100644 --- a/packages/core/src/lib/merge-diffs.unit.test.ts +++ b/packages/core/src/lib/merge-diffs.unit.test.ts @@ -34,7 +34,7 @@ describe('mergeDiffs', () => { const outputPath = await mergeDiffs(files, persistConfig); expect(outputPath).toBe(path.join(MEMFS_VOLUME, 'report-diff.md')); - await expect(fileExists(outputPath)).resolves.toBe(true); + await expect(fileExists(outputPath)).resolves.toBeTrue(); await expect(readFile(outputPath, 'utf8')).resolves.toContain( '# Code PushUp', ); diff --git a/packages/core/vitest.unit.config.ts b/packages/core/vitest.unit.config.ts index 31e0a6262..820eb538c 100644 --- a/packages/core/vitest.unit.config.ts +++ b/packages/core/vitest.unit.config.ts @@ -30,6 +30,7 @@ export default defineConfig({ '../../testing/test-setup/src/lib/portal-client.mock.ts', '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', '../../testing/test-setup/src/lib/extend/markdown-table.matcher.ts', + '../../testing/test-setup/src/lib/extend/jest-extended.matcher.ts', ], }, }); diff --git a/packages/plugin-eslint/src/lib/runner/lint.unit.test.ts b/packages/plugin-eslint/src/lib/runner/lint.unit.test.ts index c0166b1c4..516e3501e 100644 --- a/packages/plugin-eslint/src/lib/runner/lint.unit.test.ts +++ b/packages/plugin-eslint/src/lib/runner/lint.unit.test.ts @@ -98,7 +98,7 @@ describe('lint', () => { errorOnUnmatchedPattern: false, }); - expect(executeProcess).toHaveBeenCalledTimes(1); + expect(executeProcess).toHaveBeenCalledOnce(); expect(executeProcess).toHaveBeenCalledWith< Parameters >({ diff --git a/packages/plugin-jsdocs/src/lib/runner/doc-processor.unit.test.ts b/packages/plugin-jsdocs/src/lib/runner/doc-processor.unit.test.ts index 3fb57a1ae..147946671 100644 --- a/packages/plugin-jsdocs/src/lib/runner/doc-processor.unit.test.ts +++ b/packages/plugin-jsdocs/src/lib/runner/doc-processor.unit.test.ts @@ -83,8 +83,8 @@ describe('getClassNodes', () => { getClassNodes([nodeMock1] as unknown as ClassDeclaration[]); - expect(classNodeSpy).toHaveBeenCalledTimes(1); - expect(propertyNodeSpy).toHaveBeenCalledTimes(1); + expect(classNodeSpy).toHaveBeenCalledOnce(); + expect(propertyNodeSpy).toHaveBeenCalledOnce(); }); }); diff --git a/packages/utils/src/lib/env.unit.test.ts b/packages/utils/src/lib/env.unit.test.ts index c603ad7c8..1ff0f92b5 100644 --- a/packages/utils/src/lib/env.unit.test.ts +++ b/packages/utils/src/lib/env.unit.test.ts @@ -8,32 +8,32 @@ describe('isEnvVarEnabled', () => { it('should consider missing variable disabled', () => { vi.stubEnv('CP_VERBOSE', undefined!); - expect(isEnvVarEnabled('CP_VERBOSE')).toBe(false); + expect(isEnvVarEnabled('CP_VERBOSE')).toBeFalse(); }); it('should consider "true" enabled', () => { vi.stubEnv('CP_VERBOSE', 'true'); - expect(isEnvVarEnabled('CP_VERBOSE')).toBe(true); + expect(isEnvVarEnabled('CP_VERBOSE')).toBeTrue(); }); it('should consider "false" disabled', () => { vi.stubEnv('CP_VERBOSE', 'false'); - expect(isEnvVarEnabled('CP_VERBOSE')).toBe(false); + expect(isEnvVarEnabled('CP_VERBOSE')).toBeFalse(); }); it('should consider "1" enabled', () => { vi.stubEnv('CP_VERBOSE', '1'); - expect(isEnvVarEnabled('CP_VERBOSE')).toBe(true); + expect(isEnvVarEnabled('CP_VERBOSE')).toBeTrue(); }); it('should consider "0" disabled', () => { vi.stubEnv('CP_VERBOSE', '0'); - expect(isEnvVarEnabled('CP_VERBOSE')).toBe(false); + expect(isEnvVarEnabled('CP_VERBOSE')).toBeFalse(); }); it('should log a warning for unexpected values', () => { vi.stubEnv('CP_VERBOSE', 'unexpected'); - expect(isEnvVarEnabled('CP_VERBOSE')).toBe(false); + expect(isEnvVarEnabled('CP_VERBOSE')).toBeFalse(); expect(ui()).toHaveLogged( 'warn', 'Environment variable CP_VERBOSE expected to be a boolean (true/false/1/0), but received value unexpected. Treating it as disabled.', diff --git a/packages/utils/src/lib/guards.unit.test.ts b/packages/utils/src/lib/guards.unit.test.ts index f4138c8b7..6ad76d058 100644 --- a/packages/utils/src/lib/guards.unit.test.ts +++ b/packages/utils/src/lib/guards.unit.test.ts @@ -11,8 +11,8 @@ describe('promise-result', () => { status: 'fulfilled', value: 'value', } as PromiseSettledResult; - expect(isPromiseFulfilledResult(result)).toBe(true); - expect(isPromiseRejectedResult(result)).toBe(false); + expect(isPromiseFulfilledResult(result)).toBeTrue(); + expect(isPromiseRejectedResult(result)).toBeFalse(); }); it('should get rejected result', () => { @@ -20,25 +20,25 @@ describe('promise-result', () => { status: 'rejected', reason: 'reason', } as PromiseSettledResult; - expect(isPromiseFulfilledResult(result)).toBe(false); - expect(isPromiseRejectedResult(result)).toBe(true); + expect(isPromiseFulfilledResult(result)).toBeFalse(); + expect(isPromiseRejectedResult(result)).toBeTrue(); }); }); describe('hasNoNullableProps', () => { it('should return true if object prop values are neither null nor undefined', () => { - expect(hasNoNullableProps({ a: 42, b: 'foo', c: {}, d: [] })).toBe(true); + expect(hasNoNullableProps({ a: 42, b: 'foo', c: {}, d: [] })).toBeTrue(); }); it('should return false if some prop is null', () => { - expect(hasNoNullableProps({ x: 42, y: null })).toBe(false); + expect(hasNoNullableProps({ x: 42, y: null })).toBeFalse(); }); it('should return false if some prop is set to undefined', () => { - expect(hasNoNullableProps({ x: undefined })).toBe(false); + expect(hasNoNullableProps({ x: undefined })).toBeFalse(); }); it('should return true for empty object', () => { - expect(hasNoNullableProps({})).toBe(true); + expect(hasNoNullableProps({})).toBeTrue(); }); }); diff --git a/packages/utils/vitest.unit.config.ts b/packages/utils/vitest.unit.config.ts index 64208a43e..ac74f7af6 100644 --- a/packages/utils/vitest.unit.config.ts +++ b/packages/utils/vitest.unit.config.ts @@ -32,6 +32,7 @@ export default defineConfig({ '../../testing/test-setup/src/lib/extend/ui-logger.matcher.ts', '../../testing/test-setup/src/lib/extend/markdown-table.matcher.ts', '../../testing/test-setup/src/lib/extend/path.matcher.ts', + '../../testing/test-setup/src/lib/extend/jest-extended.matcher.ts', ], }, }); diff --git a/testing/test-setup/src/lib/extend/jest-extended.matcher.ts b/testing/test-setup/src/lib/extend/jest-extended.matcher.ts new file mode 100644 index 000000000..fe21fbed7 --- /dev/null +++ b/testing/test-setup/src/lib/extend/jest-extended.matcher.ts @@ -0,0 +1,4 @@ +import * as matchers from 'jest-extended'; +import { expect } from 'vitest'; + +expect.extend(matchers); diff --git a/testing/test-setup/src/vitest.d.ts b/testing/test-setup/src/vitest.d.ts index 48352ef1a..d9929e7a2 100644 --- a/testing/test-setup/src/vitest.d.ts +++ b/testing/test-setup/src/vitest.d.ts @@ -1,3 +1,4 @@ +import type { CustomMatchers as JestExtendedMatchers } from 'jest-extended'; import type { CustomMarkdownTableMatchers } from './lib/extend/markdown-table.matcher.js'; import type { CustomAsymmetricPathMatchers, @@ -9,6 +10,12 @@ declare module 'vitest' { interface Assertion extends CustomPathMatchers, CustomUiLoggerMatchers, - CustomMarkdownTableMatchers {} - interface AsymmetricMatchersContaining extends CustomAsymmetricPathMatchers {} + CustomMarkdownTableMatchers, + JestExtendedMatchers {} + + interface AsymmetricMatchersContaining + extends CustomAsymmetricPathMatchers, + JestExtendedMatchers {} + + interface ExpectStatic extends JestExtendedMatchers {} }