Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
drcmda committed Jan 27, 2023
2 parents a86c12e + 9052964 commit 5f51f8d
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 64 deletions.
6 changes: 6 additions & 0 deletions packages/test-renderer/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @react-three/test-renderer

## 8.1.1

### Patch Changes

- 9a776b71: fix(RTTR): backport traverse, update fixes

## 8.1.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/test-renderer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@react-three/test-renderer",
"version": "8.1.0",
"version": "8.1.1",
"description": "Test Renderer for react-three-fiber",
"author": "Josh Ellis",
"license": "MIT",
Expand Down
29 changes: 23 additions & 6 deletions packages/test-renderer/src/__tests__/RTTR.core.test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useFrame } from '@react-three/fiber'
import * as React from 'react'
import * as THREE from 'three'

Expand All @@ -6,7 +7,7 @@ import ReactThreeTestRenderer from '../index'
type ExampleComp = THREE.Mesh<THREE.BoxBufferGeometry, THREE.Material>

describe('ReactThreeTestRenderer Core', () => {
it('renders a simple component', async () => {
it('renders JSX', async () => {
const Mesh = () => {
return (
<mesh>
Expand All @@ -15,12 +16,28 @@ describe('ReactThreeTestRenderer Core', () => {
</mesh>
)
}
const renderer = await ReactThreeTestRenderer.create(
<React.Suspense fallback={null}>
<Mesh />
</React.Suspense>,
)

const renderer = await ReactThreeTestRenderer.create(<Mesh />)
expect(renderer.scene.children[0].type).toEqual('Mesh')
await renderer.update(<Mesh />)
expect(renderer.scene.children[0].type).toEqual('Mesh')
})

it('renders a simple component with hooks', async () => {
const Mesh = () => {
const meshRef = React.useRef<THREE.Mesh<THREE.BoxGeometry, THREE.MeshBasicMaterial>>()
useFrame(() => void (meshRef.current!.position.x += 0.01))
return (
<mesh>
<boxGeometry args={[2, 2]} />
<meshBasicMaterial />
</mesh>
)
}

const renderer = await ReactThreeTestRenderer.create(<Mesh />)
expect(renderer.scene.children[0].type).toEqual('Mesh')
await renderer.update(<Mesh />)
expect(renderer.scene.children[0].type).toEqual('Mesh')
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,19 +296,19 @@ Array [
Object {
"children": Array [],
"props": Object {
"args": Array [
2,
2,
],
"args": Array [],
},
"type": "boxGeometry",
"type": "meshBasicMaterial",
},
Object {
"children": Array [],
"props": Object {
"args": Array [],
"args": Array [
2,
2,
],
},
"type": "meshBasicMaterial",
"type": "boxGeometry",
},
],
"props": Object {
Expand Down
74 changes: 24 additions & 50 deletions packages/test-renderer/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,73 +46,47 @@ const create = async (element: React.ReactNode, options?: Partial<CreateOptions>
},
})

const _fiber = canvas
const _root = createRoot(canvas).configure({ frameloop: 'never', ...options, events: undefined })
const _store = mockRoots.get(canvas)!.store

const _root = createRoot(_fiber).configure({ frameloop: 'never', ...options, events: undefined })

let scene: MockScene = null!

await act(async () => {
scene = _root.render(element).getState().scene as unknown as MockScene
})

const _store = mockRoots.get(_fiber)!.store
await act(async () => _root.render(element))
const scene = _store.getState().scene as unknown as MockScene

return {
scene: wrapFiber(scene),
unmount: async () => {
await act(async () => {
_root.unmount()
})
async unmount() {
await act(async () => _root.unmount())
},
getInstance: () => {
// this is our root
const fiber = mockRoots.get(_fiber)?.fiber
const current = fiber?.current.child.child
if (current) {
const root = {
/**
* we wrap our child in a Provider component
* and context.Provider, so do a little
* artificial dive to get round this and
* pass context.Provider as if it was the
* actual react root
*/
current,
}
getInstance() {
// Bail if canvas is unmounted
if (!mockRoots.has(canvas)) return null

/**
* so this actually returns the instance
* the user has passed through as a Fiber
*/
return reconciler.getPublicRootInstance(root)
} else {
return null
}
// Traverse fiber nodes for R3F root
const root = { current: mockRoots.get(canvas)!.fiber.current }
while (!root.current.child?.stateNode) root.current = root.current.child

// Return R3F instance from root
return reconciler.getPublicRootInstance(root)
},
update: async (newElement: React.ReactNode) => {
const fiber = mockRoots.get(_fiber)?.fiber
if (fiber) {
await act(async () => {
reconciler.updateContainer(newElement, fiber, null, () => null)
})
}
return
async update(newElement: React.ReactNode) {
if (!mockRoots.has(canvas)) return console.warn('RTTR: attempted to update an unmounted root!')

await act(async () => _root.render(newElement))
},
toTree: () => {
toTree() {
return toTree(scene)
},
toGraph: () => {
toGraph() {
return toGraph(scene)
},
fireEvent: createEventFirer(act, _store),
advanceFrames: async (frames: number, delta: number | number[] = 1) => {
async advanceFrames(frames: number, delta: number | number[] = 1) {
const state = _store.getState()
const storeSubscribers = state.internal.subscribers

const promises: Promise<void>[] = []

storeSubscribers.forEach((subscriber) => {
for (const subscriber of storeSubscribers) {
for (let i = 0; i < frames; i++) {
if (is.arr(delta)) {
promises.push(
Expand All @@ -122,7 +96,7 @@ const create = async (element: React.ReactNode, options?: Partial<CreateOptions>
promises.push(new Promise(() => subscriber.ref.current(state, delta as number)))
}
}
})
}

Promise.all(promises)
},
Expand Down

0 comments on commit 5f51f8d

Please sign in to comment.