From 83479fbb4f8333de33f99109bde9efc5d8cd812b Mon Sep 17 00:00:00 2001 From: Zeeshan Date: Fri, 26 Sep 2025 12:31:38 +0530 Subject: [PATCH 1/2] Add support for custom cookies in snapshot options and enhance schema validation --- src/lib/processSnapshot.ts | 45 ++++++++++++++++++++++++++++++++++--- src/lib/schemaValidation.ts | 8 +++++++ src/types.ts | 11 +++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/lib/processSnapshot.ts b/src/lib/processSnapshot.ts index 0fe827d..5aa63f7 100644 --- a/src/lib/processSnapshot.ts +++ b/src/lib/processSnapshot.ts @@ -243,6 +243,47 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context): ctx.log.debug('No valid cookies to add'); } } + + let options = snapshot.options; + + // Custom cookies include those which cannot be captured by javascript function `document.cookie` like httpOnly, secure, sameSite etc. + // These custom cookies will be captured by the user in their automation browser and sent to CLI through the snapshot options using `customCookies` field. + if (options?.customCookies && Array.isArray(options.customCookies) && options.customCookies.length > 0) { + ctx.log.debug(`Setting ${options.customCookies.length} custom cookies`); + + const validCustomCookies = options.customCookies.filter(cookie => { + if (!cookie.name || !cookie.value || !cookie.domain) { + ctx.log.debug(`Skipping invalid custom cookie: missing required fields (name, value, or domain)`); + return false; + } + + if (cookie.sameSite && !['Strict', 'Lax', 'None'].includes(cookie.sameSite)) { + ctx.log.debug(`Skipping invalid custom cookie: invalid sameSite value '${cookie.sameSite}'`); + return false; + } + + return true; + }).map(cookie => ({ + name: cookie.name, + value: cookie.value, + domain: cookie.domain, + path: cookie.path || '/', + httpOnly: cookie.httpOnly || false, + secure: cookie.secure || false, + sameSite: cookie.sameSite || 'Lax' + })); + + if (validCustomCookies.length > 0) { + try { + await context.addCookies(validCustomCookies); + ctx.log.debug(`Successfully added ${validCustomCookies.length} custom cookies`); + } catch (error) { + ctx.log.debug(`Failed to add custom cookies: ${error}`); + } + } else { + ctx.log.debug('No valid custom cookies to add'); + } + } const page = await context.newPage(); // populate cache with already captured resources @@ -415,8 +456,6 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context): route.abort(); } }); - - let options = snapshot.options; let optionWarnings: Set = new Set(); let selectors: Array = []; let ignoreOrSelectDOM: string; @@ -582,6 +621,7 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context): // adding extra timeout since domcontentloaded event is fired pretty quickly await new Promise(r => setTimeout(r, 1250)); if (ctx.config.waitForTimeout) await page.waitForTimeout(ctx.config.waitForTimeout); + await page.waitForLoadState("networkidle", { timeout: 30000 }).catch(() => { ctx.log.debug('networkidle event failed to fire within 30s') }); navigated = true; ctx.log.debug(`Navigated to ${snapshot.url}`); } catch (error: any) { @@ -815,7 +855,6 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context): if (hasBrowserErrors) { discoveryErrors.timestamp = new Date().toISOString(); - // ctx.log.warn(discoveryErrors); } if (ctx.config.useGlobalCache) { diff --git a/src/lib/schemaValidation.ts b/src/lib/schemaValidation.ts index 518a404..6b015c4 100644 --- a/src/lib/schemaValidation.ts +++ b/src/lib/schemaValidation.ts @@ -582,6 +582,14 @@ const SnapshotSchema: JSONSchemaType = { minimum: 0, maximum: 100, errorMessage: "Invalid snapshot options; rejectionThreshold must be a number between 0 and 100" + }, + customCookies: { + type: "array", + items: { + type: "object", + minProperties: 1, + }, + errorMessage: "Invalid snapshot options; customCookies must be an array of objects with string properties" } }, additionalProperties: false diff --git a/src/types.ts b/src/types.ts index e647b0c..b02baeb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -164,6 +164,7 @@ export interface Snapshot { useExtendedViewport?: boolean; approvalThreshold?: number; rejectionThreshold?: number; + customCookies?: CustomCookie[]; } } @@ -251,6 +252,16 @@ export interface FigmaWebConfig { configs: Array<{ figma_file_token: string, figma_ids: Array, screenshot_names:Array }>; } +export interface CustomCookie { + name: string; + value: string; + domain: string; + path: string; + httpOnly: boolean; + secure: boolean; + sameSite: 'Strict' | 'Lax' | 'None'; +} + export interface ViewportErrors { statusCode: "aborted" | "404" | string; From ae6971faf75fa916f99138d673c7229c31b6cd41 Mon Sep 17 00:00:00 2001 From: Zeeshan Date: Fri, 26 Sep 2025 12:40:19 +0530 Subject: [PATCH 2/2] Reduce timeout for networkidle event in snapshot processing --- src/lib/processSnapshot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/processSnapshot.ts b/src/lib/processSnapshot.ts index 5aa63f7..5de3504 100644 --- a/src/lib/processSnapshot.ts +++ b/src/lib/processSnapshot.ts @@ -621,7 +621,7 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context): // adding extra timeout since domcontentloaded event is fired pretty quickly await new Promise(r => setTimeout(r, 1250)); if (ctx.config.waitForTimeout) await page.waitForTimeout(ctx.config.waitForTimeout); - await page.waitForLoadState("networkidle", { timeout: 30000 }).catch(() => { ctx.log.debug('networkidle event failed to fire within 30s') }); + await page.waitForLoadState("networkidle", { timeout: 10000 }).catch(() => { ctx.log.debug('networkidle event failed to fire within 10s') }); navigated = true; ctx.log.debug(`Navigated to ${snapshot.url}`); } catch (error: any) {