Skip to content

Commit 028b0b7

Browse files
authored
chore: add -ct for future component testing (#20)
1 parent d79a41a commit 028b0b7

9 files changed

+117
-18
lines changed

assets/playwright.config.js

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// @ts-check
22
const { devices } = require('@playwright/test');
3+
//--begin-ct
4+
const ct = require('{{ctPackageName}}');
5+
//--end-ct
36

47
/**
58
* Read environment variables from file.
@@ -31,6 +34,10 @@ const config = {
3134
workers: process.env.CI ? 1 : undefined,
3235
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
3336
reporter: 'html',
37+
//--begin-ct
38+
/* Enable component testing */
39+
plugins: [ ct() ],
40+
//--end-ct
3441
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
3542
use: {
3643
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */

assets/playwright.config.ts

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import type { PlaywrightTestConfig } from '@playwright/test';
22
import { devices } from '@playwright/test';
3+
//--begin-ct
4+
import ct from '{{ctPackageName}}';
5+
//--end-ct
36

47
/**
58
* Read environment variables from file.
@@ -29,6 +32,10 @@ const config: PlaywrightTestConfig = {
2932
workers: process.env.CI ? 1 : undefined,
3033
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
3134
reporter: 'html',
35+
//--begin-ct
36+
/* Enable component testing */
37+
plugins: [ ct() ],
38+
//--end-ct
3239
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
3340
use: {
3441
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */

assets/playwright/index.html

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Testing Page</title>
7+
</head>
8+
<body>
9+
<div id="root"></div>
10+
<script type="module" src="/playwright/index.{{extension}}"></script>
11+
</body>
12+
</html>

assets/playwright/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Import styles, initialize component theme here.
2+
// import '../src/common.css';

assets/tsconfig.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"compilerOptions": {
3+
"allowSyntheticDefaultImports": true,
4+
"noEmit": true,
5+
"jsx": "react-jsx",
6+
},
7+
"include": ["src", "playwright.d.ts"],
8+
}

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "create-playwright",
3-
"version": "1.17.110",
3+
"version": "1.17.111",
44
"description": "Getting started with writing end-to-end tests with Playwright.",
55
"repository": "github:Microsoft/playwright",
66
"homepage": "https://playwright.dev",

src/generator.ts

+77-14
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ import { executeCommands, createFiles, determinePackageManager, executeTemplate,
2424
export type PromptOptions = {
2525
testDir: string,
2626
installGitHubActions: boolean,
27-
language: 'JavaScript' | 'TypeScript'
27+
language: 'JavaScript' | 'TypeScript',
28+
framework: 'react' | 'vue' | 'svelte' | undefined,
2829
installPlaywrightDependencies: boolean,
2930
};
3031

@@ -63,10 +64,14 @@ export class Generator {
6364
language: this.options.lang?.[0] === 'js' ? 'JavaScript' : 'TypeScript',
6465
installPlaywrightDependencies: !!this.options['install-deps'],
6566
testDir: fs.existsSync(path.join(this.rootDir, 'tests')) ? 'e2e' : 'tests',
67+
framework: undefined,
6668
};
6769
}
68-
return await prompt<PromptOptions>([
69-
{
70+
71+
const isDefinitelyTS = fs.existsSync(path.join(this.rootDir, 'tsconfig.json'));
72+
73+
const questions = [
74+
!isDefinitelyTS && {
7075
type: 'select',
7176
name: 'language',
7277
message: 'Do you want to use TypeScript or JavaScript?',
@@ -75,27 +80,41 @@ export class Generator {
7580
{ name: 'JavaScript' },
7681
],
7782
},
78-
{
83+
this.options.ct && {
84+
type: 'select',
85+
name: 'framework',
86+
message: 'Which framework do you use? (experimental)',
87+
choices: [
88+
{ name: 'react' },
89+
{ name: 'vue' },
90+
{ name: 'svelte' },
91+
],
92+
},
93+
!this.options.ct && {
7994
type: 'text',
8095
name: 'testDir',
8196
message: 'Where to put your end-to-end tests?',
8297
initial: fs.existsSync(path.join(this.rootDir, 'tests')) ? 'e2e' : 'tests',
8398
},
84-
{
99+
!this.options.ct && {
85100
type: 'confirm',
86101
name: 'installGitHubActions',
87102
message: 'Add a GitHub Actions workflow?',
88-
initial: true,
103+
initial: false,
89104
},
90105
// Avoid installing dependencies on Windows (vast majority does not run create-playwright on Windows)
91106
// Avoid installing dependencies on Mac (there are no dependencies)
92-
...(process.platform === 'linux' ? [{
107+
process.platform === 'linux' && {
93108
type: 'confirm',
94109
name: 'installPlaywrightDependencies',
95110
message: 'Install Playwright operating system dependencies (requires sudo / root - can be done manually via \sudo npx playwright install-deps\')?',
96111
initial: false,
97-
}] : []),
98-
]);
112+
},
113+
];
114+
const result = await prompt<PromptOptions>(questions.filter(Boolean) as any);
115+
if (isDefinitelyTS)
116+
result.language = 'TypeScript';
117+
return result;
99118
}
100119

101120
private async _identifyChanges(answers: PromptOptions) {
@@ -107,8 +126,17 @@ export class Generator {
107126
for (const browserName of ['chromium', 'firefox', 'webkit'])
108127
sections.set(browserName, !this.options.browser || this.options.browser.includes(browserName) ? 'show' : 'comment');
109128

129+
let installExamples = true;
130+
let ctPackageName = '';
131+
if (answers.framework) {
132+
ctPackageName = `@playwright/experimental-ct-${answers.framework}`;
133+
sections.set('ct', 'show');
134+
installExamples = false;
135+
}
136+
110137
files.set(`playwright.config.${fileExtension}`, executeTemplate(this._readAsset(`playwright.config.${fileExtension}`), {
111-
testDir: answers.testDir,
138+
testDir: answers.testDir || '',
139+
ctPackageName,
112140
}, sections));
113141

114142
if (answers.installGitHubActions) {
@@ -119,7 +147,8 @@ export class Generator {
119147
files.set('.github/workflows/playwright.yml', githubActionsScript);
120148
}
121149

122-
files.set(path.join(answers.testDir, `example.spec.${fileExtension}`), this._readAsset(`example.spec.${fileExtension}`));
150+
if (installExamples)
151+
files.set(path.join(answers.testDir, `example.spec.${fileExtension}`), this._readAsset(`example.spec.${fileExtension}`));
123152

124153
if (!fs.existsSync(path.join(this.rootDir, 'package.json'))) {
125154
commands.push({
@@ -138,6 +167,25 @@ export class Generator {
138167
command: this.packageManager === 'yarn' ? `yarn add --dev ${packageName}` : `npm install --save-dev ${packageName}`,
139168
});
140169

170+
if (ctPackageName) {
171+
commands.push({
172+
name: 'Installing Playwright Component Testing',
173+
command: this.packageManager === 'yarn' ? `yarn add --dev ${ctPackageName}@latest` : `npm install --save-dev ${ctPackageName}@latest`,
174+
});
175+
176+
const extension = languageToFileExtension(answers.language);
177+
const htmlTemplate = executeTemplate(this._readAsset(path.join('playwright', 'index.html')), { extension }, new Map());
178+
files.set('playwright/index.html', htmlTemplate);
179+
180+
const jsTemplate = this._readAsset(path.join('playwright', 'index.js'));
181+
files.set(`playwright/index.${extension}`, jsTemplate);
182+
183+
if (answers.language === 'TypeScript') {
184+
files.set(`playwright/types.d.ts`, `import '${ctPackageName}';\n`);
185+
this._patchTsconfigJSON();
186+
}
187+
}
188+
141189
const browsersSuffix = this.options.browser ? ' ' + this.options.browser.join(' ') : '';
142190
commands.push({
143191
name: 'Downloading browsers',
@@ -154,8 +202,9 @@ export class Generator {
154202
gitIgnore = fs.readFileSync(gitIgnorePath, 'utf-8').trimEnd() + '\n';
155203
if (!gitIgnore.includes('node_modules'))
156204
gitIgnore += 'node_modules/\n';
157-
gitIgnore += 'test-results/\n';
158-
gitIgnore += 'playwright-report/\n';
205+
gitIgnore += '/test-results/\n';
206+
gitIgnore += '/playwright-report/\n';
207+
gitIgnore += '/dist-pw/\n';
159208
fs.writeFileSync(gitIgnorePath, gitIgnore);
160209
}
161210

@@ -175,11 +224,25 @@ export class Generator {
175224
await createFiles(this.rootDir, files, true);
176225
}
177226

227+
private async _patchTsconfigJSON() {
228+
const tsconfigFile = path.join(this.rootDir, 'tsconfig.json');
229+
const files = new Map<string, string>();
230+
if (!fs.existsSync(tsconfigFile)) {
231+
files.set(`tsconfig.json`, this._readAsset(path.join('tsconfig.json')));
232+
} else {
233+
const tsconfigJSON = fs.readFileSync(path.join(this.rootDir, 'tsconfig.json'), 'utf-8');
234+
const newJSON = tsconfigJSON.replace(/("include"[\s\S]*:[\s\S]\[[\s\S]*"src")/m, '$1, "playwright/types.d.ts"');
235+
if (!tsconfigJSON.includes('playwright') && tsconfigJSON !== newJSON)
236+
files.set('tsconfig.json', newJSON);
237+
}
238+
await createFiles(this.rootDir, files, true);
239+
}
240+
178241
private _printEpilogue(answers: PromptOptions) {
179242
console.log(colors.green('✔ Success!') + ' ' + colors.bold(`Created a Playwright Test project at ${this.rootDir}`));
180243
const pathToNavigate = path.relative(process.cwd(), this.rootDir);
181244
const prefix = pathToNavigate !== '' ? ` cd ${pathToNavigate}\n` : '';
182-
const exampleSpecPath = `${answers.testDir}${path.sep}example.spec.${languageToFileExtension(answers.language)}`;
245+
const exampleSpecPath = `example.spec.${languageToFileExtension(answers.language)}`;
183246
const playwrightConfigPath = `playwright.config.${languageToFileExtension(answers.language)}`;
184247
console.log(`Inside that directory, you can run several commands:
185248

src/utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export function executeTemplate(input: string, args: Record<string, string>, sec
7070
let mode: 'show' | 'hide' | 'comment' = 'show';
7171
let indent = '';
7272
for (const line of input.split('\n')) {
73-
const match = line.match(/([\s]+)\/\/--begin-(.*)/);
73+
const match = line.match(/(\s*)\/\/--begin-(.*)/);
7474
if (match) {
7575
mode = sections.get(match[2]) || 'comment';
7676
indent = match[1];

0 commit comments

Comments
 (0)