{"id":25566528,"url":"https://github.com/threlte/test-renderer","last_synced_at":"2026-04-07T00:01:46.452Z","repository":{"id":230605824,"uuid":"758201205","full_name":"threlte/test-renderer","owner":"threlte","description":"A component testing toolkit for Threlte","archived":false,"fork":false,"pushed_at":"2026-04-06T22:24:14.000Z","size":398,"stargazers_count":9,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-06T23:23:44.334Z","etag":null,"topics":["svelte","testing-library","threejs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/threlte.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-02-15T20:27:08.000Z","updated_at":"2026-04-06T22:23:46.000Z","dependencies_parsed_at":"2024-04-18T22:27:09.892Z","dependency_job_id":"3464ab1b-5fd8-4016-8dc0-fd70f2bc7ae4","html_url":"https://github.com/threlte/test-renderer","commit_stats":null,"previous_names":["threlte/test-renderer"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/threlte/test-renderer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/threlte%2Ftest-renderer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/threlte%2Ftest-renderer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/threlte%2Ftest-renderer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/threlte%2Ftest-renderer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/threlte","download_url":"https://codeload.github.com/threlte/test-renderer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/threlte%2Ftest-renderer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31494177,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-06T17:22:55.647Z","status":"ssl_error","status_checked_at":"2026-04-06T17:22:54.741Z","response_time":112,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["svelte","testing-library","threejs"],"created_at":"2025-02-20T22:33:01.659Z","updated_at":"2026-04-07T00:01:46.438Z","avatar_url":"https://github.com/threlte.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## @threlte/test\n\n`@threlte/test` is a lightweight component testing toolkit for Threlte.\n\n```\nnpm i @threlte/test\n```\n\nIt supports Svelte 5 + Threlte 8 onwards.\n\n```ts\nimport { describe, it, expect } from 'vitest'\nimport { render } from '@threlte/test'\nimport Scene from './Scene.svelte'\n\ndescribe('Scene', () =\u003e {\n  it('creates a box mesh with a boxGeometry and meshStandardMaterial', () =\u003e {\n    const { scene } = render(Scene)\n\n    const mesh = scene.getObjectByProperty('isMesh', true) as Mesh\n    expect(mesh).toBeDefined()\n    expect(mesh.material).toBeInstanceOf(MeshStandardMaterial)\n    expect(mesh.geometry).toBeInstanceOf(BoxGeometry)\n  })\n})\n```\n\nIt provides a function, `render`, which will instantiate a Threlte context and whatever component you pass to it.\n\nCalling `render` will provide useful tools for testing your component's behavior.\n\n```ts\nconst {\n  component, // SvelteComponent\n  scene, // THREE.Scene\n  camera, // CurrentWritable\u003cTHREE.Camera\u003e\n  advance, // ({ count?: number; delta?: number }) =\u003e { frameInvalidated: boolean }\n  fireEvent, // (object3D: THREE.Object3D, event, payload) =\u003e Promise\u003cvoid\u003e\n  rerender, // (props) =\u003e Promise\u003cvoid\u003e\n  unmount, // () =\u003e void\n} = render(Component)\n```\n\n### Scene\n\n`scene` is the `THREE.Scene` created by a Threlte context without any modifications. Querying objects from it can be useful for verifying that your component is doing what you expect it to.\n\n### Advance\n\nIf 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.\n\n```ts\n// Runs advance() 10 times with a 33.3ms delta\nadvance({ delta: 33.3, count: 10 })\n```\n\n`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.\n\n```ts\nconst { advance } = render(MyComponent)\n\nconst { frameInvalidated } = advance()\nexpect(frameInvalidated).toBe(true)\n```\n\n#### First advance after render\n\nThe 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.\n\nWhen testing invalidation behavior, call `advance()` once to drain the setup invalidation, then use subsequent calls for your assertions:\n\n```ts\nconst { advance, rerender } = render(MyComponent, {\n  props: { autoInvalidate: false },\n})\n\n// Drain setup invalidation\nadvance()\n\n// Now test real invalidation behavior\nconst { frameInvalidated } = advance()\nexpect(frameInvalidated).toBe(false)\n\n// Trigger invalidation via prop change\nawait rerender({ someProp: 'newValue' })\n\nconst result = advance()\nexpect(result.frameInvalidated).toBe(true)\n```\n\n### fireEvent\n\nIf your component uses the `interactivity` plugin, you can test events using the `fireEvent` function. Let's say we have a component like this:\n\n```svelte\n\u003cscript\u003e\n  let { onclick } = $props()\n\u003c/script\u003e\n\n\u003cT.Mesh {onclick} /\u003e\n```\n\nWe can write a test like this:\n\n```ts\nconst onclick = vi.fn()\nconst { render, fireEvent } = render(Scene, {\n  props: { onclick }\n})\n\nconst mesh = scene.getObjectByName('myMesh')\nawait fireEvent(mesh, 'click', someOptionalCustomPayload)\nexpect(onclick).toHaveBeenCalledOnce()\n```\n\nNote that if you use the event object, you will have to design a mock payload.\n\n### Setup\n\n`@threlte/test` currently only supports vitest as your test runner. To get started, add the `threlteTesting` plugin to your Vite or Vitest config.\n\n```ts\n// vite.config.js\nimport { svelte } from '@sveltejs/vite-plugin-svelte'\nimport { threlteTesting } from '@threlte/test/vite'\n\nexport default defineConfig({\n  plugins: [\n    svelte(),\n    threlteTesting(),\n  ]\n});\n```\n\nAdditionally, the [Vitest environment](https://vitest.dev/guide/environment.html) must be set to a DOM enviroment, like happy-dom or vitest browser mode.\n\n### Limitations\n\nThe test renderer runs in a node.js environment, unless if running in vite browser mode. It creates a Threlte context and renders your component with this context provided. This must be considered when testing `\u003cCanvas\u003e` or `WebGLRenderer` related configuration and behavior.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthrelte%2Ftest-renderer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthrelte%2Ftest-renderer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthrelte%2Ftest-renderer/lists"}