feat(ct-react): Support React 18 only (#19814)
BREAKING CHANGE: Drop support for React 17 and earlier Support for React 17 an earlier is provided by `@playwright/experimental-ct-react-17` Closes #19923
This commit is contained in:
Родитель
be259dac7c
Коммит
fbaf56a13f
|
@ -1297,6 +1297,10 @@
|
|||
"resolved": "packages/playwright-ct-react",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@playwright/experimental-ct-react17": {
|
||||
"resolved": "packages/playwright-ct-react17",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@playwright/experimental-ct-solid": {
|
||||
"resolved": "packages/playwright-ct-solid",
|
||||
"link": true
|
||||
|
@ -5990,6 +5994,22 @@
|
|||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"packages/playwright-ct-react17": {
|
||||
"name": "@playwright/experimental-ct-react17",
|
||||
"version": "1.32.0-next",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@playwright/test": "1.32.0-next",
|
||||
"@vitejs/plugin-react": "^3.1.0",
|
||||
"vite": "^4.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"packages/playwright-ct-solid": {
|
||||
"name": "@playwright/experimental-ct-solid",
|
||||
"version": "1.32.0-next",
|
||||
|
@ -6908,6 +6928,14 @@
|
|||
"vite": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"@playwright/experimental-ct-react17": {
|
||||
"version": "file:packages/playwright-ct-react17",
|
||||
"requires": {
|
||||
"@playwright/test": "1.32.0-next",
|
||||
"@vitejs/plugin-react": "^3.1.0",
|
||||
"vite": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"@playwright/experimental-ct-solid": {
|
||||
"version": "file:packages/playwright-ct-solid",
|
||||
"requires": {
|
||||
|
|
|
@ -84,6 +84,8 @@ test('should show the project names', async ({ mount }) => {
|
|||
>
|
||||
</HeaderView>);
|
||||
await expect(component.getByText('Project: my-project')).toBeVisible();
|
||||
|
||||
await component.unmount();
|
||||
});
|
||||
await test.step('with 1 project and empty projectName', async () => {
|
||||
const component = await mount(<HeaderView
|
||||
|
@ -94,6 +96,8 @@ test('should show the project names', async ({ mount }) => {
|
|||
>
|
||||
</HeaderView>);
|
||||
await expect(component.getByText('Project:')).toBeHidden();
|
||||
|
||||
await component.unmount();
|
||||
});
|
||||
await test.step('with more than 1 project', async () => {
|
||||
const component = await mount(<HeaderView
|
||||
|
@ -105,5 +109,7 @@ test('should show the project names', async ({ mount }) => {
|
|||
</HeaderView>);
|
||||
await expect(component.getByText('my-project')).toBeHidden();
|
||||
await expect(component.getByText('great-project')).toBeHidden();
|
||||
|
||||
await component.unmount();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,14 +17,16 @@
|
|||
// @ts-check
|
||||
// This file is injected into the registry as text, no dependencies are allowed.
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import * as React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
/** @typedef {import('../playwright-test/types/component').Component} Component */
|
||||
/** @typedef {import('react').FunctionComponent} FrameworkComponent */
|
||||
|
||||
/** @type {Map<string, FrameworkComponent>} */
|
||||
const registry = new Map();
|
||||
/** @type {Map<Element, import('react-dom/client').Root>>} */
|
||||
const rootRegistry = new Map();
|
||||
|
||||
/**
|
||||
* @param {{[key: string]: FrameworkComponent}} components
|
||||
|
@ -79,17 +81,33 @@ window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
|||
App = () => wrapper;
|
||||
}
|
||||
|
||||
ReactDOM.render(App(), rootElement);
|
||||
if (rootRegistry.has(rootElement)) {
|
||||
throw new Error(
|
||||
'Attempting to mount a component into an container that already has a React root'
|
||||
);
|
||||
}
|
||||
|
||||
const root = createRoot(rootElement);
|
||||
rootRegistry.set(rootElement, root);
|
||||
root.render(App());
|
||||
|
||||
for (const hook of window.__pw_hooks_after_mount || [])
|
||||
await hook({ hooksConfig });
|
||||
};
|
||||
|
||||
window.playwrightUnmount = async rootElement => {
|
||||
if (!ReactDOM.unmountComponentAtNode(rootElement))
|
||||
const root = rootRegistry.get(rootElement);
|
||||
if (root === undefined)
|
||||
throw new Error('Component was not mounted');
|
||||
|
||||
root.unmount();
|
||||
rootRegistry.delete(rootElement);
|
||||
};
|
||||
|
||||
window.playwrightUpdate = async (rootElement, component) => {
|
||||
ReactDOM.render(render(/** @type {Component} */(component)), rootElement);
|
||||
const root = rootRegistry.get(rootElement);
|
||||
if (root === undefined)
|
||||
throw new Error('Component was not mounted');
|
||||
|
||||
root.render(render(/** @type {Component} */ (component)));
|
||||
};
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
**/*
|
||||
|
||||
!README.md
|
||||
!LICENSE
|
||||
!cli.js
|
||||
!register.d.ts
|
||||
!register.mjs
|
||||
!registerSource.mjs
|
||||
!index.d.ts
|
||||
!index.js
|
||||
!hooks.d.ts
|
||||
!hooks.mjs
|
|
@ -0,0 +1,3 @@
|
|||
> **BEWARE** This package is EXPERIMENTAL and does not respect semver.
|
||||
|
||||
Read more at https://playwright.dev/docs/test-components
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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 = require('playwright-core/cli');
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
type JsonPrimitive = string | number | boolean | null;
|
||||
type JsonValue = JsonPrimitive | JsonObject | JsonArray;
|
||||
type JsonArray = JsonValue[];
|
||||
type JsonObject = { [Key in string]?: JsonValue };
|
||||
export declare function beforeMount<HooksConfig extends JsonObject>(
|
||||
callback: (params: { hooksConfig: HooksConfig; App: () => JSX.Element }) => Promise<void | JSX.Element>
|
||||
): void;
|
||||
export declare function afterMount<HooksConfig extends JsonObject>(
|
||||
callback: (params: { hooksConfig: HooksConfig }) => Promise<void>
|
||||
): void;
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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 __pw_hooks_before_mount = [];
|
||||
const __pw_hooks_after_mount = [];
|
||||
|
||||
window.__pw_hooks_before_mount = __pw_hooks_before_mount;
|
||||
window.__pw_hooks_after_mount = __pw_hooks_after_mount;
|
||||
|
||||
export const beforeMount = callback => {
|
||||
__pw_hooks_before_mount.push(callback);
|
||||
};
|
||||
|
||||
export const afterMount = callback => {
|
||||
__pw_hooks_after_mount.push(callback);
|
||||
};
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import type {
|
||||
TestType,
|
||||
PlaywrightTestArgs,
|
||||
PlaywrightTestConfig as BasePlaywrightTestConfig,
|
||||
PlaywrightTestOptions,
|
||||
PlaywrightWorkerArgs,
|
||||
PlaywrightWorkerOptions,
|
||||
Locator,
|
||||
} from '@playwright/test';
|
||||
import type { InlineConfig } from 'vite';
|
||||
|
||||
export type PlaywrightTestConfig<T = {}, W = {}> = Omit<BasePlaywrightTestConfig<T, W>, 'use'> & {
|
||||
use?: BasePlaywrightTestConfig<T, W>['use'] & {
|
||||
ctPort?: number;
|
||||
ctTemplateDir?: string;
|
||||
ctCacheDir?: string;
|
||||
ctViteConfig?: InlineConfig | (() => Promise<InlineConfig>);
|
||||
};
|
||||
};
|
||||
|
||||
type JsonPrimitive = string | number | boolean | null;
|
||||
type JsonValue = JsonPrimitive | JsonObject | JsonArray;
|
||||
type JsonArray = JsonValue[];
|
||||
type JsonObject = { [Key in string]?: JsonValue };
|
||||
|
||||
export interface MountOptions<HooksConfig extends JsonObject> {
|
||||
hooksConfig?: HooksConfig;
|
||||
}
|
||||
|
||||
interface MountResult extends Locator {
|
||||
unmount(): Promise<void>;
|
||||
update(component: JSX.Element): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ComponentFixtures {
|
||||
mount<HooksConfig extends JsonObject>(
|
||||
component: JSX.Element,
|
||||
options?: MountOptions<HooksConfig>
|
||||
): Promise<MountResult>;
|
||||
}
|
||||
|
||||
export const test: TestType<
|
||||
PlaywrightTestArgs & PlaywrightTestOptions & ComponentFixtures,
|
||||
PlaywrightWorkerArgs & PlaywrightWorkerOptions
|
||||
>;
|
||||
|
||||
/**
|
||||
* Defines Playwright config
|
||||
*/
|
||||
export function defineConfig(config: PlaywrightTestConfig): PlaywrightTestConfig;
|
||||
export function defineConfig<T>(config: PlaywrightTestConfig<T>): PlaywrightTestConfig<T>;
|
||||
export function defineConfig<T, W>(config: PlaywrightTestConfig<T, W>): PlaywrightTestConfig<T, W>;
|
||||
|
||||
export { expect, devices } from '@playwright/test';
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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 { test: baseTest, expect, devices, defineConfig: originalDefineConfig } = require('@playwright/test');
|
||||
const { fixtures } = require('@playwright/test/lib/mount');
|
||||
const path = require('path');
|
||||
|
||||
const plugin = () => {
|
||||
// Only fetch upon request to avoid resolution in workers.
|
||||
const { createPlugin } = require('@playwright/test/lib/plugins/vitePlugin');
|
||||
return createPlugin(
|
||||
path.join(__dirname, 'registerSource.mjs'),
|
||||
() => import('@vitejs/plugin-react').then(plugin => plugin.default()));
|
||||
};
|
||||
const defineConfig = config => originalDefineConfig({ ...config, _plugins: [plugin] });
|
||||
const test = baseTest.extend(fixtures);
|
||||
|
||||
module.exports = { test, expect, devices, defineConfig };
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "@playwright/experimental-ct-react17",
|
||||
"version": "1.32.0-next",
|
||||
"description": "Playwright Component Testing for React",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./index.d.ts",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./register": {
|
||||
"types": "./register.d.ts",
|
||||
"default": "./register.mjs"
|
||||
},
|
||||
"./hooks": {
|
||||
"types": "./hooks.d.ts",
|
||||
"default": "./hooks.mjs"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@vitejs/plugin-react": "^3.1.0",
|
||||
"@playwright/test": "1.32.0-next",
|
||||
"vite": "^4.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "./cli.js"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export default function register(
|
||||
components: { [key: string]: any },
|
||||
): void
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { register } from './registerSource.mjs';
|
||||
|
||||
export default components => {
|
||||
register(components);
|
||||
};
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
// This file is injected into the registry as text, no dependencies are allowed.
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
/** @typedef {import('../playwright-test/types/component').Component} Component */
|
||||
/** @typedef {import('react').FunctionComponent} FrameworkComponent */
|
||||
|
||||
/** @type {Map<string, FrameworkComponent>} */
|
||||
const registry = new Map();
|
||||
|
||||
/**
|
||||
* @param {{[key: string]: FrameworkComponent}} components
|
||||
*/
|
||||
export function register(components) {
|
||||
for (const [name, value] of Object.entries(components))
|
||||
registry.set(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Component} component
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
function render(component) {
|
||||
let componentFunc = registry.get(component.type);
|
||||
if (!componentFunc) {
|
||||
// Lookup by shorthand.
|
||||
for (const [name, value] of registry) {
|
||||
if (component.type.endsWith(`_${name}`)) {
|
||||
componentFunc = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!componentFunc && component.type[0].toUpperCase() === component.type[0])
|
||||
throw new Error(`Unregistered component: ${component.type}. Following components are registered: ${[...registry.keys()]}`);
|
||||
|
||||
const componentFuncOrString = componentFunc || component.type;
|
||||
|
||||
if (component.kind !== 'jsx')
|
||||
throw new Error('Object mount notation is not supported');
|
||||
|
||||
return React.createElement(componentFuncOrString, component.props, ...component.children.map(child => {
|
||||
if (typeof child === 'string')
|
||||
return child;
|
||||
return render(child);
|
||||
}).filter(child => {
|
||||
if (typeof child === 'string')
|
||||
return !!child.trim();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
||||
let App = () => render(component);
|
||||
for (const hook of window.__pw_hooks_before_mount || []) {
|
||||
const wrapper = await hook({ App, hooksConfig });
|
||||
if (wrapper)
|
||||
App = () => wrapper;
|
||||
}
|
||||
|
||||
ReactDOM.render(App(), rootElement);
|
||||
|
||||
for (const hook of window.__pw_hooks_after_mount || [])
|
||||
await hook({ hooksConfig });
|
||||
};
|
||||
|
||||
window.playwrightUnmount = async rootElement => {
|
||||
if (!ReactDOM.unmountComponentAtNode(rootElement))
|
||||
throw new Error('Component was not mounted');
|
||||
};
|
||||
|
||||
window.playwrightUpdate = async (rootElement, component) => {
|
||||
ReactDOM.render(render(/** @type {Component} */(component)), rootElement);
|
||||
};
|
|
@ -9,19 +9,19 @@
|
|||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-router-dom": "^6.4.2"
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^17.0.33",
|
||||
"@types/react-dom": "^17.0.10",
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.10",
|
||||
"@vitejs/plugin-react": "^3.0.0",
|
||||
"typescript": "^4.5.4",
|
||||
"vite": "^4.1.1"
|
||||
},
|
||||
"@standaloneDevDependencies": {
|
||||
"@playwright/experimental-ct-react": "^1.22.2",
|
||||
"@playwright/experimental-ct-react": "^1.22.0",
|
||||
"@playwright/test": "^1.22.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useRef } from "react"
|
||||
import { useLayoutEffect, useRef, useState } from "react"
|
||||
|
||||
type CounterProps = {
|
||||
count?: number;
|
||||
|
@ -9,11 +9,17 @@ import { useRef } from "react"
|
|||
let _remountCount = 1;
|
||||
|
||||
export default function Counter(props: CounterProps) {
|
||||
const remountCount = useRef(_remountCount++);
|
||||
const [remountCount] = useState(_remountCount);
|
||||
const didMountRef = useRef(false)
|
||||
useLayoutEffect(() => {
|
||||
if (!didMountRef.current) {
|
||||
didMountRef.current = true;
|
||||
_remountCount++;
|
||||
}
|
||||
}, [])
|
||||
return <div onClick={() => props.onClick?.('hello')}>
|
||||
<div id="props">{ props.count }</div>
|
||||
<div id="remount-count">{ remountCount.current }</div>
|
||||
<div id="remount-count">{ remountCount }</div>
|
||||
{ props.children }
|
||||
</div>
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import * as React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import App from './App';
|
||||
import './assets/index.css';
|
||||
|
||||
ReactDOM.render(
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter><App /></BrowserRouter>
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
)
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
|
|
@ -3,19 +3,19 @@
|
|||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-router-dom": "^6.4.2"
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.26",
|
||||
"@types/react": "^17.0.39",
|
||||
"@types/react-dom": "^17.0.13",
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.10",
|
||||
"react-scripts": "5.0.0",
|
||||
"typescript": "^4.6.2"
|
||||
},
|
||||
"@standaloneDevDependencies": {
|
||||
"@playwright/experimental-ct-react": "^1.22.2",
|
||||
"@playwright/experimental-ct-react": "^1.2.2",
|
||||
"@playwright/test": "^1.22.2"
|
||||
},
|
||||
"scripts": {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useRef } from "react"
|
||||
import { useLayoutEffect, useRef, useState } from "react"
|
||||
|
||||
type CounterProps = {
|
||||
count?: number;
|
||||
|
@ -9,11 +9,17 @@ import { useRef } from "react"
|
|||
let _remountCount = 1;
|
||||
|
||||
export default function Counter(props: CounterProps) {
|
||||
const remountCount = useRef(_remountCount++);
|
||||
const [remountCount] = useState(_remountCount);
|
||||
const didMountRef = useRef(false)
|
||||
useLayoutEffect(() => {
|
||||
if (!didMountRef.current) {
|
||||
didMountRef.current = true;
|
||||
_remountCount++;
|
||||
}
|
||||
}, [])
|
||||
return <div onClick={() => props.onClick?.('hello')}>
|
||||
<div id="props">{ props.count }</div>
|
||||
<div id="remount-count">{ remountCount.current }</div>
|
||||
<div id="remount-count">{ remountCount }</div>
|
||||
{ props.children }
|
||||
</div>
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import * as React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import App from './App';
|
||||
import './assets/index.css';
|
||||
|
||||
ReactDOM.render(
|
||||
createRoot(document.getElementById("root")).render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter><App /></BrowserRouter>
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
|
|
@ -45,7 +45,7 @@ test('should work with the empty component list', async ({ runInlineTest }, test
|
|||
expect(metainfo.version).toEqual(require('playwright-core/package.json').version);
|
||||
expect(metainfo.viteVersion).toEqual(require('vite/package.json').version);
|
||||
expect(Object.entries(metainfo.tests)).toHaveLength(1);
|
||||
expect(Object.entries(metainfo.sources)).toHaveLength(8);
|
||||
expect(Object.entries(metainfo.sources)).toHaveLength(9);
|
||||
});
|
||||
|
||||
test('should extract component list', async ({ runInlineTest }, testInfo) => {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
"packages/*/lib",
|
||||
"packages/html-reporter",
|
||||
"packages/playwright-ct-react",
|
||||
"packages/playwright-ct-react17",
|
||||
"packages/playwright-ct-solid",
|
||||
"packages/playwright-ct-svelte",
|
||||
"packages/playwright-ct-vue",
|
||||
|
|
|
@ -178,6 +178,11 @@ const workspace = new Workspace(ROOT_PATH, [
|
|||
path: path.join(ROOT_PATH, 'packages', 'playwright-ct-react'),
|
||||
files: ['LICENSE'],
|
||||
}),
|
||||
new PWPackage({
|
||||
name: '@playwright/experimental-ct-react17',
|
||||
path: path.join(ROOT_PATH, 'packages', 'playwright-ct-react17'),
|
||||
files: ['LICENSE'],
|
||||
}),
|
||||
new PWPackage({
|
||||
name: '@playwright/experimental-ct-solid',
|
||||
path: path.join(ROOT_PATH, 'packages', 'playwright-ct-solid'),
|
||||
|
|
Загрузка…
Ссылка в новой задаче