forked from puppeteer/puppeteer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: Break 'page.spec.js' to smaller files (puppeteer#2218)
This patch breaks huge `page.spec.js` into a bunch of smaller files.
- Loading branch information
1 parent
38c6873
commit 4748196
Showing
11 changed files
with
1,638 additions
and
1,462 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/** | ||
* Copyright 2018 Google Inc. All rights reserved. | ||
* | ||
* 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. | ||
*/ | ||
|
||
module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, puppeteer}) { | ||
const {describe, xdescribe, fdescribe} = testRunner; | ||
const {it, fit, xit} = testRunner; | ||
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; | ||
const headless = defaultBrowserOptions.headless; | ||
|
||
describe('Browser.version', function() { | ||
it('should return whether we are in headless', async({browser}) => { | ||
const version = await browser.version(); | ||
expect(version.length).toBeGreaterThan(0); | ||
expect(version.startsWith('Headless')).toBe(headless); | ||
}); | ||
}); | ||
|
||
describe('Browser.userAgent', function() { | ||
it('should include WebKit', async({browser}) => { | ||
const userAgent = await browser.userAgent(); | ||
expect(userAgent.length).toBeGreaterThan(0); | ||
expect(userAgent).toContain('WebKit'); | ||
}); | ||
}); | ||
|
||
describe('Browser.process', function() { | ||
it('should return child_process instance', async function({browser}) { | ||
const process = await browser.process(); | ||
expect(process.pid).toBeGreaterThan(0); | ||
const browserWSEndpoint = browser.wsEndpoint(); | ||
const remoteBrowser = await puppeteer.connect({browserWSEndpoint}); | ||
expect(remoteBrowser.process()).toBe(null); | ||
await remoteBrowser.disconnect(); | ||
}); | ||
}); | ||
|
||
describe('Browser.Events.disconnected', function() { | ||
it('should emitted when: browser gets closed, disconnected or underlying websocket gets closed', async() => { | ||
const originalBrowser = await puppeteer.launch(defaultBrowserOptions); | ||
const browserWSEndpoint = originalBrowser.wsEndpoint(); | ||
const remoteBrowser1 = await puppeteer.connect({browserWSEndpoint}); | ||
const remoteBrowser2 = await puppeteer.connect({browserWSEndpoint}); | ||
|
||
let disconnectedOriginal = 0; | ||
let disconnectedRemote1 = 0; | ||
let disconnectedRemote2 = 0; | ||
originalBrowser.on('disconnected', () => ++disconnectedOriginal); | ||
remoteBrowser1.on('disconnected', () => ++disconnectedRemote1); | ||
remoteBrowser2.on('disconnected', () => ++disconnectedRemote2); | ||
|
||
await remoteBrowser2.disconnect(); | ||
expect(disconnectedOriginal).toBe(0); | ||
expect(disconnectedRemote1).toBe(0); | ||
expect(disconnectedRemote2).toBe(1); | ||
|
||
await originalBrowser.close(); | ||
expect(disconnectedOriginal).toBe(1); | ||
expect(disconnectedRemote1).toBe(1); | ||
expect(disconnectedRemote2).toBe(1); | ||
}); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,272 @@ | ||
/** | ||
* Copyright 2018 Google Inc. All rights reserved. | ||
* | ||
* 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 utils = require('./utils'); | ||
|
||
module.exports.addTests = function({testRunner, expect}) { | ||
const {describe, xdescribe, fdescribe} = testRunner; | ||
const {it, fit, xit} = testRunner; | ||
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; | ||
|
||
describe('ElementHandle.boundingBox', function() { | ||
it('should work', async({page, server}) => { | ||
await page.setViewport({width: 500, height: 500}); | ||
await page.goto(server.PREFIX + '/grid.html'); | ||
const elementHandle = await page.$('.box:nth-of-type(13)'); | ||
const box = await elementHandle.boundingBox(); | ||
expect(box).toEqual({ x: 100, y: 50, width: 50, height: 50 }); | ||
}); | ||
it('should handle nested frames', async({page, server}) => { | ||
await page.setViewport({width: 500, height: 500}); | ||
await page.goto(server.PREFIX + '/frames/nested-frames.html'); | ||
const nestedFrame = page.frames()[1].childFrames()[1]; | ||
const elementHandle = await nestedFrame.$('div'); | ||
const box = await elementHandle.boundingBox(); | ||
expect(box).toEqual({ x: 28, y: 260, width: 264, height: 18 }); | ||
}); | ||
it('should return null for invisible elements', async({page, server}) => { | ||
await page.setContent('<div style="display:none">hi</div>'); | ||
const element = await page.$('div'); | ||
expect(await element.boundingBox()).toBe(null); | ||
}); | ||
it('should force a layout', async({page, server}) => { | ||
await page.setViewport({ width: 500, height: 500 }); | ||
await page.setContent('<div style="width: 100px; height: 100px">hello</div>'); | ||
const elementHandle = await page.$('div'); | ||
await page.evaluate(element => element.style.height = '200px', elementHandle); | ||
const box = await elementHandle.boundingBox(); | ||
expect(box).toEqual({ x: 8, y: 8, width: 100, height: 200 }); | ||
}); | ||
}); | ||
|
||
describe('ElementHandle.contentFrame', function() { | ||
it('should work', async({page,server}) => { | ||
await page.goto(server.EMPTY_PAGE); | ||
await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE); | ||
const elementHandle = await page.$('#frame1'); | ||
const frame = await elementHandle.contentFrame(); | ||
expect(frame).toBe(page.frames()[1]); | ||
}); | ||
}); | ||
|
||
describe('ElementHandle.click', function() { | ||
it('should work', async({page, server}) => { | ||
await page.goto(server.PREFIX + '/input/button.html'); | ||
const button = await page.$('button'); | ||
await button.click(); | ||
expect(await page.evaluate(() => result)).toBe('Clicked'); | ||
}); | ||
it('should work for Shadow DOM v1', async({page, server}) => { | ||
await page.goto(server.PREFIX + '/shadow.html'); | ||
const buttonHandle = await page.evaluateHandle(() => button); | ||
await buttonHandle.click(); | ||
expect(await page.evaluate(() => clicked)).toBe(true); | ||
}); | ||
it('should work for TextNodes', async({page, server}) => { | ||
await page.goto(server.PREFIX + '/input/button.html'); | ||
const buttonTextNode = await page.evaluateHandle(() => document.querySelector('button').firstChild); | ||
let error = null; | ||
await buttonTextNode.click().catch(err => error = err); | ||
expect(error.message).toBe('Node is not of type HTMLElement'); | ||
}); | ||
it('should throw for detached nodes', async({page, server}) => { | ||
await page.goto(server.PREFIX + '/input/button.html'); | ||
const button = await page.$('button'); | ||
await page.evaluate(button => button.remove(), button); | ||
let error = null; | ||
await button.click().catch(err => error = err); | ||
expect(error.message).toBe('Node is detached from document'); | ||
}); | ||
it('should throw for hidden nodes', async({page, server}) => { | ||
await page.goto(server.PREFIX + '/input/button.html'); | ||
const button = await page.$('button'); | ||
await page.evaluate(button => button.style.display = 'none', button); | ||
const error = await button.click().catch(err => err); | ||
expect(error.message).toBe('Node is either not visible or not an HTMLElement'); | ||
}); | ||
it('should throw for recursively hidden nodes', async({page, server}) => { | ||
await page.goto(server.PREFIX + '/input/button.html'); | ||
const button = await page.$('button'); | ||
await page.evaluate(button => button.parentElement.style.display = 'none', button); | ||
const error = await button.click().catch(err => err); | ||
expect(error.message).toBe('Node is either not visible or not an HTMLElement'); | ||
}); | ||
it('should throw for <br> elements', async({page, server}) => { | ||
await page.setContent('hello<br>goodbye'); | ||
const br = await page.$('br'); | ||
const error = await br.click().catch(err => err); | ||
expect(error.message).toBe('Node is either not visible or not an HTMLElement'); | ||
}); | ||
}); | ||
|
||
describe('ElementHandle.hover', function() { | ||
it('should work', async({page, server}) => { | ||
await page.goto(server.PREFIX + '/input/scrollable.html'); | ||
const button = await page.$('#button-6'); | ||
await button.hover(); | ||
expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-6'); | ||
}); | ||
}); | ||
|
||
describe('ElementHandle.screenshot', function() { | ||
it('should work', async({page, server}) => { | ||
await page.setViewport({width: 500, height: 500}); | ||
await page.goto(server.PREFIX + '/grid.html'); | ||
await page.evaluate(() => window.scrollBy(50, 100)); | ||
const elementHandle = await page.$('.box:nth-of-type(3)'); | ||
const screenshot = await elementHandle.screenshot(); | ||
expect(screenshot).toBeGolden('screenshot-element-bounding-box.png'); | ||
}); | ||
it('should take into account padding and border', async({page, server}) => { | ||
await page.setViewport({width: 500, height: 500}); | ||
await page.setContent(` | ||
something above | ||
<style>div { | ||
border: 2px solid blue; | ||
background: green; | ||
width: 50px; | ||
height: 50px; | ||
} | ||
</style> | ||
<div></div> | ||
`); | ||
const elementHandle = await page.$('div'); | ||
const screenshot = await elementHandle.screenshot(); | ||
expect(screenshot).toBeGolden('screenshot-element-padding-border.png'); | ||
}); | ||
it('should capture full element when larger than viewport', async({page, server}) => { | ||
await page.setViewport({width: 500, height: 500}); | ||
|
||
await page.setContent(` | ||
something above | ||
<style> | ||
div.to-screenshot { | ||
border: 1px solid blue; | ||
width: 600px; | ||
height: 600px; | ||
margin-left: 50px; | ||
} | ||
</style> | ||
<div class="to-screenshot"></div> | ||
`); | ||
const elementHandle = await page.$('div.to-screenshot'); | ||
const screenshot = await elementHandle.screenshot(); | ||
expect(screenshot).toBeGolden('screenshot-element-larger-than-viewport.png'); | ||
|
||
expect(await page.evaluate(() => ({ w: window.innerWidth, h: window.innerHeight }))).toEqual({ w: 500, h: 500 }); | ||
}); | ||
it('should scroll element into view', async({page, server}) => { | ||
await page.setViewport({width: 500, height: 500}); | ||
await page.setContent(` | ||
something above | ||
<style>div.above { | ||
border: 2px solid blue; | ||
background: red; | ||
height: 1500px; | ||
} | ||
div.to-screenshot { | ||
border: 2px solid blue; | ||
background: green; | ||
width: 50px; | ||
height: 50px; | ||
} | ||
</style> | ||
<div class="above"></div> | ||
<div class="to-screenshot"></div> | ||
`); | ||
const elementHandle = await page.$('div.to-screenshot'); | ||
const screenshot = await elementHandle.screenshot(); | ||
expect(screenshot).toBeGolden('screenshot-element-scrolled-into-view.png'); | ||
}); | ||
it('should work with a rotated element', async({page, server}) => { | ||
await page.setViewport({width: 500, height: 500}); | ||
await page.setContent(`<div style="position:absolute; | ||
top: 100px; | ||
left: 100px; | ||
width: 100px; | ||
height: 100px; | ||
background: green; | ||
transform: rotateZ(200deg);"> </div>`); | ||
const elementHandle = await page.$('div'); | ||
const screenshot = await elementHandle.screenshot(); | ||
expect(screenshot).toBeGolden('screenshot-element-rotate.png'); | ||
}); | ||
it('should fail to screenshot a detached element', async({page, server}) => { | ||
await page.setContent('<h1>remove this</h1>'); | ||
const elementHandle = await page.$('h1'); | ||
await page.evaluate(element => element.remove(), elementHandle); | ||
const screenshotError = await elementHandle.screenshot().catch(error => error); | ||
expect(screenshotError.message).toBe('Node is either not visible or not an HTMLElement'); | ||
}); | ||
}); | ||
|
||
describe('ElementHandle.$', function() { | ||
it('should query existing element', async({page, server}) => { | ||
await page.goto(server.PREFIX + '/playground.html'); | ||
await page.setContent('<html><body><div class="second"><div class="inner">A</div></div></body></html>'); | ||
const html = await page.$('html'); | ||
const second = await html.$('.second'); | ||
const inner = await second.$('.inner'); | ||
const content = await page.evaluate(e => e.textContent, inner); | ||
expect(content).toBe('A'); | ||
}); | ||
|
||
it('should return null for non-existing element', async({page, server}) => { | ||
await page.setContent('<html><body><div class="second"><div class="inner">B</div></div></body></html>'); | ||
const html = await page.$('html'); | ||
const second = await html.$('.third'); | ||
expect(second).toBe(null); | ||
}); | ||
}); | ||
|
||
describe('ElementHandle.$$', function() { | ||
it('should query existing elements', async({page, server}) => { | ||
await page.setContent('<html><body><div>A</div><br/><div>B</div></body></html>'); | ||
const html = await page.$('html'); | ||
const elements = await html.$$('div'); | ||
expect(elements.length).toBe(2); | ||
const promises = elements.map(element => page.evaluate(e => e.textContent, element)); | ||
expect(await Promise.all(promises)).toEqual(['A', 'B']); | ||
}); | ||
|
||
it('should return empty array for non-existing elements', async({page, server}) => { | ||
await page.setContent('<html><body><span>A</span><br/><span>B</span></body></html>'); | ||
const html = await page.$('html'); | ||
const elements = await html.$$('div'); | ||
expect(elements.length).toBe(0); | ||
}); | ||
}); | ||
|
||
|
||
describe('ElementHandle.$x', function() { | ||
it('should query existing element', async({page, server}) => { | ||
await page.goto(server.PREFIX + '/playground.html'); | ||
await page.setContent('<html><body><div class="second"><div class="inner">A</div></div></body></html>'); | ||
const html = await page.$('html'); | ||
const second = await html.$x(`./body/div[contains(@class, 'second')]`); | ||
const inner = await second[0].$x(`./div[contains(@class, 'inner')]`); | ||
const content = await page.evaluate(e => e.textContent, inner[0]); | ||
expect(content).toBe('A'); | ||
}); | ||
|
||
it('should return null for non-existing element', async({page, server}) => { | ||
await page.setContent('<html><body><div class="second"><div class="inner">B</div></div></body></html>'); | ||
const html = await page.$('html'); | ||
const second = await html.$x(`/div[contains(@class, 'third')]`); | ||
expect(second).toEqual([]); | ||
}); | ||
}); | ||
}; |
Oops, something went wrong.