chore: retry selecting option for the notconnected case (#35610)

This commit is contained in:
Pavel Feldman 2025-04-14 16:51:08 -07:00 committed by GitHub
parent 2a3f1cbf8a
commit 6262a1264f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 66 additions and 1 deletions

View File

@ -581,7 +581,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
async _selectOption(progress: Progress, elements: ElementHandle[], values: types.SelectOption[], options: types.CommonActionOptions): Promise<string[] | 'error:notconnected'> {
let resultingOptions: string[] = [];
await this._retryAction(progress, 'select option', async () => {
const result = await this._retryAction(progress, 'select option', async () => {
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
if (!options.force)
progress.log(` waiting for element to be visible and enabled`);
@ -601,6 +601,8 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
}
return result;
}, options);
if (result === 'error:notconnected')
return result;
return resultingOptions;
}

View File

@ -319,3 +319,66 @@ it('input event.composed should be true and cross shadow dom boundary', async ({
expect(await page.evaluate(() => window['firedEvents'])).toEqual(['input:true', 'change:false']);
expect(await page.evaluate(() => window['firedBodyEvents'])).toEqual(['input:true']);
});
it('should wait for option to be enabled', async ({ page }) => {
await page.setContent(`
<select disabled>
<option>one</option>
<option>two</option>
</select>
<script>
function hydrate() {
const select = document.querySelector('select');
select.removeAttribute('disabled');
select.addEventListener('change', () => {
window['result'] = select.value;
});
}
</script>
`);
const selectPromise = page.locator('select').selectOption('two');
await new Promise(f => setTimeout(f, 1000));
await page.evaluate(() => (window as any).hydrate());
await selectPromise;
expect(await page.evaluate(() => window['result'])).toEqual('two');
await expect(page.locator('select')).toHaveValue('two');
});
it('should wait for select to be swapped', async ({ page }) => {
await page.setContent(`
<select disabled>
<option>one</option>
<option>two</option>
</select>
<script>
function hydrate() {
const select = document.querySelector('select');
select.remove();
const newSelect = document.createElement('select');
const option1 = document.createElement('option');
option1.textContent = 'one';
newSelect.appendChild(option1);
const option2 = document.createElement('option');
option2.textContent = 'two';
newSelect.appendChild(option2);
document.body.appendChild(newSelect);
newSelect.addEventListener('change', () => {
window['result'] = newSelect.value;
});
}
</script>
`);
const selectPromise = page.locator('select').selectOption('two');
await new Promise(f => setTimeout(f, 1000));
await page.evaluate(() => (window as any).hydrate());
await selectPromise;
await expect(page.locator('select')).toHaveValue('two');
expect(await page.evaluate(() => window['result'])).toEqual('two');
});