|
- import fs from 'node:fs'
- import path from 'node:path'
- import { expect, type Frame, type Page, type TestInfo } from '@playwright/test'
- // @ts-ignore Repository helper reads credentials privately; no trace/storageState is emitted.
- import { call, login, fixture, writeFixture, report, work } from '../tools/model-editor-closure-live.mjs'
- export { call, login, fixture, writeFixture, report, work }
-
- export async function signIn(page: Page, account = 'root') {
- const session = await login(account)
- await page.addInitScript(({ accessToken, refreshToken }) => {
- if (!sessionStorage.getItem('model-closure-initialized')) {
- sessionStorage.setItem('unreal-tran:web:access-token:v1', accessToken)
- sessionStorage.setItem('unreal-tran:web:refresh-token:v1', refreshToken || '')
- sessionStorage.setItem('model-closure-initialized', '1')
- }
- }, { accessToken: session.accessToken, refreshToken: session.refreshToken })
- return session.accessToken as string
- }
-
- export async function openEditor(page: Page, key: 'fox' | 'truck' | string = 'fox') {
- const id = fixture().models[key]?.id || key
- await page.goto(`/content/models/${id}/edit`)
- return readyFrame(page)
- }
-
- export async function readyFrame(page: Page): Promise<Frame> {
- await expect.poll(() => page.frames().some(frame => frame.url().includes('/legacy-model-editor/editor.html')), { timeout: 60_000 }).toBe(true)
- const frame = page.frames().find(frame => frame.url().includes('/legacy-model-editor/editor.html'))!
- await frame.waitForFunction(() => {
- const editor = (window as any).editorApp
- return editor?.apiEditorHydrated && editor?.modelPivot && editor?.apiState === 'ready' && !editor.apiImportBusy && !editor.apiCoverSavePending
- }, undefined, { timeout: 90_000 })
- await expect(frame.locator('.editor-shell')).toHaveAttribute('data-host-readonly', /true|false/)
- return frame
- }
-
- export async function saveEditor(frame: Frame) {
- await frame.locator('[data-action="save"]').first().click()
- await expect.poll(() => frame.evaluate(() => {
- const e = (window as any).editorApp
- return e.apiState === 'ready' && !e.apiCoverSavePending && !e.apiSession.savePending
- })).toBe(true)
- }
-
- export async function selectMesh(frame: Frame) {
- await frame.locator('[data-selection-scope="part"]').click()
- const mesh = await frame.evaluate(() => {
- const e = (window as any).editorApp
- let selected: any
- e.modelPivot.traverse((o: any) => { if (!selected && o.isMesh) selected = o })
- return { uuid: selected.uuid, id: selected.userData.editorId, name: selected.name }
- })
- await frame.locator(`[data-object-id="${mesh.uuid}"]`).click()
- return mesh
- }
-
- export async function setRange(frame: Frame, selector: string, value: string) {
- await frame.locator(selector).evaluate((element, next) => {
- (element as HTMLInputElement).value = next
- element.dispatchEvent(new Event('input', { bubbles: true }))
- element.dispatchEvent(new Event('change', { bubbles: true }))
- }, value)
- }
-
- export async function shot(page: Page, info: TestInfo, name: string) {
- const folder = path.join(report, 'screenshots')
- fs.mkdirSync(folder, { recursive: true })
- await expect(page.locator('.el-loading-mask:visible')).toHaveCount(0)
- const file = path.join(folder, `${name}.png`)
- await page.screenshot({ path: file, fullPage: true, animations: 'disabled' })
- await info.attach(name, { path: file, contentType: 'image/png' })
- }
-
- export async function closeSession(page: Page) {
- const token = await page.evaluate(() => sessionStorage.getItem('unreal-tran:web:access-token:v1')).catch(() => null)
- if (token) await call('auth/v1/auth/logout', token, {}).catch(() => {})
- }
-
- export function evidence(name: string, data: unknown) {
- const folder = path.join(report, 'evidence')
- fs.mkdirSync(folder, { recursive: true })
- fs.writeFileSync(path.join(folder, `${name}.json`), JSON.stringify({ time: new Date().toISOString(), data }, null, 2))
- }
|