Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 27 additions & 24 deletions src/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { prompt } from 'enquirer';
import colors from 'ansi-colors';

import { executeCommands, createFiles, executeTemplate, Command, languageToFileExtension, getFileExtensionCT } from './utils';
import { packageManager } from './packageManager';
import { type PackageManager, determinePackageManager } from './packageManager';

export type PromptOptions = {
testDir: string,
Expand All @@ -46,9 +46,12 @@ type CliArgumentKey = 'browser'
| 'lang';

export class Generator {
private packageManager: PackageManager;

constructor(private readonly rootDir: string, private readonly options: Partial<Record<CliArgumentKey, string[]>>) {
if (!fs.existsSync(rootDir))
fs.mkdirSync(rootDir);
this.packageManager = determinePackageManager(rootDir);
}

async run() {
Expand Down Expand Up @@ -124,15 +127,15 @@ export class Generator {
{
type: 'confirm',
name: 'installPlaywrightBrowsers',
message: `Install Playwright browsers (can be done manually via '${packageManager.npx('playwright', 'install')}')?`,
message: `Install Playwright browsers (can be done manually via '${this.packageManager.npx('playwright', 'install')}')?`,
initial: true,
},
// Avoid installing dependencies on Windows (vast majority does not run create-playwright on Windows)
// Avoid installing dependencies on Mac (there are no dependencies)
process.platform === 'linux' && {
type: 'confirm',
name: 'installPlaywrightDependencies',
message: `Install Playwright operating system dependencies (requires sudo / root - can be done manually via 'sudo ${packageManager.npx('playwright', 'install-deps')}')?`,
message: `Install Playwright operating system dependencies (requires sudo / root - can be done manually via 'sudo ${this.packageManager.npx('playwright', 'install-deps')}')?`,
initial: false,
},
];
Expand Down Expand Up @@ -168,9 +171,9 @@ export class Generator {

if (answers.installGitHubActions) {
const githubActionsScript = executeTemplate(this._readAsset('github-actions.yml'), {
installDepsCommand: packageManager.ci(),
installPlaywrightCommand: packageManager.npx('playwright', 'install --with-deps'),
runTestsCommand: answers.framework ? packageManager.run('test-ct') : packageManager.runPlaywrightTest(),
installDepsCommand: this.packageManager.ci(),
installPlaywrightCommand: this.packageManager.npx('playwright', 'install --with-deps'),
runTestsCommand: answers.framework ? this.packageManager.run('test-ct') : this.packageManager.runPlaywrightTest(),
}, new Map());
files.set('.github/workflows/playwright.yml', githubActionsScript);
}
Expand All @@ -182,8 +185,8 @@ export class Generator {

if (!fs.existsSync(path.join(this.rootDir, 'package.json'))) {
commands.push({
name: `Initializing ${packageManager.name} project`,
command: packageManager.init(),
name: `Initializing ${this.packageManager.name} project`,
command: this.packageManager.init(),
});
}

Expand All @@ -196,14 +199,14 @@ export class Generator {
if (!this.options.ct) {
commands.push({
name: 'Installing Playwright Test',
command: packageManager.installDevDependency(`@playwright/test${packageTag}`),
command: this.packageManager.installDevDependency(`@playwright/test${packageTag}`),
});
}

if (this.options.ct) {
commands.push({
name: 'Installing Playwright Component Testing',
command: packageManager.installDevDependency(`${ctPackageName}${packageTag}`),
command: this.packageManager.installDevDependency(`${ctPackageName}${packageTag}`),
});

const extension = getFileExtensionCT(answers.language, answers.framework);
Expand All @@ -217,15 +220,15 @@ export class Generator {
if (!this._hasDependency('@types/node')) {
commands.push({
name: 'Installing Types',
command: packageManager.installDevDependency(`@types/node`),
command: this.packageManager.installDevDependency(`@types/node`),
});
}

const browsersSuffix = this.options.browser ? ' ' + this.options.browser.join(' ') : '';
if (answers.installPlaywrightBrowsers) {
commands.push({
name: 'Downloading browsers',
command: packageManager.npx('playwright', 'install') + (answers.installPlaywrightDependencies ? ' --with-deps' : '') + browsersSuffix,
command: this.packageManager.npx('playwright', 'install') + (answers.installPlaywrightDependencies ? ' --with-deps' : '') + browsersSuffix,
});
}

Expand Down Expand Up @@ -285,27 +288,27 @@ export class Generator {
console.log(`
Inside that directory, you can run several commands:

${colors.cyan(packageManager.runPlaywrightTest())}
${colors.cyan(this.packageManager.runPlaywrightTest())}
Runs the end-to-end tests.

${colors.cyan(packageManager.runPlaywrightTest('--ui'))}
${colors.cyan(this.packageManager.runPlaywrightTest('--ui'))}
Starts the interactive UI mode.

${colors.cyan(packageManager.runPlaywrightTest('--project=chromium'))}
${colors.cyan(this.packageManager.runPlaywrightTest('--project=chromium'))}
Runs the tests only on Desktop Chrome.

${colors.cyan(packageManager.runPlaywrightTest('example'))}
${colors.cyan(this.packageManager.runPlaywrightTest('example'))}
Runs the tests in a specific file.

${colors.cyan(packageManager.runPlaywrightTest('--debug'))}
${colors.cyan(this.packageManager.runPlaywrightTest('--debug'))}
Runs the tests in debug mode.

${colors.cyan(packageManager.npx('playwright', 'codegen'))}
${colors.cyan(this.packageManager.npx('playwright', 'codegen'))}
Auto generate tests with Codegen.

We suggest that you begin by typing:

${colors.cyan(prefix + ' ' + packageManager.runPlaywrightTest())}
${colors.cyan(prefix + ' ' + this.packageManager.runPlaywrightTest())}

And check out the following files:
- .${path.sep}${pathToNavigate ? path.join(pathToNavigate, exampleSpecPath) : exampleSpecPath} - Example end-to-end test
Expand All @@ -322,21 +325,21 @@ Happy hacking! 🎭`);
console.log(`
Inside that directory, you can run several commands:

${colors.cyan(`${packageManager.cli} run test-ct`)}
${colors.cyan(`${this.packageManager.cli} run test-ct`)}
Runs the component tests.

${colors.cyan(`${packageManager.cli} run test-ct -- --project=chromium`)}
${colors.cyan(`${this.packageManager.cli} run test-ct -- --project=chromium`)}
Runs the tests only on Desktop Chrome.

${colors.cyan(`${packageManager.cli} run test-ct App.test.ts`)}
${colors.cyan(`${this.packageManager.cli} run test-ct App.test.ts`)}
Runs the tests in the specific file.

${colors.cyan(`${packageManager.cli} run test-ct -- --debug`)}
${colors.cyan(`${this.packageManager.cli} run test-ct -- --debug`)}
Runs the tests in debug mode.

We suggest that you begin by typing:

${colors.cyan(`${packageManager.cli} run test-ct`)}
${colors.cyan(`${this.packageManager.cli} run test-ct`)}

Visit https://playwright.dev/docs/intro for more information. ✨

Expand Down
24 changes: 14 additions & 10 deletions src/packageManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
interface PackageManager {
import path from 'path';
import fs from 'fs';

export interface PackageManager {
cli: string;
name: string
init(): string
Expand Down Expand Up @@ -61,7 +64,7 @@ class Yarn implements PackageManager {
runPlaywrightTest(args: string): string {
return this.npx('playwright', `test${args ? (' ' + args) : ''}`);
}

run(script: string): string {
return `yarn ${script}`;
}
Expand All @@ -71,6 +74,9 @@ class PNPM implements PackageManager {
name = 'pnpm'
cli = 'pnpm'

constructor(private workspace: boolean) {
}

init(): string {
return 'pnpm init'
}
Expand All @@ -84,7 +90,7 @@ class PNPM implements PackageManager {
}

installDevDependency(name: string): string {
return `pnpm add --save-dev ${name}`
return `pnpm add --save-dev ${this.workspace ? '-w ' : ''}${name}`
}

runPlaywrightTest(args: string): string {
Expand All @@ -96,15 +102,13 @@ class PNPM implements PackageManager {
}
}

function determinePackageManager(): PackageManager {
export function determinePackageManager(rootDir: string): PackageManager {
if (process.env.npm_config_user_agent) {
if (process.env.npm_config_user_agent.includes('yarn'))
return new Yarn()
return new Yarn();
if (process.env.npm_config_user_agent.includes('pnpm'))
return new PNPM()
return new NPM()
return new PNPM(fs.existsSync(path.resolve(rootDir, 'pnpm-workspace.yaml')));
return new NPM();
}
return new NPM()
return new NPM();
}

export const packageManager = determinePackageManager();
17 changes: 17 additions & 0 deletions tests/integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import { test, expect, packageManagerToNpxCommand, assertLockFilesExist } from './baseFixtures';
import path from 'path';
import fs from 'fs';
import childProcess from 'child_process';

test('should generate a project in the current directory', async ({ run, dir, packageManager }) => {
test.slow();
Expand Down Expand Up @@ -84,3 +85,19 @@ test('should generate be able to run JS examples successfully', async ({ run, di
await exec(packageManagerToNpxCommand(packageManager), ['playwright', 'test']);
});

test('should generate in the root of pnpm workspace', async ({ run, packageManager }) => {
test.skip(packageManager !== 'pnpm');

const dir = test.info().outputDir;
fs.mkdirSync(dir, { recursive: true });
childProcess.execSync('pnpm init', { cwd: dir });
fs.writeFileSync(path.join(dir, 'pnpm-workspace.yaml'), `packages:\n - 'packages/*'\n`);
fs.mkdirSync(path.join(dir, 'packages', 'foo'), { recursive: true });
fs.writeFileSync(path.join(dir, 'packages', 'foo', 'package.json'), `{}`);

await run([], { installGitHubActions: false, testDir: 'tests', language: 'TypeScript', installPlaywrightDependencies: false, installPlaywrightBrowsers: false });
assertLockFilesExist(dir, packageManager);
expect(fs.existsSync(path.join(dir, 'tests/example.spec.ts'))).toBeTruthy();
expect(fs.existsSync(path.join(dir, 'package.json'))).toBeTruthy();
expect(fs.existsSync(path.join(dir, 'playwright.config.ts'))).toBeTruthy();
});