From b1a8568bff464f68ed3136860b2fa875039a0227 Mon Sep 17 00:00:00 2001 From: Jeffrey Smith Date: Thu, 2 Apr 2026 16:18:01 +0000 Subject: [PATCH] Fix CI auth: inject token via localStorage + document.cookie MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Playwright's addCookies (both domain-based and url-based) fails to send SameSite=Strict cookies in Docker DNS environments. The server middleware reads arm_token from cookies, but the cookie is originally set by client-side JS (document.cookie with SameSite=Strict). New approach: navigate to /login first, then inject the token into localStorage (key: arm_auth) and set the cookie via document.cookie in page context — exactly how the real login flow works. This ensures the cookie attributes match what the server expects. Co-Authored-By: Claude Opus 4.6 (1M context) --- ci/e2e-smoke-driver.js | 25 +++++++++++++++++-------- ci/surface-test-driver.js | 23 +++++++++++++++-------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/ci/e2e-smoke-driver.js b/ci/e2e-smoke-driver.js index c8e554b..4feb74e 100644 --- a/ci/e2e-smoke-driver.js +++ b/ci/e2e-smoke-driver.js @@ -97,19 +97,28 @@ async function discoverSurfaces(page) { const browser = await chromium.launch({ headless: true }); const context = await browser.newContext(); - // Set auth cookie — use url instead of domain for reliable matching - await context.addCookies([{ - name: 'arm_token', - value: TOKEN, - url: SERVER, - }]); - const page = await context.newPage(); + // ── Authenticate via page context ───────── + // Navigate to login first, then inject tokens into localStorage + // and set the arm_token cookie via JS — same mechanism the login + // page uses. Playwright's addCookies doesn't reliably work with + // SameSite=Strict cookies in Docker DNS environments. + console.log('Setting up auth...'); + await page.goto(SERVER + '/login', { waitUntil: 'networkidle', timeout: 30000 }); + await page.evaluate((token) => { + localStorage.setItem('arm_auth', JSON.stringify({ + accessToken: token, + refreshToken: token, + user: null, + cookieMaxAge: 604800, + })); + document.cookie = `arm_token=${token}; path=/; max-age=604800; SameSite=Strict`; + }, TOKEN); + // ── Discover surfaces ───────────────────── console.log('Discovering surfaces...'); - // Navigate to a page first so cookies are sent with API call await page.goto(SERVER + '/admin', { waitUntil: 'networkidle', timeout: 30000 }); const surfaces = await discoverSurfaces(page); diff --git a/ci/surface-test-driver.js b/ci/surface-test-driver.js index 13e3789..b106250 100644 --- a/ci/surface-test-driver.js +++ b/ci/surface-test-driver.js @@ -33,16 +33,23 @@ if (!TOKEN) { const browser = await chromium.launch({ headless: true }); const context = await browser.newContext(); - // Set auth cookie — use url instead of domain for reliable matching - // in Docker/CI where hostname is a Docker DNS name (e.g. "armature") - await context.addCookies([{ - name: 'arm_token', - value: TOKEN, - url: SERVER, - }]); - const page = await context.newPage(); + // Authenticate via page context — inject tokens into localStorage + // and set the arm_token cookie via JS. Playwright's addCookies + // doesn't reliably work with SameSite=Strict cookies in Docker. + console.log('Setting up auth...'); + await page.goto(SERVER + '/login', { waitUntil: 'networkidle', timeout: 30000 }); + await page.evaluate((token) => { + localStorage.setItem('arm_auth', JSON.stringify({ + accessToken: token, + refreshToken: token, + user: null, + cookieMaxAge: 604800, + })); + document.cookie = `arm_token=${token}; path=/; max-age=604800; SameSite=Strict`; + }, TOKEN); + // Collect console errors const consoleErrors = []; page.on('console', msg => {