@gravity-ui/playwright-tools 1.1.1 → 1.1.3
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/component-tests/fixtures/mount/mount-fixture.d.ts +13 -0
- package/component-tests/fixtures/mount/mount-fixture.js +17 -10
- package/component-tests/fixtures/mount/mount-wrapper.d.ts +29 -0
- package/component-tests/fixtures/mount/mount-wrapper.js +66 -0
- package/fixtures/mock-network/mock-network-fixture.js +2 -2
- package/har/index.d.ts +1 -0
- package/har/initDumps.d.ts +2 -1
- package/har/initDumps.js +2 -0
- package/package.json +2 -4
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
import type { PlaywrightTestArgs, PlaywrightTestOptions, TestFixture } from '@playwright/test';
|
|
2
2
|
import type { MountFn, MountTestArgs } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Enhanced mount fixture that wraps components with styling and layout controls.
|
|
5
|
+
*
|
|
6
|
+
* This fixture intercepts the base mount function to:
|
|
7
|
+
* 1. Always wrap components in a div with TEST_WRAPPER_CLASS for screenshot targeting
|
|
8
|
+
* 2. Apply padding and fit-content sizing for better visual testing
|
|
9
|
+
* 3. Disable CSS transform animations that can cause flaky screenshots
|
|
10
|
+
* 4. Support custom width and rootStyle options
|
|
11
|
+
*
|
|
12
|
+
* The wrapper is inlined using string element types ('div', 'style') because
|
|
13
|
+
* Playwright blocks function components defined in test context. See mount-wrapper.ts
|
|
14
|
+
* for more details on this restriction.
|
|
15
|
+
*/
|
|
3
16
|
export declare const mountFixture: TestFixture<MountFn, PlaywrightTestArgs & PlaywrightTestOptions & MountTestArgs>;
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.mountFixture = void 0;
|
|
4
|
-
const
|
|
5
|
-
|
|
4
|
+
const mount_wrapper_1 = require("./mount-wrapper");
|
|
5
|
+
/**
|
|
6
|
+
* Enhanced mount fixture that wraps components with styling and layout controls.
|
|
7
|
+
*
|
|
8
|
+
* This fixture intercepts the base mount function to:
|
|
9
|
+
* 1. Always wrap components in a div with TEST_WRAPPER_CLASS for screenshot targeting
|
|
10
|
+
* 2. Apply padding and fit-content sizing for better visual testing
|
|
11
|
+
* 3. Disable CSS transform animations that can cause flaky screenshots
|
|
12
|
+
* 4. Support custom width and rootStyle options
|
|
13
|
+
*
|
|
14
|
+
* The wrapper is inlined using string element types ('div', 'style') because
|
|
15
|
+
* Playwright blocks function components defined in test context. See mount-wrapper.ts
|
|
16
|
+
* for more details on this restriction.
|
|
17
|
+
*/
|
|
6
18
|
const mountFixture = async ({ mount: baseMount }, use) => {
|
|
7
19
|
const mount = async (component, options) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
boxSizing: options?.width ? 'content-box' : undefined,
|
|
12
|
-
width: options?.width ? options.width : 'fit-content',
|
|
13
|
-
height: 'fit-content',
|
|
14
|
-
...options?.rootStyle,
|
|
15
|
-
}, className: constants_1.TEST_WRAPPER_CLASS, children: [(0, jsx_runtime_1.jsx)("style", { children: '.g-button, .g-button::after { transform: scale(1) !important; }' }), component] }), options);
|
|
20
|
+
const { width, rootStyle, ...baseMountOptions } = options || {};
|
|
21
|
+
const wrapper = (0, mount_wrapper_1.createComponentWrapper)(component, { width, rootStyle });
|
|
22
|
+
return await baseMount(wrapper, baseMountOptions);
|
|
16
23
|
};
|
|
17
24
|
await use(mount);
|
|
18
25
|
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type * as React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Playwright JSX object structure that mimics Playwright's jsx-runtime output.
|
|
4
|
+
* This is the internal structure Playwright expects when mounting components.
|
|
5
|
+
*/
|
|
6
|
+
type PlaywrightJsxObject<T extends keyof React.JSX.IntrinsicElements> = {
|
|
7
|
+
__pw_type: 'jsx';
|
|
8
|
+
type: T;
|
|
9
|
+
props: React.JSX.IntrinsicElements[T];
|
|
10
|
+
key: string | null;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Creates a wrapper around a component with styling and animation controls.
|
|
14
|
+
*
|
|
15
|
+
* This wrapper:
|
|
16
|
+
* 1. Wraps component in a div with TEST_WRAPPER_CLASS for screenshot targeting
|
|
17
|
+
* 2. Applies padding and fit-content sizing for better visual testing
|
|
18
|
+
* 3. Injects global styles to disable CSS transform animations
|
|
19
|
+
* 4. Supports custom width and rootStyle options
|
|
20
|
+
*
|
|
21
|
+
* The wrapper uses only string element types ('div', 'style') because
|
|
22
|
+
* Playwright blocks function components defined in test context.
|
|
23
|
+
* See createPlaywrightJsxObject documentation for details.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createComponentWrapper(component: React.JSX.Element, options?: {
|
|
26
|
+
width?: number | string;
|
|
27
|
+
rootStyle?: React.CSSProperties;
|
|
28
|
+
}): PlaywrightJsxObject<"div">;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createComponentWrapper = createComponentWrapper;
|
|
4
|
+
const constants_1 = require("./constants");
|
|
5
|
+
/**
|
|
6
|
+
* Creates a Playwright JSX object representation.
|
|
7
|
+
*
|
|
8
|
+
* Playwright expects JSX components in a special format with __pw_type: 'jsx'.
|
|
9
|
+
* This mimics what Playwright's jsx-runtime creates when you write JSX in test files.
|
|
10
|
+
*
|
|
11
|
+
* IMPORTANT: The `type` parameter MUST be either:
|
|
12
|
+
* - A string (HTML element name like 'div', 'span', 'style')
|
|
13
|
+
* - An import reference resolved by Playwright's import registry
|
|
14
|
+
*
|
|
15
|
+
* Function references are explicitly blocked by Playwright's serializers.js:
|
|
16
|
+
* "if (value?.__pw_type === 'jsx' && typeof value.type === 'function')"
|
|
17
|
+
* This prevents components defined in test context from being mounted.
|
|
18
|
+
*
|
|
19
|
+
* That's why we use only string types (like 'div', 'style')
|
|
20
|
+
* instead of function component references.
|
|
21
|
+
*
|
|
22
|
+
* @template T - The HTML element type (e.g., 'div', 'span', 'style')
|
|
23
|
+
* @param type - HTML element name
|
|
24
|
+
* @param props - Props for the HTML element
|
|
25
|
+
* @returns A Playwright JSX object compatible with React.JSX.Element
|
|
26
|
+
*/
|
|
27
|
+
function createPlaywrightJsxObject(type, props) {
|
|
28
|
+
return {
|
|
29
|
+
__pw_type: 'jsx',
|
|
30
|
+
type,
|
|
31
|
+
props,
|
|
32
|
+
key: null, // Must be null (not undefined) to match React.JSX.Element type
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a wrapper around a component with styling and animation controls.
|
|
37
|
+
*
|
|
38
|
+
* This wrapper:
|
|
39
|
+
* 1. Wraps component in a div with TEST_WRAPPER_CLASS for screenshot targeting
|
|
40
|
+
* 2. Applies padding and fit-content sizing for better visual testing
|
|
41
|
+
* 3. Injects global styles to disable CSS transform animations
|
|
42
|
+
* 4. Supports custom width and rootStyle options
|
|
43
|
+
*
|
|
44
|
+
* The wrapper uses only string element types ('div', 'style') because
|
|
45
|
+
* Playwright blocks function components defined in test context.
|
|
46
|
+
* See createPlaywrightJsxObject documentation for details.
|
|
47
|
+
*/
|
|
48
|
+
function createComponentWrapper(component, options) {
|
|
49
|
+
const { width, rootStyle } = options || {};
|
|
50
|
+
const styleElement = createPlaywrightJsxObject('style', {
|
|
51
|
+
children: '.g-button, .g-button::after { transform: scale(1) !important; }',
|
|
52
|
+
});
|
|
53
|
+
const wrapper = createPlaywrightJsxObject('div', {
|
|
54
|
+
style: {
|
|
55
|
+
padding: 20,
|
|
56
|
+
// When width is set, padding should not affect total width
|
|
57
|
+
boxSizing: width ? 'content-box' : undefined,
|
|
58
|
+
width: width ? width : 'fit-content',
|
|
59
|
+
height: 'fit-content',
|
|
60
|
+
...rootStyle,
|
|
61
|
+
},
|
|
62
|
+
className: constants_1.TEST_WRAPPER_CLASS,
|
|
63
|
+
children: [styleElement, component],
|
|
64
|
+
});
|
|
65
|
+
return wrapper;
|
|
66
|
+
}
|
|
@@ -14,7 +14,7 @@ const fixtureFunction = async ({ baseURL: rawBaseURL, page, }, { shouldUpdate, f
|
|
|
14
14
|
});
|
|
15
15
|
const update = Boolean(shouldUpdate);
|
|
16
16
|
const url = urlMatcherBuilder(baseURL);
|
|
17
|
-
await (0, har_1.initDumps)(page, testInfo, {
|
|
17
|
+
const finalUpdate = await (0, har_1.initDumps)(page, testInfo, {
|
|
18
18
|
dumpsFilePath,
|
|
19
19
|
forceUpdateIfHarMissing,
|
|
20
20
|
updateTimeout,
|
|
@@ -22,7 +22,7 @@ const fixtureFunction = async ({ baseURL: rawBaseURL, page, }, { shouldUpdate, f
|
|
|
22
22
|
url,
|
|
23
23
|
zip,
|
|
24
24
|
});
|
|
25
|
-
await use(!
|
|
25
|
+
await use(!finalUpdate);
|
|
26
26
|
};
|
|
27
27
|
function mockNetworkFixtureBuilder({ shouldUpdate, forceUpdateIfHarMissing, updateTimeout, zip = true, url, dumpsFilePath, optionallyEnabled, ...harPatcherParams }) {
|
|
28
28
|
const mockNetworkFixture = async ({ baseURL, page }, use, testInfo) => {
|
package/har/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { addHarRecorderTransform } from './addHarRecorderTransform';
|
|
|
7
7
|
export type { FlushTransformFunction } from './addFlushTransform';
|
|
8
8
|
export { addFlushTransform } from './addFlushTransform';
|
|
9
9
|
export { clearHeaders } from './clearHeaders';
|
|
10
|
+
export type { InitDumpsOptions } from './initDumps';
|
|
10
11
|
export { initDumps } from './initDumps';
|
|
11
12
|
export { replaceBaseUrlInEntry } from './replaceBaseUrlInEntry';
|
|
12
13
|
export { setExtraHash } from './setExtraHash';
|
package/har/initDumps.d.ts
CHANGED
|
@@ -49,5 +49,6 @@ export type InitDumpsOptions = {
|
|
|
49
49
|
};
|
|
50
50
|
/**
|
|
51
51
|
* Makes the necessary preparations for saving query dumps
|
|
52
|
+
* @returns boolean - true if update mode is active, false if mock mode is active
|
|
52
53
|
*/
|
|
53
|
-
export declare function initDumps(page: Page, testInfo: TestInfo, { dumpsFilePath: dumpsFilePathBuilder, rootPath, forceUpdateIfHarMissing, updateTimeout, notFound, url, zip, update, }?: InitDumpsOptions): Promise<
|
|
54
|
+
export declare function initDumps(page: Page, testInfo: TestInfo, { dumpsFilePath: dumpsFilePathBuilder, rootPath, forceUpdateIfHarMissing, updateTimeout, notFound, url, zip, update, }?: InitDumpsOptions): Promise<boolean>;
|
package/har/initDumps.js
CHANGED
|
@@ -6,6 +6,7 @@ const node_path_1 = require("node:path");
|
|
|
6
6
|
const dumpsFilePathBulders_1 = require("./dumpsFilePathBulders");
|
|
7
7
|
/**
|
|
8
8
|
* Makes the necessary preparations for saving query dumps
|
|
9
|
+
* @returns boolean - true if update mode is active, false if mock mode is active
|
|
9
10
|
*/
|
|
10
11
|
async function initDumps(page, testInfo, { dumpsFilePath: dumpsFilePathBuilder = dumpsFilePathBulders_1.defaultDumpsFilePathBuilder, rootPath, forceUpdateIfHarMissing = false, updateTimeout, notFound = 'abort', url, zip = true, update = false, } = {}) {
|
|
11
12
|
let harPath;
|
|
@@ -32,4 +33,5 @@ async function initDumps(page, testInfo, { dumpsFilePath: dumpsFilePathBuilder =
|
|
|
32
33
|
notFound,
|
|
33
34
|
url,
|
|
34
35
|
});
|
|
36
|
+
return update;
|
|
35
37
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravity-ui/playwright-tools",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Tools for Playwright Test",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"playwright",
|
|
@@ -100,9 +100,7 @@
|
|
|
100
100
|
},
|
|
101
101
|
"peerDependencies": {
|
|
102
102
|
"@playwright/experimental-ct-react": "^1.22",
|
|
103
|
-
"@playwright/test": "^1.22"
|
|
104
|
-
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
105
|
-
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
103
|
+
"@playwright/test": "^1.22"
|
|
106
104
|
},
|
|
107
105
|
"engines": {
|
|
108
106
|
"node": ">=20"
|