diff --git a/test/check.jest.js b/test/check.jest.js
new file mode 100644
index 0000000000..e83626a423
--- /dev/null
+++ b/test/check.jest.js
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2018 Google Inc. All rights reserved.
+ * Modifications copyright (c) Microsoft Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+describe('Page.check', function() {
+ it('should check the box', async({page}) => {
+ await page.setContent(``);
+ await page.check('input');
+ expect(await page.evaluate(() => checkbox.checked)).toBe(true);
+ });
+ it('should not check the checked box', async({page}) => {
+ await page.setContent(``);
+ await page.check('input');
+ expect(await page.evaluate(() => checkbox.checked)).toBe(true);
+ });
+ it('should uncheck the box', async({page}) => {
+ await page.setContent(``);
+ await page.uncheck('input');
+ expect(await page.evaluate(() => checkbox.checked)).toBe(false);
+ });
+ it('should not uncheck the unchecked box', async({page}) => {
+ await page.setContent(``);
+ await page.uncheck('input');
+ expect(await page.evaluate(() => checkbox.checked)).toBe(false);
+ });
+ it('should check the box by label', async({page}) => {
+ await page.setContent(``);
+ await page.check('label');
+ expect(await page.evaluate(() => checkbox.checked)).toBe(true);
+ });
+ it('should check the box outside label', async({page}) => {
+ await page.setContent(`
+ `);
+ await page.check('div');
+ expect(await page.evaluate(() => checkbox.getAttribute('aria-checked'))).toBe('true');
+ });
+});
diff --git a/test/click-timeout-1.jest.js b/test/click-timeout-1.jest.js
new file mode 100644
index 0000000000..24f04d4442
--- /dev/null
+++ b/test/click-timeout-1.jest.js
@@ -0,0 +1,35 @@
+/**
+ * Copyright 2018 Google Inc. All rights reserved.
+ * Modifications copyright (c) Microsoft Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const {USES_HOOKS} = testOptions;
+
+describe('Page.click', function() {
+ it.skip(USES_HOOKS)('should avoid side effects after timeout', async({page, server}) => {
+ await page.goto(server.PREFIX + '/input/button.html');
+ const error = await page.click('button', { timeout: 2000, __testHookBeforePointerAction: () => new Promise(f => setTimeout(f, 2500))}).catch(e => e);
+ await page.waitForTimeout(5000); // Give it some time to click after the test hook is done waiting.
+ expect(await page.evaluate(() => result)).toBe('Was not clicked');
+ expect(error.message).toContain('page.click: Timeout 2000ms exceeded.');
+ });
+ it('should timeout waiting for button to be enabled', async({page, server}) => {
+ await page.setContent('');
+ const error = await page.click('text=Click target', { timeout: 3000 }).catch(e => e);
+ expect(await page.evaluate(() => window.__CLICKED)).toBe(undefined);
+ expect(error.message).toContain('page.click: Timeout 3000ms exceeded.');
+ expect(error.message).toContain('element is disabled - waiting');
+ });
+});
diff --git a/test/click-timeout-2.jest.js b/test/click-timeout-2.jest.js
new file mode 100644
index 0000000000..cd643abfa8
--- /dev/null
+++ b/test/click-timeout-2.jest.js
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2018 Google Inc. All rights reserved.
+ * Modifications copyright (c) Microsoft Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const {USES_HOOKS} = testOptions;
+
+describe('Page.click', function() {
+ it('should timeout waiting for display:none to be gone', async({page, server}) => {
+ await page.goto(server.PREFIX + '/input/button.html');
+ await page.$eval('button', b => b.style.display = 'none');
+ const error = await page.click('button', { timeout: 5000 }).catch(e => e);
+ expect(error.message).toContain('page.click: Timeout 5000ms exceeded.');
+ expect(error.message).toContain('waiting for element to be visible, enabled and not moving');
+ expect(error.message).toContain('element is not visible - waiting');
+ });
+ it('should timeout waiting for visbility:hidden to be gone', async({page, server}) => {
+ await page.goto(server.PREFIX + '/input/button.html');
+ await page.$eval('button', b => b.style.visibility = 'hidden');
+ const error = await page.click('button', { timeout: 5000 }).catch(e => e);
+ expect(error.message).toContain('page.click: Timeout 5000ms exceeded.');
+ expect(error.message).toContain('waiting for element to be visible, enabled and not moving');
+ expect(error.message).toContain('element is not visible - waiting');
+ });
+});
diff --git a/test/click-timeout-3.jest.js b/test/click-timeout-3.jest.js
new file mode 100644
index 0000000000..f77e3ead3f
--- /dev/null
+++ b/test/click-timeout-3.jest.js
@@ -0,0 +1,55 @@
+/**
+ * Copyright 2018 Google Inc. All rights reserved.
+ * Modifications copyright (c) Microsoft Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const {USES_HOOKS} = testOptions;
+
+describe('Page.click', function() {
+ it.skip(USES_HOOKS)('should fail when element jumps during hit testing', async({page, server}) => {
+ await page.setContent('');
+ let clicked = false;
+ const handle = await page.$('button');
+ const __testHookBeforeHitTarget = () => page.evaluate(() => {
+ const margin = parseInt(document.querySelector('button').style.marginLeft || 0) + 100;
+ document.querySelector('button').style.marginLeft = margin + 'px';
+ });
+ const promise = handle.click({ timeout: 5000, __testHookBeforeHitTarget }).then(() => clicked = true).catch(e => e);
+ const error = await promise;
+ expect(clicked).toBe(false);
+ expect(await page.evaluate(() => window.clicked)).toBe(undefined);
+ expect(error.message).toContain('elementHandle.click: Timeout 5000ms exceeded.');
+ expect(error.message).toContain('element does not receive pointer events');
+ expect(error.message).toContain('retrying click action');
+ });
+ it('should timeout waiting for hit target', async({page, server}) => {
+ await page.goto(server.PREFIX + '/input/button.html');
+ const button = await page.$('button');
+ await page.evaluate(() => {
+ document.body.style.position = 'relative';
+ const blocker = document.createElement('div');
+ blocker.style.position = 'absolute';
+ blocker.style.width = '400px';
+ blocker.style.height = '20px';
+ blocker.style.left = '0';
+ blocker.style.top = '0';
+ document.body.appendChild(blocker);
+ });
+ const error = await button.click({ timeout: 5000 }).catch(e => e);
+ expect(error.message).toContain('elementHandle.click: Timeout 5000ms exceeded.');
+ expect(error.message).toContain('element does not receive pointer events');
+ expect(error.message).toContain('retrying click action');
+ });
+});
diff --git a/test/click-timeout-4.jest.js b/test/click-timeout-4.jest.js
new file mode 100644
index 0000000000..825cbef068
--- /dev/null
+++ b/test/click-timeout-4.jest.js
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2018 Google Inc. All rights reserved.
+ * Modifications copyright (c) Microsoft Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const {USES_HOOKS} = testOptions;
+
+describe('Page.click', function() {
+ it('should timeout waiting for stable position', async({page, server}) => {
+ await page.goto(server.PREFIX + '/input/button.html');
+ const button = await page.$('button');
+ await button.evaluate(button => {
+ button.style.transition = 'margin 5s linear 0s';
+ button.style.marginLeft = '200px';
+ });
+ const error = await button.click({ timeout: 5000 }).catch(e => e);
+ expect(error.message).toContain('elementHandle.click: Timeout 5000ms exceeded.');
+ expect(error.message).toContain('waiting for element to be visible, enabled and not moving');
+ expect(error.message).toContain('element is moving - waiting');
+ });
+});
diff --git a/test/click-timeout-5.jest.js b/test/click-timeout-5.jest.js
new file mode 100644
index 0000000000..bb523306bd
--- /dev/null
+++ b/test/click-timeout-5.jest.js
@@ -0,0 +1,64 @@
+/**
+ * Copyright 2018 Google Inc. All rights reserved.
+ * Modifications copyright (c) Microsoft Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const {USES_HOOKS} = testOptions;
+
+describe('Page.click', function() {
+ it.fail(true)('should report that selector does not match anymore', async ({page, server}) => {
+ await page.goto(server.PREFIX + '/react.html');
+ await page.evaluate(() => {
+ renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2' })] ));
+ });
+ const __testHookAfterStable = () => page.evaluate(() => {
+ window.counter = (window.counter || 0) + 1;
+ if (window.counter === 1)
+ renderComponent(e('div', {}, [e(MyButton, { name: 'button2' }), e(MyButton, { name: 'button1' })] ));
+ else
+ renderComponent(e('div', {}, []));
+ });
+ const error = await page.dblclick('text=button1', { __testHookAfterStable, timeout: 3000 }).catch(e => e);
+ expect(await page.evaluate(() => window.button1)).toBe(undefined);
+ expect(await page.evaluate(() => window.button2)).toBe(undefined);
+ expect(error.message).toContain('page.dblclick: Timeout 3000ms exceeded.');
+ expect(error.message).toContain('element does not match the selector anymore');
+ });
+ it.fail(true)('should not retarget the handle when element is recycled', async ({page, server}) => {
+ await page.goto(server.PREFIX + '/react.html');
+ await page.evaluate(() => {
+ renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2', disabled: true })] ));
+ });
+ const __testHookBeforeStable = () => page.evaluate(() => {
+ window.counter = (window.counter || 0) + 1;
+ if (window.counter === 1)
+ renderComponent(e('div', {}, [e(MyButton, { name: 'button2', disabled: true }), e(MyButton, { name: 'button1' })] ));
+ });
+ const handle = await page.$('text=button1');
+ const error = await handle.click({ __testHookBeforeStable, timeout: 3000 }).catch(e => e);
+ expect(await page.evaluate(() => window.button1)).toBe(undefined);
+ expect(await page.evaluate(() => window.button2)).toBe(undefined);
+ expect(error.message).toContain('elementHandle.click: Timeout 3000ms exceeded.');
+ expect(error.message).toContain('element is disabled - waiting');
+ });
+ it('should timeout when click opens alert', async({page, server}) => {
+ const dialogPromise = page.waitForEvent('dialog');
+ await page.setContent(`