`);
  await page.evaluate(() => {
    // touchstart is not cancelable unless passive is false
    document.addEventListener('touchstart', t => t.preventDefault(), { passive: false });
  });
  const eventsHandle = await trackEvents(await page.$('div'));
  await page.tap('div');
  expect(await eventsHandle.jsonValue()).toEqual([
    'pointerover',  'pointerenter',
    'pointerdown',  'touchstart',
    'pointerup',    'pointerout',
    'pointerleave', 'touchend',
  ]);
});
it('should not send mouse events when touchend is canceled', async ({ page }) => {
  await page.setContent(`
`);
  await page.evaluate(() => {
    document.addEventListener('touchend', t => t.preventDefault());
  });
  const eventsHandle = await trackEvents(await page.$('div'));
  await page.tap('div');
  expect(await eventsHandle.jsonValue()).toEqual([
    'pointerover',  'pointerenter',
    'pointerdown',  'touchstart',
    'pointerup',    'pointerout',
    'pointerleave', 'touchend',
  ]);
});
it('should not wait for a navigation caused by a tap', async ({ page, server }) => {
  await page.goto(server.EMPTY_PAGE);
  await page.setContent(`
link;`);
  await Promise.all([
    new Promise(resolve => server.setRoute('/intercept-this.html', resolve)),
    page.tap('a'),
  ]);
});
it('should work with modifiers', async ({ page  }) => {
  await page.setContent('hello world');
  const altKeyPromise = page.evaluate(() => new Promise(resolve => {
    document.addEventListener('touchstart', event => {
      resolve(event.altKey);
    }, { passive: false });
  }));
  // make sure the evals hit the page
  await page.evaluate(() => void 0);
  await page.tap('body', {
    modifiers: ['Alt']
  });
  expect(await altKeyPromise).toBe(true);
});
it('should send well formed touch points', async ({ page }) => {
  const promises = Promise.all([
    page.evaluate(() => new Promise(resolve => {
      document.addEventListener('touchstart', event => {
        resolve([...event.touches].map(t => ({
          identifier: t.identifier,
          clientX: t.clientX,
          clientY: t.clientY,
          pageX: t.pageX,
          pageY: t.pageY,
          radiusX: 'radiusX' in t ? t.radiusX : t['webkitRadiusX'],
          radiusY: 'radiusY' in t ? t.radiusY : t['webkitRadiusY'],
          rotationAngle: 'rotationAngle' in t ? t.rotationAngle : t['webkitRotationAngle'],
          force: 'force' in t ? t.force : t['webkitForce'],
        })));
      }, false);
    })),
    page.evaluate(() => new Promise(resolve => {
      document.addEventListener('touchend', event => {
        resolve([...event.touches].map(t => ({
          identifier: t.identifier,
          clientX: t.clientX,
          clientY: t.clientY,
          pageX: t.pageX,
          pageY: t.pageY,
          radiusX: 'radiusX' in t ? t.radiusX : t['webkitRadiusX'],
          radiusY: 'radiusY' in t ? t.radiusY : t['webkitRadiusY'],
          rotationAngle: 'rotationAngle' in t ? t.rotationAngle : t['webkitRotationAngle'],
          force: 'force' in t ? t.force : t['webkitForce'],
        })));
      }, false);
    })),
  ]);
  // make sure the evals hit the page
  await page.evaluate(() => void 0);
  await page.touchscreen.tap(40, 60);
  const [touchstart, touchend] = await promises;
  expect(touchstart).toEqual([{
    clientX: 40,
    clientY: 60,
    force: 1,
    identifier: 0,
    pageX: 40,
    pageY: 60,
    radiusX: 1,
    radiusY: 1,
    rotationAngle: 0,
  }]);
  expect(touchend).toEqual([]);
});
it('should wait until an element is visible to tap it', async ({ page }) => {
  const div = await page.evaluateHandle(() => {
    const button = document.createElement('button');
    button.textContent = 'not clicked';
    document.body.appendChild(button);
    button.style.display = 'none';
    return button;
  });
  const tapPromise = div.tap();
  await div.evaluate(div => div.onclick = () => div.textContent = 'clicked');
  await div.evaluate(div => div.style.display = 'block');
  await tapPromise;
  expect(await div.textContent()).toBe('clicked');
});
async function trackEvents(target: ElementHandle) {
  const eventsHandle = await target.evaluateHandle(target => {
    const events: string[] = [];
    for (const event of [
      'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'click',
      'pointercancel', 'pointerdown', 'pointerenter', 'pointerleave', 'pointermove', 'pointerout', 'pointerover', 'pointerup',
      'touchstart', 'touchend', 'touchmove', 'touchcancel',
    ])
      target.addEventListener(event, () => events.push(event), false);
    return events;
  });
  return eventsHandle;
}
it.describe('locators', () => {
  it('should send all of the correct events', async ({ page }) => {
    await page.setContent(`
      
a
      b
    `);
    await page.locator('#a').tap();
    await page.locator('#b').tap();
  });
});