From 5a822120de80d2c61faf3fbcf44c19caa14e55a9 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Thu, 11 Jan 2024 13:50:28 +0100 Subject: [PATCH] feat: add support for Bun --- .github/workflows/ci.yml | 3 ++ package-lock.json | 82 ++++++++++++++++++++++++--------------- package.json | 4 +- playwright.config.ts | 14 ++++++- src/packageManager.ts | 31 +++++++++++++++ tests/baseFixtures.ts | 22 ++++++++++- tests/integration.spec.ts | 4 ++ 7 files changed, 123 insertions(+), 37 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82a0a77..c426a78 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,9 @@ jobs: - run: npm i -g npm@8 - run: npm i -g yarn@1 - run: npm i -g pnpm@7 + # https://github.com/oven-sh/bun/issues/43 + - run: npm i -g bun@1 + if: matrix.os != 'windows-latest' - run: npm ci - run: npx playwright install-deps - run: npm run build diff --git a/package-lock.json b/package-lock.json index 57f46fa..822622b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,8 +12,8 @@ "create-playwright": "index.js" }, "devDependencies": { - "@playwright/test": "^1.38.1", - "@types/node": "^16.11.11", + "@playwright/test": "^1.41.0-alpha-1704968142000", + "@types/node": "^18.19.6", "ansi-colors": "^4.1.1", "enquirer": "^2.3.6", "esbuild": "^0.14.25", @@ -24,12 +24,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.38.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.1.tgz", - "integrity": "sha512-NqRp8XMwj3AK+zKLbZShl0r/9wKgzqI/527bkptKXomtuo+dOjU9NdMASQ8DNC9z9zLOMbG53T4eihYr3XR+BQ==", + "version": "1.41.0-alpha-1704968142000", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.0-alpha-1704968142000.tgz", + "integrity": "sha512-M0TyIcRsDokUXb+NJKJQRncnnC9/S42pzJCeI18sPJBdgtKBYksANcgzVKpo4SvYyoWy1opHUMaTPjbVMaLJrg==", "dev": true, "dependencies": { - "playwright": "1.38.1" + "playwright": "1.41.0-alpha-1704968142000" }, "bin": { "playwright": "cli.js" @@ -39,10 +39,13 @@ } }, "node_modules/@types/node": { - "version": "16.11.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", - "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==", - "dev": true + "version": "18.19.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.6.tgz", + "integrity": "sha512-X36s5CXMrrJOs2lQCdDF68apW4Rfx9ixYMawlepwmE4Anezv/AV2LSpKD1Ub8DAc+urp5bk0BGZ6NtmBitfnsg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/ansi-colors": { "version": "4.1.1", @@ -435,12 +438,12 @@ } }, "node_modules/playwright": { - "version": "1.38.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.1.tgz", - "integrity": "sha512-oRMSJmZrOu1FP5iu3UrCx8JEFRIMxLDM0c/3o4bpzU5Tz97BypefWf7TuTNPWeCe279TPal5RtPPZ+9lW/Qkow==", + "version": "1.41.0-alpha-1704968142000", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.0-alpha-1704968142000.tgz", + "integrity": "sha512-5igNln0Tcfn6ba7YXz1pKE66YLhzqFlz+aElvIAP11XXLMPv4u7EG3u+DLaK4R4C1njjd+J0hYBpVWGp7QcKJQ==", "dev": true, "dependencies": { - "playwright-core": "1.38.1" + "playwright-core": "1.41.0-alpha-1704968142000" }, "bin": { "playwright": "cli.js" @@ -453,9 +456,9 @@ } }, "node_modules/playwright-core": { - "version": "1.38.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.1.tgz", - "integrity": "sha512-tQqNFUKa3OfMf4b2jQ7aGLB8o9bS3bOY0yMEtldtC2+spf8QXG9zvXLTXUeRsoNuxEYMgLYR+NXfAa1rjKRcrg==", + "version": "1.41.0-alpha-1704968142000", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.0-alpha-1704968142000.tgz", + "integrity": "sha512-XIl9mpBt3AVy7p9DkI14NilFNYITpoEMqsy3mFuGTVCnagX4qZOhzN43dUwIvwfJECdmA1GAa3kUbkuZAtnpvg==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -476,23 +479,32 @@ "engines": { "node": ">=4.2.0" } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true } }, "dependencies": { "@playwright/test": { - "version": "1.38.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.1.tgz", - "integrity": "sha512-NqRp8XMwj3AK+zKLbZShl0r/9wKgzqI/527bkptKXomtuo+dOjU9NdMASQ8DNC9z9zLOMbG53T4eihYr3XR+BQ==", + "version": "1.41.0-alpha-1704968142000", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.0-alpha-1704968142000.tgz", + "integrity": "sha512-M0TyIcRsDokUXb+NJKJQRncnnC9/S42pzJCeI18sPJBdgtKBYksANcgzVKpo4SvYyoWy1opHUMaTPjbVMaLJrg==", "dev": true, "requires": { - "playwright": "1.38.1" + "playwright": "1.41.0-alpha-1704968142000" } }, "@types/node": { - "version": "16.11.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", - "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==", - "dev": true + "version": "18.19.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.6.tgz", + "integrity": "sha512-X36s5CXMrrJOs2lQCdDF68apW4Rfx9ixYMawlepwmE4Anezv/AV2LSpKD1Ub8DAc+urp5bk0BGZ6NtmBitfnsg==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } }, "ansi-colors": { "version": "4.1.1", @@ -685,19 +697,19 @@ "optional": true }, "playwright": { - "version": "1.38.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.1.tgz", - "integrity": "sha512-oRMSJmZrOu1FP5iu3UrCx8JEFRIMxLDM0c/3o4bpzU5Tz97BypefWf7TuTNPWeCe279TPal5RtPPZ+9lW/Qkow==", + "version": "1.41.0-alpha-1704968142000", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.0-alpha-1704968142000.tgz", + "integrity": "sha512-5igNln0Tcfn6ba7YXz1pKE66YLhzqFlz+aElvIAP11XXLMPv4u7EG3u+DLaK4R4C1njjd+J0hYBpVWGp7QcKJQ==", "dev": true, "requires": { "fsevents": "2.3.2", - "playwright-core": "1.38.1" + "playwright-core": "1.41.0-alpha-1704968142000" } }, "playwright-core": { - "version": "1.38.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.1.tgz", - "integrity": "sha512-tQqNFUKa3OfMf4b2jQ7aGLB8o9bS3bOY0yMEtldtC2+spf8QXG9zvXLTXUeRsoNuxEYMgLYR+NXfAa1rjKRcrg==", + "version": "1.41.0-alpha-1704968142000", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.0-alpha-1704968142000.tgz", + "integrity": "sha512-XIl9mpBt3AVy7p9DkI14NilFNYITpoEMqsy3mFuGTVCnagX4qZOhzN43dUwIvwfJECdmA1GAa3kUbkuZAtnpvg==", "dev": true }, "typescript": { @@ -705,6 +717,12 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", "dev": true + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true } } } diff --git a/package.json b/package.json index 8940311..dfc9fc0 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "prepublish": "npm run build" }, "devDependencies": { - "@playwright/test": "^1.38.1", - "@types/node": "^16.11.11", + "@playwright/test": "^1.41.0-alpha-1704968142000", + "@types/node": "^18.19.6", "ansi-colors": "^4.1.1", "enquirer": "^2.3.6", "esbuild": "^0.14.25", diff --git a/playwright.config.ts b/playwright.config.ts index cf87857..b0122cd 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -16,7 +16,7 @@ import { defineConfig } from '@playwright/test'; import type { TestFixtures } from './tests/baseFixtures'; -export default defineConfig({ +const config = defineConfig({ timeout: 120 * 1000, testDir: './tests', reporter: 'list', @@ -42,3 +42,15 @@ export default defineConfig({ }, ] }); + +// https://github.com/oven-sh/bun/issues/43 +if (process.platform !== 'win32') { + config.projects?.push({ + name: 'bun', + use: { + packageManager: 'bun' + } + }) +} + +export default config; diff --git a/src/packageManager.ts b/src/packageManager.ts index 6fda2bc..d0ffbd4 100644 --- a/src/packageManager.ts +++ b/src/packageManager.ts @@ -102,12 +102,43 @@ class PNPM implements PackageManager { } } +class Bun implements PackageManager { + name = 'Bun' + cli = 'bun' + + init(): string { + return 'bun init -y' + } + + npx(command: string, args: string): string { + return `bun --bun x ${command} ${args}` + } + + ci(): string { + return 'bun install' + } + + installDevDependency(name: string): string { + return `bun install --dev ${name}` + } + + runPlaywrightTest(args: string): string { + return this.npx('playwright', `test${args ? (' ' + args) : ''}`); + } + + run(script: string): string { + return `bun run ${script}`; + } +} + 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(); if (process.env.npm_config_user_agent.includes('pnpm')) return new PNPM(fs.existsSync(path.resolve(rootDir, 'pnpm-workspace.yaml'))); + if (process.env.npm_config_user_agent.includes('bun')) + return new Bun(); return new NPM(); } return new NPM(); diff --git a/tests/baseFixtures.ts b/tests/baseFixtures.ts index 285d19d..9ef4625 100644 --- a/tests/baseFixtures.ts +++ b/tests/baseFixtures.ts @@ -20,7 +20,7 @@ import path from 'path'; import fs from 'fs'; import type { PromptOptions } from '../src/generator'; -export type PackageManager = 'npm' | 'pnpm' | 'yarn'; +export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun'; export type TestFixtures = { packageManager: PackageManager; @@ -82,7 +82,7 @@ export const test = base.extend({ cwd: dir, env: { ...process.env, - 'npm_config_user_agent': packageManager === 'yarn' ? 'yarn' : packageManager === 'pnpm' ? 'pnpm/0.0.0' : undefined, + 'npm_config_user_agent': packageManagerToNpmConfigUserAgent(packageManager), 'TEST_OPTIONS': JSON.stringify(options), }, }); @@ -90,6 +90,19 @@ export const test = base.extend({ }, }); +function packageManagerToNpmConfigUserAgent(packageManager: PackageManager): string { + switch (packageManager) { + case 'npm': + return 'npm/10.2.4 node/v20.11.0 linux x64 workspaces/false' + case 'yarn': + return 'yarn/1.22.21 npm/? node/v20.11.0 linux x64'; + case 'pnpm': + return 'pnpm/8.14.1 npm/? node/v20.11.0 linux x64'; + case 'bun': + return 'bun/1.0.22 npm/? node/v20.8.0 linux x64' + } +} + export function assertLockFilesExist(dir: string, packageManager: PackageManager) { expect(fs.existsSync(path.join(dir, 'package.json'))).toBeTruthy(); if (packageManager === 'npm') @@ -98,6 +111,8 @@ export function assertLockFilesExist(dir: string, packageManager: PackageManager expect(fs.existsSync(path.join(dir, 'yarn.lock'))).toBeTruthy(); else if (packageManager === 'pnpm') expect(fs.existsSync(path.join(dir, 'pnpm-lock.yaml'))).toBeTruthy(); + else if (packageManager === 'bun') + expect(fs.existsSync(path.join(dir, 'bun.lockb'))).toBeTruthy(); } export function packageManagerToNpxCommand(packageManager: PackageManager): string { @@ -108,7 +123,10 @@ export function packageManagerToNpxCommand(packageManager: PackageManager): stri return 'yarn'; case 'pnpm': return 'pnpm dlx'; + case 'bun': + return 'bun --bun x'; } + throw new Error(`Unsupported package manager: ${packageManager}!`); } export const expect = test.expect; diff --git a/tests/integration.spec.ts b/tests/integration.spec.ts index 059d3bd..e7abf12 100644 --- a/tests/integration.spec.ts +++ b/tests/integration.spec.ts @@ -41,6 +41,10 @@ test('should generate a project in the current directory', async ({ run, dir, pa expect(stdout).toContain('pnpm init'); // pnpm command outputs name in different case, hence we are not testing the whole string expect(stdout).toContain('Installing Playwright Test (pnpm add --save-dev @playwright/test)…'); expect(stdout).toContain('Installing Types (pnpm add --save-dev @types/node)…'); + } else if (packageManager === 'bun') { + expect(stdout).toContain('Initializing Bun project (bun init -y)…'); + expect(stdout).toContain('Installing Playwright Test (bun install --dev @playwright/test)…'); + expect(stdout).toContain('Installing Types (bun install --dev @types/node)…'); } expect(stdout).toContain('npx playwright install' + process.platform === 'linux' ? ' --with-deps' : ''); });