-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(scene composer): setting up 3D test harness
- Loading branch information
1 parent
84d2ce4
commit df62eef
Showing
32 changed files
with
373 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
**/e2e/**/*.png filter=lfs diff=lfs merge=lfs -text |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/sh | ||
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-checkout' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; } | ||
git lfs post-checkout "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/sh | ||
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-commit' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; } | ||
git lfs post-commit "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/sh | ||
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-merge' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; } | ||
git lfs post-merge "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/sh | ||
command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'pre-push' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; } | ||
git lfs pre-push "$@" |
43 changes: 43 additions & 0 deletions
43
packages/scene-composer/e2e/tests/local-scene/scene-composer--local-scene.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { test, expect } from '@playwright/test'; | ||
|
||
import { PlaywrightHelper } from '../utils/sceneHelpers'; | ||
|
||
const localScene = '/iframe.html?args=&id=developer-scene-composer--local-scene'; | ||
const canvas = '#tm-scene-unselectable-canvas'; | ||
|
||
test.describe('scene-composer--local-scene', () => { | ||
test('visual regression', async ({ page }) => { | ||
await page.goto(localScene); | ||
const frame = page.locator('#root'); | ||
expect(await frame.locator(canvas).screenshot()).toMatchSnapshot({ | ||
name: 'local-scene-canvas.png', | ||
threshold: 1, | ||
}); | ||
}); | ||
|
||
test('get object by name', async ({ page }) => { | ||
const state = new PlaywrightHelper(page, localScene); | ||
// find object named 'PalletJack' | ||
const palletJack = await state.getObjecByName('PalletJack'); | ||
|
||
// assert expected values on object | ||
expect(palletJack.isObject3D).toBeTruthy(); | ||
expect(palletJack.type).toEqual('Group'); | ||
expect(palletJack.visible).toBeTruthy(); | ||
}); | ||
|
||
test('select object', async ({ page }) => { | ||
const state = new PlaywrightHelper(page, localScene); | ||
// find object named 'PalletJack' | ||
const palletJack = await state.getObjecByName('PalletJack'); | ||
|
||
// select object in hierarchy | ||
const formattedName = palletJack.name.replace(/([A-Z])/g, ' $1').trim(); | ||
const handle = await page.$(`text=${formattedName}`); | ||
await handle?.hover(); | ||
await handle?.click(); | ||
|
||
// assert that the associated selectedSceneNode.ref was selected in the Inspector Panel | ||
expect(page.getByTestId('cb85148b-00ca-4006-8b0f-600890eaee46')).toBeDefined(); | ||
}); | ||
}); |
Binary file added
BIN
+46.7 KB
...-composer--local-scene.spec.ts-snapshots/local-scene-canvas-chromium-darwin.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+33 KB
...e-composer--local-scene.spec.ts-snapshots/local-scene-canvas-chromium-linux.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions
24
packages/scene-composer/e2e/tests/motion-indicator/scene-composer--motion-indicator.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { test, expect } from '@playwright/test'; | ||
|
||
import { PlaywrightHelper } from '../utils/sceneHelpers'; | ||
|
||
const localScene = '/iframe.html?args=&id=tests-scene-viewer--motion-indicator'; | ||
const canvas = '#tm-scene-unselectable-canvas'; | ||
|
||
test.describe('scene-viewer--motion-indicator', () => { | ||
test('visual regression', async ({ page }) => { | ||
await page.goto(localScene); | ||
const frame = page.locator('#root'); | ||
expect(await frame.locator(canvas).screenshot()).toMatchSnapshot({ | ||
name: 'motion-indicator-canvas.png', | ||
threshold: 1, | ||
}); | ||
}); | ||
|
||
test('get scene', async ({ page }) => { | ||
const state = new PlaywrightHelper(page, localScene); | ||
const scene = await state.getScene(); | ||
expect(scene.sceneId).toEqual('motion-indicator-view-options'); | ||
expect(scene.scene.type).toEqual('Scene'); | ||
}); | ||
}); |
Binary file added
BIN
+14.9 KB
...-motion-indicator.spec.ts-snapshots/motion-indicator-canvas-chromium-darwin.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+45.9 KB
...--motion-indicator.spec.ts-snapshots/motion-indicator-canvas-chromium-linux.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Object3D } from 'three'; | ||
|
||
export default class R3FTestHarness { | ||
scene; | ||
sceneId; | ||
|
||
constructor(scene: Object3D, sceneId: string) { | ||
this.scene = scene; | ||
this.sceneId = sceneId; | ||
} | ||
|
||
// Get Object By Name | ||
/* | ||
* Returns scene object | ||
* `name` as string | ||
*/ | ||
async getObjecByName(name: string) { | ||
return this.scene.getObjectByName(name); | ||
} | ||
} |
113 changes: 113 additions & 0 deletions
113
packages/scene-composer/e2e/tests/utils/sceneHelpers.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { Scene, WebGLRenderer } from 'three'; | ||
import type { Page, Locator } from '@playwright/test'; | ||
|
||
import R3FTestHarness from './r3fTestHarness'; | ||
|
||
declare global { | ||
interface Window { | ||
__twinmaker_tests: { | ||
[key: string]: { | ||
scene: Scene; | ||
gl: WebGLRenderer; | ||
}; | ||
}; | ||
} | ||
} | ||
|
||
type SceneLoadedEventDetail = { sceneComposerId: string; scene: Scene; gl: WebGLRenderer }; | ||
|
||
interface SceneLoadedEvent extends Event { | ||
detail: SceneLoadedEventDetail; | ||
} | ||
|
||
type evaluateProps = { | ||
sceneId: string; | ||
arg?: string; | ||
callback?: string; | ||
callbackString?: string; | ||
TMHarnessClass: string; | ||
}; | ||
export class PlaywrightHelper { | ||
localScene: string; | ||
|
||
constructor(public readonly page: Page, localScene: string) { | ||
this.page = page; | ||
this.localScene = localScene; | ||
} | ||
|
||
async goto(localScene: string) { | ||
await this.page.goto(localScene); | ||
} | ||
|
||
async getFrame(localFrame: string) { | ||
return this.page.locator(localFrame); | ||
} | ||
|
||
async getSceneId(frame: Locator) { | ||
const sceneId: string = await frame.evaluate(async () => { | ||
return await new Promise((res, rej) => { | ||
const timer = setTimeout( | ||
() => rej(new Error('Timeout, twinmaker:scene-loaded was not reached in reasonable time.')), | ||
30000, | ||
); | ||
|
||
window.addEventListener('twinmaker:scene-loaded', (evt: Event) => { | ||
const { detail } = evt as SceneLoadedEvent; | ||
const { sceneComposerId, scene, gl } = detail; | ||
window['__twinmaker_tests'] = window['__twinmaker_tests'] || {}; | ||
window['__twinmaker_tests'][sceneComposerId] = { scene, gl }; | ||
clearTimeout(timer); | ||
res(sceneComposerId); | ||
}); | ||
}); | ||
}); | ||
return sceneId; | ||
} | ||
|
||
async tmScene(frame: Locator, sceneId: string) { | ||
const sceneResult = await frame.evaluate((_element: HTMLElement, sceneId: string) => { | ||
return Promise.resolve<Scene>(window['__twinmaker_tests'][sceneId].scene); | ||
}, sceneId); | ||
return sceneResult; | ||
} | ||
|
||
async getScene() { | ||
await this.page.goto(this.localScene); | ||
const frame = this.page.locator('#root'); | ||
const sceneId = await this.getSceneId(frame); | ||
const scene = await this.tmScene(frame, sceneId); | ||
return { | ||
frame, | ||
sceneId, | ||
scene, | ||
}; | ||
} | ||
|
||
async playwrightState(...props) { | ||
const result = await this.getScene(); | ||
const sceneId = result.sceneId; | ||
return await this.page.evaluate( | ||
async ({ arg, callback, sceneId, TMHarnessClass }: evaluateProps) => { | ||
const { scene } = window['__twinmaker_tests'][sceneId]; | ||
if (!scene) throw new Error('Scene is not loaded'); | ||
const HarnessClass = await eval('window.TMHarnessClass = ' + TMHarnessClass); | ||
const harness = await new HarnessClass(scene); | ||
|
||
if (callback) { | ||
return await Promise.resolve(harness[callback](arg)); | ||
} | ||
}, | ||
{ | ||
sceneId: sceneId, | ||
arg: props[1], | ||
callback: props[0], | ||
TMHarnessClass: R3FTestHarness.toString(), | ||
}, | ||
); | ||
} | ||
|
||
// map harness functions here | ||
async getObjecByName(name: string) { | ||
return await this.playwrightState('getObjecByName', name); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { defineConfig, devices } from '@playwright/test'; | ||
|
||
/** | ||
* See https://playwright.dev/docs/test-configuration. | ||
*/ | ||
export default defineConfig({ | ||
testDir: './e2e', | ||
/* Maximum time one test can run for. */ | ||
timeout: 100 * 1000, | ||
expect: { | ||
/** | ||
* Maximum time expect() should wait for the condition to be met. | ||
* For example in `await expect(locator).toHaveText();` | ||
*/ | ||
timeout: 5000, | ||
toMatchSnapshot: { maxDiffPixels: 200 }, | ||
}, | ||
/* Run tests in files in parallel */ | ||
fullyParallel: true, | ||
/* Fail the build on CI if you accidentally left test.only in the source code. */ | ||
forbidOnly: !!process.env.CI, | ||
/* Retry on CI only */ | ||
retries: process.env.CI ? 2 : 0, | ||
/* Opt out of parallel tests on CI. */ | ||
workers: process.env.CI ? 1 : undefined, | ||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */ | ||
reporter: 'html', | ||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ | ||
use: { | ||
viewport: { height: 1500, width: 1028 }, | ||
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ | ||
actionTimeout: 0, | ||
/* Base URL to use in actions like `await page.goto('/')`. */ | ||
// baseURL: 'http://localhost:3000', | ||
|
||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ | ||
trace: 'on-first-retry', | ||
baseURL: 'http://localhost:6006/', | ||
}, | ||
|
||
/* Configure projects for major browsers */ | ||
projects: [ | ||
{ | ||
name: 'chromium', | ||
use: { ...devices['Desktop Chrome'] }, | ||
}, | ||
], | ||
|
||
/* Folder for test artifacts such as screenshots, videos, traces, etc. */ | ||
// outputDir: 'test-results/', | ||
|
||
/* Run your local dev server before starting the tests */ | ||
webServer: { | ||
command: 'npm run start', | ||
reuseExistingServer: true, | ||
url: 'http://localhost:6006', | ||
timeout: 300 * 1000, // 5 minutes | ||
stdout: 'pipe', | ||
stderr: 'pipe', | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.