11import { expect , test } from '@playwright/test' ;
22import { createEmptyProject } from '../../src/model/emptyProject' ;
3- import { dismissViewHint , dispatchAction , dragAssetToCanvas , dragDropByTestIdAtClientPoint , dropAssetOnTestId , entityClientCenter , getEntitySpriteWorldRect , getSceneSnapshot , getState , hitTestAtClientPoint , openSceneScope , panByScreenDelta , seedProject , triggerUndo , waitForViewportToSettle , worldToClient } from './helpers' ;
3+ import { dismissViewHint , dispatchAction , dragAssetToCanvas , dropAssetAtClientPoint , dropAssetOnTestId , entityClientCenter , getEntitySpriteWorldRect , getSceneSnapshot , getState , hitTestAtClientPoint , openSceneScope , panByScreenDelta , seedProject , triggerUndo , waitForViewportToSettle , worldToClient } from './helpers' ;
44
55test . describe ( 'Assets dock' , ( ) => {
66 test . describe . configure ( { timeout : 120000 } ) ;
77
8+ async function normalizedEntityPosition ( page : Parameters < typeof entityClientCenter > [ 0 ] , entityId : string ) {
9+ const canvas = page . locator ( '#game-container canvas' ) ;
10+ await expect ( canvas ) . toBeVisible ( ) ;
11+ const canvasBox = await canvas . boundingBox ( ) ;
12+ if ( ! canvasBox ) throw new Error ( 'Canvas bounding box unavailable' ) ;
13+
14+ const center = await entityClientCenter ( page , entityId ) ;
15+ return {
16+ x : ( center . x - canvasBox . x ) / canvasBox . width ,
17+ y : ( center . y - canvasBox . y ) / canvasBox . height ,
18+ } ;
19+ }
20+
821 test ( 'imports an image and drags to canvas to create an entity with asset ref @critical @browser' , async ( { page } ) => {
922 await seedProject ( page , createEmptyProject ( ) ) ;
1023 await dismissViewHint ( page ) ;
@@ -91,7 +104,7 @@ test.describe('Assets dock', () => {
91104 return markerId ;
92105 } ) . toBeTruthy ( ) ;
93106 if ( typeof markerId !== 'string' ) throw new Error ( 'Failed to create marker entity' ) ;
94- const markerClientBefore = await entityClientCenter ( page , markerId ) ;
107+ const markerNormalizedBefore = await normalizedEntityPosition ( page , markerId ) ;
95108
96109 // Use the same drag/drop path across browsers. Our helper uses a synthetic HTML5 drop for WebKit
97110 // to avoid flakiness from native `dragTo` while still exercising the real drop handler.
@@ -103,13 +116,15 @@ test.describe('Assets dock', () => {
103116
104117 // Minor subpixel/camera rounding differences are acceptable; ensure the viewport is effectively preserved.
105118 expect ( Math . abs ( ( after . zoom ?? 0 ) - ( before . zoom ?? 0 ) ) ) . toBeLessThanOrEqual ( 1e-3 ) ;
106- const markerClientAfter = await entityClientCenter ( page , markerId ) ;
107- expect (
108- Math . max (
109- Math . abs ( markerClientAfter . x - markerClientBefore . x ) ,
110- Math . abs ( markerClientAfter . y - markerClientBefore . y ) ,
111- ) ,
112- ) . toBeLessThanOrEqual ( 5 ) ;
119+ await expect
120+ . poll ( async ( ) => {
121+ const markerNormalizedAfter = await normalizedEntityPosition ( page , markerId ! ) ;
122+ return Math . max (
123+ Math . abs ( markerNormalizedAfter . x - markerNormalizedBefore . x ) ,
124+ Math . abs ( markerNormalizedAfter . y - markerNormalizedBefore . y ) ,
125+ ) ;
126+ } )
127+ . toBeLessThanOrEqual ( 0.02 ) ;
113128 } ) ;
114129
115130 test ( 'dragging an image asset onto an existing sprite replaces its asset @critical @browser' , async ( { page } , testInfo ) => {
@@ -206,9 +221,10 @@ test.describe('Assets dock', () => {
206221 target : { kind : 'entity-sprite' , sceneId, entityId : createdEntityId } ,
207222 } as any ) ;
208223 } else {
209- // Prefer a real drag gesture so Playwright supplies a stable `dataTransfer` payload across engines (Firefox
210- // can intermittently drop synthetic DragEvent `dataTransfer` in CI).
211- await dragDropByTestIdAtClientPoint ( page , 'assets-dock-item-image-meteor-large' , 'game-container' , clientPoint ) ;
224+ // Chromium can intermittently route a native drag to the canvas as "create entity" instead of
225+ // replacing the sprite under the pointer. Use a targeted HTML5 drop at the hit-tested client point
226+ // so we still exercise the real drop handler with a deterministic payload.
227+ await dropAssetAtClientPoint ( page , { assetKind : 'image' , assetId : 'meteor-large' } , 'game-container' , clientPoint ) ;
212228 }
213229
214230 try {
0 commit comments