// @vitest-environment node import {expect,it} from 'vitest' import {randomUUID} from 'node:crypto' import {mkdtemp,realpath,rm} from 'node:fs/promises' import {tmpdir} from 'node:os' import {join} from 'node:path' import {chromium,type Page} from 'playwright' import {BrowserRuntime,type BrowserScope,type BrowserAction} from '../../src/runner/browser/runtime.js' // Real Chromium, isolated profile and synthetic page. No external website or account. it.runIf(process.env.YAOYAO_BROWSER_SMOKE==='1')('real Chromium: sliders, text selection, HTML drop and live holds with cancellation',async()=>{ const root=await realpath(await mkdtemp(join(tmpdir(),'yaoyao-browser-drag-'))) const scope:BrowserScope={ownerKey:'drag-test',environmentId:'drag-bot',profile:'temporary'} let page!:Page const runtime=new BrowserRuntime({root,enabled:true,launcher:{launchPersistentContext:async(directory,options)=>{ const context=await chromium.launchPersistentContext(directory,options);page=context.pages()[0]! await page.setContent(`

Drag this sentence to select the text.

Drag me
Drop here
0 `) return context }}}) let generation=0 const execute=(action:BrowserAction)=>runtime.execute(scope,{generation,operationId:randomUUID(),action}) try{ generation=(await runtime.open(scope)).generation const slider=(await page.locator('input').boundingBox())!,y=slider.y+slider.height/2 await execute({kind:'drag',fromX:slider.x+8,fromY:y,toX:slider.x+390,toY:y}) expect(Number(await page.locator('input').inputValue())).toBeGreaterThan(95) const text=(await page.locator('p').boundingBox())! await execute({kind:'drag',fromX:text.x+1,fromY:text.y+10,toX:text.x+240,toY:text.y+10}) expect(await page.evaluate(()=>getSelection()?.toString())).toContain('Drag this sentence') const source=(await page.locator('#source').boundingBox())!,target=(await page.locator('#target').boundingBox())! const start={x:source.x+40,y:source.y+40},end={x:target.x+40,y:target.y+40} await execute({kind:'drag',fromX:start.x,fromY:start.y,toX:end.x,toY:end.y}) expect(await page.locator('#drops').innerText()).toBe('1') const gestureId=randomUUID() await execute({kind:'pointer',gestureId,phase:'start',x:slider.x+390,y}) const releases=await page.evaluate(()=>(window as any).releases) await execute({kind:'pointer',gestureId,phase:'move',x:slider.x+200,y}) // This observation happens while the button is still held, before pointer end. expect(Number(await page.locator('input').inputValue())).toBeGreaterThan(45) expect(Number(await page.locator('input').inputValue())).toBeLessThan(55) expect(await page.evaluate(()=>(window as any).buttons)).toBe(1) expect(await page.evaluate(()=>(window as any).releases)).toBe(releases) await execute({kind:'screenshot'}) await execute({kind:'pointer',gestureId,phase:'end',x:slider.x+300,y}) expect(Number(await page.locator('input').inputValue())).toBeGreaterThan(70) expect(await page.evaluate(()=>(window as any).releases)).toBe(releases+1) const dropId=randomUUID() await execute({kind:'pointer',gestureId:dropId,phase:'start',...start}) await execute({kind:'pointer',gestureId:dropId,phase:'move',...end}) await execute({kind:'pointer',gestureId:dropId,phase:'end',...end}) expect(await page.locator('#drops').innerText()).toBe('2') const cancelId=randomUUID() await execute({kind:'pointer',gestureId:cancelId,phase:'start',...start}) await execute({kind:'pointer',gestureId:cancelId,phase:'move',...end}) await execute({kind:'pointer',gestureId:cancelId,phase:'cancel',...end}) expect(await page.locator('#drops').innerText()).toBe('2') await page.mouse.move(100,700) expect(await page.evaluate(()=>(window as any).buttons)).toBe(0) }finally{await runtime.shutdown();await rm(root,{recursive:true,force:true})} },30000)