From ac09420995ee91679ec3d4bc5d5c222e9f10e3e5 Mon Sep 17 00:00:00 2001 From: Devin Rousso Date: Fri, 18 Sep 2026 13:10:57 -0600 Subject: [PATCH] feat(cli): remove component testing setup `create-playwright` should only set up end-to-end tests remove `--ct` and the component testing prompts, templates, and setup code preserve JavaScript and TypeScript test generation --- assets/playwright-ct.config.js | 47 -------------- assets/playwright-ct.config.ts | 46 ------------- assets/playwright/index.html | 12 ---- assets/playwright/index.js | 2 - src/cli.ts | 2 - src/generator.ts | 110 +++++--------------------------- src/packageManager.ts | 17 ----- src/utils.ts | 11 ---- tests/component-testing.spec.ts | 54 ---------------- tests/integration.spec.ts | 27 ++++---- tsconfig.json | 2 +- 11 files changed, 28 insertions(+), 302 deletions(-) delete mode 100644 assets/playwright-ct.config.js delete mode 100644 assets/playwright-ct.config.ts delete mode 100644 assets/playwright/index.html delete mode 100644 assets/playwright/index.js delete mode 100644 tests/component-testing.spec.ts diff --git a/assets/playwright-ct.config.js b/assets/playwright-ct.config.js deleted file mode 100644 index 2590b93..0000000 --- a/assets/playwright-ct.config.js +++ /dev/null @@ -1,47 +0,0 @@ -// @ts-check -import { defineConfig, devices } from '{{ctPackageName}}'; - -/** - * @see https://playwright.dev/docs/test-configuration - */ -module.exports = defineConfig({ - testDir: './{{testDir}}', - /* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */ - snapshotDir: './__snapshots__', - /* Maximum time one test can run for. */ - timeout: 10 * 1000, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, - /* Limit the whole test run, so that it fails with a report instead of hanging. */ - globalTimeout: 60 * 60 * 1000, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: process.env.CI ? [['list', { printOnlyFailures: true }], ['html']] : 'html', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - - /* Port to use for Playwright component endpoint. */ - ctPort: 3100, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, - }, - { - name: 'firefox', - use: { ...devices['Desktop Firefox'] }, - }, - { - name: 'webkit', - use: { ...devices['Desktop Safari'] }, - }, - ], -}); diff --git a/assets/playwright-ct.config.ts b/assets/playwright-ct.config.ts deleted file mode 100644 index 59c9d68..0000000 --- a/assets/playwright-ct.config.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { defineConfig, devices } from '{{ctPackageName}}'; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -export default defineConfig({ - testDir: './{{testDir}}', - /* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */ - snapshotDir: './__snapshots__', - /* Maximum time one test can run for. */ - timeout: 10 * 1000, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, - /* Limit the whole test run, so that it fails with a report instead of hanging. */ - globalTimeout: 60 * 60 * 1000, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: process.env.CI ? [['list', { printOnlyFailures: true }], ['html']] : 'html', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - - /* Port to use for Playwright component endpoint. */ - ctPort: 3100, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, - }, - { - name: 'firefox', - use: { ...devices['Desktop Firefox'] }, - }, - { - name: 'webkit', - use: { ...devices['Desktop Safari'] }, - }, - ], -}); diff --git a/assets/playwright/index.html b/assets/playwright/index.html deleted file mode 100644 index 6aadf94..0000000 --- a/assets/playwright/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Testing Page - - -
- - - diff --git a/assets/playwright/index.js b/assets/playwright/index.js deleted file mode 100644 index ac6de14..0000000 --- a/assets/playwright/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// Import styles, initialize component theme here. -// import '../src/common.css'; diff --git a/src/cli.ts b/src/cli.ts index 11c73a2..e01225f 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -30,7 +30,6 @@ program .option('--install-deps', 'install dependencies') .option('--next', 'install @next version of Playwright') .option('--beta', 'install @beta version of Playwright') - .option('--ct', 'install Playwright Component testing') .option('--quiet', 'do not ask for interactive input prompts') .option('--gha', 'install GitHub Actions') .option('--lang ', 'language to use (js, TypeScript)') @@ -44,7 +43,6 @@ program installDeps: options.installDeps, next: options.next, beta: options.beta, - ct: options.ct, quiet: options.quiet, gha: options.gha, lang: options.lang, diff --git a/src/generator.ts b/src/generator.ts index 1383460..f69c768 100644 --- a/src/generator.ts +++ b/src/generator.ts @@ -21,13 +21,12 @@ import { prompt } from 'enquirer'; import ini from 'ini'; import { type PackageManager, determinePackageManager } from './packageManager'; -import { Command, createFiles, executeCommands, executeTemplate, getFileExtensionCT, languageToFileExtension } from './utils'; +import { Command, createFiles, executeCommands, executeTemplate, languageToFileExtension } from './utils'; export type PromptOptions = { testDir: string, installGitHubActions: boolean, language: 'JavaScript' | 'TypeScript', - framework?: 'react' | 'react17' | 'vue' | 'vue2' | 'svelte' | 'solid' | undefined, installPlaywrightDependencies: boolean, installPlaywrightBrowsers: boolean, }; @@ -42,7 +41,6 @@ export type CliOptions = { installDeps?: boolean; next?: boolean; beta?: boolean; - ct?: boolean; quiet?: boolean; gha?: boolean; testDir?: string; @@ -70,12 +68,9 @@ export class Generator { executeCommands(this.rootDir, preCommands); await createFiles(this.rootDir, files, false, !!this.options.quiet); this._patchGitIgnore(); - await this._patchPackageJSON(answers); + await this._patchPackageJSON(); executeCommands(this.rootDir, postCommands); - if (answers.framework) - this._printEpilogueCT(); - else - this._printEpilogue(answers); + this._printEpilogue(answers); } private _printPrologue() { @@ -95,7 +90,6 @@ export class Generator { language: this.options.lang === 'js' ? 'JavaScript' : 'TypeScript', installPlaywrightDependencies: !!this.options.installDeps, testDir, - framework: undefined, installPlaywrightBrowsers: !this.options.noBrowsers, }; } @@ -114,27 +108,14 @@ export class Generator { initial: this.options.lang === 'js' ? 'JavaScript' : 'TypeScript', skip: !!this.options.lang, }, - this.options.ct && { - type: 'select', - name: 'framework', - message: 'Which framework do you use? (experimental)', - choices: [ - { name: 'react', message: 'React 18' }, - { name: 'react17', message: 'React 17' }, - { name: 'vue', message: 'Vue 3' }, - { name: 'vue2', message: 'Vue 2' }, - { name: 'svelte', message: 'Svelte' }, - { name: 'solid', message: 'Solid' }, - ], - }, - !this.options.ct && { + { type: 'text', name: 'testDir', message: 'Where to put your end-to-end tests?', initial: testDir, skip: !!this.options.testDir, }, - !this.options.ct && { + { type: 'confirm', name: 'installGitHubActions', message: 'Add a GitHub Actions workflow?', @@ -181,20 +162,9 @@ export class Generator { if (answers.language === 'TypeScript') files.set('tsconfig.json', this._readAsset('tsconfig.json')); - let ctPackageName; - let installExamples = !this.options.noExamples; - if (answers.framework) { - ctPackageName = `@playwright/experimental-ct-${answers.framework}`; - installExamples = false; - files.set(`playwright-ct.config.${fileExtension}`, executeTemplate(this._readAsset(`playwright-ct.config.${fileExtension}`), { - testDir: answers.testDir || '', - ctPackageName, - }, sections)); - } else { - files.set(`playwright.config.${fileExtension}`, executeTemplate(this._readAsset(`playwright.config.${fileExtension}`), { - testDir: answers.testDir || '', - }, sections)); - } + files.set(`playwright.config.${fileExtension}`, executeTemplate(this._readAsset(`playwright.config.${fileExtension}`), { + testDir: answers.testDir || '', + }, sections)); if (answers.installGitHubActions) { const npmrcExists = fs.existsSync(path.join(this.rootDir, '.npmrc')); @@ -202,12 +172,12 @@ export class Generator { const githubActionsScript = executeTemplate(this._readAsset('github-actions.yml'), { installDepsCommand: packageLockDisabled ? this.packageManager.i() : this.packageManager.ci(), installPlaywrightCommand: this.packageManager.npx('playwright', 'install --with-deps'), - runTestsCommand: answers.framework ? this.packageManager.run('test-ct') : this.packageManager.runPlaywrightTest(), + runTestsCommand: this.packageManager.runPlaywrightTest(), }, new Map()); files.set('.github/workflows/playwright.yml', githubActionsScript); } - if (installExamples) + if (!this.options.noExamples) files.set(path.join(answers.testDir, `example.spec.${fileExtension}`), this._readAsset(`example.spec.${fileExtension}`)); if (!fs.existsSync(path.join(this.rootDir, 'package.json'))) { @@ -224,28 +194,11 @@ export class Generator { if (this.options.next) packageTag = '@next'; - if (!this.options.ct) { - commands.push({ - name: 'Installing Playwright Test', - command: this.packageManager.installDevDependency(`@playwright/test${packageTag}`), - phase: 'pre', - }); - } - - if (this.options.ct) { - commands.push({ - name: 'Installing Playwright Component Testing', - command: this.packageManager.installDevDependency(`${ctPackageName}${packageTag}`), - phase: 'pre', - }); - - const extension = getFileExtensionCT(answers.language, answers.framework); - const htmlTemplate = executeTemplate(this._readAsset(path.join('playwright', 'index.html')), { extension }, new Map()); - files.set('playwright/index.html', htmlTemplate); - - const jsTemplate = this._readAsset(path.join('playwright', 'index.js')); - files.set(`playwright/index.${extension}`, jsTemplate); - } + commands.push({ + name: 'Installing Playwright Test', + command: this.packageManager.installDevDependency(`@playwright/test${packageTag}`), + phase: 'pre', + }); if (!this._hasDependency('@types/node')) { commands.push({ @@ -291,7 +244,6 @@ export class Generator { '/test-results/': /^\/?test-results\/?$/m, '/playwright-report/': /^\/playwright-report\/?$/m, '/blob-report/': /^\/blob-report\/?$/m, - '/playwright/.cache/': /^\/playwright\/\.cache\/?$/m, '/playwright/.auth/': /^\/playwright\/\.auth\/?$/m, }; Object.entries(valuesToAdd).forEach(([value, regex]) => { @@ -311,17 +263,13 @@ export class Generator { return fs.readFileSync(path.isAbsolute(asset) ? asset : path.join(assetsDir, asset), 'utf-8'); } - private async _patchPackageJSON(answers: PromptOptions) { + private async _patchPackageJSON() { const packageJSON = JSON.parse(fs.readFileSync(path.join(this.rootDir, 'package.json'), 'utf-8')); if (!packageJSON.scripts) packageJSON.scripts = {}; if (packageJSON.scripts['test']?.includes('no test specified')) delete packageJSON.scripts['test']; - const extension = languageToFileExtension(answers.language); - if (answers.framework) - packageJSON.scripts['test-ct'] = `playwright test -c playwright-ct.config.${extension}`; - const files = new Map(); files.set('package.json', JSON.stringify(packageJSON, null, 2) + '\n'); // NPM keeps a trailing new-line await createFiles(this.rootDir, files, true, false); @@ -364,32 +312,6 @@ And check out the following files: Visit https://playwright.dev/docs/intro for more information. ✨ -Happy hacking! 🎭`); - } - - private _printEpilogueCT() { - console.log(colors.green('✔ Success!') + ' ' + colors.bold(`Created a Playwright Test project at ${this.rootDir}`)); - console.log(` -Inside that directory, you can run several commands: - - ${colors.cyan(`${this.packageManager.cli} run test-ct`)} - Runs the component tests. - - ${colors.cyan(`${this.packageManager.cli} run test-ct -- --project=chromium`)} - Runs the tests only on Desktop Chrome. - - ${colors.cyan(`${this.packageManager.cli} run test-ct App.test.ts`)} - Runs the tests in the specific file. - - ${colors.cyan(`${this.packageManager.cli} run test-ct -- --debug`)} - Runs the tests in debug mode. - -We suggest that you begin by typing: - - ${colors.cyan(`${this.packageManager.cli} run test-ct`)} - -Visit https://playwright.dev/docs/intro for more information. ✨ - Happy hacking! 🎭`); } } diff --git a/src/packageManager.ts b/src/packageManager.ts index b35a417..d054e33 100644 --- a/src/packageManager.ts +++ b/src/packageManager.ts @@ -18,7 +18,6 @@ import path from 'path'; import fs from 'fs'; export interface PackageManager { - cli: string; name: string init(): string npx(command: string, args: string): string @@ -26,12 +25,10 @@ export interface PackageManager { i(): string installDevDependency(name: string): string runPlaywrightTest(args?: string): string - run(script: string): string } class NPM implements PackageManager { name = 'NPM' - cli = 'npm' init(): string { return 'npm init -y' @@ -56,15 +53,10 @@ class NPM implements PackageManager { runPlaywrightTest(args: string): string { return this.npx('playwright', `test${args ? (' ' + args) : ''}`); } - - run(script: string): string { - return `npm run ${script}`; - } } class Yarn implements PackageManager { name = 'Yarn' - cli = 'yarn' private workspace: boolean private classic = false; @@ -106,15 +98,10 @@ class Yarn implements PackageManager { runPlaywrightTest(args: string): string { return this.npx('playwright', `test${args ? (' ' + args) : ''}`); } - - run(script: string): string { - return `yarn ${script}`; - } } class PNPM implements PackageManager { name = 'pnpm' - cli = 'pnpm' private workspace: boolean; constructor(rootDir: string) { @@ -144,10 +131,6 @@ class PNPM implements PackageManager { runPlaywrightTest(args: string): string { return this.npx('playwright', `test${args ? (' ' + args) : ''}`); } - - run(script: string): string { - return `pnpm run ${script}`; - } } export function determinePackageManager(rootDir: string): PackageManager { diff --git a/src/utils.ts b/src/utils.ts index d66e67f..4e74c68 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -91,17 +91,6 @@ export function executeTemplate(input: string, args: Record, sec return result.join('\n'); } -export function getFileExtensionCT(language: PromptOptions['language'], framework: PromptOptions['framework']) { - const isJsxFramework = framework === 'solid' || framework === 'react' || framework === 'react17'; - if (isJsxFramework && language === 'JavaScript') - return 'jsx'; - else if (isJsxFramework && language === 'TypeScript') - return 'tsx'; - else if (language === 'TypeScript') - return 'ts'; - return 'js'; -} - export function languageToFileExtension(language: PromptOptions['language']): 'js' | 'ts' { return language === 'JavaScript' ? 'js' : 'ts'; } diff --git a/tests/component-testing.spec.ts b/tests/component-testing.spec.ts deleted file mode 100644 index c228550..0000000 --- a/tests/component-testing.spec.ts +++ /dev/null @@ -1,54 +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 { test, expect, assertLockFilesExist, packageManagerToNpxCommand } from './baseFixtures'; -import path from 'path'; -import fs from 'fs'; - -test('should be able to generate and run a CT React project', { lock: 'apt-get' }, async ({ run, dir, exec, packageManager }) => { - test.skip(packageManager === 'yarn-classic' || packageManager === 'yarn-berry'); - test.slow(); - await run(['--ct'], { installGitHubActions: true, testDir: 'tests', language: 'TypeScript', installPlaywrightDependencies: false, installPlaywrightBrowsers: true, framework: 'react' }); - { - expect(fs.existsSync(path.join(dir, 'playwright/index.html'))).toBeTruthy(); - expect(fs.existsSync(path.join(dir, 'playwright-ct.config.ts'))).toBeTruthy(); - assertLockFilesExist(dir, packageManager); - } - - { - expect(fs.existsSync(path.join(dir, '.github/workflows/playwright.yml'))).toBeTruthy(); - expect(fs.readFileSync(path.join(dir, '.github/workflows/playwright.yml'), 'utf8')).toContain('test-ct'); - } - - await exec(packageManager, [((packageManager === 'yarn-classic' || packageManager === 'yarn-berry') ? 'add' : 'install'), 'react', 'react-dom']); - - fs.mkdirSync(path.join(dir, 'src')); - fs.writeFileSync(path.join(dir, 'src/App.tsx'), 'export default () => <>Learn React;'); - fs.mkdirSync(path.join(dir, 'tests')); - fs.writeFileSync(path.join(dir, 'tests/App.spec.tsx'), ` - import { test, expect } from '@playwright/experimental-ct-react'; - import App from '../src/App'; - - test.use({ viewport: { width: 500, height: 500 } }); - - test('should work', async ({ mount }) => { - const component = await mount(); - await expect(component).toContainText('Learn React'); - }); - `); - - await exec(packageManagerToNpxCommand(packageManager), ['playwright', 'install-deps']); - await exec(packageManager, ['run', 'test-ct']); -}); diff --git a/tests/integration.spec.ts b/tests/integration.spec.ts index cbac715..2187600 100644 --- a/tests/integration.spec.ts +++ b/tests/integration.spec.ts @@ -23,27 +23,22 @@ const validGitignore = [ '/test-results/', '/playwright-report/', '/blob-report/', - '/playwright/.cache/', '/playwright/.auth/' ].join('\n'); for (const language of ['TypeScript', 'JavaScript'] as const) { - for (const componentTesting of [false, true]) { - test(`should configure failures-only CI reporting for ${language} ${componentTesting ? 'component' : 'end-to-end'} tests`, async ({ run, dir }) => { - await run(componentTesting ? ['--ct'] : [], { - language, - testDir: 'tests', - installGitHubActions: false, - installPlaywrightDependencies: false, - installPlaywrightBrowsers: false, - framework: componentTesting ? 'react' : undefined, - }); - const extension = language === 'TypeScript' ? 'ts' : 'js'; - const file = componentTesting ? `playwright-ct.config.${extension}` : `playwright.config.${extension}`; - const config = fs.readFileSync(path.join(dir, file), 'utf8'); - expect(config).toContain("reporter: process.env.CI ? [['list', { printOnlyFailures: true }], ['html']] : 'html',"); + test(`should configure failures-only CI reporting for ${language} end-to-end tests`, async ({ run, dir }) => { + await run([], { + language, + testDir: 'tests', + installGitHubActions: false, + installPlaywrightDependencies: false, + installPlaywrightBrowsers: false, }); - } + const extension = language === 'TypeScript' ? 'ts' : 'js'; + const config = fs.readFileSync(path.join(dir, `playwright.config.${extension}`), 'utf8'); + expect(config).toContain("reporter: process.env.CI ? [['list', { printOnlyFailures: true }], ['html']] : 'html',"); + }); } test('should generate a project in the current directory', async ({ run, dir, packageManager }) => { diff --git a/tsconfig.json b/tsconfig.json index c83e81d..210fcd9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,5 +14,5 @@ "noUncheckedIndexedAccess": true }, "compileOnSave": true, - "exclude": ["node_modules", "lib", "test-results", "assets/playwright-ct.config.ts", "assets/playwright-ct.config.js"] + "exclude": ["node_modules", "lib", "test-results"] } \ No newline at end of file