11import { expect , test } from '@playwright/test' ;
2- import { dismissViewHint , entityClientCenter , getSceneSnapshot , getState , panByScreenDelta , seedSampleScene , waitForViewportToSettle } from './helpers' ;
2+ import { getResizedViewportScroll } from '../../src/editor/viewport' ;
3+ import { dismissViewHint , getSceneSnapshot , panByScreenDelta , seedSampleScene , setEditorModeViaUi , waitForViewportToSettle } from './helpers' ;
34
4- async function normalizedEntityPosition ( page : Parameters < typeof entityClientCenter > [ 0 ] , entityId : string ) {
5- const canvas = page . locator ( '#game-container canvas' ) ;
6- await expect ( canvas ) . toBeVisible ( ) ;
7- const canvasBox = await canvas . boundingBox ( ) ;
8- if ( ! canvasBox ) throw new Error ( 'Canvas bounding box unavailable' ) ;
5+ type CameraSnapshot = {
6+ zoom : number ;
7+ scrollX : number ;
8+ scrollY : number ;
9+ viewportWidth : number ;
10+ viewportHeight : number ;
11+ } ;
912
10- const center = await entityClientCenter ( page , entityId ) ;
11- return {
12- x : ( center . x - canvasBox . x ) / canvasBox . width ,
13- y : ( center . y - canvasBox . y ) / canvasBox . height ,
14- } ;
13+ function cameraTransferDifference ( source : CameraSnapshot , current : CameraSnapshot ) : number {
14+ const expectedScroll = getResizedViewportScroll (
15+ source . scrollX ,
16+ source . scrollY ,
17+ source . viewportWidth ,
18+ source . viewportHeight ,
19+ current . viewportWidth ,
20+ current . viewportHeight ,
21+ source . zoom ,
22+ ) ;
23+ return Math . max (
24+ Math . abs ( current . zoom - source . zoom ) / 0.01 ,
25+ Math . abs ( current . scrollX - expectedScroll . scrollX ) ,
26+ Math . abs ( current . scrollY - expectedScroll . scrollY ) ,
27+ ) ;
1528}
1629
1730test ( 'Edit and Preview preserve camera view state @critical' , async ( { page } ) => {
1831 await seedSampleScene ( page ) ;
1932 await dismissViewHint ( page ) ;
33+ await expect ( page . getByTestId ( 'toolbar-status' ) ) . toBeHidden ( ) ;
2034
2135 const editBefore = await getSceneSnapshot < { zoom : number ; scrollX : number ; scrollY : number ; sceneKey ?: string } > ( page ) ;
2236 expect ( editBefore . sceneKey ) . toBe ( 'EditorScene' ) ;
@@ -33,39 +47,27 @@ test('Edit and Preview preserve camera view state @critical', async ({ page }) =
3347 expect ( editSnapshot . sceneKey ) . toBe ( 'EditorScene' ) ;
3448 expect ( editSnapshot . ready ) . toBe ( true ) ;
3549 expect ( editSnapshot . zoom ) . toBeGreaterThan ( editBefore . zoom ) ;
36- const editAnchorNormalized = await normalizedEntityPosition ( page , 'e1' ) ;
50+ const transferSnapshot = await getSceneSnapshot < CameraSnapshot > ( page ) ;
3751
38- await page . getByTestId ( 'toggle-mode-button' ) . click ( ) ;
39- await expect . poll ( async ( ) => ( await getState < { mode ?: string } > ( page ) ) ?. mode ) . toBe ( 'play' ) ;
52+ await setEditorModeViaUi ( page , 'play' ) ;
4053 await expect . poll ( async ( ) => {
4154 const snap = await getSceneSnapshot < { sceneKey ?: string ; ready ?: boolean ; isActive ?: boolean } > ( page ) ;
4255 return { sceneKey : snap ?. sceneKey , ready : snap ?. ready , isActive : snap ?. isActive } ;
4356 } ) . toEqual ( { sceneKey : 'GameScene' , ready : true , isActive : true } ) ;
4457
45- const playSnapshot = await getSceneSnapshot < { zoom : number ; scrollX : number ; scrollY : number } > ( page ) ;
46- expect ( Math . abs ( playSnapshot . zoom - editSnapshot . zoom ) ) . toBeLessThanOrEqual ( 0.01 ) ;
47- expect ( Math . abs ( playSnapshot . scrollX - editSnapshot . scrollX ) ) . toBeLessThanOrEqual ( 1 ) ;
48- expect ( Math . abs ( playSnapshot . scrollY - editSnapshot . scrollY ) ) . toBeLessThanOrEqual ( 1 ) ;
58+ await expect . poll ( async ( ) => {
59+ const playSnapshot = await getSceneSnapshot < CameraSnapshot > ( page ) ;
60+ return cameraTransferDifference ( transferSnapshot , playSnapshot ) ;
61+ } ) . toBeLessThanOrEqual ( 1 ) ;
4962
50- await page . getByTestId ( 'toggle-mode-button' ) . click ( ) ;
51- await expect . poll ( async ( ) => ( await getState < { mode ?: string } > ( page ) ) ?. mode ) . toBe ( 'edit' ) ;
63+ await setEditorModeViaUi ( page , 'edit' ) ;
5264 await expect . poll ( async ( ) => {
5365 const snap = await getSceneSnapshot < { sceneKey ?: string ; ready ?: boolean ; isActive ?: boolean } > ( page ) ;
5466 return { sceneKey : snap ?. sceneKey , ready : snap ?. ready , isActive : snap ?. isActive } ;
5567 } ) . toEqual ( { sceneKey : 'EditorScene' , ready : true , isActive : true } ) ;
5668 await waitForViewportToSettle ( page , { stableForMs : 150 } ) ;
5769
58- const editRestoredSnapshot = await getSceneSnapshot < { zoom : number ; scrollX : number ; scrollY : number ; ready ?: boolean } > ( page ) ;
70+ const editRestoredSnapshot = await getSceneSnapshot < CameraSnapshot & { ready ?: boolean } > ( page ) ;
5971 expect ( editRestoredSnapshot . ready ) . toBe ( true ) ;
60- expect ( Math . abs ( editRestoredSnapshot . zoom - editSnapshot . zoom ) ) . toBeLessThanOrEqual ( 0.01 ) ;
61- expect ( Math . abs ( editRestoredSnapshot . scrollX - editSnapshot . scrollX ) ) . toBeLessThanOrEqual ( 1 ) ;
62- expect ( Math . abs ( editRestoredSnapshot . scrollY - editSnapshot . scrollY ) ) . toBeLessThanOrEqual ( 1 ) ;
63- await expect
64- . poll ( async ( ) => {
65- const restoredAnchorNormalized = await normalizedEntityPosition ( page , 'e1' ) ;
66- const dx = Math . abs ( restoredAnchorNormalized . x - editAnchorNormalized . x ) ;
67- const dy = Math . abs ( restoredAnchorNormalized . y - editAnchorNormalized . y ) ;
68- return Math . max ( dx , dy ) ;
69- } )
70- . toBeLessThanOrEqual ( 0.02 ) ;
72+ expect ( cameraTransferDifference ( transferSnapshot , editRestoredSnapshot ) ) . toBeLessThanOrEqual ( 1 ) ;
7173} ) ;
0 commit comments