From 09703eaeeeab553e13142153b55030db05611f7c Mon Sep 17 00:00:00 2001 From: Konstantin Krivlenia Date: Wed, 28 Aug 2019 09:24:37 +0300 Subject: [PATCH] feat(expect-puppeteer): support frames (#275) --- packages/expect-puppeteer/src/index.js | 1 + .../src/matchers/notToMatch.test.js | 8 ++++- .../src/matchers/notToMatchElement.test.js | 8 ++++- .../src/matchers/setupPage.js | 32 +++++++++++++++++++ .../src/matchers/toClick.test.js | 8 ++++- .../src/matchers/toFill.test.js | 8 ++++- .../src/matchers/toFillForm.test.js | 8 ++++- .../src/matchers/toMatch.test.js | 8 ++++- .../src/matchers/toMatchElement.test.js | 16 ++++++++-- .../expect-puppeteer/src/matchers/toSelect.js | 3 +- .../src/matchers/toSelect.test.js | 8 ++++- .../src/matchers/toUploadFile.test.js | 7 +++- packages/expect-puppeteer/src/utils.js | 3 +- server/public/frame.html | 1 + 14 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 packages/expect-puppeteer/src/matchers/setupPage.js create mode 100644 server/public/frame.html diff --git a/packages/expect-puppeteer/src/index.js b/packages/expect-puppeteer/src/index.js index e43883c2..5091ba06 100644 --- a/packages/expect-puppeteer/src/index.js +++ b/packages/expect-puppeteer/src/index.js @@ -77,6 +77,7 @@ function expectPuppeteer(actual) { const type = getPuppeteerType(actual) switch (type) { case 'Page': + case 'Frame': return internalExpect(actual, pageMatchers) case 'ElementHandle': return internalExpect(actual, elementHandleMatchers) diff --git a/packages/expect-puppeteer/src/matchers/notToMatch.test.js b/packages/expect-puppeteer/src/matchers/notToMatch.test.js index 5dd7a4af..cdee6c52 100644 --- a/packages/expect-puppeteer/src/matchers/notToMatch.test.js +++ b/packages/expect-puppeteer/src/matchers/notToMatch.test.js @@ -1,9 +1,15 @@ +import { setupPage } from './setupPage' + describe('not.toMatch', () => { beforeEach(async () => { await page.goto(`http://localhost:${process.env.TEST_SERVER_PORT}`) }) - describe('Page', () => { + describe.each(['Page', 'Frame'])('%s', pageType => { + let page + setupPage(pageType, ({ currentPage }) => { + page = currentPage + }) it('should be ok if text is not in the page', async () => { await expect(page).not.toMatch('Nop!') }) diff --git a/packages/expect-puppeteer/src/matchers/notToMatchElement.test.js b/packages/expect-puppeteer/src/matchers/notToMatchElement.test.js index 80c93417..4ee529ad 100644 --- a/packages/expect-puppeteer/src/matchers/notToMatchElement.test.js +++ b/packages/expect-puppeteer/src/matchers/notToMatchElement.test.js @@ -1,9 +1,15 @@ +import { setupPage } from './setupPage' + describe('not.toMatchElement', () => { beforeEach(async () => { await page.goto(`http://localhost:${process.env.TEST_SERVER_PORT}`) }) - describe('Page', () => { + describe.each(['Page', 'Frame'])('%s', pageType => { + let page + setupPage(pageType, ({ currentPage }) => { + page = currentPage + }) it('should not match using selector', async () => { await expect(page).not.toMatchElement('wtf') }) diff --git a/packages/expect-puppeteer/src/matchers/setupPage.js b/packages/expect-puppeteer/src/matchers/setupPage.js new file mode 100644 index 00000000..ddfa4beb --- /dev/null +++ b/packages/expect-puppeteer/src/matchers/setupPage.js @@ -0,0 +1,32 @@ +function waitForFrame(page) { + let fulfill + const promise = new Promise(resolve => { + fulfill = resolve + }) + function checkFrame() { + const frame = page.frames().find(f => f.parentFrame() !== null) + if (frame) fulfill(frame) + else page.once(`frameattached`, checkFrame) + } + checkFrame() + return promise +} + +export const setupPage = (pageType, cb) => { + let currentPage = page + beforeEach(async () => { + if (pageType === `Page`) { + cb({ + currentPage, + }) + return + } + await page.goto( + `http://localhost:${process.env.TEST_SERVER_PORT}/frame.html`, + ) + currentPage = await waitForFrame(page) + cb({ + currentPage, + }) + }) +} diff --git a/packages/expect-puppeteer/src/matchers/toClick.test.js b/packages/expect-puppeteer/src/matchers/toClick.test.js index 448bfaf6..95ac5c4a 100644 --- a/packages/expect-puppeteer/src/matchers/toClick.test.js +++ b/packages/expect-puppeteer/src/matchers/toClick.test.js @@ -1,9 +1,15 @@ +import { setupPage } from './setupPage' + describe('toClick', () => { beforeEach(async () => { await page.goto(`http://localhost:${process.env.TEST_SERVER_PORT}`) }) - describe('Page', () => { + describe.each(['Page', 'Frame'])('%s', pageType => { + let page + setupPage(pageType, ({ currentPage }) => { + page = currentPage + }) it('should click using selector', async () => { await expect(page).toClick('a[href="/page2.html"]') await page.waitForSelector('html') diff --git a/packages/expect-puppeteer/src/matchers/toFill.test.js b/packages/expect-puppeteer/src/matchers/toFill.test.js index 2431b516..51e16cf8 100644 --- a/packages/expect-puppeteer/src/matchers/toFill.test.js +++ b/packages/expect-puppeteer/src/matchers/toFill.test.js @@ -1,9 +1,15 @@ +import { setupPage } from './setupPage' + describe('toFill', () => { beforeEach(async () => { await page.goto(`http://localhost:${process.env.TEST_SERVER_PORT}`) }) - describe('Page', () => { + describe.each(['Page', 'Frame'])('%s', pageType => { + let page + setupPage(pageType, ({ currentPage }) => { + page = currentPage + }) it('should fill input', async () => { await expect(page).toFill('[name="firstName"]', 'James') const value = await page.evaluate( diff --git a/packages/expect-puppeteer/src/matchers/toFillForm.test.js b/packages/expect-puppeteer/src/matchers/toFillForm.test.js index 3494afd0..3ef98713 100644 --- a/packages/expect-puppeteer/src/matchers/toFillForm.test.js +++ b/packages/expect-puppeteer/src/matchers/toFillForm.test.js @@ -1,9 +1,15 @@ +import { setupPage } from './setupPage' + describe('toFillForm', () => { beforeEach(async () => { await page.goto(`http://localhost:${process.env.TEST_SERVER_PORT}`) }) - describe('Page', () => { + describe.each(['Page', 'Frame'])('%s', pageType => { + let page + setupPage(pageType, ({ currentPage }) => { + page = currentPage + }) it('should fill input', async () => { await expect(page).toFillForm('form', { firstName: 'James', diff --git a/packages/expect-puppeteer/src/matchers/toMatch.test.js b/packages/expect-puppeteer/src/matchers/toMatch.test.js index fc7f0482..70ec2bca 100644 --- a/packages/expect-puppeteer/src/matchers/toMatch.test.js +++ b/packages/expect-puppeteer/src/matchers/toMatch.test.js @@ -1,9 +1,15 @@ +import { setupPage } from './setupPage' + describe('toMatch', () => { beforeEach(async () => { await page.goto(`http://localhost:${process.env.TEST_SERVER_PORT}`) }) - describe('Page', () => { + describe.each(['Page', 'Frame'])('%s', pageType => { + let page + setupPage(pageType, ({ currentPage }) => { + page = currentPage + }) it('should be ok if text is in the page', async () => { await expect(page).toMatch('This is home!') }) diff --git a/packages/expect-puppeteer/src/matchers/toMatchElement.test.js b/packages/expect-puppeteer/src/matchers/toMatchElement.test.js index f10374fd..f0be56d8 100644 --- a/packages/expect-puppeteer/src/matchers/toMatchElement.test.js +++ b/packages/expect-puppeteer/src/matchers/toMatchElement.test.js @@ -1,9 +1,15 @@ +import { setupPage } from './setupPage' + describe('toMatchElement', () => { beforeEach(async () => { await page.goto(`http://localhost:${process.env.TEST_SERVER_PORT}`) }) - describe('Page', () => { + describe.each(['Page', 'Frame'])('%s', pageType => { + let page + setupPage(pageType, ({ currentPage }) => { + page = currentPage + }) it('should match using selector', async () => { const element = await expect(page).toMatchElement('a[href="/page2.html"]') const textContentProperty = await element.getProperty('textContent') @@ -12,7 +18,9 @@ describe('toMatchElement', () => { }) it('should match using text (string)', async () => { - const element = await expect(page).toMatchElement('a', { text: 'Page 2' }) + const element = await expect(page).toMatchElement('a', { + text: 'Page 2', + }) const textContentProperty = await element.getProperty('textContent') const textContent = await textContentProperty.jsonValue() expect(textContent).toBe('Page 2') @@ -56,7 +64,9 @@ describe('toMatchElement', () => { } try { - await expect(page).toMatchElement('.displayed', { visible: true }) + await expect(page).toMatchElement('.displayed', { + visible: true, + }) } catch (error) { expect(error.message).toMatch('Element .displayed not found') expect(error.message).toMatch('waiting for function failed') diff --git a/packages/expect-puppeteer/src/matchers/toSelect.js b/packages/expect-puppeteer/src/matchers/toSelect.js index 0f272fff..da606114 100644 --- a/packages/expect-puppeteer/src/matchers/toSelect.js +++ b/packages/expect-puppeteer/src/matchers/toSelect.js @@ -1,5 +1,6 @@ /* eslint-disable no-restricted-syntax */ import toMatchElement from './toMatchElement' +import { getContext } from '../utils' function select(page, element, value) { return page.evaluate( @@ -48,7 +49,7 @@ async function toSelect(instance, selector, valueOrText, options) { if (!option) { throw new Error(`Option not found "${selector}" ("${valueOrText}")`) } - + const { page } = await getContext(instance, () => document) await select(page, element, option.value) // await page.select(selector, foundValue) diff --git a/packages/expect-puppeteer/src/matchers/toSelect.test.js b/packages/expect-puppeteer/src/matchers/toSelect.test.js index 5aebad5c..2d6a6a45 100644 --- a/packages/expect-puppeteer/src/matchers/toSelect.test.js +++ b/packages/expect-puppeteer/src/matchers/toSelect.test.js @@ -1,9 +1,15 @@ +import { setupPage } from './setupPage' + describe('toSelect', () => { beforeEach(async () => { await page.goto(`http://localhost:${process.env.TEST_SERVER_PORT}`) }) - describe('Page', () => { + describe.each(['Page', 'Frame'])('%s', pageType => { + let page + setupPage(pageType, ({ currentPage }) => { + page = currentPage + }) it('should select an option using value', async () => { await expect(page).toSelect('select[name="my-select"]', 'opt1') const currentValue = await page.evaluate( diff --git a/packages/expect-puppeteer/src/matchers/toUploadFile.test.js b/packages/expect-puppeteer/src/matchers/toUploadFile.test.js index 3c55a9b0..fa66c693 100644 --- a/packages/expect-puppeteer/src/matchers/toUploadFile.test.js +++ b/packages/expect-puppeteer/src/matchers/toUploadFile.test.js @@ -1,11 +1,16 @@ import path from 'path' +import { setupPage } from './setupPage' describe('toUploadFile', () => { beforeEach(async () => { await page.goto(`http://localhost:${process.env.TEST_SERVER_PORT}`) }) - describe('Page', () => { + describe.each(['Page', 'Frame'])('%s', pageType => { + let page + setupPage(pageType, ({ currentPage }) => { + page = currentPage + }) it('should upload a select file', async () => { await expect(page).toUploadFile( 'input[type="file"]', diff --git a/packages/expect-puppeteer/src/utils.js b/packages/expect-puppeteer/src/utils.js index 05bbac20..36613606 100644 --- a/packages/expect-puppeteer/src/utils.js +++ b/packages/expect-puppeteer/src/utils.js @@ -3,7 +3,7 @@ export const getPuppeteerType = instance => { instance && instance.constructor && instance.constructor.name && - ['Page', 'ElementHandle'].includes(instance.constructor.name) && + ['Page', 'Frame', 'ElementHandle'].includes(instance.constructor.name) && instance.$ ) { return instance.constructor.name @@ -16,6 +16,7 @@ export const getContext = async (instance, pageFunction) => { const type = getPuppeteerType(instance) switch (type) { case 'Page': + case 'Frame': return { page: instance, handle: await instance.evaluateHandle(pageFunction), diff --git a/server/public/frame.html b/server/public/frame.html new file mode 100644 index 00000000..452862fe --- /dev/null +++ b/server/public/frame.html @@ -0,0 +1 @@ +