diff --git a/.changeset/real-mugs-whisper.md b/.changeset/real-mugs-whisper.md new file mode 100644 index 0000000..596cde5 --- /dev/null +++ b/.changeset/real-mugs-whisper.md @@ -0,0 +1,5 @@ +--- +'@threlte/test': patch +--- + +Add type export diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 349091c..efdd90f 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -23,3 +23,21 @@ jobs: - name: Prettier 💅 run: npm run prettier + + unit-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install 🔧 + run: npm ci + + - name: Test 🔬 + run: npm run test diff --git a/package.json b/package.json index e7059b8..0a3e2bd 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "prettier": "prettier --check .", "lint": "prettier --check . && eslint .", "format": "prettier --write .", - "test": "vitest", + "test": "vitest run", "test:watch": "vitest --watch", "release": "changeset publish" }, diff --git a/src/lib/index.d.ts b/src/lib/index.d.ts index 7239521..b817cb3 100644 --- a/src/lib/index.d.ts +++ b/src/lib/index.d.ts @@ -1 +1,55 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import * as Svelte from 'svelte' +import * as THREE from 'three' +import type { ThrelteContext } from '@threlte/core' +import type { IntersectionEvent } from '@threlte/extras' + export { act, cleanup, render } from './pure' + +type ThrelteEvents = + | 'click' + | 'contextmenu' + | 'dblclick' + | 'wheel' + | 'pointerup' + | 'pointerdown' + | 'pointerover' + | 'pointerout' + | 'pointerenter' + | 'pointerleave' + | 'pointermove' + | 'pointermissed' + +export function act(fn?: (() => Promise) | (() => void)): Promise + +export function cleanup(): void + +export function render( + component: typeof Svelte.SvelteComponent, + componentOptions?: { target: HTMLElement } & Record, + renderOptions?: { + baseElement?: HTMLElement + canvas?: HTMLCanvasElement + userSize?: { width: number; height: number } + } +): { + baseElement: HTMLElement + camera: THREE.PerspectiveCamera | THREE.OrthographicCamera + component: Svelte.SvelteComponent + container: HTMLElement + context: ThrelteContext + scene: THREE.Scene + + advance: (options?: { count?: number; delta?: number }) => void + + fireEvent( + object3D: THREE.Object3D, + event: ThrelteEvents, + payload: IntersectionEvent + ): Promise + + rerender(props: Record): Promise + + unmount(): void +} diff --git a/src/routes/Scene.svelte b/src/routes/Scene.svelte index f6f8ede..79d6daa 100644 --- a/src/routes/Scene.svelte +++ b/src/routes/Scene.svelte @@ -2,6 +2,7 @@ import type { Mesh } from 'three' import { T, useTask } from '@threlte/core' + export let positionX = 0 export let onClick: (() => void) | undefined = undefined let ref: Mesh @@ -21,7 +22,7 @@ - + diff --git a/src/routes/__tests__/Scene.spec.ts b/src/routes/__tests__/Scene.spec.ts index 0691e67..010f70d 100644 --- a/src/routes/__tests__/Scene.spec.ts +++ b/src/routes/__tests__/Scene.spec.ts @@ -21,6 +21,17 @@ describe('Scene', () => { expect(mesh.geometry).toBeInstanceOf(BoxGeometry) }) + it('updates position', async () => { + const { scene, rerender } = render(Scene, { positionX: 1 }) + + const mesh = scene.getObjectByProperty('isMesh', true) as Mesh + expect(mesh.position.x).toBe(1) + + await rerender({ positionX: 2 }) + + expect(mesh.position.x).toBe(2) + }) + it('creates a default perspective camera at position [1, 1, 1]', () => { const { camera } = render(Scene) diff --git a/vite.config.ts b/vite.config.ts index 063695c..88e1852 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,31 +1,20 @@ import { defineConfig } from 'vite' import { sveltekit } from '@sveltejs/kit/vite' +import { threlteTesting } from './src/lib/plugin' // https://vitejs.dev/config/ -export default defineConfig(({ mode }) => { - return { - plugins: [sveltekit()], - resolve: { - /* - * Ensure `browser` exports are used in tests - * Vitest prefers modules' `node` export by default - * Svelte's `node` export is its SSR bundle, which does not have onMount - * https://github.com/testing-library/svelte-testing-library/issues/222#issuecomment-1909993331 - */ - conditions: mode === 'test' ? ['browser'] : [], +export default defineConfig({ + plugins: [sveltekit(), threlteTesting()], + ssr: { + noExternal: ['three'], + }, + test: { + coverage: { + include: ['src'], + provider: 'v8', }, - ssr: { - noExternal: ['three'], - }, - test: { - coverage: { - include: ['src'], - provider: 'v8', - }, - environment: 'jsdom', - mockReset: true, - setupFiles: ['./src/lib/vitest.js'], - unstubGlobals: true, - }, - } + environment: 'jsdom', + mockReset: true, + unstubGlobals: true, + }, })