fix(stage-tamagotchi): harden overlay isolation and iframe coordinates (#1751)

---------

Co-authored-by-agent: Antigravity <antigravity@gemini.com>
This commit is contained in:
刘梓恒
2026-04-29 22:52:00 +08:00
committed by GitHub
parent 9d0719e6b5
commit 5bd0b19e84
5 changed files with 202 additions and 39 deletions
@@ -332,6 +332,36 @@ describe('chromeElementsToTargetCandidates', () => {
expect(candidates[0].bounds.y).toBe(50 + 88 + 140 + 24)
})
it('uses cumulative nested iframe offsets before converting to screen coordinates', () => {
const parentFrameOffset = { x: 320, y: 180 }
const childFrameOffset = { x: 24, y: 48 }
const nestedFrameOffset = {
x: parentFrameOffset.x + childFrameOffset.x,
y: parentFrameOffset.y + childFrameOffset.y,
}
const taggedEl = {
tag: 'button',
text: 'Nested iframe CTA',
rect: { x: 12, y: 24, w: 90, h: 32 },
_frameId: 9,
_frameOffsetX: nestedFrameOffset.x,
_frameOffsetY: nestedFrameOffset.y,
} as any
const candidates = chromeElementsToTargetCandidates(
[taggedEl],
windowBounds,
88,
0,
)
expect(candidates[0].frameId).toBe(9)
expect(candidates[0].bounds.x).toBe(100 + 320 + 24 + 12)
expect(candidates[0].bounds.y).toBe(50 + 88 + 180 + 48 + 24)
expect(candidates[0].bounds.width).toBe(90)
expect(candidates[0].bounds.height).toBe(32)
})
it('falls back to function-level frameId when _frameId is absent', () => {
const el = {
tag: 'button',
@@ -470,12 +470,14 @@ describe('desktop_click_target handler integration', () => {
it('falls back to OS click when the connected extension transport is read-only', async () => {
const sm = new RunStateManager()
const iframeAbsoluteBounds = { x: 456, y: 390, width: 90, height: 32 }
const candidate = makeCandidate({
id: 't_0',
source: 'chrome_dom',
selector: '#login-btn',
frameId: 0,
frameId: 7,
isPageContent: true,
bounds: iframeAbsoluteBounds,
})
sm.updateGroundingSnapshot(freshSnapshot([candidate]))
@@ -494,7 +496,13 @@ describe('desktop_click_target handler integration', () => {
expect(result.executionRoute).toBe('os_input')
expect(result.routeReason).toContain('does not support getClickTarget + clickAt')
expect(bridge.clickSelector).not.toHaveBeenCalled()
expect(executor.click).toHaveBeenCalledOnce()
expect(executor.click).toHaveBeenCalledWith({
x: 501,
y: 406,
button: 'left',
clickCount: 1,
})
expect(result.text).toContain('Point: (501, 406)')
})
// -----------------------------------------------------------------------