Skip to content

Commit 940e07e

Browse files
authored
fix(command): re-throw swallowed remote errors for element click, rect, and screenshot (#457)
1 parent d16c952 commit 940e07e

2 files changed

Lines changed: 59 additions & 3 deletions

File tree

src/command.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ export async function elementClick(
277277
} else if (isXCUITestDriverSession(driver)) {
278278
return await driver.click(elementUUID);
279279
}
280-
return await driver.elementClick(elementUUID);
280+
const result = await driver.elementClick(elementUUID);
281+
throwIfSwallowedRemoteError(result);
281282
}
282283

283284
/**
@@ -319,7 +320,9 @@ export async function getElementRect(
319320
} else if (isXCUITestDriverSession(driver)) {
320321
return await driver.getElementRect(elementUUID);
321322
}
322-
return await driver.getElementRect(elementUUID);
323+
const result = await driver.getElementRect(elementUUID);
324+
throwIfSwallowedRemoteError(result);
325+
return result;
323326
}
324327

325328
/**
@@ -386,7 +389,9 @@ export async function getScreenshot(
386389
} else if (isXCUITestDriverSession(driver)) {
387390
return await driver.getElementScreenshot(elementId);
388391
}
389-
return await driver.takeElementScreenshot(elementId);
392+
const result = await driver.takeElementScreenshot(elementId);
393+
throwIfSwallowedRemoteError(result);
394+
return result;
390395
}
391396

392397
if (isAndroidUiautomator2DriverSession(driver)) {

src/tests/command.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ const {
1616
getElementText,
1717
getElementAttribute,
1818
getActiveElement,
19+
elementClick,
20+
getElementRect,
21+
getScreenshot,
1922
} = await import('../command.js');
2023

2124
// What the remote client resolves with when it swallows a "no such element" 404.
@@ -123,6 +126,54 @@ describe('element commands: re-throw swallowed remote "no such element"', () =>
123126
).resolves.toBe(el);
124127
});
125128

129+
test('elementClick re-throws swallowed error, resolves otherwise', async () => {
130+
await expect(
131+
elementClick(
132+
{ elementClick: jest.fn(async () => NO_SUCH_ELEMENT_VALUE) } as never,
133+
'bad'
134+
)
135+
).rejects.toThrow(/could not be located/i);
136+
await expect(
137+
elementClick(
138+
{ elementClick: jest.fn(async () => undefined) } as never,
139+
'el'
140+
)
141+
).resolves.toBeUndefined();
142+
});
143+
144+
test('getElementRect re-throws swallowed error, returns rect otherwise', async () => {
145+
await expect(
146+
getElementRect(
147+
{ getElementRect: jest.fn(async () => NO_SUCH_ELEMENT_VALUE) } as never,
148+
'bad'
149+
)
150+
).rejects.toThrow(/could not be located/i);
151+
const rect = { x: 0, y: 0, width: 100, height: 40 };
152+
await expect(
153+
getElementRect(
154+
{ getElementRect: jest.fn(async () => rect) } as never,
155+
'el'
156+
)
157+
).resolves.toBe(rect);
158+
});
159+
160+
test('getScreenshot(elementId) re-throws swallowed error, returns base64 otherwise', async () => {
161+
await expect(
162+
getScreenshot(
163+
{
164+
takeElementScreenshot: jest.fn(async () => NO_SUCH_ELEMENT_VALUE),
165+
} as never,
166+
'bad'
167+
)
168+
).rejects.toThrow(/could not be located/i);
169+
await expect(
170+
getScreenshot(
171+
{ takeElementScreenshot: jest.fn(async () => 'base64png') } as never,
172+
'el'
173+
)
174+
).resolves.toBe('base64png');
175+
});
176+
126177
test('preserves the W3C error code as the error name (for classifyError)', async () => {
127178
await expect(
128179
getElementText(

0 commit comments

Comments
 (0)