chore: clear locator handlers upon disconnect (#36093)
This commit is contained in:
		
							parent
							
								
									b8ed476258
								
							
						
					
					
						commit
						2a777c3816
					
				| 
						 | 
				
			
			@ -48,6 +48,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
 | 
			
		|||
  _webSocketInterceptionPatterns: channels.PageSetWebSocketInterceptionPatternsParams['patterns'] = [];
 | 
			
		||||
  private _bindings: PageBinding[] = [];
 | 
			
		||||
  private _initScripts: InitScript[] = [];
 | 
			
		||||
  private _locatorHandlers = new Set<number>();
 | 
			
		||||
 | 
			
		||||
  static from(parentScope: BrowserContextDispatcher, page: Page): PageDispatcher {
 | 
			
		||||
    return PageDispatcher.fromNullable(parentScope, page)!;
 | 
			
		||||
| 
						 | 
				
			
			@ -144,6 +145,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
 | 
			
		|||
 | 
			
		||||
  async registerLocatorHandler(params: channels.PageRegisterLocatorHandlerParams, metadata: CallMetadata): Promise<channels.PageRegisterLocatorHandlerResult> {
 | 
			
		||||
    const uid = this._page.registerLocatorHandler(params.selector, params.noWaitAfter);
 | 
			
		||||
    this._locatorHandlers.add(uid);
 | 
			
		||||
    return { uid };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -153,6 +155,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
 | 
			
		|||
 | 
			
		||||
  async unregisterLocatorHandler(params: channels.PageUnregisterLocatorHandlerParams, metadata: CallMetadata): Promise<void> {
 | 
			
		||||
    this._page.unregisterLocatorHandler(params.uid);
 | 
			
		||||
    this._locatorHandlers.delete(params.uid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async emulateMedia(params: channels.PageEmulateMediaParams, metadata: CallMetadata): Promise<void> {
 | 
			
		||||
| 
						 | 
				
			
			@ -337,6 +340,9 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
 | 
			
		|||
    this._bindings = [];
 | 
			
		||||
    this._page.removeInitScripts(this._initScripts).catch(() => {});
 | 
			
		||||
    this._initScripts = [];
 | 
			
		||||
    for (const uid of this._locatorHandlers)
 | 
			
		||||
      this._page.unregisterLocatorHandler(uid);
 | 
			
		||||
    this._locatorHandlers.clear();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -188,3 +188,37 @@ test('should remove init scripts upon disconnect', async ({ twoPages, server })
 | 
			
		|||
  expect(await pageA.evaluate(() => (window as any).pageValueA)).toBe('pageValueA');
 | 
			
		||||
  expect(await pageA.evaluate(() => (window as any).contextValueA)).toBe('contextValueA');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('should remove locator handlers upon disconnect', async ({ twoPages, server }) => {
 | 
			
		||||
  const { pageA, pageB } = twoPages;
 | 
			
		||||
 | 
			
		||||
  await pageA.goto(server.PREFIX + '/input/handle-locator.html');
 | 
			
		||||
 | 
			
		||||
  let count = 0;
 | 
			
		||||
  await pageA.addLocatorHandler(pageA.getByText('This interstitial covers the button'), async () => {
 | 
			
		||||
    ++count;
 | 
			
		||||
    await pageA.locator('#close').click();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  await pageA.locator('#aside').hover();
 | 
			
		||||
  await pageA.evaluate(() => {
 | 
			
		||||
    (window as any).clicked = 0;
 | 
			
		||||
    (window as any).setupAnnoyingInterstitial('mouseover', 1);
 | 
			
		||||
  });
 | 
			
		||||
  await pageA.locator('#target').click();
 | 
			
		||||
  expect(count).toBe(1);
 | 
			
		||||
  expect(await pageB.evaluate('window.clicked')).toBe(1);
 | 
			
		||||
  await expect(pageB.locator('#interstitial')).not.toBeVisible();
 | 
			
		||||
 | 
			
		||||
  await pageA.locator('#aside').hover();
 | 
			
		||||
  await pageA.evaluate(() => {
 | 
			
		||||
    (window as any).clicked = 0;
 | 
			
		||||
    (window as any).setupAnnoyingInterstitial('mouseover', 1);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  await pageA.context().browser().close();
 | 
			
		||||
  const error = await pageB.locator('#target').click({ timeout: 3000 }).catch(e => e);
 | 
			
		||||
  expect(error.message).toContain('Timeout 3000ms exceeded');
 | 
			
		||||
  expect(error.message).toContain('intercepts pointer events');
 | 
			
		||||
  expect(error.message).not.toContain('locator handler');
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue