From 05cf78fe0588c3c26a0c8fb9019563dd153c947b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 07:45:05 +0000 Subject: [PATCH 1/6] Initial plan From 388e33b534c45da108f5df6bf62556a3e59ee096 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 07:49:23 +0000 Subject: [PATCH 2/6] fix: remove --with-deps from playwright install to prevent sudo requirement Co-authored-by: valentinpalkovic <5889929+valentinpalkovic@users.noreply.github.com> --- code/addons/vitest/src/postinstall.ts | 2 +- code/core/src/cli/AddonVitestService.test.ts | 4 ++-- code/core/src/cli/AddonVitestService.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/code/addons/vitest/src/postinstall.ts b/code/addons/vitest/src/postinstall.ts index 543d5c579b4f..3a493650dd8f 100644 --- a/code/addons/vitest/src/postinstall.ts +++ b/code/addons/vitest/src/postinstall.ts @@ -167,7 +167,7 @@ export default async function postInstall(options: PostinstallOptions) { } else { logger.warn(dedent` Playwright browser binaries installation skipped. Please run the following command manually later: - ${CLI_COLORS.cta('npx playwright install chromium --with-deps')} + ${CLI_COLORS.cta('npx playwright install chromium')} `); } } diff --git a/code/core/src/cli/AddonVitestService.test.ts b/code/core/src/cli/AddonVitestService.test.ts index 17379adac94a..beba97f84124 100644 --- a/code/core/src/cli/AddonVitestService.test.ts +++ b/code/core/src/cli/AddonVitestService.test.ts @@ -391,7 +391,7 @@ describe('AddonVitestService', () => { vi.mocked(logger.warn).mockImplementation(() => {}); // Mock getPackageCommand to return a string vi.mocked(mockPackageManager.getPackageCommand).mockReturnValue( - 'npx playwright install chromium --with-deps' + 'npx playwright install chromium' ); }); @@ -430,7 +430,7 @@ describe('AddonVitestService', () => { await service.installPlaywright(); expect(mockPackageManager.runPackageCommand).toHaveBeenCalledWith({ - args: ['playwright', 'install', 'chromium', '--with-deps'], + args: ['playwright', 'install', 'chromium'], signal: undefined, stdio: ['inherit', 'pipe', 'pipe'], }); diff --git a/code/core/src/cli/AddonVitestService.ts b/code/core/src/cli/AddonVitestService.ts index 2212f74b9b4d..c2b3e4e0df26 100644 --- a/code/core/src/cli/AddonVitestService.ts +++ b/code/core/src/cli/AddonVitestService.ts @@ -106,7 +106,7 @@ export class AddonVitestService { /** * Install Playwright browser binaries for @storybook/addon-vitest * - * Installs Chromium with dependencies via `npx playwright install chromium --with-deps` + * Installs Chromium via `npx playwright install chromium` * * @param packageManager - The package manager to use for installation * @param prompt - The prompt instance for displaying progress @@ -123,7 +123,7 @@ export class AddonVitestService { ): Promise<{ errors: string[]; result: 'installed' | 'skipped' | 'aborted' | 'failed' }> { const errors: string[] = []; - const playwrightCommand = ['playwright', 'install', 'chromium', '--with-deps']; + const playwrightCommand = ['playwright', 'install', 'chromium']; const playwrightCommandString = this.packageManager.getPackageCommand(playwrightCommand); let result: 'installed' | 'skipped' | 'aborted' | 'failed'; From 590dffbc6e666174e4a2fa9468041eba36e9fccb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 08:45:46 +0000 Subject: [PATCH 3/6] fix: use --with-deps only in CI environments for playwright install Co-authored-by: valentinpalkovic <5889929+valentinpalkovic@users.noreply.github.com> --- code/core/src/cli/AddonVitestService.test.ts | 72 +++++++++++++++----- code/core/src/cli/AddonVitestService.ts | 7 +- 2 files changed, 60 insertions(+), 19 deletions(-) diff --git a/code/core/src/cli/AddonVitestService.test.ts b/code/core/src/cli/AddonVitestService.test.ts index beba97f84124..c82fbd275b79 100644 --- a/code/core/src/cli/AddonVitestService.test.ts +++ b/code/core/src/cli/AddonVitestService.test.ts @@ -416,24 +416,62 @@ describe('AddonVitestService', () => { }); it('should execute playwright install command', async () => { - type ChildProcessFactory = (signal?: AbortSignal) => ResultPromise; - let commandFactory: ChildProcessFactory | ChildProcessFactory[]; - vi.mocked(prompt.confirm).mockResolvedValue(true); - vi.mocked(prompt.executeTaskWithSpinner).mockImplementation( - async (factory: ChildProcessFactory | ChildProcessFactory[]) => { - commandFactory = Array.isArray(factory) ? factory[0] : factory; - // Simulate the child process completion - commandFactory(); + const originalCI = process.env.CI; + delete process.env.CI; + try { + type ChildProcessFactory = (signal?: AbortSignal) => ResultPromise; + let commandFactory: ChildProcessFactory | ChildProcessFactory[]; + vi.mocked(prompt.confirm).mockResolvedValue(true); + vi.mocked(prompt.executeTaskWithSpinner).mockImplementation( + async (factory: ChildProcessFactory | ChildProcessFactory[]) => { + commandFactory = Array.isArray(factory) ? factory[0] : factory; + // Simulate the child process completion + commandFactory(); + } + ); + + await service.installPlaywright(); + + expect(mockPackageManager.runPackageCommand).toHaveBeenCalledWith({ + args: ['playwright', 'install', 'chromium'], + signal: undefined, + stdio: ['inherit', 'pipe', 'pipe'], + }); + } finally { + if (originalCI !== undefined) { + process.env.CI = originalCI; } - ); - - await service.installPlaywright(); - - expect(mockPackageManager.runPackageCommand).toHaveBeenCalledWith({ - args: ['playwright', 'install', 'chromium'], - signal: undefined, - stdio: ['inherit', 'pipe', 'pipe'], - }); + } + }); + + it('should execute playwright install command with --with-deps in CI', async () => { + const originalCI = process.env.CI; + process.env.CI = 'true'; + try { + type ChildProcessFactory = (signal?: AbortSignal) => ResultPromise; + let commandFactory: ChildProcessFactory | ChildProcessFactory[]; + vi.mocked(prompt.confirm).mockResolvedValue(true); + vi.mocked(prompt.executeTaskWithSpinner).mockImplementation( + async (factory: ChildProcessFactory | ChildProcessFactory[]) => { + commandFactory = Array.isArray(factory) ? factory[0] : factory; + commandFactory(); + } + ); + + await service.installPlaywright(); + + expect(mockPackageManager.runPackageCommand).toHaveBeenCalledWith({ + args: ['playwright', 'install', 'chromium', '--with-deps'], + signal: undefined, + stdio: ['inherit', 'pipe', 'pipe'], + }); + } finally { + if (originalCI === undefined) { + delete process.env.CI; + } else { + process.env.CI = originalCI; + } + } }); it('should capture error stack when installation fails', async () => { diff --git a/code/core/src/cli/AddonVitestService.ts b/code/core/src/cli/AddonVitestService.ts index c2b3e4e0df26..ecf77915feed 100644 --- a/code/core/src/cli/AddonVitestService.ts +++ b/code/core/src/cli/AddonVitestService.ts @@ -106,7 +106,8 @@ export class AddonVitestService { /** * Install Playwright browser binaries for @storybook/addon-vitest * - * Installs Chromium via `npx playwright install chromium` + * Installs Chromium via `npx playwright install chromium`. In CI environments, also installs + * system-level browser dependencies via `--with-deps`. * * @param packageManager - The package manager to use for installation * @param prompt - The prompt instance for displaying progress @@ -123,7 +124,9 @@ export class AddonVitestService { ): Promise<{ errors: string[]; result: 'installed' | 'skipped' | 'aborted' | 'failed' }> { const errors: string[] = []; - const playwrightCommand = ['playwright', 'install', 'chromium']; + const playwrightCommand = process.env.CI + ? ['playwright', 'install', 'chromium', '--with-deps'] + : ['playwright', 'install', 'chromium']; const playwrightCommandString = this.packageManager.getPackageCommand(playwrightCommand); let result: 'installed' | 'skipped' | 'aborted' | 'failed'; From 8de539ae0bde62742be17bf322201c2f177c1340 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 10:11:11 +0000 Subject: [PATCH 4/6] fix: use --with-deps on macOS/Windows and CI, skip on other Linux distros Co-authored-by: Sidnioulz <5108577+Sidnioulz@users.noreply.github.com> --- code/addons/vitest/src/postinstall.ts | 11 +++++- code/core/src/cli/AddonVitestService.test.ts | 36 ++++++++++++++++++++ code/core/src/cli/AddonVitestService.ts | 11 ++++-- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/code/addons/vitest/src/postinstall.ts b/code/addons/vitest/src/postinstall.ts index 3a493650dd8f..d627fa416497 100644 --- a/code/addons/vitest/src/postinstall.ts +++ b/code/addons/vitest/src/postinstall.ts @@ -1,6 +1,7 @@ import { existsSync } from 'node:fs'; import * as fs from 'node:fs/promises'; import { writeFile } from 'node:fs/promises'; +import os from 'node:os'; import { babelParse, generate, traverse } from 'storybook/internal/babel'; import { AddonVitestService } from 'storybook/internal/cli'; @@ -165,9 +166,17 @@ export default async function postInstall(options: PostinstallOptions) { useRemotePkg: !!options.skipInstall, }); } else { + const platform = os.platform(); + const useWithDeps = platform === 'darwin' || platform === 'win32'; + const manualCommand = useWithDeps + ? 'npx playwright install chromium --with-deps' + : 'npx playwright install chromium'; + const linuxNote = !useWithDeps + ? '\n Note: add --with-deps to the command above if you are on Debian or Ubuntu.' + : ''; logger.warn(dedent` Playwright browser binaries installation skipped. Please run the following command manually later: - ${CLI_COLORS.cta('npx playwright install chromium')} + ${CLI_COLORS.cta(manualCommand)}${linuxNote} `); } } diff --git a/code/core/src/cli/AddonVitestService.test.ts b/code/core/src/cli/AddonVitestService.test.ts index c82fbd275b79..88eb98d0597e 100644 --- a/code/core/src/cli/AddonVitestService.test.ts +++ b/code/core/src/cli/AddonVitestService.test.ts @@ -1,4 +1,5 @@ import * as fs from 'node:fs/promises'; +import os from 'node:os'; import { beforeEach, describe, expect, it, vi } from 'vitest'; @@ -14,6 +15,7 @@ import { SupportedBuilder, SupportedFramework } from '../types'; import { AddonVitestService } from './AddonVitestService'; vi.mock('node:fs/promises', { spy: true }); +vi.mock('node:os', { spy: true }); vi.mock('storybook/internal/common', { spy: true }); vi.mock('storybook/internal/node-logger', { spy: true }); vi.mock('empathic/find', { spy: true }); @@ -418,6 +420,7 @@ describe('AddonVitestService', () => { it('should execute playwright install command', async () => { const originalCI = process.env.CI; delete process.env.CI; + vi.mocked(os.platform).mockReturnValue('linux'); try { type ChildProcessFactory = (signal?: AbortSignal) => ResultPromise; let commandFactory: ChildProcessFactory | ChildProcessFactory[]; @@ -447,6 +450,7 @@ describe('AddonVitestService', () => { it('should execute playwright install command with --with-deps in CI', async () => { const originalCI = process.env.CI; process.env.CI = 'true'; + vi.mocked(os.platform).mockReturnValue('linux'); try { type ChildProcessFactory = (signal?: AbortSignal) => ResultPromise; let commandFactory: ChildProcessFactory | ChildProcessFactory[]; @@ -474,6 +478,38 @@ describe('AddonVitestService', () => { } }); + it.each(['darwin', 'win32'] as const)( + 'should execute playwright install command with --with-deps on %s', + async (platform) => { + const originalCI = process.env.CI; + delete process.env.CI; + vi.mocked(os.platform).mockReturnValue(platform); + try { + type ChildProcessFactory = (signal?: AbortSignal) => ResultPromise; + let commandFactory: ChildProcessFactory | ChildProcessFactory[]; + vi.mocked(prompt.confirm).mockResolvedValue(true); + vi.mocked(prompt.executeTaskWithSpinner).mockImplementation( + async (factory: ChildProcessFactory | ChildProcessFactory[]) => { + commandFactory = Array.isArray(factory) ? factory[0] : factory; + commandFactory(); + } + ); + + await service.installPlaywright(); + + expect(mockPackageManager.runPackageCommand).toHaveBeenCalledWith({ + args: ['playwright', 'install', 'chromium', '--with-deps'], + signal: undefined, + stdio: ['inherit', 'pipe', 'pipe'], + }); + } finally { + if (originalCI !== undefined) { + process.env.CI = originalCI; + } + } + } + ); + it('should capture error stack when installation fails', async () => { const error = new Error('Installation failed'); error.stack = 'Error stack trace'; diff --git a/code/core/src/cli/AddonVitestService.ts b/code/core/src/cli/AddonVitestService.ts index ecf77915feed..09a86bfa0e3a 100644 --- a/code/core/src/cli/AddonVitestService.ts +++ b/code/core/src/cli/AddonVitestService.ts @@ -1,4 +1,5 @@ import fs from 'node:fs/promises'; +import os from 'node:os'; import * as babel from 'storybook/internal/babel'; import type { JsPackageManager } from 'storybook/internal/common'; @@ -106,8 +107,10 @@ export class AddonVitestService { /** * Install Playwright browser binaries for @storybook/addon-vitest * - * Installs Chromium via `npx playwright install chromium`. In CI environments, also installs - * system-level browser dependencies via `--with-deps`. + * Installs Chromium via `npx playwright install chromium`. In CI environments and on + * macOS/Windows (officially supported platforms), also installs system-level browser dependencies + * via `--with-deps`. On other platforms (e.g. Linux), `--with-deps` is omitted to avoid requiring + * `sudo` — system packages are typically managed by the distro package manager. * * @param packageManager - The package manager to use for installation * @param prompt - The prompt instance for displaying progress @@ -124,7 +127,9 @@ export class AddonVitestService { ): Promise<{ errors: string[]; result: 'installed' | 'skipped' | 'aborted' | 'failed' }> { const errors: string[] = []; - const playwrightCommand = process.env.CI + const platform = os.platform(); + const useWithDeps = !!process.env.CI || platform === 'darwin' || platform === 'win32'; + const playwrightCommand = useWithDeps ? ['playwright', 'install', 'chromium', '--with-deps'] : ['playwright', 'install', 'chromium']; const playwrightCommandString = this.packageManager.getPackageCommand(playwrightCommand); From c9f38b031faffe7109396e0382036fd00a58462b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 10:26:30 +0000 Subject: [PATCH 5/6] fix: warn about missing system deps after Playwright install without --with-deps Co-authored-by: Sidnioulz <5108577+Sidnioulz@users.noreply.github.com> --- code/core/src/cli/AddonVitestService.test.ts | 30 ++++++++++++++++++++ code/core/src/cli/AddonVitestService.ts | 8 ++++++ 2 files changed, 38 insertions(+) diff --git a/code/core/src/cli/AddonVitestService.test.ts b/code/core/src/cli/AddonVitestService.test.ts index 88eb98d0597e..e54f5b54f907 100644 --- a/code/core/src/cli/AddonVitestService.test.ts +++ b/code/core/src/cli/AddonVitestService.test.ts @@ -447,6 +447,36 @@ describe('AddonVitestService', () => { } }); + it('should warn about missing system dependencies after install on Linux', async () => { + const originalCI = process.env.CI; + delete process.env.CI; + vi.mocked(os.platform).mockReturnValue('linux'); + try { + type ChildProcessFactory = (signal?: AbortSignal) => ResultPromise; + vi.mocked(prompt.confirm).mockResolvedValue(true); + vi.mocked(prompt.executeTaskWithSpinner).mockImplementation( + async (factory: ChildProcessFactory | ChildProcessFactory[]) => { + const commandFactory = Array.isArray(factory) ? factory[0] : factory; + commandFactory(); + } + ); + + const { result } = await service.installPlaywright(); + + expect(result).toBe('installed'); + expect(logger.warn).toHaveBeenCalledWith( + expect.stringContaining('installed without system dependencies') + ); + expect(logger.warn).toHaveBeenCalledWith( + expect.stringContaining('run Storybook Test from the Storybook UI') + ); + } finally { + if (originalCI !== undefined) { + process.env.CI = originalCI; + } + } + }); + it('should execute playwright install command with --with-deps in CI', async () => { const originalCI = process.env.CI; process.env.CI = 'true'; diff --git a/code/core/src/cli/AddonVitestService.ts b/code/core/src/cli/AddonVitestService.ts index 09a86bfa0e3a..8f2c4d297d52 100644 --- a/code/core/src/cli/AddonVitestService.ts +++ b/code/core/src/cli/AddonVitestService.ts @@ -176,6 +176,14 @@ export class AddonVitestService { result = 'aborted'; } else { result = 'installed'; + if (!useWithDeps) { + logger.warn(dedent` + Playwright was installed without system dependencies. Depending on your operating system, you may need to install additional libraries for Playwright to work correctly. + To check for missing dependencies, run Storybook Test from the Storybook UI — it will report any libraries that need to be installed. + If needed, you can install system dependencies manually by running: + ${CLI_COLORS.cta(this.packageManager.getPackageCommand(['playwright', 'install', 'chromium', '--with-deps']))} + `); + } } } else { logger.warn('Playwright installation skipped'); From bfb242e4faed215ee29046a68efb07b18684a6a3 Mon Sep 17 00:00:00 2001 From: Steve Dodier-Lazaro Date: Fri, 13 Mar 2026 13:38:24 +0100 Subject: [PATCH 6/6] Apply suggestion from @Sidnioulz --- code/core/src/cli/AddonVitestService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/core/src/cli/AddonVitestService.ts b/code/core/src/cli/AddonVitestService.ts index 8f2c4d297d52..9fd7fc8c964f 100644 --- a/code/core/src/cli/AddonVitestService.ts +++ b/code/core/src/cli/AddonVitestService.ts @@ -180,7 +180,7 @@ export class AddonVitestService { logger.warn(dedent` Playwright was installed without system dependencies. Depending on your operating system, you may need to install additional libraries for Playwright to work correctly. To check for missing dependencies, run Storybook Test from the Storybook UI — it will report any libraries that need to be installed. - If needed, you can install system dependencies manually by running: + On MacOS, Windows, Debian and Ubuntu, you can install system dependencies manually by running: ${CLI_COLORS.cta(this.packageManager.getPackageCommand(['playwright', 'install', 'chromium', '--with-deps']))} `); }