@stencil/playwright 0.0.0-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +27 -0
- package/README.md +175 -0
- package/dist/create-config.d.ts +29 -0
- package/dist/index.cjs +7076 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7055 -0
- package/dist/index.js.map +7 -0
- package/dist/load-config-meta.d.ts +13 -0
- package/dist/matchers/index.d.ts +12 -0
- package/dist/matchers/to-have-first-received-event-detail.d.ts +5 -0
- package/dist/matchers/to-have-nth-received-event-detail.d.ts +5 -0
- package/dist/matchers/to-have-received-event-detail.d.ts +5 -0
- package/dist/matchers/to-have-received-event-times.d.ts +5 -0
- package/dist/matchers/to-have-received-event.d.ts +5 -0
- package/dist/page/event-spy.d.ts +44 -0
- package/dist/page/utils/goto.d.ts +12 -0
- package/dist/page/utils/index.d.ts +5 -0
- package/dist/page/utils/locator.d.ts +21 -0
- package/dist/page/utils/set-content.d.ts +14 -0
- package/dist/page/utils/spy-on-event.d.ts +3 -0
- package/dist/page/utils/wait-for-changes.d.ts +11 -0
- package/dist/playwright-declarations.d.ts +105 -0
- package/dist/playwright-page.d.ts +8 -0
- package/dist/process-constants.d.ts +4 -0
- package/dist/test-expect.d.ts +22 -0
- package/package.json +76 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* For internal use only.
|
|
3
|
+
*
|
|
4
|
+
* Loads and validates the project's Stencil config.
|
|
5
|
+
*
|
|
6
|
+
* @returns The processed Stencil config metadata.
|
|
7
|
+
*/
|
|
8
|
+
export declare const loadConfigMeta: () => Promise<{
|
|
9
|
+
baseURL: string;
|
|
10
|
+
webServerUrl: string;
|
|
11
|
+
stencilNamespace: string;
|
|
12
|
+
stencilEntryPath: string;
|
|
13
|
+
}>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { toHaveFirstReceivedEventDetail } from './to-have-first-received-event-detail';
|
|
2
|
+
import { toHaveNthReceivedEventDetail } from './to-have-nth-received-event-detail';
|
|
3
|
+
import { toHaveReceivedEvent } from './to-have-received-event';
|
|
4
|
+
import { toHaveReceivedEventDetail } from './to-have-received-event-detail';
|
|
5
|
+
import { toHaveReceivedEventTimes } from './to-have-received-event-times';
|
|
6
|
+
export declare const matchers: {
|
|
7
|
+
toHaveReceivedEvent: typeof toHaveReceivedEvent;
|
|
8
|
+
toHaveReceivedEventDetail: typeof toHaveReceivedEventDetail;
|
|
9
|
+
toHaveReceivedEventTimes: typeof toHaveReceivedEventTimes;
|
|
10
|
+
toHaveFirstReceivedEventDetail: typeof toHaveFirstReceivedEventDetail;
|
|
11
|
+
toHaveNthReceivedEventDetail: typeof toHaveNthReceivedEventDetail;
|
|
12
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { JSHandle } from '@playwright/test';
|
|
2
|
+
import type { E2EPage } from '../playwright-declarations';
|
|
3
|
+
/**
|
|
4
|
+
* The EventSpy class allows developers to listen for a particular event emission and
|
|
5
|
+
* pass/fail the test based on whether or not the event was emitted.
|
|
6
|
+
* Based off https://github.com/ionic-team/stencil/blob/16b8ea4dabb22024872a38bc58ba1dcf1c7cc25b/src/testing/puppeteer/puppeteer-events.ts#L64
|
|
7
|
+
*/
|
|
8
|
+
export declare class EventSpy {
|
|
9
|
+
eventName: string;
|
|
10
|
+
/**
|
|
11
|
+
* Keeping track of a cursor ensures that no two spy.next() calls point to the same event.
|
|
12
|
+
*/
|
|
13
|
+
private cursor;
|
|
14
|
+
private queuedHandler;
|
|
15
|
+
events: CustomEvent[];
|
|
16
|
+
constructor(eventName: string);
|
|
17
|
+
get length(): number;
|
|
18
|
+
get firstEvent(): CustomEvent<any>;
|
|
19
|
+
get lastEvent(): CustomEvent<any>;
|
|
20
|
+
next(): Promise<CustomEvent<any>>;
|
|
21
|
+
push(ev: CustomEvent): void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* For internal use only.
|
|
25
|
+
*
|
|
26
|
+
* Initializes information required to spy on events.
|
|
27
|
+
* The stencilOnEvent function is called in the context of the current page.
|
|
28
|
+
* This lets us respond to an event listener created within the page itself.
|
|
29
|
+
*
|
|
30
|
+
* @param page The Playwright test page object.
|
|
31
|
+
*/
|
|
32
|
+
export declare const initPageEvents: (page: E2EPage) => Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* For internal use only.
|
|
35
|
+
*
|
|
36
|
+
* Adds a new event listener in the current page context to updates
|
|
37
|
+
* the _e2eEvents map when an event is fired.
|
|
38
|
+
*
|
|
39
|
+
* @param page The Playwright test page object.
|
|
40
|
+
* @param elmHandle A {@link JSHandle} representing the element to listen for events on.
|
|
41
|
+
* @param eventName The event name to listen for.
|
|
42
|
+
* @param callback The callback to execute when the event is fired.
|
|
43
|
+
*/
|
|
44
|
+
export declare const addE2EListener: (page: E2EPage, elmHandle: JSHandle, eventName: string, callback: (ev: any) => void) => Promise<void>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Page } from '@playwright/test';
|
|
2
|
+
import type { E2EPageOptions } from '../../playwright-declarations';
|
|
3
|
+
/**
|
|
4
|
+
* This is an extended version of Playwright's `page.goto` method. In addition to performing
|
|
5
|
+
* the normal `page.goto` work, this code also automatically waits for the Stencil components
|
|
6
|
+
* to be hydrated before proceeding with the test.
|
|
7
|
+
*/
|
|
8
|
+
export declare const goto: (page: Page, url: string, originalFn: (url: string, options?: {
|
|
9
|
+
referer?: string | undefined;
|
|
10
|
+
timeout?: number | undefined;
|
|
11
|
+
waitUntil?: "load" | "domcontentloaded" | "networkidle" | "commit" | undefined;
|
|
12
|
+
} | undefined) => Promise<import("playwright-core").Response | null>, options?: E2EPageOptions) => Promise<import("playwright-core").Response | null>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Locator } from '@playwright/test';
|
|
2
|
+
import type { E2EPage } from '../../playwright-declarations';
|
|
3
|
+
import { EventSpy } from '../event-spy';
|
|
4
|
+
export type LocatorOptions = {
|
|
5
|
+
hasText?: string | RegExp;
|
|
6
|
+
has?: Locator;
|
|
7
|
+
};
|
|
8
|
+
export interface E2ELocator extends Locator {
|
|
9
|
+
/**
|
|
10
|
+
* Creates a new EventSpy and listens on the element for an event.
|
|
11
|
+
* The test will timeout if the event never fires.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* const input = page.locator('ion-input');
|
|
15
|
+
* const ionChange = await locator.spyOnEvent('ionChange');
|
|
16
|
+
* ...
|
|
17
|
+
* await ionChange.next();
|
|
18
|
+
*/
|
|
19
|
+
spyOnEvent: (eventName: string) => Promise<EventSpy>;
|
|
20
|
+
}
|
|
21
|
+
export declare const locator: (page: E2EPage, originalFn: (selector: string, options?: LocatorOptions | undefined) => E2ELocator, selector: string, options?: LocatorOptions) => E2ELocator;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Page, TestInfo } from '@playwright/test';
|
|
2
|
+
import type { E2EPageOptions } from '../../playwright-declarations';
|
|
3
|
+
/**
|
|
4
|
+
* Overwrites the default Playwright page.setContent method.
|
|
5
|
+
*
|
|
6
|
+
* Navigates to a blank page, sets the content, and waits for the
|
|
7
|
+
* Stencil components to be hydrated before proceeding with the test.
|
|
8
|
+
*
|
|
9
|
+
* @param page The Playwright page object.
|
|
10
|
+
* @param html The HTML content to set on the page.
|
|
11
|
+
* @param testInfo Test information from the test bed. Used to access base URL.
|
|
12
|
+
* @param options The test config associated with the current test run.
|
|
13
|
+
*/
|
|
14
|
+
export declare const setContent: (page: Page, html: string, testInfo: TestInfo, options?: E2EPageOptions) => Promise<void>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Page } from '@playwright/test';
|
|
2
|
+
/**
|
|
3
|
+
* Waits for a combined threshold of a Stencil web component to be re-hydrated in the next repaint + 100ms.
|
|
4
|
+
* Used for testing changes to a web component that does not modify CSS classes or introduce new DOM nodes.
|
|
5
|
+
*
|
|
6
|
+
* Original source: https://github.com/ionic-team/stencil/blob/main/src/testing/puppeteer/puppeteer-page.ts#L298-L363
|
|
7
|
+
*
|
|
8
|
+
* @param page The Playwright page object.
|
|
9
|
+
* @param timeoutMs The time to wait for the changes to occur.
|
|
10
|
+
*/
|
|
11
|
+
export declare const waitForChanges: (page: Page, timeoutMs?: number) => Promise<void>;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { Page, Response } from '@playwright/test';
|
|
2
|
+
import type { EventSpy } from './page/event-spy';
|
|
3
|
+
import type { E2ELocator, LocatorOptions } from './page/utils/locator';
|
|
4
|
+
export interface E2EPageOptions extends PageOptions {
|
|
5
|
+
}
|
|
6
|
+
interface PageOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Referer header value. If provided it will take preference over the referer header value set by
|
|
9
|
+
* [page.setExtraHTTPHeaders(headers)](https://playwright.dev/docs/api/class-page#page-set-extra-http-headers).
|
|
10
|
+
*/
|
|
11
|
+
referer?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can be
|
|
14
|
+
* changed by using the
|
|
15
|
+
* [browserContext.setDefaultNavigationTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-navigation-timeout),
|
|
16
|
+
* [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout),
|
|
17
|
+
* [page.setDefaultNavigationTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-navigation-timeout)
|
|
18
|
+
* or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods.
|
|
19
|
+
*/
|
|
20
|
+
timeout?: number;
|
|
21
|
+
/**
|
|
22
|
+
* When to consider operation succeeded, defaults to `load`. Events can be either:
|
|
23
|
+
* - `'domcontentloaded'` - consider operation to be finished when the `DOMContentLoaded` event is fired.
|
|
24
|
+
* - `'load'` - consider operation to be finished when the `load` event is fired.
|
|
25
|
+
* - `'networkidle'` - consider operation to be finished when there are no network connections for at least `500` ms.
|
|
26
|
+
* - `'commit'` - consider operation to be finished when network response is received and the document started loading.
|
|
27
|
+
*/
|
|
28
|
+
waitUntil?: 'load' | 'domcontentloaded' | 'networkidle' | 'commit';
|
|
29
|
+
}
|
|
30
|
+
export interface E2EPage extends Page {
|
|
31
|
+
/**
|
|
32
|
+
* Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
|
|
33
|
+
* last redirect.
|
|
34
|
+
*
|
|
35
|
+
* The method will throw an error if:
|
|
36
|
+
* - there's an SSL error (e.g. in case of self-signed certificates).
|
|
37
|
+
* - target URL is invalid.
|
|
38
|
+
* - the `timeout` is exceeded during navigation.
|
|
39
|
+
* - the remote server does not respond or is unreachable.
|
|
40
|
+
* - the main resource failed to load.
|
|
41
|
+
*
|
|
42
|
+
* The method will not throw an error when any valid HTTP status code is returned by the remote server, including 404 "Not
|
|
43
|
+
* Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling
|
|
44
|
+
* [response.status()](https://playwright.dev/docs/api/class-response#response-status).
|
|
45
|
+
*
|
|
46
|
+
* > NOTE: The method either throws an error or returns a main resource response. The only exceptions are navigation to
|
|
47
|
+
* `about:blank` or navigation to the same URL with a different hash, which would succeed and return `null`.
|
|
48
|
+
* > NOTE: Headless mode doesn't support navigation to a PDF document. See the
|
|
49
|
+
* [upstream issue](https://bugs.chromium.org/p/chromium/issues/detail?id=761295).
|
|
50
|
+
*
|
|
51
|
+
* Shortcut for main frame's [frame.goto(url[, options])](https://playwright.dev/docs/api/class-frame#frame-goto)
|
|
52
|
+
* @param url URL to navigate page to. The url should include scheme, e.g. `https://`. When a `baseURL` via the context options was
|
|
53
|
+
* provided and the passed URL is a path, it gets merged via the [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
|
|
54
|
+
*/
|
|
55
|
+
goto: (url: string, options?: E2EPageOptions) => Promise<null | Response>;
|
|
56
|
+
/**
|
|
57
|
+
* Assigns HTML markup to a page.
|
|
58
|
+
* @param html - The HTML markup to assign to the page
|
|
59
|
+
* @param options - Ionic config options or Playwright options for the page
|
|
60
|
+
*/
|
|
61
|
+
setContent: (html: string, options?: E2EPageOptions) => Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Find an element by selector.
|
|
64
|
+
* See https://playwright.dev/docs/locators for more information.
|
|
65
|
+
*/
|
|
66
|
+
locator: (selector: string, options?: LocatorOptions) => E2ELocator;
|
|
67
|
+
/**
|
|
68
|
+
* Increases the size of the page viewport to match the `ion-content` contents.
|
|
69
|
+
* Use this method when taking full-screen screenshots.
|
|
70
|
+
*/
|
|
71
|
+
setIonViewport: (options?: SetIonViewportOptions) => Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* After changes have been made to a component, such as an update to a property or attribute,
|
|
74
|
+
* we need to wait until the changes have been applied to the DOM.
|
|
75
|
+
*/
|
|
76
|
+
waitForChanges: (timeoutMs?: number) => Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Creates a new EventSpy and listens on the window for an event.
|
|
79
|
+
* The test will timeout if the event never fires.
|
|
80
|
+
*
|
|
81
|
+
* Usage:
|
|
82
|
+
* ```ts
|
|
83
|
+
* const ionChange = await page.spyOnEvent('ionChange');
|
|
84
|
+
* ...
|
|
85
|
+
* await ionChange.next();
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
spyOnEvent: (eventName: string) => Promise<EventSpy>;
|
|
89
|
+
_e2eEventsIds: number;
|
|
90
|
+
_e2eEvents: Map<number, any>;
|
|
91
|
+
}
|
|
92
|
+
type BrowserName = 'chromium' | 'firefox' | 'webkit';
|
|
93
|
+
export type BrowserNameOrCallback = BrowserName | ((browserName: BrowserName) => boolean);
|
|
94
|
+
export interface E2ESkip {
|
|
95
|
+
browser: (browserNameOrCallback: BrowserNameOrCallback, reason?: string) => void;
|
|
96
|
+
mode: (mode: string, reason?: string) => void;
|
|
97
|
+
}
|
|
98
|
+
export interface SetIonViewportOptions {
|
|
99
|
+
/**
|
|
100
|
+
* `true` if the viewport should be scaled to match the `ion-content`
|
|
101
|
+
* scrollable width. Defaults to `false`.
|
|
102
|
+
*/
|
|
103
|
+
resizeViewportWidth?: boolean;
|
|
104
|
+
}
|
|
105
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions } from '@playwright/test';
|
|
2
|
+
import type { E2EPage, E2ESkip } from './playwright-declarations';
|
|
3
|
+
type CustomFixtures = {
|
|
4
|
+
page: E2EPage;
|
|
5
|
+
skip: E2ESkip;
|
|
6
|
+
};
|
|
7
|
+
export declare const test: import("@playwright/test").TestType<PlaywrightTestArgs & PlaywrightTestOptions & CustomFixtures, PlaywrightWorkerArgs & PlaywrightWorkerOptions>;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
interface CustomMatchers<R = unknown> {
|
|
2
|
+
/**
|
|
3
|
+
* Will check if the event spy received the expected event.
|
|
4
|
+
*/
|
|
5
|
+
toHaveReceivedEvent(): R;
|
|
6
|
+
/**
|
|
7
|
+
* Will check if the event spy received the expected event with the expected detail.
|
|
8
|
+
* @param eventDetail The expected detail of the event.
|
|
9
|
+
*/
|
|
10
|
+
toHaveReceivedEventDetail(eventDetail: any): R;
|
|
11
|
+
/**
|
|
12
|
+
* Will check how many times the event has been received.
|
|
13
|
+
*/
|
|
14
|
+
toHaveReceivedEventTimes(count: number): R;
|
|
15
|
+
}
|
|
16
|
+
declare global {
|
|
17
|
+
namespace PlaywrightTest {
|
|
18
|
+
interface Matchers<R> extends CustomMatchers<R> {
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stencil/playwright",
|
|
3
|
+
"version": "0.0.0-dev",
|
|
4
|
+
"description": "Testing adapter to use Playwright with Stencil",
|
|
5
|
+
"main": "dist/index.cjs",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "npm run build.empty && npm run build.types && npm run build.bundle",
|
|
13
|
+
"build.empty": "rm -rf ./dist && rm -f ./build/build.js",
|
|
14
|
+
"build.types": "tsc --emitDeclarationOnly --outDir ./dist",
|
|
15
|
+
"build.bundle": "tsc ./build/build.ts && node ./build/build.js",
|
|
16
|
+
"format": "npm run format.base -- --write",
|
|
17
|
+
"format.base": "prettier --cache \"src/**/*.ts\"",
|
|
18
|
+
"format.dry-run": "npm run format.base -- --list-different",
|
|
19
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
20
|
+
"spellcheck": "cspell --no-progress \"src/**/*.ts\" \"build/**/*.ts\" \"*.md\"",
|
|
21
|
+
"test": "jest"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/ionic-team/stencil-playwright.git"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"stencil",
|
|
29
|
+
"playwright",
|
|
30
|
+
"testing"
|
|
31
|
+
],
|
|
32
|
+
"author": "Stencil Team",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/ionic-team/stencil-playwright/issues"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/ionic-team/stencil-playwright#readme",
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=12.0.0",
|
|
40
|
+
"npm": ">=6.0.0"
|
|
41
|
+
},
|
|
42
|
+
"volta": {
|
|
43
|
+
"node": "20.11.1",
|
|
44
|
+
"npm": "10.4.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@playwright/test": ">=1.41.2",
|
|
48
|
+
"@stencil/core": ">=4.13.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@ionic/prettier-config": "^4.0.0",
|
|
52
|
+
"@playwright/test": "^1.41.2",
|
|
53
|
+
"@stencil/core": "^4.13.0",
|
|
54
|
+
"@types/eslint": "^8.56.2",
|
|
55
|
+
"@types/jest": "^29.5.12",
|
|
56
|
+
"@types/node": "^20.11.19",
|
|
57
|
+
"@typescript-eslint/eslint-plugin": "^7.0.2",
|
|
58
|
+
"@typescript-eslint/parser": "^7.0.2",
|
|
59
|
+
"cspell": "^8.6.0",
|
|
60
|
+
"esbuild": "^0.20.1",
|
|
61
|
+
"eslint": "^8.56.0",
|
|
62
|
+
"eslint-config-prettier": "^9.1.0",
|
|
63
|
+
"eslint-plugin-jsdoc": "^48.2.0",
|
|
64
|
+
"eslint-plugin-simple-import-sort": "^12.0.0",
|
|
65
|
+
"eslint-plugin-unused-imports": "^3.1.0",
|
|
66
|
+
"jest": "^29.7.0",
|
|
67
|
+
"prettier": "^3.2.5",
|
|
68
|
+
"ts-jest": "^29.1.2",
|
|
69
|
+
"ts-node": "^10.9.2",
|
|
70
|
+
"typescript": "^5.3.3"
|
|
71
|
+
},
|
|
72
|
+
"prettier": "@ionic/prettier-config",
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"glob": "^10.3.10"
|
|
75
|
+
}
|
|
76
|
+
}
|