From 2d194733c93800bfdcd35ed69784b10cb9ed025b Mon Sep 17 00:00:00 2001 From: Robert DeLuca Date: Mon, 16 Feb 2026 14:10:23 -0600 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Make=20full-page=20screenshots=20th?= =?UTF-8?q?e=20default=20in=20static-site=20and=20storybook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flip screenshot.fullPage defaults to true across config, schema, CLI init defaults, and screenshot helpers in both SDKs. Add --no-full-page so teams can keep viewport-only behavior explicitly. This is a breaking default change; existing behavior can be preserved with screenshot.fullPage: false or --no-full-page. --- clients/static-site/README.md | 5 +++-- clients/static-site/examples/vizzly.config.js | 2 +- clients/static-site/src/config-schema.js | 16 +++++++++++----- clients/static-site/src/config.js | 2 +- clients/static-site/src/plugin.js | 3 ++- clients/static-site/src/screenshot.js | 4 ++-- clients/static-site/tests/cli-options.test.js | 10 +++++----- clients/static-site/tests/config-schema.test.js | 6 ++++++ clients/storybook/README.md | 5 +++-- clients/storybook/src/config.js | 2 +- clients/storybook/src/plugin.js | 5 +++-- clients/storybook/src/screenshot.js | 4 ++-- clients/storybook/tests/config.test.js | 11 +++++++++-- clients/storybook/tests/screenshot.test.js | 14 +++++++------- 14 files changed, 56 insertions(+), 33 deletions(-) diff --git a/clients/static-site/README.md b/clients/static-site/README.md index 4c013b40..be9e0f58 100644 --- a/clients/static-site/README.md +++ b/clients/static-site/README.md @@ -73,7 +73,7 @@ export default { }, screenshot: { - fullPage: false, + fullPage: true, omitBackground: false, }, @@ -140,7 +140,8 @@ Configuration is merged in this order (later overrides earlier): - `--exclude ` - Exclude page pattern (glob) - `--browser-args ` - Additional Puppeteer browser arguments - `--headless` - Run browser in headless mode (default: true) -- `--full-page` - Capture full page screenshots (default: false) +- `--full-page` - Capture full page screenshots (default: true) +- `--no-full-page` - Capture viewport-only screenshots - `--timeout ` - Screenshot timeout in milliseconds (default: 45000) - `--dry-run` - Print discovered pages and task count without capturing screenshots - `--use-sitemap` - Use sitemap.xml for page discovery (default: true) diff --git a/clients/static-site/examples/vizzly.config.js b/clients/static-site/examples/vizzly.config.js index da57d994..90e2ae65 100644 --- a/clients/static-site/examples/vizzly.config.js +++ b/clients/static-site/examples/vizzly.config.js @@ -44,7 +44,7 @@ export default { // Screenshot options screenshot: { - fullPage: false, // Capture visible viewport only + fullPage: true, // Capture full scrollable page omitBackground: false, // Include page background }, diff --git a/clients/static-site/src/config-schema.js b/clients/static-site/src/config-schema.js index a79ec1f2..68207b3f 100644 --- a/clients/static-site/src/config-schema.js +++ b/clients/static-site/src/config-schema.js @@ -43,7 +43,7 @@ let browserSchema = z.object({ * Screenshot configuration schema */ let screenshotSchema = z.object({ - fullPage: z.boolean().default(false), + fullPage: z.boolean().default(true), omitBackground: z.boolean().default(false), timeout: z.number().int().positive().default(45_000), // 45 seconds }); @@ -96,13 +96,19 @@ export let staticSiteConfigSchema = z args: [], }), screenshot: screenshotSchema.default({ - fullPage: false, + fullPage: true, omitBackground: false, timeout: 45_000, }), concurrency: z.number().int().positive().default(getDefaultConcurrency()), - include: z.union([z.string(), z.array(z.string())]).nullable().optional(), - exclude: z.union([z.string(), z.array(z.string())]).nullable().optional(), + include: z + .union([z.string(), z.array(z.string())]) + .nullable() + .optional(), + exclude: z + .union([z.string(), z.array(z.string())]) + .nullable() + .optional(), pageDiscovery: pageDiscoverySchema.default({ useSitemap: true, sitemapPath: 'sitemap.xml', @@ -114,7 +120,7 @@ export let staticSiteConfigSchema = z .default({ viewports: [{ name: 'default', width: 1920, height: 1080 }], browser: { type: 'chromium', headless: true, args: [] }, - screenshot: { fullPage: false, omitBackground: false, timeout: 45_000 }, + screenshot: { fullPage: true, omitBackground: false, timeout: 45_000 }, concurrency: getDefaultConcurrency(), pageDiscovery: { useSitemap: true, diff --git a/clients/static-site/src/config.js b/clients/static-site/src/config.js index 2cc68821..fe936aa9 100644 --- a/clients/static-site/src/config.js +++ b/clients/static-site/src/config.js @@ -20,7 +20,7 @@ export let defaultConfig = { args: [], }, screenshot: { - fullPage: false, + fullPage: true, omitBackground: false, }, concurrency: 3, diff --git a/clients/static-site/src/plugin.js b/clients/static-site/src/plugin.js index ee634135..58559517 100644 --- a/clients/static-site/src/plugin.js +++ b/clients/static-site/src/plugin.js @@ -25,7 +25,7 @@ export default { args: [], }, screenshot: { - fullPage: false, + fullPage: true, omitBackground: false, }, concurrency: getDefaultConcurrency(), @@ -71,6 +71,7 @@ export default { .option('--browser-args ', 'Additional browser arguments') .option('--headless', 'Run browser in headless mode') .option('--full-page', 'Capture full page screenshots') + .option('--no-full-page', 'Capture viewport-only screenshots') .option( '--timeout ', 'Screenshot timeout in milliseconds (default: 45000)', diff --git a/clients/static-site/src/screenshot.js b/clients/static-site/src/screenshot.js index 33f17da7..749f3dd1 100644 --- a/clients/static-site/src/screenshot.js +++ b/clients/static-site/src/screenshot.js @@ -65,14 +65,14 @@ let DEFAULT_SCREENSHOT_TIMEOUT = 45_000; * Capture a screenshot from a page * @param {Object} page - Playwright page instance * @param {Object} options - Screenshot options - * @param {boolean} [options.fullPage=false] - Capture full page + * @param {boolean} [options.fullPage=true] - Capture full page * @param {boolean} [options.omitBackground=false] - Omit background (transparent) * @param {number} [options.timeout=45000] - Screenshot timeout in ms * @returns {Promise} Screenshot buffer */ export async function captureScreenshot(page, options = {}) { let { - fullPage = false, + fullPage = true, omitBackground = false, timeout = DEFAULT_SCREENSHOT_TIMEOUT, } = options; diff --git a/clients/static-site/tests/cli-options.test.js b/clients/static-site/tests/cli-options.test.js index c0384b8b..b943d310 100644 --- a/clients/static-site/tests/cli-options.test.js +++ b/clients/static-site/tests/cli-options.test.js @@ -29,13 +29,13 @@ describe('CLI Options', () => { assert.deepStrictEqual(result.screenshot, { fullPage: false }); }); - it('preserves config fullPage: true when CLI option not set', () => { + it('preserves config fullPage: false when CLI option not set', () => { let defaultConfig = { - screenshot: { fullPage: false, omitBackground: false }, + screenshot: { fullPage: true, omitBackground: false }, }; let userConfig = { - screenshot: { fullPage: true, omitBackground: false }, + screenshot: { fullPage: false, omitBackground: false }, }; let cliOptions = {}; // No CLI options @@ -43,12 +43,12 @@ describe('CLI Options', () => { let result = mergeConfigs(defaultConfig, userConfig, parsedCli); - assert.strictEqual(result.screenshot.fullPage, true); + assert.strictEqual(result.screenshot.fullPage, false); }); it('allows CLI option to override config fullPage', () => { let defaultConfig = { - screenshot: { fullPage: false, omitBackground: false }, + screenshot: { fullPage: true, omitBackground: false }, }; let userConfig = { diff --git a/clients/static-site/tests/config-schema.test.js b/clients/static-site/tests/config-schema.test.js index 394ccc44..ae8ff809 100644 --- a/clients/static-site/tests/config-schema.test.js +++ b/clients/static-site/tests/config-schema.test.js @@ -53,6 +53,12 @@ describe('config-schema', () => { assert.ok(validated.pageDiscovery); }); + it('defaults screenshot.fullPage to true', () => { + let validated = validateStaticSiteConfig({}); + + assert.strictEqual(validated.screenshot.fullPage, true); + }); + it('applies default concurrency from CPU cores', () => { let config = {}; diff --git a/clients/storybook/README.md b/clients/storybook/README.md index e06621d8..92c4e4cb 100644 --- a/clients/storybook/README.md +++ b/clients/storybook/README.md @@ -68,7 +68,7 @@ export default { }, screenshot: { - fullPage: false, + fullPage: true, omitBackground: false, }, @@ -139,7 +139,8 @@ Configuration is merged in this order (later overrides earlier): - `--config ` - Path to custom config file - `--browser-args ` - Additional Puppeteer browser arguments - `--headless` - Run browser in headless mode (default: true) -- `--full-page` - Capture full page screenshots (default: false) +- `--full-page` - Capture full page screenshots (default: true) +- `--no-full-page` - Capture viewport-only screenshots ## Interaction Hooks diff --git a/clients/storybook/src/config.js b/clients/storybook/src/config.js index a293b434..d9ed2501 100644 --- a/clients/storybook/src/config.js +++ b/clients/storybook/src/config.js @@ -32,7 +32,7 @@ export let defaultConfig = { args: [], }, screenshot: { - fullPage: false, + fullPage: true, omitBackground: false, }, concurrency: getDefaultConcurrency(), diff --git a/clients/storybook/src/plugin.js b/clients/storybook/src/plugin.js index 5217d63a..c3cabf5d 100644 --- a/clients/storybook/src/plugin.js +++ b/clients/storybook/src/plugin.js @@ -23,7 +23,7 @@ export default { args: [], }, screenshot: { - fullPage: false, + fullPage: true, omitBackground: false, }, concurrency: 3, @@ -67,7 +67,8 @@ export default { 'Run browser in headless mode (default: true)', true ) - .option('--full-page', 'Capture full page screenshots', false) + .option('--full-page', 'Capture full page screenshots') + .option('--no-full-page', 'Capture viewport-only screenshots') .action(async (path, options) => { try { let { run } = await import('./index.js'); diff --git a/clients/storybook/src/screenshot.js b/clients/storybook/src/screenshot.js index 3b52973a..a2880e96 100644 --- a/clients/storybook/src/screenshot.js +++ b/clients/storybook/src/screenshot.js @@ -43,12 +43,12 @@ const SCREENSHOT_TIMEOUT_MS = 45_000; * Capture a screenshot from a page * @param {Object} page - Playwright page instance * @param {Object} options - Screenshot options - * @param {boolean} [options.fullPage=false] - Capture full page + * @param {boolean} [options.fullPage=true] - Capture full page * @param {boolean} [options.omitBackground=false] - Omit background (transparent) * @returns {Promise} Screenshot buffer */ export async function captureScreenshot(page, options = {}) { - let { fullPage = false, omitBackground = false } = options; + let { fullPage = true, omitBackground = false } = options; // Playwright has built-in timeout support let screenshot = await page.screenshot({ diff --git a/clients/storybook/tests/config.test.js b/clients/storybook/tests/config.test.js index d1b4a8dc..452800ef 100644 --- a/clients/storybook/tests/config.test.js +++ b/clients/storybook/tests/config.test.js @@ -71,6 +71,13 @@ describe('parseCliOptions', () => { assert.equal(config.screenshot.fullPage, true); }); + + it('should parse fullPage false for --no-full-page', () => { + let options = { fullPage: false }; + let config = parseCliOptions(options); + + assert.equal(config.screenshot.fullPage, false); + }); }); describe('mergeConfigs', () => { @@ -124,7 +131,7 @@ describe('mergeStoryConfig', () => { it('should merge story config with global config', () => { let globalConfig = { viewports: [{ name: 'desktop', width: 1920, height: 1080 }], - screenshot: { fullPage: false }, + screenshot: { fullPage: true }, }; let storyConfig = { @@ -134,7 +141,7 @@ describe('mergeStoryConfig', () => { let merged = mergeStoryConfig(globalConfig, storyConfig); assert.equal(merged.viewports[0].name, 'mobile'); - assert.equal(merged.screenshot.fullPage, false); + assert.equal(merged.screenshot.fullPage, true); }); it('should return global config if no story config', () => { diff --git a/clients/storybook/tests/screenshot.test.js b/clients/storybook/tests/screenshot.test.js index 1f5e8840..f89e77e3 100644 --- a/clients/storybook/tests/screenshot.test.js +++ b/clients/storybook/tests/screenshot.test.js @@ -50,21 +50,21 @@ describe('captureScreenshot', () => { assert.equal(result, mockBuffer); assert.equal(mockScreenshot.mock.calls.length, 1); assert.deepEqual(mockScreenshot.mock.calls[0].arguments[0], { - fullPage: false, + fullPage: true, omitBackground: false, timeout: 45000, }); }); - it('should capture full page screenshot', async () => { + it('should capture viewport screenshot when fullPage is false', async () => { let mockBuffer = Buffer.from('fake-screenshot'); let mockScreenshot = mock.fn(() => mockBuffer); let mockPage = { screenshot: mockScreenshot }; - await captureScreenshot(mockPage, { fullPage: true }); + await captureScreenshot(mockPage, { fullPage: false }); assert.deepEqual(mockScreenshot.mock.calls[0].arguments[0], { - fullPage: true, + fullPage: false, omitBackground: false, timeout: 45000, }); @@ -78,7 +78,7 @@ describe('captureScreenshot', () => { await captureScreenshot(mockPage, { omitBackground: true }); assert.deepEqual(mockScreenshot.mock.calls[0].arguments[0], { - fullPage: false, + fullPage: true, omitBackground: true, timeout: 45000, }); @@ -107,11 +107,11 @@ describe('captureAndSendScreenshot', () => { let viewport = { name: 'mobile' }; await captureAndSendScreenshot(mockPage, story, viewport, { - fullPage: true, + fullPage: false, }); assert.deepEqual(mockScreenshot.mock.calls[0].arguments[0], { - fullPage: true, + fullPage: false, omitBackground: false, timeout: 45000, });