@@ -20,17 +20,102 @@ export async function dropOnChat(page: Page, target: Locator, payload: ChatDropP
2020 ] ,
2121 dragOperationsMask : 1 ,
2222 }
23- const session = await page . context ( ) . newCDPSession ( page )
23+ const observed = await target . evaluateHandle ( ( element ) => {
24+ const events : {
25+ event : DragEvent
26+ receipt : {
27+ type : string
28+ trusted : boolean
29+ tag : string | null
30+ intendedTarget : boolean
31+ chatBody : boolean
32+ inert : boolean
33+ files : number
34+ types : string [ ]
35+ defaultPrevented : boolean
36+ dropEffect : string | null
37+ x : number
38+ y : number
39+ }
40+ } [ ] = [ ]
41+ const receive = ( event : DragEvent ) => {
42+ const target = event . target instanceof Element ? event . target : null
43+ const receipt = {
44+ type : event . type ,
45+ trusted : event . isTrusted ,
46+ tag : target ?. tagName ?? null ,
47+ intendedTarget : target !== null && element . contains ( target ) ,
48+ chatBody : Boolean ( target ?. closest ( 'main' ) ) ,
49+ inert : Boolean ( target ?. closest ( '[inert]' ) ) ,
50+ files : event . dataTransfer ?. files . length ?? 0 ,
51+ types : Array . from ( event . dataTransfer ?. types ?? [ ] ) ,
52+ defaultPrevented : event . defaultPrevented ,
53+ dropEffect : event . dataTransfer ?. dropEffect ?? null ,
54+ x : event . clientX ,
55+ y : event . clientY ,
56+ }
57+ events . push ( { event, receipt } )
58+ }
59+ for ( const type of [ 'dragenter' , 'dragover' , 'drop' ] as const )
60+ element . ownerDocument . addEventListener ( type , receive , true )
61+ const rect = element . getBoundingClientRect ( )
62+ const x = rect . x + rect . width / 2
63+ const y = rect . y + rect . height / 2
64+ const hit = element . ownerDocument . elementFromPoint ( x , y )
65+ return {
66+ readEvents : ( ) =>
67+ events . map ( ( { event, receipt } ) => ( {
68+ ...receipt ,
69+ defaultPrevented : event . defaultPrevented ,
70+ dropEffect : event . dataTransfer ?. dropEffect ?? null ,
71+ } ) ) ,
72+ frameTarget : {
73+ x,
74+ y,
75+ width : window . innerWidth ,
76+ height : window . innerHeight ,
77+ tag : hit ?. tagName ?? null ,
78+ intendedTarget : hit !== null && element . contains ( hit ) ,
79+ inert : Boolean ( hit ?. closest ( '[inert]' ) ) ,
80+ } ,
81+ connected : ( ) => element . isConnected ,
82+ dispose : ( ) => {
83+ for ( const type of [ 'dragenter' , 'dragover' , 'drop' ] as const )
84+ element . ownerDocument . removeEventListener ( type , receive , true )
85+ } ,
86+ }
87+ } )
2488 try {
25- for ( const type of [ 'dragEnter' , 'dragOver' , 'drop' ] as const ) {
26- await session . send ( 'Input.dispatchDragEvent' , {
27- type,
28- x : box . x + box . width / 2 ,
29- y : box . y + box . height / 2 ,
30- data,
31- } )
89+ const session = await page . context ( ) . newCDPSession ( page )
90+ try {
91+ const { windowId, bounds } = await session . send ( 'Browser.getWindowForTarget' )
92+ for ( const type of [ 'dragEnter' , 'dragOver' , 'drop' ] as const ) {
93+ await session . send ( 'Input.dispatchDragEvent' , {
94+ type,
95+ x : box . x + box . width / 2 ,
96+ y : box . y + box . height / 2 ,
97+ data,
98+ } )
99+ }
100+ return {
101+ box,
102+ nativeWindow : { windowId, bounds } ,
103+ viewport : page . viewportSize ( ) ,
104+ topHitTag : await page . evaluate (
105+ ( { x, y } ) => document . elementFromPoint ( x , y ) ?. tagName ?? null ,
106+ { x : box . x + box . width / 2 , y : box . y + box . height / 2 }
107+ ) ,
108+ ...( await observed . evaluate ( ( state ) => ( {
109+ events : state . readEvents ( ) ,
110+ frameTarget : state . frameTarget ,
111+ connected : state . connected ( ) ,
112+ } ) ) ) ,
113+ }
114+ } finally {
115+ await session . detach ( )
32116 }
33117 } finally {
34- await session . detach ( )
118+ await observed . evaluate ( ( state ) => state . dispose ( ) ) . catch ( ( ) => { } )
119+ await observed . dispose ( )
35120 }
36121}
0 commit comments