From 6e076dadf1c4e3b46ad01223cd7f6f4ea75653a0 Mon Sep 17 00:00:00 2001 From: Michael Cousins Date: Wed, 24 Apr 2024 15:04:39 -0400 Subject: [PATCH 1/2] test(jest): add Jest to CI matrix --- .github/workflows/release.yml | 6 +++++- jest.config.cjs | 16 ++++++++++++++++ package.json | 4 ++++ src/__tests__/_jest-setup.js | 9 +++++++++ src/__tests__/_jest-vitest-alias.js | 25 +++++++++++++++++++++++++ src/__tests__/cleanup.test.js | 2 +- src/__tests__/mount.test.js | 4 ++-- src/__tests__/rerender.test.js | 2 +- 8 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 jest.config.cjs create mode 100644 src/__tests__/_jest-setup.js create mode 100644 src/__tests__/_jest-vitest-alias.js diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index be47107..509895b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: matrix: node: ['16', '18', '20'] svelte: ['3', '4'] - test-runner: ['vitest:jsdom', 'vitest:happy-dom'] + test-runner: ['vitest:jsdom', 'vitest:happy-dom', 'jest'] experimental: [false] include: - node: '20' @@ -36,6 +36,10 @@ jobs: svelte: 'next' test-runner: 'vitest:happy-dom' experimental: true + - node: '20' + svelte: 'next' + test-runner: 'jest' + experimental: true steps: - name: ⬇️ Checkout repo diff --git a/jest.config.cjs b/jest.config.cjs new file mode 100644 index 0000000..9963ca1 --- /dev/null +++ b/jest.config.cjs @@ -0,0 +1,16 @@ +module.exports = { + testMatch: ['/src/__tests__/**/*.test.js'], + transform: { + '^.+\\.svelte$': 'svelte-jester', + }, + moduleFileExtensions: ['js', 'svelte'], + extensionsToTreatAsEsm: ['.svelte'], + testEnvironment: 'jsdom', + setupFilesAfterEnv: ['/src/__tests__/_jest-setup.js'], + injectGlobals: false, + moduleNameMapper: { + '^vitest$': '/src/__tests__/_jest-vitest-alias.js', + }, + resetMocks: true, + restoreMocks: true, +} diff --git a/package.json b/package.json index 795e117..b67db89 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "test:watch": "vitest", "test:vitest:jsdom": "vitest run --coverage --environment jsdom", "test:vitest:happy-dom": "vitest run --coverage --environment happy-dom", + "test:jest": "npx --node-options=\"--experimental-vm-modules --no-warnings\" jest --coverage", "types": "svelte-check", "validate": "npm-run-all test:vitest:* types", "contributors:add": "all-contributors add", @@ -89,6 +90,7 @@ "@testing-library/dom": "^10.0.0" }, "devDependencies": { + "@jest/globals": "^29.7.0", "@sveltejs/vite-plugin-svelte": "^3.0.2", "@testing-library/jest-dom": "^6.3.0", "@testing-library/user-event": "^14.5.2", @@ -109,6 +111,8 @@ "eslint-plugin-vitest-globals": "1.5.0", "expect-type": "^0.19.0", "happy-dom": "^14.7.1", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", "jsdom": "^24.0.0", "npm-run-all": "^4.1.5", "prettier": "3.2.5", diff --git a/src/__tests__/_jest-setup.js b/src/__tests__/_jest-setup.js new file mode 100644 index 0000000..d1c255c --- /dev/null +++ b/src/__tests__/_jest-setup.js @@ -0,0 +1,9 @@ +import '@testing-library/jest-dom/jest-globals' + +import { afterEach } from '@jest/globals' +import { act, cleanup } from '@testing-library/svelte' + +afterEach(async () => { + await act() + cleanup() +}) diff --git a/src/__tests__/_jest-vitest-alias.js b/src/__tests__/_jest-vitest-alias.js new file mode 100644 index 0000000..6628c80 --- /dev/null +++ b/src/__tests__/_jest-vitest-alias.js @@ -0,0 +1,25 @@ +import { describe, jest, test } from '@jest/globals' + +export { + afterAll, + afterEach, + beforeAll, + beforeEach, + describe, + expect, + test, + jest as vi, +} from '@jest/globals' + +// Add support for describe.skipIf and test.skipIf +describe.skipIf = (condition) => (condition ? describe.skip : describe) +test.skipIf = (condition) => (condition ? test.skip : test) + +// Add support for `stubGlobal` +jest.stubGlobal = (property, stub) => { + if (typeof stub === 'function') { + jest.spyOn(globalThis, property).mockImplementation(stub) + } else { + jest.replaceProperty(globalThis, property, stub) + } +} diff --git a/src/__tests__/cleanup.test.js b/src/__tests__/cleanup.test.js index 7131624..d0ae026 100644 --- a/src/__tests__/cleanup.test.js +++ b/src/__tests__/cleanup.test.js @@ -19,7 +19,7 @@ describe('cleanup', () => { renderSubject() cleanup() - expect(onDestroyed).toHaveBeenCalledOnce() + expect(onDestroyed).toHaveBeenCalledTimes(1) }) test('cleanup handles unexpected errors during mount', () => { diff --git a/src/__tests__/mount.test.js b/src/__tests__/mount.test.js index 48d985f..e25c429 100644 --- a/src/__tests__/mount.test.js +++ b/src/__tests__/mount.test.js @@ -15,7 +15,7 @@ describe('mount and destroy', () => { expect(content).toBeInTheDocument() await act() - expect(onMounted).toHaveBeenCalledOnce() + expect(onMounted).toHaveBeenCalledTimes(1) }) test('component is destroyed', async () => { @@ -28,6 +28,6 @@ describe('mount and destroy', () => { expect(content).not.toBeInTheDocument() await act() - expect(onDestroyed).toHaveBeenCalledOnce() + expect(onDestroyed).toHaveBeenCalledTimes(1) }) }) diff --git a/src/__tests__/rerender.test.js b/src/__tests__/rerender.test.js index ca4b8e8..21a782c 100644 --- a/src/__tests__/rerender.test.js +++ b/src/__tests__/rerender.test.js @@ -23,7 +23,7 @@ describe('rerender', () => { await rerender({ props: { name: 'Dolly' } }) expect(element).toHaveTextContent('Hello Dolly!') - expect(console.warn).toHaveBeenCalledOnce() + expect(console.warn).toHaveBeenCalledTimes(1) expect(console.warn).toHaveBeenCalledWith( expect.stringMatching(/deprecated/iu) ) From e8b9c9404de1f18fc4de9dd4e29100bb5e483e62 Mon Sep 17 00:00:00 2001 From: Michael Cousins Date: Tue, 30 Apr 2024 00:39:10 -0400 Subject: [PATCH 2/2] fixup: svelte5 alias for jest --- .github/workflows/release.yml | 2 +- jest.config.cjs => jest.config.js | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) rename jest.config.cjs => jest.config.js (65%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 509895b..27af7a8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,7 +59,7 @@ jobs: run: npm run test:${{ matrix.test-runner }} - name: ▶️ Run type-checks - if: ${{ matrix.node == '20' && matrix.svelte == '4' }} + if: ${{ matrix.node == '20' && matrix.svelte == '4' && matrix.test-runner == 'vitest:jsdom' }} run: npm run types - name: ⬆️ Upload coverage report diff --git a/jest.config.cjs b/jest.config.js similarity index 65% rename from jest.config.cjs rename to jest.config.js index 9963ca1..d6b1fde 100644 --- a/jest.config.cjs +++ b/jest.config.js @@ -1,4 +1,8 @@ -module.exports = { +import { VERSION as SVELTE_VERSION } from 'svelte/compiler' + +const IS_SVELTE_5 = SVELTE_VERSION >= '5' + +export default { testMatch: ['/src/__tests__/**/*.test.js'], transform: { '^.+\\.svelte$': 'svelte-jester', @@ -10,6 +14,9 @@ module.exports = { injectGlobals: false, moduleNameMapper: { '^vitest$': '/src/__tests__/_jest-vitest-alias.js', + '^@testing-library/svelte$': IS_SVELTE_5 + ? '/src/svelte5-index.js' + : '/src/index.js', }, resetMocks: true, restoreMocks: true,