test(e2e): add infrastructure for migration to playwright (#25033)
12
core/src/components/button/test/basic/button.e2e.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { expect, describe } from '@playwright/test';
|
||||
import { test } from '@utils/test/playwright';
|
||||
|
||||
test.describe('button: basic', () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.goto(`/src/components/button/test/basic`);
|
||||
|
||||
await page.setIonViewport();
|
||||
|
||||
expect(await page.screenshot({ fullPage: true })).toMatchSnapshot(`button-diff-${page.getSnapshotSettings()}.png`);
|
||||
});
|
||||
});
|
After Width: | Height: | Size: 306 KiB |
After Width: | Height: | Size: 278 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 123 KiB |
After Width: | Height: | Size: 166 KiB |
After Width: | Height: | Size: 304 KiB |
After Width: | Height: | Size: 278 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 123 KiB |
After Width: | Height: | Size: 167 KiB |
After Width: | Height: | Size: 299 KiB |
After Width: | Height: | Size: 277 KiB |
After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 138 KiB |
After Width: | Height: | Size: 174 KiB |
After Width: | Height: | Size: 300 KiB |
After Width: | Height: | Size: 277 KiB |
After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 175 KiB |
@ -1,10 +0,0 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('button: basic', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/button/test/basic?ionic:_testing=true'
|
||||
});
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
97
core/src/utils/test/playwright.ts
Normal file
@ -0,0 +1,97 @@
|
||||
import { test as base } from '@playwright/test';
|
||||
|
||||
export const test = base.extend({
|
||||
page: async ({ page }, use, testInfo) => {
|
||||
const oldGoTo = page.goto.bind(page);
|
||||
|
||||
|
||||
/**
|
||||
* This is an extended version of Playwright's
|
||||
* page.goto method. In addition to performing
|
||||
* the normal page.goto work, this code also
|
||||
* automatically waits for the Stencil components
|
||||
* to be hydrated before proceeding with the test.
|
||||
*/
|
||||
page.goto = (url: string) => {
|
||||
const { mode, rtl } = testInfo.project.metadata;
|
||||
|
||||
const splitUrl = url.split('?');
|
||||
const paramsString = splitUrl[1];
|
||||
|
||||
/**
|
||||
* This allows developers to force a
|
||||
* certain mode or LTR/RTL config per test.
|
||||
*/
|
||||
const urlToParams = new URLSearchParams(paramsString);
|
||||
const formattedMode = urlToParams.get('ionic:mode') ?? mode;
|
||||
const formattedRtl = urlToParams.get('rtl') ?? rtl;
|
||||
|
||||
const formattedUrl = `${splitUrl[0]}?ionic:_testing=true&ionic:mode=${formattedMode}&rtl=${formattedRtl}`;
|
||||
|
||||
return Promise.all([
|
||||
page.waitForFunction(() => window.stencilAppLoaded === true),
|
||||
oldGoTo(formattedUrl)
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* This provides metadata that can be used to
|
||||
* create a unique screenshot URL.
|
||||
* For example, we need to be able to differentiate
|
||||
* between iOS in LTR mode and iOS in RTL mode.
|
||||
*/
|
||||
page.getSnapshotSettings = () => {
|
||||
const url = page.url();
|
||||
const splitUrl = url.split('?');
|
||||
const paramsString = splitUrl[1];
|
||||
|
||||
const { mode, rtl } = testInfo.project.metadata;
|
||||
|
||||
/**
|
||||
* Account for custom settings when overriding
|
||||
* the mode/rtl setting. Fall back to the
|
||||
* project metadata if nothing was found. This
|
||||
* will happen if you call page.getSnapshotSettings
|
||||
* before page.goto.
|
||||
*/
|
||||
const urlToParams = new URLSearchParams(paramsString);
|
||||
const formattedMode = urlToParams.get('ionic:mode') ?? mode;
|
||||
const formattedRtl = urlToParams.get('rtl') ?? rtl;
|
||||
|
||||
/**
|
||||
* If encoded in the search params, the rtl value
|
||||
* can be `'true'` instead of `true`.
|
||||
*/
|
||||
const rtlString = formattedRtl === true || formattedRtl === 'true' ? 'rtl' : 'ltr';
|
||||
return `${formattedMode}-${rtlString}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Taking fullpage screenshots in Playwright
|
||||
* does not work with ion-content by default.
|
||||
* The reason is that full page screenshots do not
|
||||
* expand any scrollable container on the page. Instead,
|
||||
* they render the full scrollable content of the document itself.
|
||||
* To work around this, we increase the size of the document
|
||||
* so the full scrollable content inside of ion-content
|
||||
* can be captured in a screenshot.
|
||||
*/
|
||||
page.setIonViewport = async () => {
|
||||
const currentViewport = await page.viewportSize();
|
||||
|
||||
const pixelAmountRenderedOffscreen = await page.evaluate(() => {
|
||||
const content = document.querySelector('ion-content');
|
||||
const innerScroll = content.shadowRoot.querySelector('.inner-scroll');
|
||||
|
||||
return innerScroll.scrollHeight - content.clientHeight;
|
||||
});
|
||||
|
||||
await page.setViewportSize({
|
||||
width: currentViewport.width,
|
||||
height: currentViewport.height + pixelAmountRenderedOffscreen
|
||||
})
|
||||
}
|
||||
|
||||
await use(page);
|
||||
},
|
||||
});
|