chore: remove playwright-ct-vue2 (#33302)
This commit is contained in:
parent
1e8884621a
commit
87b896e597
|
@ -521,7 +521,6 @@ You can use `beforeMount` and `afterMount` hooks to configure your app. This let
|
|||
{label: 'React', value: 'react'},
|
||||
{label: 'Solid', value: 'solid'},
|
||||
{label: 'Vue3', value: 'vue3'},
|
||||
{label: 'Vue2', value: 'vue2'},
|
||||
]
|
||||
}>
|
||||
<TabItem value="react">
|
||||
|
@ -617,40 +616,6 @@ You can use `beforeMount` and `afterMount` hooks to configure your app. This let
|
|||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="vue2">
|
||||
|
||||
```js title="playwright/index.ts"
|
||||
import { beforeMount, afterMount } from '@playwright/experimental-ct-vue2/hooks';
|
||||
import Router from 'vue-router';
|
||||
import { router } from '../src/router';
|
||||
|
||||
export type HooksConfig = {
|
||||
enableRouting?: boolean;
|
||||
}
|
||||
|
||||
beforeMount<HooksConfig>(async ({ app, hooksConfig }) => {
|
||||
if (hooksConfig?.enableRouting) {
|
||||
Vue.use(Router);
|
||||
return { router }
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
```js title="src/pages/ProductsPage.spec.ts"
|
||||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import type { HooksConfig } from '../playwright';
|
||||
import ProductsPage from './pages/ProductsPage.vue';
|
||||
|
||||
test('configure routing through hooks config', async ({ page, mount }) => {
|
||||
const component = await mount<HooksConfig>(ProductsPage, {
|
||||
hooksConfig: { enableRouting: true },
|
||||
});
|
||||
await expect(component.getByRole('link')).toHaveAttribute('href', '/products/42');
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
</Tabs>
|
||||
|
||||
### unmount
|
||||
|
|
|
@ -1508,10 +1508,6 @@
|
|||
"resolved": "packages/playwright-ct-vue",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@playwright/experimental-ct-vue2": {
|
||||
"resolved": "packages/playwright-ct-vue2",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"resolved": "packages/playwright-test",
|
||||
"link": true
|
||||
|
@ -5964,21 +5960,6 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.8.8",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
|
||||
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/progress": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||
|
@ -6593,14 +6574,6 @@
|
|||
"solid-js": "^1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
|
@ -8097,59 +8070,6 @@
|
|||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"packages/playwright-ct-vue2": {
|
||||
"name": "@playwright/experimental-ct-vue2",
|
||||
"version": "1.49.0-next",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.49.0-next",
|
||||
"@vitejs/plugin-vue2": "^2.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vue": "^2.7.14"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"packages/playwright-ct-vue2/node_modules/@vitejs/plugin-vue2": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue2/-/plugin-vue2-2.3.1.tgz",
|
||||
"integrity": "sha512-/ksaaz2SRLN11JQhLdEUhDzOn909WEk99q9t9w+N12GjQCljzv7GyvAbD/p20aBUjHkvpGOoQ+FCOkG+mjDF4A==",
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >= 16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0",
|
||||
"vue": "^2.7.0-0"
|
||||
}
|
||||
},
|
||||
"packages/playwright-ct-vue2/node_modules/@vue/compiler-sfc": {
|
||||
"version": "2.7.16",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz",
|
||||
"integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.5",
|
||||
"postcss": "^8.4.14",
|
||||
"source-map": "^0.6.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"prettier": "^1.18.2 || ^2.0.0"
|
||||
}
|
||||
},
|
||||
"packages/playwright-ct-vue2/node_modules/vue": {
|
||||
"version": "2.7.16",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz",
|
||||
"integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==",
|
||||
"deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.",
|
||||
"dependencies": {
|
||||
"@vue/compiler-sfc": "2.7.16",
|
||||
"csstype": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"packages/playwright-firefox": {
|
||||
"version": "1.49.0-next",
|
||||
"hasInstallScript": true,
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
**/*
|
||||
|
||||
!README.md
|
||||
!LICENSE
|
||||
!cli.js
|
||||
!register.d.ts
|
||||
!register.mjs
|
||||
!registerSource.mjs
|
||||
!index.d.ts
|
||||
!index.js
|
||||
!hooks.d.ts
|
||||
!hooks.mjs
|
|
@ -1,3 +0,0 @@
|
|||
> **BEWARE** This package is EXPERIMENTAL and does not respect semver.
|
||||
|
||||
Read more at https://playwright.dev/docs/test-components
|
|
@ -1,20 +0,0 @@
|
|||
#!/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.
|
||||
*/
|
||||
|
||||
const { program } = require('@playwright/experimental-ct-core/lib/program');
|
||||
|
||||
program.parse(process.argv);
|
|
@ -1,37 +0,0 @@
|
|||
/**
|
||||
* 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 { ComponentOptions } from 'vue';
|
||||
import type { CombinedVueInstance, Vue, VueConstructor } from 'vue/types/vue';
|
||||
|
||||
export declare function beforeMount<HooksConfig>(
|
||||
callback: (params: {
|
||||
hooksConfig?: HooksConfig,
|
||||
Vue: VueConstructor<Vue>,
|
||||
}) => Promise<void | ComponentOptions<Vue> & Record<string, unknown>>
|
||||
): void;
|
||||
export declare function afterMount<HooksConfig>(
|
||||
callback: (params: {
|
||||
hooksConfig?: HooksConfig;
|
||||
instance: CombinedVueInstance<
|
||||
Vue,
|
||||
object,
|
||||
object,
|
||||
object,
|
||||
Record<never, any>
|
||||
>;
|
||||
}) => Promise<void>
|
||||
): void;
|
|
@ -1,29 +0,0 @@
|
|||
/**
|
||||
* 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);
|
||||
};
|
|
@ -1,66 +0,0 @@
|
|||
/**
|
||||
* 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, Locator } from '@playwright/experimental-ct-core';
|
||||
|
||||
type Slot = string | string[];
|
||||
type ComponentSlots = Record<string, Slot> & { default?: Slot };
|
||||
|
||||
type ComponentEvents = Record<string, Function>;
|
||||
|
||||
// Copied from: https://github.com/vuejs/language-tools/blob/master/packages/vue-component-type-helpers/index.d.ts#L10-L13
|
||||
type ComponentProps<T> =
|
||||
T extends new (...angs: any) => { $props: infer P; } ? NonNullable<P> :
|
||||
T extends (props: infer P, ...args: any) => any ? P :
|
||||
{};
|
||||
|
||||
export interface MountOptions<HooksConfig, Component> {
|
||||
props?: ComponentProps<Component>;
|
||||
slots?: ComponentSlots;
|
||||
on?: ComponentEvents;
|
||||
hooksConfig?: HooksConfig;
|
||||
}
|
||||
|
||||
export interface MountOptionsJsx<HooksConfig> {
|
||||
hooksConfig?: HooksConfig;
|
||||
}
|
||||
|
||||
export interface MountResult<Component> extends Locator {
|
||||
unmount(): Promise<void>;
|
||||
update(options: {
|
||||
props?: Partial<ComponentProps<Component>>;
|
||||
slots?: Partial<ComponentSlots>;
|
||||
on?: Partial<ComponentEvents>;
|
||||
}): Promise<void>;
|
||||
}
|
||||
|
||||
export interface MountResultJsx extends Locator {
|
||||
unmount(): Promise<void>;
|
||||
update(component: JSX.Element): Promise<void>;
|
||||
}
|
||||
|
||||
export const test: TestType<{
|
||||
mount<HooksConfig>(
|
||||
component: JSX.Element,
|
||||
options?: MountOptionsJsx<HooksConfig>
|
||||
): Promise<MountResultJsx>;
|
||||
mount<HooksConfig, Component = unknown>(
|
||||
component: Component,
|
||||
options?: MountOptions<HooksConfig, Component>
|
||||
): Promise<MountResult<Component>>;
|
||||
}>;
|
||||
|
||||
export { defineConfig, PlaywrightTestConfig, expect, devices } from '@playwright/experimental-ct-core';
|
|
@ -1,33 +0,0 @@
|
|||
/**
|
||||
* 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, expect, devices, defineConfig: originalDefineConfig } = require('@playwright/experimental-ct-core');
|
||||
const path = require('path');
|
||||
|
||||
const defineConfig = (config, ...configs) => {
|
||||
return originalDefineConfig({
|
||||
...config,
|
||||
'@playwright/test': {
|
||||
packageJSON: require.resolve('./package.json'),
|
||||
},
|
||||
'@playwright/experimental-ct-core': {
|
||||
registerSourceFile: path.join(__dirname, 'registerSource.mjs'),
|
||||
frameworkPluginFactory: () => import('@vitejs/plugin-vue2').then(plugin => plugin.default()),
|
||||
},
|
||||
}, ...configs);
|
||||
};
|
||||
|
||||
module.exports = { test, expect, devices, defineConfig };
|
|
@ -1,42 +0,0 @@
|
|||
{
|
||||
"name": "@playwright/experimental-ct-vue2",
|
||||
"version": "1.49.0-next",
|
||||
"description": "Playwright Component Testing for Vue2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/microsoft/playwright.git"
|
||||
},
|
||||
"homepage": "https://playwright.dev",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.49.0-next",
|
||||
"@vitejs/plugin-vue2": "^2.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vue": "^2.7.14"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
* 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 pwRegister(
|
||||
components: Record<string, any>,
|
||||
options?: {
|
||||
createApp: any,
|
||||
setDevtoolsHook: any,
|
||||
h: any,
|
||||
}
|
||||
): void;
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* 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 { pwRegister } from './registerSource.mjs';
|
||||
|
||||
export default components => {
|
||||
pwRegister(components);
|
||||
};
|
|
@ -1,212 +0,0 @@
|
|||
/**
|
||||
* 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 __pwVue, { h as __pwH } from 'vue';
|
||||
|
||||
/** @typedef {import('../playwright-ct-core/types/component').Component} Component */
|
||||
/** @typedef {import('../playwright-ct-core/types/component').JsxComponent} JsxComponent */
|
||||
/** @typedef {import('../playwright-ct-core/types/component').ObjectComponent} ObjectComponent */
|
||||
/** @typedef {import('vue').Component} FrameworkComponent */
|
||||
|
||||
/**
|
||||
* @param {any} component
|
||||
* @returns {component is ObjectComponent}
|
||||
*/
|
||||
function isObjectComponent(component) {
|
||||
return typeof component === 'object' && component && component.__pw_type === 'object-component';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} component
|
||||
* @returns {component is JsxComponent}
|
||||
*/
|
||||
function isJsxComponent(component) {
|
||||
return typeof component === 'object' && component && component.__pw_type === 'jsx';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} child
|
||||
*/
|
||||
function __pwCreateChild(child) {
|
||||
if (Array.isArray(child))
|
||||
return child.map(grandChild => __pwCreateChild(grandChild));
|
||||
if (isJsxComponent(child) || isObjectComponent(child))
|
||||
return __pwCreateWrapper(child);
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exists to support fallthrough attributes:
|
||||
* https://vuejs.org/guide/components/attrs.html#fallthrough-attributes
|
||||
* @param {any} Component
|
||||
* @param {string} key
|
||||
* @return {boolean}
|
||||
*/
|
||||
function __pwComponentHasKeyInProps(Component, key) {
|
||||
return typeof Component.props === 'object' && Component.props && key in Component.props;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {JsxComponent} component
|
||||
* @returns {any[] | undefined}
|
||||
*/
|
||||
function __pwJsxChildArray(component) {
|
||||
if (!component.props.children)
|
||||
return;
|
||||
if (Array.isArray(component.props.children))
|
||||
return component.props.children;
|
||||
return [component.props.children];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Component} component
|
||||
*/
|
||||
function __pwCreateComponent(component) {
|
||||
const isVueComponent = typeof component.type !== 'string';
|
||||
|
||||
/**
|
||||
* @type {(import('vue').VNode | string)[]}
|
||||
*/
|
||||
const children = [];
|
||||
|
||||
/** @type {import('vue').VNodeData} */
|
||||
const nodeData = {};
|
||||
nodeData.attrs = {};
|
||||
nodeData.props = {};
|
||||
nodeData.scopedSlots = {};
|
||||
nodeData.on = {};
|
||||
|
||||
if (component.__pw_type === 'jsx') {
|
||||
for (const child of __pwJsxChildArray(component) || []) {
|
||||
if (isJsxComponent(child) && child.type === 'template') {
|
||||
const slotProperty = Object.keys(child.props).find(k => k.startsWith('v-slot:'));
|
||||
const slot = slotProperty ? slotProperty.substring('v-slot:'.length) : 'default';
|
||||
nodeData.scopedSlots[slot] = () => __pwJsxChildArray(child)?.map(c => __pwCreateChild(c));
|
||||
} else {
|
||||
children.push(__pwCreateChild(child));
|
||||
}
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(component.props)) {
|
||||
if (key.startsWith('v-on:')) {
|
||||
const event = key.substring('v-on:'.length);
|
||||
nodeData.on[event] = value;
|
||||
} else {
|
||||
if (isVueComponent && __pwComponentHasKeyInProps(component.type, key))
|
||||
nodeData.props[key] = value;
|
||||
else
|
||||
nodeData.attrs[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (component.__pw_type === 'object-component') {
|
||||
// Vue test util syntax.
|
||||
for (const [key, value] of Object.entries(component.slots || {})) {
|
||||
const list = (Array.isArray(value) ? value : [value]).map(v => __pwCreateChild(v));
|
||||
if (key === 'default')
|
||||
children.push(...list);
|
||||
else
|
||||
nodeData.scopedSlots[key] = () => list;
|
||||
}
|
||||
nodeData.props = component.props || {};
|
||||
for (const [key, value] of Object.entries(component.on || {}))
|
||||
nodeData.on[key] = value;
|
||||
}
|
||||
|
||||
/** @type {(string|import('vue').VNode)[] | undefined} */
|
||||
let lastArg;
|
||||
if (Object.entries(nodeData.scopedSlots).length) {
|
||||
if (children.length)
|
||||
nodeData.scopedSlots.default = () => children;
|
||||
} else if (children.length) {
|
||||
lastArg = children;
|
||||
}
|
||||
|
||||
return { Component: component.type, nodeData, slots: lastArg };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Component} component
|
||||
* @returns {import('vue').VNode}
|
||||
*/
|
||||
function __pwCreateWrapper(component) {
|
||||
const { Component, nodeData, slots } = __pwCreateComponent(component);
|
||||
const wrapper = __pwH(Component, nodeData, slots);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
const instanceKey = Symbol('instanceKey');
|
||||
const wrapperKey = Symbol('wrapperKey');
|
||||
|
||||
window.playwrightMount = async (component, rootElement, hooksConfig) => {
|
||||
let options = {};
|
||||
for (const hook of window.__pw_hooks_before_mount || [])
|
||||
options = await hook({ hooksConfig, Vue: __pwVue });
|
||||
|
||||
const instance = new __pwVue({
|
||||
...options,
|
||||
render: () => {
|
||||
const wrapper = __pwCreateWrapper(component);
|
||||
/** @type {any} */ (rootElement)[wrapperKey] = wrapper;
|
||||
return wrapper;
|
||||
},
|
||||
}).$mount();
|
||||
rootElement.appendChild(instance.$el);
|
||||
/** @type {any} */ (rootElement)[instanceKey] = instance;
|
||||
|
||||
for (const hook of window.__pw_hooks_after_mount || [])
|
||||
await hook({ hooksConfig, instance });
|
||||
};
|
||||
|
||||
window.playwrightUnmount = async rootElement => {
|
||||
const component = rootElement[instanceKey];
|
||||
if (!component)
|
||||
throw new Error('Component was not mounted');
|
||||
component.$destroy();
|
||||
component.$el.remove();
|
||||
delete rootElement[instanceKey];
|
||||
};
|
||||
|
||||
window.playwrightUpdate = async (element, options) => {
|
||||
const wrapper = /** @type {any} */(element)[wrapperKey];
|
||||
if (!wrapper)
|
||||
throw new Error('Component was not mounted');
|
||||
|
||||
const component = wrapper.componentInstance;
|
||||
if (!component)
|
||||
throw new Error('Updating a native HTML element is not supported');
|
||||
|
||||
const { nodeData, slots } = __pwCreateComponent(options);
|
||||
|
||||
for (const [name, value] of Object.entries(nodeData.on || {})) {
|
||||
component.$on(name, value);
|
||||
component.$listeners[name] = value;
|
||||
}
|
||||
|
||||
Object.assign(component.$scopedSlots, nodeData.scopedSlots);
|
||||
component.$slots.default = slots;
|
||||
|
||||
for (const [key, value] of Object.entries(nodeData.props || {}))
|
||||
component[key] = value;
|
||||
|
||||
if (!Object.keys(nodeData.props || {}).length)
|
||||
component.$forceUpdate();
|
||||
};
|
|
@ -1,23 +0,0 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
*.tsbuildinfo
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
|
@ -1,24 +0,0 @@
|
|||
# ct-vue2-cli
|
||||
|
||||
## Project setup
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
|
@ -1,5 +0,0 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
]
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
{
|
||||
"name": "ct-vue2-cli",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint",
|
||||
"typecheck": "tsc --noEmit --project tsconfig.test.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.8.3",
|
||||
"vue": "^2.7.13",
|
||||
"vue-router": "^3.6.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.23.2",
|
||||
"@babel/eslint-parser": "^7.22.15",
|
||||
"@vue/cli-plugin-babel": "~5.0.0",
|
||||
"@vue/cli-plugin-eslint": "~5.0.0",
|
||||
"@vue/cli-service": "~5.0.0",
|
||||
"@vue/tsconfig": "^0.1.3",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-vue": "^8.0.3"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/essential",
|
||||
"eslint:recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"parser": "@babel/eslint-parser"
|
||||
},
|
||||
"rules": {}
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not dead"
|
||||
]
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/**
|
||||
* 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 { defineConfig, devices } from '@playwright/experimental-ct-vue2';
|
||||
import { resolve } from 'path';
|
||||
|
||||
export default defineConfig({
|
||||
testDir: 'tests',
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
reporter: process.env.CI ? 'html' : 'line',
|
||||
use: {
|
||||
trace: 'on-first-retry',
|
||||
ctViteConfig: {
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(__dirname, './src'),
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
],
|
||||
});
|
|
@ -1,12 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,17 +0,0 @@
|
|||
import { beforeMount, afterMount } from '@playwright/experimental-ct-vue2/hooks';
|
||||
import Router from 'vue-router';
|
||||
import { router } from '../src/router';
|
||||
import '../src/assets/index.css';
|
||||
|
||||
beforeMount(async ({ Vue, hooksConfig }) => {
|
||||
console.log(`Before mount: ${JSON.stringify(hooksConfig)}`);
|
||||
|
||||
if (hooksConfig?.routing) {
|
||||
Vue.use(Router);
|
||||
return { router }
|
||||
}
|
||||
});
|
||||
|
||||
afterMount(async ({ instance }) => {
|
||||
console.log(`After mount el: ${instance.$el.constructor.name}`);
|
||||
});
|
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
|
@ -1,17 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
|
@ -1,10 +0,0 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<header>
|
||||
<img alt="Vue logo" src="./assets/logo.png" width="60" height="60">
|
||||
<router-link to="/">Login</router-link>
|
||||
<router-link to="/dashboard">Dashboard</router-link>
|
||||
</header>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
|
@ -1,20 +0,0 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #e3e3e3;
|
||||
background-color: #1b1b1d;
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 6.7 KiB |
|
@ -1,10 +0,0 @@
|
|||
<template>
|
||||
<button @click="$emit('submit', 'hello')">{{ title }}</button>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'ButtonButton',
|
||||
props: ['title']
|
||||
}
|
||||
</script>
|
|
@ -1,3 +0,0 @@
|
|||
<template>
|
||||
<div>test</div>
|
||||
</template>
|
|
@ -1,23 +0,0 @@
|
|||
<template>
|
||||
<button @click="$emit('submit', 'hello')">
|
||||
<span data-testid="props">{{ count }}</span>
|
||||
<span data-testid="remount-count">{{ remountCount }}</span>
|
||||
<slot name="main" />
|
||||
<slot />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
let remountCount = 0;
|
||||
|
||||
export default {
|
||||
name: 'Button',
|
||||
props: ['count'],
|
||||
data() {
|
||||
return { remountCount }
|
||||
},
|
||||
beforeCreate() {
|
||||
remountCount++;
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -1,11 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<h1>Welcome!</h1>
|
||||
<main>
|
||||
<slot />
|
||||
</main>
|
||||
<footer>
|
||||
Thanks for visiting.
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
|
@ -1,8 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { useSlots } from 'vue';
|
||||
const slots = useSlots();
|
||||
Object.assign(window, { slots });
|
||||
</script>
|
||||
<template>
|
||||
</template>
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<header>
|
||||
<slot name="header" />
|
||||
</header>
|
||||
<main>
|
||||
<slot name="main" />
|
||||
</main>
|
||||
<footer>
|
||||
<slot name="footer" />
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
|
@ -1,14 +0,0 @@
|
|||
import Vue from 'vue';
|
||||
import Router from 'vue-router';
|
||||
import App from './App.vue';
|
||||
import { router } from './router';
|
||||
import './assets/index.css';
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
Vue.use(Router);
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
render: h => h(App),
|
||||
}).$mount('#app');
|
|
@ -1,3 +0,0 @@
|
|||
<template>
|
||||
<main>Dashboard</main>
|
||||
</template>
|
|
@ -1,3 +0,0 @@
|
|||
<template>
|
||||
<main>Login</main>
|
||||
</template>
|
|
@ -1,12 +0,0 @@
|
|||
import Router from 'vue-router';
|
||||
import LoginPage from '../pages/LoginPage.vue';
|
||||
import DashboardPage from '../pages/DashboardPage.vue';
|
||||
|
||||
export const router = new Router({
|
||||
mode: 'history',
|
||||
base: '/',
|
||||
routes: [
|
||||
{ path: '/', component: LoginPage },
|
||||
{ path: '/dashboard', component: DashboardPage }
|
||||
]
|
||||
});
|
|
@ -1,4 +0,0 @@
|
|||
declare module '*.vue' {
|
||||
import Vue from 'vue';
|
||||
export default Vue;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import Button from '@/components/Button.vue';
|
||||
|
||||
test('emit an submit event when the button is clicked', async ({ mount }) => {
|
||||
const messages: string[] = [];
|
||||
const component = await mount(Button, {
|
||||
props: {
|
||||
title: 'Submit',
|
||||
},
|
||||
on: {
|
||||
submit: (data: string) => messages.push(data),
|
||||
},
|
||||
});
|
||||
await component.click();
|
||||
expect(messages).toEqual(['hello']);
|
||||
});
|
|
@ -1,28 +0,0 @@
|
|||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import Button from '@/components/Button.vue';
|
||||
import DefaultSlot from '@/components/DefaultSlot.vue';
|
||||
|
||||
test('emit an submit event when the button is clicked', async ({ mount }) => {
|
||||
const messages: string[] = [];
|
||||
const component = await mount(
|
||||
<Button
|
||||
title="Submit"
|
||||
v-on:submit={(data: string) => {
|
||||
messages.push(data);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
await component.click();
|
||||
expect(messages).toEqual(['hello']);
|
||||
});
|
||||
|
||||
test('emit a event when a slot is clicked', async ({ mount }) => {
|
||||
let clickFired = false;
|
||||
const component = await mount(
|
||||
<DefaultSlot>
|
||||
<span v-on:click={() => (clickFired = true)}>Main Content</span>
|
||||
</DefaultSlot>
|
||||
);
|
||||
await component.getByText('Main Content').click();
|
||||
expect(clickFired).toBeTruthy();
|
||||
});
|
|
@ -1,25 +0,0 @@
|
|||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import Button from '@/components/Button.vue';
|
||||
import Component from '@/components/Component.vue';
|
||||
import EmptyTemplate from '@/components/EmptyTemplate.vue';
|
||||
|
||||
test('render props', async ({ mount }) => {
|
||||
const component = await mount(Button, {
|
||||
props: {
|
||||
title: 'Submit',
|
||||
},
|
||||
});
|
||||
await expect(component).toContainText('Submit');
|
||||
});
|
||||
|
||||
test('render a component without options', async ({ mount }) => {
|
||||
const component = await mount(Component);
|
||||
await expect(component).toContainText('test');
|
||||
});
|
||||
|
||||
test('get textContent of the empty template', async ({ mount }) => {
|
||||
const component = await mount(EmptyTemplate);
|
||||
expect(await component.allTextContents()).toEqual(['']);
|
||||
expect(await component.textContent()).toBe('');
|
||||
await expect(component).toHaveText('');
|
||||
});
|
|
@ -1,21 +0,0 @@
|
|||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import Button from '@/components/Button.vue';
|
||||
import EmptyTemplate from '@/components/EmptyTemplate.vue';
|
||||
|
||||
test('render props', async ({ mount }) => {
|
||||
const component = await mount(<Button title="Submit" />);
|
||||
await expect(component).toContainText('Submit');
|
||||
});
|
||||
|
||||
test('render attributes', async ({ mount }) => {
|
||||
const component = await mount(<Button class="primary" title="Submit" />);
|
||||
await expect(component).toHaveClass('primary');
|
||||
});
|
||||
|
||||
test('render an empty component', async ({ page, mount }) => {
|
||||
const component = await mount(<EmptyTemplate />);
|
||||
expect(await page.evaluate(() => 'slots' in window && window.slots)).toEqual({});
|
||||
expect(await component.allTextContents()).toEqual(['']);
|
||||
expect(await component.textContent()).toBe('');
|
||||
await expect(component).toHaveText('');
|
||||
});
|
|
@ -1,35 +0,0 @@
|
|||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import DefaultSlot from '@/components/DefaultSlot.vue';
|
||||
import NamedSlots from '@/components/NamedSlots.vue';
|
||||
|
||||
test('render a default slot', async ({ mount }) => {
|
||||
const component = await mount(DefaultSlot, {
|
||||
slots: {
|
||||
default: 'Main Content',
|
||||
},
|
||||
});
|
||||
await expect(component).toContainText('Main Content');
|
||||
});
|
||||
|
||||
test('render a component with multiple slots', async ({ mount }) => {
|
||||
const component = await mount(DefaultSlot, {
|
||||
slots: {
|
||||
default: ['one', 'two'],
|
||||
},
|
||||
});
|
||||
await expect(component).toContainText('one');
|
||||
await expect(component).toContainText('two');
|
||||
});
|
||||
|
||||
test('render a component with a named slot', async ({ mount }) => {
|
||||
const component = await mount(NamedSlots, {
|
||||
slots: {
|
||||
header: 'Header',
|
||||
main: 'Main Content',
|
||||
footer: 'Footer',
|
||||
},
|
||||
});
|
||||
await expect(component).toContainText('Header');
|
||||
await expect(component).toContainText('Main Content');
|
||||
await expect(component).toContainText('Footer');
|
||||
});
|
|
@ -1,48 +0,0 @@
|
|||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import Button from '@/components/Button.vue';
|
||||
import DefaultSlot from '@/components/DefaultSlot.vue';
|
||||
import NamedSlots from '@/components/NamedSlots.vue';
|
||||
|
||||
test('render a default slot', async ({ mount }) => {
|
||||
const component = await mount(<DefaultSlot>Main Content</DefaultSlot>);
|
||||
await expect(component).toContainText('Main Content');
|
||||
});
|
||||
|
||||
test('render a component as slot', async ({ mount }) => {
|
||||
const component = await mount(
|
||||
<DefaultSlot>
|
||||
<Button title="Submit" />
|
||||
</DefaultSlot>
|
||||
);
|
||||
await expect(component).toContainText('Submit');
|
||||
});
|
||||
|
||||
test('render a component with multiple slots', async ({ mount }) => {
|
||||
const component = await mount(
|
||||
<DefaultSlot>
|
||||
<div data-testid="one">One</div>
|
||||
<div data-testid="two">Two</div>
|
||||
</DefaultSlot>
|
||||
);
|
||||
await expect(component.getByTestId('one')).toContainText('One');
|
||||
await expect(component.getByTestId('two')).toContainText('Two');
|
||||
});
|
||||
|
||||
test('render a component with a named slot', async ({ mount }) => {
|
||||
const component = await mount(
|
||||
<NamedSlots>
|
||||
<template v-slot:header>Header</template>
|
||||
<template v-slot:main>Main Content</template>
|
||||
<template v-slot:footer>Footer</template>
|
||||
</NamedSlots>
|
||||
);
|
||||
await expect(component).toContainText('Header');
|
||||
await expect(component).toContainText('Main Content');
|
||||
await expect(component).toContainText('Footer');
|
||||
});
|
||||
|
||||
test('render array as child', async ({ mount }) => {
|
||||
const component = await mount(<DefaultSlot>{[<h4>{[4]}</h4>,[[<p>[2,3]</p>]]]}</DefaultSlot>);
|
||||
await expect(component.getByRole('heading', { level: 4 })).toHaveText('4');
|
||||
await expect(component.getByRole('paragraph')).toHaveText('[2,3]');
|
||||
});
|
|
@ -1,38 +0,0 @@
|
|||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import Button from '@/components/Button.vue';
|
||||
|
||||
test('unmount', async ({ page, mount }) => {
|
||||
const component = await mount(Button, {
|
||||
props: {
|
||||
title: 'Submit',
|
||||
},
|
||||
});
|
||||
await expect(page.locator('#root')).toContainText('Submit');
|
||||
await component.unmount();
|
||||
await expect(page.locator('#root')).not.toContainText('Submit');
|
||||
});
|
||||
|
||||
test('unmount twice throws an error', async ({ mount }) => {
|
||||
const component = await mount(Button, {
|
||||
props: {
|
||||
title: 'Submit',
|
||||
},
|
||||
});
|
||||
await component.unmount();
|
||||
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||
});
|
||||
|
||||
test('mount then unmount then mount', async ({ mount }) => {
|
||||
let component = await mount(Button, {
|
||||
props: {
|
||||
title: 'Submit',
|
||||
},
|
||||
});
|
||||
await component.unmount();
|
||||
component = await mount(Button, {
|
||||
props: {
|
||||
title: 'Save',
|
||||
},
|
||||
});
|
||||
await expect(component).toContainText('Save');
|
||||
});
|
|
@ -1,22 +0,0 @@
|
|||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import Button from '@/components/Button.vue';
|
||||
|
||||
test('unmount', async ({ page, mount }) => {
|
||||
const component = await mount(<Button title="Submit" />);
|
||||
await expect(page.locator('#root')).toContainText('Submit');
|
||||
await component.unmount();
|
||||
await expect(page.locator('#root')).not.toContainText('Submit');
|
||||
});
|
||||
|
||||
test('unmount twice throws an error', async ({ mount }) => {
|
||||
const component = await mount(<Button title="Submit" />);
|
||||
await component.unmount();
|
||||
await expect(component.unmount()).rejects.toThrowError('Component was not mounted');
|
||||
});
|
||||
|
||||
test('mount then unmount then mount', async ({ mount }) => {
|
||||
let component = await mount(<Button title="Submit" />);
|
||||
await component.unmount();
|
||||
component = await mount(<Button title="Save" />);
|
||||
await expect(component).toContainText('Save');
|
||||
});
|
|
@ -1,52 +0,0 @@
|
|||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import Counter from '@/components/Counter.vue';
|
||||
|
||||
test('update props without remounting', async ({ mount }) => {
|
||||
const component = await mount(Counter, {
|
||||
props: { count: 9001 },
|
||||
});
|
||||
await expect(component.getByTestId('props')).toContainText('9001');
|
||||
|
||||
await component.update({
|
||||
props: { count: 1337 },
|
||||
});
|
||||
await expect(component).not.toContainText('9001');
|
||||
await expect(component.getByTestId('props')).toContainText('1337');
|
||||
|
||||
await expect(component.getByTestId('remount-count')).toContainText('1');
|
||||
});
|
||||
|
||||
test('update event listeners without remounting', async ({ mount }) => {
|
||||
const component = await mount(Counter);
|
||||
|
||||
const messages: string[] = [];
|
||||
await component.update({
|
||||
on: {
|
||||
submit: (data: string) => messages.push(data),
|
||||
},
|
||||
});
|
||||
await component.click();
|
||||
expect(messages).toEqual(['hello']);
|
||||
|
||||
await expect(component.getByTestId('remount-count')).toContainText('1');
|
||||
});
|
||||
|
||||
test('update slots without remounting', async ({ mount }) => {
|
||||
const component = await mount(Counter, {
|
||||
slots: { default: 'Default Slot' },
|
||||
});
|
||||
await expect(component).toContainText('Default Slot');
|
||||
|
||||
await component.update({
|
||||
slots: { main: 'Test Slot' },
|
||||
});
|
||||
await expect(component).not.toContainText('Default Slot');
|
||||
await expect(component).toContainText('Test Slot');
|
||||
|
||||
await component.update({
|
||||
slots: { default: 'Default Slot' },
|
||||
});
|
||||
await expect(component).toContainText('Default Slot');
|
||||
|
||||
await expect(component.getByTestId('remount-count')).toContainText('1');
|
||||
});
|
|
@ -1,53 +0,0 @@
|
|||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import Counter from '@/components/Counter.vue';
|
||||
|
||||
test('update props without remounting', async ({ mount }) => {
|
||||
const component = await mount(<Counter count={9001} />);
|
||||
await expect(component.getByTestId('props')).toContainText('9001');
|
||||
|
||||
await component.update(<Counter count={1337} />);
|
||||
await expect(component).not.toContainText('9001');
|
||||
await expect(component.getByTestId('props')).toContainText('1337');
|
||||
|
||||
await expect(component.getByTestId('remount-count')).toContainText('1');
|
||||
});
|
||||
|
||||
test('update event listeners without remounting', async ({ mount }) => {
|
||||
const messages: string[] = [];
|
||||
const component = await mount(<Counter />);
|
||||
|
||||
await component.update(
|
||||
<Counter
|
||||
v-on:submit={(count: string) => {
|
||||
messages.push(count);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
await component.click();
|
||||
expect(messages).toEqual(['hello']);
|
||||
|
||||
await expect(component.getByTestId('remount-count')).toContainText('1');
|
||||
});
|
||||
|
||||
test('update slots without remounting', async ({ mount }) => {
|
||||
const component = await mount(<Counter>Default Slot</Counter>);
|
||||
await expect(component).toContainText('Default Slot');
|
||||
|
||||
await component.update(
|
||||
<Counter>
|
||||
<template v-slot:main>Test Slot</template>
|
||||
</Counter>
|
||||
);
|
||||
await expect(component).not.toContainText('Default Slot');
|
||||
await expect(component).toContainText('Test Slot');
|
||||
|
||||
await expect(component.getByTestId('remount-count')).toContainText('1');
|
||||
});
|
||||
|
||||
test('throw error when updating a native html element', async ({ mount }) => {
|
||||
const component = await mount(<div id="1337"></div>);
|
||||
|
||||
await expect(async () => {
|
||||
await component.update(<div id="9001"></div>);
|
||||
}).rejects.toThrowError('Updating a native HTML element is not supported');
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import App from '@/App.vue';
|
||||
|
||||
test('navigate to a page by clicking a link', async ({ page, mount }) => {
|
||||
const component = await mount(App, {
|
||||
hooksConfig: { routing: true },
|
||||
});
|
||||
await expect(component.getByRole('main')).toHaveText('Login');
|
||||
await expect(page).toHaveURL('/');
|
||||
await component.getByRole('link', { name: 'Dashboard' }).click();
|
||||
await expect(component.getByRole('main')).toHaveText('Dashboard');
|
||||
await expect(page).toHaveURL('/dashboard');
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||
import App from '@/App.vue';
|
||||
|
||||
test('navigate to a page by clicking a link', async ({ page, mount }) => {
|
||||
const component = await mount(<App />, {
|
||||
hooksConfig: { routing: true },
|
||||
});
|
||||
await expect(component.getByRole('main')).toHaveText('Login');
|
||||
await expect(page).toHaveURL('/');
|
||||
await component.getByRole('link', { name: 'Dashboard' }).click();
|
||||
await expect(component.getByRole('main')).toHaveText('Dashboard');
|
||||
await expect(page).toHaveURL('/dashboard');
|
||||
});
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.web.json",
|
||||
"include": ["src/**/*", "src/**/*.vue"],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"],
|
||||
"*": ["_"],
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.node.json",
|
||||
"include": ["playwright.config.*"],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"types": ["node"]
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.config.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.test.json"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"extends": "./tsconfig.app.json",
|
||||
"include": ["tests/**/*", "src/shims-vue.d.ts"],
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"composite": true,
|
||||
"lib": [],
|
||||
"types": ["node"],
|
||||
"ignoreDeprecations": "5.0"
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
const { defineConfig } = require('@vue/cli-service')
|
||||
module.exports = defineConfig({
|
||||
transpileDependencies: true
|
||||
})
|
|
@ -212,11 +212,6 @@ const workspace = new Workspace(ROOT_PATH, [
|
|||
path: path.join(ROOT_PATH, 'packages', 'playwright-ct-vue'),
|
||||
files: ['LICENSE'],
|
||||
}),
|
||||
new PWPackage({
|
||||
name: '@playwright/experimental-ct-vue2',
|
||||
path: path.join(ROOT_PATH, 'packages', 'playwright-ct-vue2'),
|
||||
files: ['LICENSE'],
|
||||
}),
|
||||
]);
|
||||
|
||||
if (require.main === module) {
|
||||
|
|
Loading…
Reference in New Issue