diff --git a/jest.config.js b/jest.config.js index 4857b64..17340db 100644 --- a/jest.config.js +++ b/jest.config.js @@ -4,23 +4,22 @@ const SVELTE_TRANSFORM_PATTERN = SVELTE_VERSION >= '5' ? '^.+\\.svelte(?:\\.js)?$' : '^.+\\.svelte$' export default { - testMatch: ['/src/__tests__/**/*.test.js'], + testMatch: ['/tests/**/*.test.js'], transform: { [SVELTE_TRANSFORM_PATTERN]: 'svelte-jester', }, moduleFileExtensions: ['js', 'svelte'], extensionsToTreatAsEsm: ['.svelte'], testEnvironment: 'jsdom', - setupFilesAfterEnv: ['/src/__tests__/_jest-setup.js'], - injectGlobals: false, + setupFilesAfterEnv: ['/tests/_jest-setup.js'], + injectGlobals: true, moduleNameMapper: { - '^vitest$': '/src/__tests__/_jest-vitest-alias.js', + '^vitest$': '/tests/_jest-vitest-alias.js', }, resetMocks: true, restoreMocks: true, collectCoverageFrom: ['/src/**/*'], coveragePathIgnorePatterns: [ - '/__tests__/', '/src/vite.js', '/src/vitest.js', ], diff --git a/package.json b/package.json index cada7e0..2a93d91 100644 --- a/package.json +++ b/package.json @@ -49,8 +49,7 @@ ], "files": [ "src", - "types", - "!__tests__" + "types" ], "scripts": { "all": "npm-run-all contributors:generate toc format types build test:vitest:* test:jest", @@ -129,5 +128,6 @@ "typescript": "^5.5.3", "vite": "^4.0.0 || ^5.3.3", "vitest": "^1.0.0 || ^2.0.2" - } + }, + "packageManager": "pnpm@9.15.0+sha512.76e2379760a4328ec4415815bcd6628dee727af3779aaa4c914e3944156c4299921a89f976381ee107d41f12cfa4b66681ca9c718f0668fa0831ed4c6d8ba56c" } diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..6b70011 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: + - ./ + - ./tests diff --git a/src/__tests__/_jest-setup.js b/src/__tests__/_jest-setup.js deleted file mode 100644 index d1c255c..0000000 --- a/src/__tests__/_jest-setup.js +++ /dev/null @@ -1,9 +0,0 @@ -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 deleted file mode 100644 index 6628c80..0000000 --- a/src/__tests__/_jest-vitest-alias.js +++ /dev/null @@ -1,25 +0,0 @@ -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__/_vitest-setup.js b/src/__tests__/_vitest-setup.js deleted file mode 100644 index a9d0dd3..0000000 --- a/src/__tests__/_vitest-setup.js +++ /dev/null @@ -1 +0,0 @@ -import '@testing-library/jest-dom/vitest' diff --git a/src/__tests__/auto-cleanup.test.js b/src/__tests__/auto-cleanup.test.js deleted file mode 100644 index 7962925..0000000 --- a/src/__tests__/auto-cleanup.test.js +++ /dev/null @@ -1,42 +0,0 @@ -import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest' - -import { IS_JEST } from './utils.js' - -// TODO(mcous, 2024-12-08): clearing module cache and re-importing -// in Jest breaks Svelte's environment checking heuristics. -// Re-implement this test in a more accurate environment, without mocks. -describe.skipIf(IS_JEST)('auto-cleanup', () => { - const globalAfterEach = vi.fn() - - beforeEach(() => { - vi.resetModules() - globalThis.afterEach = globalAfterEach - }) - - afterEach(() => { - delete process.env.STL_SKIP_AUTO_CLEANUP - delete globalThis.afterEach - }) - - test('calls afterEach with cleanup if globally defined', async () => { - const { render } = await import('../index.js') - - expect(globalAfterEach).toHaveBeenCalledTimes(1) - expect(globalAfterEach).toHaveBeenLastCalledWith(expect.any(Function)) - const globalCleanup = globalAfterEach.mock.lastCall[0] - - const { default: Comp } = await import('./fixtures/Comp.svelte') - render(Comp, { props: { name: 'world' } }) - await globalCleanup() - - expect(document.body).toBeEmptyDOMElement() - }) - - test('does not call afterEach if process STL_SKIP_AUTO_CLEANUP is set', async () => { - process.env.STL_SKIP_AUTO_CLEANUP = 'true' - - await import('../index.js') - - expect(globalAfterEach).toHaveBeenCalledTimes(0) - }) -}) diff --git a/tests/_jest-setup.js b/tests/_jest-setup.js new file mode 100644 index 0000000..c448fe0 --- /dev/null +++ b/tests/_jest-setup.js @@ -0,0 +1,21 @@ +import '@testing-library/jest-dom/jest-globals' + +import * as Jest from '@jest/globals' + +import { initializeRunner } from './runner.js' + +// Add support for describe.skipIf and test.skipIf +Jest.describe.skipIf = (condition) => + condition ? Jest.describe.skip : Jest.describe +Jest.test.skipIf = (condition) => (condition ? Jest.test.skip : Jest.test) + +// Add support for `stubGlobal` +Jest.jest.stubGlobal = (property, stub) => { + if (typeof stub === 'function') { + Jest.jest.spyOn(globalThis, property).mockImplementation(stub) + } else { + Jest.jest.replaceProperty(globalThis, property, stub) + } +} + +initializeRunner({ ...Jest, vi: Jest.jest }) diff --git a/tests/_vitest-setup.js b/tests/_vitest-setup.js new file mode 100644 index 0000000..9682cff --- /dev/null +++ b/tests/_vitest-setup.js @@ -0,0 +1,7 @@ +import '@testing-library/jest-dom/vitest' + +import * as Vitest from 'vitest' + +import { initializeRunner } from './runner.js' + +initializeRunner(Vitest) diff --git a/src/__tests__/act.test.js b/tests/act.test.js similarity index 93% rename from src/__tests__/act.test.js rename to tests/act.test.js index 75c9ded..b5badf6 100644 --- a/src/__tests__/act.test.js +++ b/tests/act.test.js @@ -1,9 +1,9 @@ import { setTimeout } from 'node:timers/promises' import { act, render } from '@testing-library/svelte' -import { describe, expect, test } from 'vitest' import Comp from './fixtures/Comp.svelte' +import { describe, expect, test } from './runner.js' describe('act', () => { test('state updates are flushed', async () => { diff --git a/src/__tests__/cleanup.test.js b/tests/cleanup.test.js similarity index 93% rename from src/__tests__/cleanup.test.js rename to tests/cleanup.test.js index d0ae026..a59b42e 100644 --- a/src/__tests__/cleanup.test.js +++ b/tests/cleanup.test.js @@ -1,7 +1,7 @@ import { cleanup, render } from '@testing-library/svelte' -import { describe, expect, test, vi } from 'vitest' import Mounter from './fixtures/Mounter.svelte' +import { describe, expect, test, vi } from './runner.js' const onExecuted = vi.fn() const onDestroyed = vi.fn() diff --git a/src/__tests__/context.test.js b/tests/context.test.js similarity index 87% rename from src/__tests__/context.test.js rename to tests/context.test.js index da54b9d..d498416 100644 --- a/src/__tests__/context.test.js +++ b/tests/context.test.js @@ -1,7 +1,7 @@ import { render } from '@testing-library/svelte' -import { expect, test } from 'vitest' import Comp from './fixtures/Context.svelte' +import { expect, test } from './runner.js' test('can set a context', () => { const message = 'Got it' diff --git a/src/__tests__/debug.test.js b/tests/debug.test.js similarity index 90% rename from src/__tests__/debug.test.js rename to tests/debug.test.js index e2a9eda..5e9faea 100644 --- a/src/__tests__/debug.test.js +++ b/tests/debug.test.js @@ -1,8 +1,8 @@ import { prettyDOM } from '@testing-library/dom' import { render } from '@testing-library/svelte' -import { describe, expect, test, vi } from 'vitest' import Comp from './fixtures/Comp.svelte' +import { describe, expect, test, vi } from './runner.js' describe('debug', () => { test('pretty prints the base element', () => { diff --git a/src/__tests__/events.test.js b/tests/events.test.js similarity index 94% rename from src/__tests__/events.test.js rename to tests/events.test.js index e0aba4d..355da8b 100644 --- a/src/__tests__/events.test.js +++ b/tests/events.test.js @@ -1,7 +1,7 @@ import { fireEvent, render } from '@testing-library/svelte' -import { describe, expect, test } from 'vitest' import Comp from './fixtures/Comp.svelte' +import { describe, expect, test } from './runner.js' describe('events', () => { test('state changes are flushed after firing an event', async () => { diff --git a/src/__tests__/fixtures/Comp.svelte b/tests/fixtures/Comp.svelte similarity index 100% rename from src/__tests__/fixtures/Comp.svelte rename to tests/fixtures/Comp.svelte diff --git a/src/__tests__/fixtures/CompRunes.svelte b/tests/fixtures/CompRunes.svelte similarity index 100% rename from src/__tests__/fixtures/CompRunes.svelte rename to tests/fixtures/CompRunes.svelte diff --git a/src/__tests__/fixtures/Context.svelte b/tests/fixtures/Context.svelte similarity index 100% rename from src/__tests__/fixtures/Context.svelte rename to tests/fixtures/Context.svelte diff --git a/src/__tests__/fixtures/Mounter.svelte b/tests/fixtures/Mounter.svelte similarity index 100% rename from src/__tests__/fixtures/Mounter.svelte rename to tests/fixtures/Mounter.svelte diff --git a/src/__tests__/fixtures/Transitioner.svelte b/tests/fixtures/Transitioner.svelte similarity index 100% rename from src/__tests__/fixtures/Transitioner.svelte rename to tests/fixtures/Transitioner.svelte diff --git a/src/__tests__/fixtures/Typed.svelte b/tests/fixtures/Typed.svelte similarity index 100% rename from src/__tests__/fixtures/Typed.svelte rename to tests/fixtures/Typed.svelte diff --git a/src/__tests__/fixtures/TypedRunes.svelte b/tests/fixtures/TypedRunes.svelte similarity index 100% rename from src/__tests__/fixtures/TypedRunes.svelte rename to tests/fixtures/TypedRunes.svelte diff --git a/src/__tests__/mount.test.js b/tests/mount.test.js similarity index 92% rename from src/__tests__/mount.test.js rename to tests/mount.test.js index df6351d..59f3598 100644 --- a/src/__tests__/mount.test.js +++ b/tests/mount.test.js @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/svelte' -import { describe, expect, test, vi } from 'vitest' import Mounter from './fixtures/Mounter.svelte' +import { describe, expect, test, vi } from './runner.js' const onMounted = vi.fn() const onDestroyed = vi.fn() diff --git a/src/__tests__/multi-base.test.js b/tests/multi-base.test.js similarity index 94% rename from src/__tests__/multi-base.test.js rename to tests/multi-base.test.js index bf5fd4e..8820908 100644 --- a/src/__tests__/multi-base.test.js +++ b/tests/multi-base.test.js @@ -1,7 +1,7 @@ import { render } from '@testing-library/svelte' -import { describe, expect, test } from 'vitest' import Comp from './fixtures/Comp.svelte' +import { describe, expect, test } from './runner.js' describe('multi-base', () => { const treeA = document.createElement('div') diff --git a/tests/package.json b/tests/package.json new file mode 100644 index 0000000..4bfb962 --- /dev/null +++ b/tests/package.json @@ -0,0 +1,8 @@ +{ + "name": "@testing-library/svelte-tests", + "private": true, + "type": "module", + "devDependencies": { + "@testing-library/svelte": "workspace:*" + } +} diff --git a/src/__tests__/render-runes.test-d.ts b/tests/render-runes.test-d.ts similarity index 96% rename from src/__tests__/render-runes.test-d.ts rename to tests/render-runes.test-d.ts index 2d0c69f..a9ce31c 100644 --- a/src/__tests__/render-runes.test-d.ts +++ b/tests/render-runes.test-d.ts @@ -1,7 +1,7 @@ +import * as subject from '@testing-library/svelte' import { expectTypeOf } from 'expect-type' import { describe, test } from 'vitest' -import * as subject from '../index.js' import Component from './fixtures/TypedRunes.svelte' describe('types', () => { diff --git a/src/__tests__/render-utilities.test-d.ts b/tests/render-utilities.test-d.ts similarity index 97% rename from src/__tests__/render-utilities.test-d.ts rename to tests/render-utilities.test-d.ts index b45614e..72e2a67 100644 --- a/src/__tests__/render-utilities.test-d.ts +++ b/tests/render-utilities.test-d.ts @@ -1,7 +1,7 @@ +import * as subject from '@testing-library/svelte' import { expectTypeOf } from 'expect-type' import { describe, test } from 'vitest' -import * as subject from '../index.js' import Component from './fixtures/Comp.svelte' describe('render query and utility types', () => { diff --git a/src/__tests__/render.test-d.ts b/tests/render.test-d.ts similarity index 97% rename from src/__tests__/render.test-d.ts rename to tests/render.test-d.ts index 08cad70..07df5a9 100644 --- a/src/__tests__/render.test-d.ts +++ b/tests/render.test-d.ts @@ -1,8 +1,8 @@ +import * as subject from '@testing-library/svelte' import { expectTypeOf } from 'expect-type' import { ComponentProps } from 'svelte' import { describe, test } from 'vitest' -import * as subject from '../index.js' import Component from './fixtures/Typed.svelte' describe('types', () => { diff --git a/src/__tests__/render.test.js b/tests/render.test.js similarity index 97% rename from src/__tests__/render.test.js rename to tests/render.test.js index f396751..9041953 100644 --- a/src/__tests__/render.test.js +++ b/tests/render.test.js @@ -1,6 +1,6 @@ import { render } from '@testing-library/svelte' -import { beforeAll, describe, expect, test } from 'vitest' +import { beforeAll, describe, expect, test } from './runner.js' import { COMPONENT_FIXTURES } from './utils.js' describe.each(COMPONENT_FIXTURES)('render ($mode)', ({ component }) => { diff --git a/src/__tests__/rerender.test.js b/tests/rerender.test.js similarity index 95% rename from src/__tests__/rerender.test.js rename to tests/rerender.test.js index 52acd0f..fe7fde6 100644 --- a/src/__tests__/rerender.test.js +++ b/tests/rerender.test.js @@ -1,6 +1,6 @@ import { act, render, screen } from '@testing-library/svelte' -import { beforeAll, describe, expect, test, vi } from 'vitest' +import { beforeAll, describe, expect, test, vi } from './runner.js' import { COMPONENT_FIXTURES, IS_SVELTE_5, MODE_RUNES } from './utils.js' describe.each(COMPONENT_FIXTURES)('rerender ($mode)', ({ mode, component }) => { diff --git a/tests/runner.js b/tests/runner.js new file mode 100644 index 0000000..666c32f --- /dev/null +++ b/tests/runner.js @@ -0,0 +1,49 @@ +const runner = { + afterAll: () => {}, + afterEach: () => {}, + beforeAll: () => {}, + beforeEach: () => {}, + describe: () => {}, + expect: () => {}, + test: () => {}, + vi: {}, +} + +const createRunnerProxy = (name) => { + const target = runner[name] + const handler = { + apply(_target, _thisArg, args) { + return runner[name](...args) + }, + get(_target, prop) { + return runner[name][prop] + }, + } + + return new Proxy(target, handler) +} + +const afterAll = createRunnerProxy('afterAll') +const afterEach = createRunnerProxy('afterEach') +const beforeAll = createRunnerProxy('beforeAll') +const beforeEach = createRunnerProxy('beforeEach') +const describe = createRunnerProxy('describe') +const expect = createRunnerProxy('expect') +const test = createRunnerProxy('test') +const vi = createRunnerProxy('vi') + +const initializeRunner = (runnerConfig) => { + Object.assign(runner, runnerConfig) +} + +export { + afterAll, + afterEach, + beforeAll, + beforeEach, + describe, + expect, + initializeRunner, + test, + vi, +} diff --git a/src/__tests__/transition.test.js b/tests/transition.test.js similarity index 92% rename from src/__tests__/transition.test.js rename to tests/transition.test.js index a9c8e02..d317ee5 100644 --- a/src/__tests__/transition.test.js +++ b/tests/transition.test.js @@ -1,8 +1,8 @@ import { render, screen, waitFor } from '@testing-library/svelte' import { userEvent } from '@testing-library/user-event' -import { beforeEach, describe, expect, test, vi } from 'vitest' import Transitioner from './fixtures/Transitioner.svelte' +import { beforeEach, describe, expect, test, vi } from './runner.js' import { IS_JSDOM, IS_SVELTE_5 } from './utils.js' describe.skipIf(IS_SVELTE_5)('transitions', () => { diff --git a/src/__tests__/utils.js b/tests/utils.js similarity index 100% rename from src/__tests__/utils.js rename to tests/utils.js diff --git a/src/__tests__/vite-plugin.test.js b/tests/vite-plugin.test.js similarity index 97% rename from src/__tests__/vite-plugin.test.js rename to tests/vite-plugin.test.js index 9232f65..ac67c82 100644 --- a/src/__tests__/vite-plugin.test.js +++ b/tests/vite-plugin.test.js @@ -1,6 +1,6 @@ -import { beforeEach, describe, expect, test, vi } from 'vitest' +import { svelteTesting } from '@testing-library/svelte/vite' -import { svelteTesting } from '../vite.js' +import { beforeEach, describe, expect, test, vi } from './runner.js' import { IS_JEST } from './utils.js' describe.skipIf(IS_JEST)('vite plugin', () => { diff --git a/tsconfig.build.json b/tsconfig.build.json index 0baa218..0cc73fd 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -8,5 +8,5 @@ "rootDir": "src", "outDir": "types" }, - "exclude": ["src/**/__tests__/**"] + "exclude": ["tests"] } diff --git a/tsconfig.json b/tsconfig.json index f79cace..b56dc40 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,5 +7,5 @@ "strict": true, "types": ["svelte", "vite/client", "vitest", "vitest/globals"] }, - "include": ["src"] + "include": ["src", "tests"] } diff --git a/tsconfig.legacy.json b/tsconfig.legacy.json index b5d9e57..304d872 100644 --- a/tsconfig.legacy.json +++ b/tsconfig.legacy.json @@ -1,8 +1,8 @@ { "extends": ["./tsconfig.json"], "exclude": [ - "src/__tests__/render-runes.test-d.ts", - "src/__tests__/fixtures/CompRunes.svelte", - "src/__tests__/fixtures/TypedRunes.svelte" + "tests/render-runes.test-d.ts", + "tests/fixtures/CompRunes.svelte", + "tests/fixtures/TypedRunes.svelte" ] } diff --git a/vite.config.js b/vite.config.js index 1ddeea5..086aeba 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,21 +1,20 @@ import { svelte } from '@sveltejs/vite-plugin-svelte' +import { svelteTesting } from '@testing-library/svelte/vite' import { defineConfig } from 'vite' -import { svelteTesting } from './src/vite.js' - // https://vitejs.dev/config/ export default defineConfig({ plugins: [svelte(), svelteTesting()], test: { environment: 'jsdom', - setupFiles: ['./src/__tests__/_vitest-setup.js'], + setupFiles: ['./tests/_vitest-setup.js'], mockReset: true, unstubGlobals: true, unstubEnvs: true, coverage: { provider: 'v8', include: ['src/**/*'], - exclude: ['**/__tests__/**', 'src/vite.js', 'src/vitest.js'], + exclude: ['src/vitest.js'], }, }, })