Skip to content
Merged

v2 #34

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .changeset/chilled-hornets-draw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
"@threlte/test": major
---

Rewrites internal architecture to align with @testing-library/svelte:
* discrete modules for cleanup, mounting, setup, and props replace the old core / directory
* Drop all Svelte 3/4 legacy code paths; Svelte 5 only
* Use Proxy-based shallow reactive props ($state.raw) instead of $state with Object.assign
* Task-based cleanup system with addCleanupTask/removeCleanupTask replaces the dual-Set (targetCache/componentCache) approach
* advance() now returns { frameInvalidated: boolean } for testing on-demand and manual render mode invalidation logic
* Container accepts contextOptions via renderOptions.context for passing
* Canvas-level props like colorSpace, toneMapping, shadows, and dpr
* Container uses a properly sized DOM element so getBoundingClientRect() returns real dimensions, fixing default camera aspect ratio
* Vite plugin skips adding auto-cleanup setup files when test.globals is enabled

41 changes: 20 additions & 21 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,42 +1,41 @@
name: Main
name: Release

on:
push:
branches: [main]
branches:
- main

permissions: write-all
permissions:
contents: write
pull-requests: write
id-token: write

jobs:
deploy-and-publish:
release:
name: Release
runs-on: ubuntu-latest

steps:
- name: Checkout 🛎️
uses: actions/checkout@v4

- uses: pnpm/action-setup@v4
name: Install pnpm
- name: Setup Node.js
uses: actions/setup-node@v4
with:
version: 10
run_install: false
node-version: 24
registry-url: 'https://registry.npmjs.org'

- name: Install Node.js
uses: actions/setup-node@v4
- name: Install pnpm 🔧
uses: pnpm/action-setup@v4
with:
node-version: 22
cache: 'pnpm'
run_install: true

- name: Install and Build 🔧
run: |
pnpm i
pnpm build
- name: Build packages 🔧
run: pnpm run package

- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@v1
with:
# This expects you to have a script called release which does a build for your packages and calls changeset publish
publish: pnpm run release
publish: pnpm release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}
109 changes: 42 additions & 67 deletions .github/workflows/pullrequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,123 +13,98 @@ jobs:
- name: Checkout 🛎️
uses: actions/checkout@v4

- uses: pnpm/action-setup@v4
name: Install pnpm
with:
version: 10
run_install: false

- name: Install Node.js
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
node-version: 24

- name: Install 🔧
run: pnpm i
- name: Install pnpm 🔧
uses: pnpm/action-setup@v4
with:
run_install: true

- name: Prettier 💅
run: pnpm prettier

check:
lint:
runs-on: ubuntu-latest

steps:
- name: Checkout 🛎️
uses: actions/checkout@v4

- uses: pnpm/action-setup@v4
name: Install pnpm
with:
version: 10
run_install: false

- name: Install Node.js
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
node-version: 24

- name: Install 🔧
run: pnpm i
- name: Install pnpm 🔧
uses: pnpm/action-setup@v4
with:
run_install: true

- name: Check
run: pnpm check
- name: Lint 💅
run: pnpm lint

package:
check:
runs-on: ubuntu-latest

steps:
- name: Checkout 🛎️
uses: actions/checkout@v4

- uses: pnpm/action-setup@v4
name: Install pnpm
with:
version: 10
run_install: false

- name: Install Node.js
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
node-version: 24

- name: Install 🔧
run: pnpm i
- name: Install pnpm 🔧
uses: pnpm/action-setup@v4
with:
run_install: true

- name: Package
run: pnpm package
- name: Check
run: pnpm check

lint:
package:
runs-on: ubuntu-latest

steps:
- name: Checkout 🛎️
uses: actions/checkout@v4

- uses: pnpm/action-setup@v4
name: Install pnpm
with:
version: 10
run_install: false

- name: Install Node.js
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
node-version: 24

- name: Install 🔧
run: pnpm i
- name: Install pnpm 🔧
uses: pnpm/action-setup@v4
with:
run_install: true

- name: Lint 💅
run: pnpm lint
- name: Package
run: pnpm package

unit-test:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout 🛎️
uses: actions/checkout@v4

- uses: pnpm/action-setup@v4
name: Install pnpm
with:
version: 10
run_install: false

- name: Install Node.js
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
node-version: 24

- name: Install 🔧
run: pnpm i
- name: Install pnpm 🔧
uses: pnpm/action-setup@v4
with:
run_install: true

- name: Install playwright 🔧
run: npx playwright install chromium --with-deps
- name: Install Playwright Browsers
run: npx playwright install --with-deps chromium

- name: Test 🔬
run: pnpm test
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ pnpm-lock.yaml
package-lock.json
yarn.lock
README.md
.changeset
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const {
component, // SvelteComponent
scene, // THREE.Scene
camera, // CurrentWritable<THREE.Camera>
advance, // ({ count?: number; delta?: number }) => void
advance, // ({ count?: number; delta?: number }) => { frameInvalidated: boolean }
fireEvent, // (object3D: THREE.Object3D, event, payload) => Promise<void>
rerender, // (props) => Promise<void>
unmount, // () => void
Expand All @@ -47,13 +47,47 @@ const {

### Advance

In the test renderer environment, Threlte's render mode is set to `manual`. If you wish to test results produced by running `useTask`, you must call `advance`. `advance` is very similar to the function of the same name returned by the `useThrelte` hook, but it advances at a fixed rate (16ms) regardless of environment. The number of times called and delta can also be configured when calling it.
If you wish to test results produced by running `useTask`, you must call `advance`. `advance` runs the scheduler and returns `{ frameInvalidated }` indicating whether the frame needed rendering. The delta defaults to 16ms but can be configured.

```ts
// Runs advance() 10 times with a 33.3ms delta
advance({ delta: 33.3, count: 10 })
```

`advance` returns `{ frameInvalidated: boolean }`, which reflects whether `shouldRender()` was true for that frame. This is useful for testing on-demand and manual render mode invalidation logic.

```ts
const { advance } = render(MyComponent)

const { frameInvalidated } = advance()
expect(frameInvalidated).toBe(true)
```

#### First advance after render

The first `advance()` call after `render()` will always return `{ frameInvalidated: true }`. This is expected — Threlte's internal setup (renderer properties, camera, resize detection) calls `invalidate()` during initialization, just as it does in production on the first animation frame.

When testing invalidation behavior, call `advance()` once to drain the setup invalidation, then use subsequent calls for your assertions:

```ts
const { advance, rerender } = render(MyComponent, {
props: { autoInvalidate: false },
})

// Drain setup invalidation
advance()

// Now test real invalidation behavior
const { frameInvalidated } = advance()
expect(frameInvalidated).toBe(false)

// Trigger invalidation via prop change
await rerender({ someProp: 'newValue' })

const result = advance()
expect(result.frameInvalidated).toBe(true)
```

### fireEvent

If your component uses the `interactivity` plugin, you can test events using the `fireEvent` function. Let's say we have a component like this:
Expand Down
Loading
Loading