mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-12 11:50:22 +03:00
chore: relax transpilation criteria to allow ems imports of .vue files (#15592)
This commit is contained in:
parent
44e214a972
commit
d02914fa3a
@ -16,7 +16,7 @@
|
||||
|
||||
import fs from 'fs';
|
||||
import url from 'url';
|
||||
import { transformHook, resolveHook } from './transform';
|
||||
import { transformHook, resolveHook, belongsToNodeModules } from './transform';
|
||||
|
||||
async function resolve(specifier: string, context: { parentURL: string }, defaultResolve: any) {
|
||||
if (context.parentURL && context.parentURL.startsWith('file://')) {
|
||||
@ -29,13 +29,27 @@ async function resolve(specifier: string, context: { parentURL: string }, defaul
|
||||
}
|
||||
|
||||
async function load(moduleUrl: string, context: any, defaultLoad: any) {
|
||||
if (moduleUrl.startsWith('file://') && (moduleUrl.endsWith('.ts') || moduleUrl.endsWith('.tsx'))) {
|
||||
const filename = url.fileURLToPath(moduleUrl);
|
||||
const code = fs.readFileSync(filename, 'utf-8');
|
||||
const source = transformHook(code, filename, moduleUrl);
|
||||
return { format: 'module', source };
|
||||
}
|
||||
return defaultLoad(moduleUrl, context, defaultLoad);
|
||||
// Bail out for wasm, json, etc.
|
||||
// non-js files have context.format === undefined
|
||||
if (context.format !== 'commonjs' && context.format !== 'module' && context.format !== undefined)
|
||||
return defaultLoad(moduleUrl, context, defaultLoad);
|
||||
|
||||
// Bail for built-in modules.
|
||||
if (!moduleUrl.startsWith('file://'))
|
||||
return defaultLoad(moduleUrl, context, defaultLoad);
|
||||
|
||||
if (!moduleUrl.startsWith('file://'))
|
||||
return defaultLoad(moduleUrl, context, defaultLoad);
|
||||
|
||||
const filename = url.fileURLToPath(moduleUrl);
|
||||
// Bail for node_modules.
|
||||
if (belongsToNodeModules(filename))
|
||||
return defaultLoad(moduleUrl, context, defaultLoad);
|
||||
|
||||
const code = fs.readFileSync(filename, 'utf-8');
|
||||
const source = transformHook(code, filename, moduleUrl);
|
||||
// Output format is always the same as input format, if it was unknown, we always report modules.
|
||||
return { format: context.format || 'module', source };
|
||||
}
|
||||
|
||||
module.exports = { resolve, load };
|
||||
|
@ -135,7 +135,7 @@ export function resolveHook(filename: string, specifier: string): string | undef
|
||||
if (value.includes('*'))
|
||||
candidate = candidate.replace('*', matchedPartOfSpecifier);
|
||||
candidate = path.resolve(tsconfig.absoluteBaseUrl, candidate.replace(/\//g, path.sep));
|
||||
for (const ext of ['', '.js', '.ts', '.mjs', '.cjs', '.jsx', '.tsx']) {
|
||||
for (const ext of ['', '.js', '.ts', '.mjs', '.cjs', '.jsx', '.tsx', '.cjs', '.mts', '.cts']) {
|
||||
if (fs.existsSync(candidate + ext)) {
|
||||
if (keyPrefix.length > longestPrefixLength) {
|
||||
longestPrefixLength = keyPrefix.length;
|
||||
@ -162,15 +162,11 @@ export function transformHook(code: string, filename: string, moduleUrl?: string
|
||||
// If we are not TypeScript and there is no applicable preprocessor - bail out.
|
||||
const isModule = !!moduleUrl;
|
||||
const isTypeScript = filename.endsWith('.ts') || filename.endsWith('.tsx');
|
||||
const isJSX = filename.endsWith('.jsx');
|
||||
const hasPreprocessor =
|
||||
process.env.PW_TEST_SOURCE_TRANSFORM &&
|
||||
process.env.PW_TEST_SOURCE_TRANSFORM_SCOPE &&
|
||||
process.env.PW_TEST_SOURCE_TRANSFORM_SCOPE.split(pathSeparator).some(f => filename.startsWith(f));
|
||||
|
||||
if (!isTypeScript && !isJSX && !hasPreprocessor)
|
||||
return code;
|
||||
|
||||
const cachePath = calculateCachePath(code, filename, isModule);
|
||||
const codePath = cachePath + '.js';
|
||||
const sourceMapPath = cachePath + '.map';
|
||||
@ -212,11 +208,11 @@ export function installTransform(): () => void {
|
||||
}
|
||||
(Module as any)._resolveFilename = resolveFilename;
|
||||
|
||||
const exts = ['.ts', '.tsx', '.jsx'];
|
||||
// When script preprocessor is engaged, we transpile JS as well.
|
||||
if (scriptPreprocessor)
|
||||
exts.push('.js', '.mjs');
|
||||
const revertPirates = pirates.addHook((code: string, filename: string) => transformHook(code, filename), { exts });
|
||||
const revertPirates = pirates.addHook((code: string, filename: string) => {
|
||||
if (belongsToNodeModules(filename))
|
||||
return code;
|
||||
return transformHook(code, filename);
|
||||
}, { exts: ['.ts', '.tsx', '.js', '.jsx', '.mjs'] });
|
||||
|
||||
return () => {
|
||||
reverted = true;
|
||||
@ -248,3 +244,13 @@ export function wrapFunctionWithLocation<A extends any[], R>(func: (location: Lo
|
||||
return func(location, ...args);
|
||||
};
|
||||
}
|
||||
|
||||
export function belongsToNodeModules(file: string) {
|
||||
if (file.includes(`${path.sep}node_modules${path.sep}`))
|
||||
return true;
|
||||
if (file.includes(`${path.sep}playwright${path.sep}packages${path.sep}playwright`))
|
||||
return true;
|
||||
if (file.includes(`${path.sep}playwright${path.sep}tests${path.sep}config${path.sep}coverage.js`))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
81
tests/components/ct-vue-vite/src/notation-vue.spec.js
Normal file
81
tests/components/ct-vue-vite/src/notation-vue.spec.js
Normal file
@ -0,0 +1,81 @@
|
||||
import { test, expect } from '@playwright/experimental-ct-vue'
|
||||
|
||||
import has from 'has'
|
||||
import Button from './components/Button.vue'
|
||||
import DefaultSlot from './components/DefaultSlot.vue'
|
||||
import NamedSlots from './components/NamedSlots.vue'
|
||||
import Component from './components/Component.vue'
|
||||
|
||||
test.use({ viewport: { width: 500, height: 500 } })
|
||||
|
||||
test('props should work', async ({ mount }) => {
|
||||
const component = await mount(Button, {
|
||||
props: {
|
||||
title: 'Submit'
|
||||
}
|
||||
})
|
||||
await expect(component).toContainText('Submit')
|
||||
})
|
||||
|
||||
test('event should work', async ({ mount }) => {
|
||||
const messages = []
|
||||
const component = await mount(Button, {
|
||||
props: {
|
||||
title: 'Submit'
|
||||
},
|
||||
on: {
|
||||
submit: data => messages.push(data)
|
||||
}
|
||||
})
|
||||
await component.click()
|
||||
expect(messages).toEqual(['hello'])
|
||||
})
|
||||
|
||||
test('default slot should work', async ({ mount }) => {
|
||||
const component = await mount(DefaultSlot, {
|
||||
slots: {
|
||||
default: 'Main Content'
|
||||
}
|
||||
})
|
||||
await expect(component).toContainText('Main Content')
|
||||
})
|
||||
|
||||
test('multiple slots should work', async ({ mount }) => {
|
||||
const component = await mount(DefaultSlot, {
|
||||
slots: {
|
||||
default: ['one', 'two']
|
||||
}
|
||||
})
|
||||
await expect(component).toContainText('one')
|
||||
await expect(component).toContainText('two')
|
||||
})
|
||||
|
||||
test('named slots should work', 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')
|
||||
})
|
||||
|
||||
test('optionless should work', async ({ mount }) => {
|
||||
const component = await mount(Component)
|
||||
await expect(component).toContainText('test')
|
||||
})
|
||||
|
||||
test('should run hooks', async ({ page, mount }) => {
|
||||
const messages = []
|
||||
page.on('console', m => messages.push(m.text()))
|
||||
await mount(Button, {
|
||||
props: {
|
||||
title: 'Submit'
|
||||
},
|
||||
hooksConfig: { route: 'A' }
|
||||
})
|
||||
expect(messages).toEqual(['Before mount: {\"route\":\"A\"}, app: true', 'After mount el: HTMLButtonElement'])
|
||||
})
|
@ -16,7 +16,7 @@
|
||||
|
||||
import { playwrightTest as it, expect } from '../config/browserTest';
|
||||
import type { AttributeSelector } from '../../packages/playwright-core/src/server/isomorphic/selectorParser';
|
||||
import { parseAttributeSelector } from '../../packages/playwright-core/src/server/isomorphic/selectorParser';
|
||||
import { parseAttributeSelector } from '../../packages/playwright-core/lib/server/isomorphic/selectorParser';
|
||||
|
||||
const parse = (selector: string) => parseAttributeSelector(selector, false);
|
||||
const serialize = (parsed: AttributeSelector) => {
|
||||
|
@ -28,7 +28,8 @@ test('should return the location of a syntax error', async ({ runInlineTest }) =
|
||||
expect(result.exitCode).toBe(1);
|
||||
expect(result.passed).toBe(0);
|
||||
expect(result.failed).toBe(0);
|
||||
expect(result.output).toContain('error.spec.js:6');
|
||||
expect(result.output).toContain('error.spec.js');
|
||||
expect(result.output).toContain('(6:18)');
|
||||
});
|
||||
|
||||
test('should print an improper error', async ({ runInlineTest }) => {
|
||||
@ -163,19 +164,17 @@ test('should load an mjs file', async ({ runInlineTest }) => {
|
||||
expect(exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should throw a nice error if a js file uses import', async ({ runInlineTest }) => {
|
||||
const { exitCode, output } = await runInlineTest({
|
||||
test('should allow using import', async ({ runInlineTest }) => {
|
||||
const { exitCode } = await runInlineTest({
|
||||
'a.spec.js': `
|
||||
import fs from 'fs';
|
||||
const { test } = folio;
|
||||
const { test } = pwt;
|
||||
test('succeeds', () => {
|
||||
expect(1 + 1).toBe(2);
|
||||
});
|
||||
`
|
||||
});
|
||||
expect(exitCode).toBe(1);
|
||||
expect(output).toContain('a.spec.js');
|
||||
expect(output).toContain('Cannot use import statement outside a module');
|
||||
expect(exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should load esm when package.json has type module', async ({ runInlineTest }) => {
|
||||
|
@ -261,8 +261,9 @@ test('should print errors with inconsistent message/stack', async ({ runInlineTe
|
||||
});
|
||||
expect(result.exitCode).toBe(1);
|
||||
expect(result.failed).toBe(1);
|
||||
expect(result.output).toContain('hi!Error: Hello');
|
||||
expect(result.output).toContain('at myTest');
|
||||
const output = stripAnsi(result.output);
|
||||
expect(output).toContain('hi!Error: Hello');
|
||||
expect(output).toContain('function myTest');
|
||||
});
|
||||
|
||||
test('should print "no tests found" error', async ({ runInlineTest }) => {
|
||||
|
Loading…
Reference in New Issue
Block a user