You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GitLab流水线Docker容器中Playwright storageSession失效问题

GitLab CI中Playwright storageState不生效问题

本地测试正常,但GitLab CI流水线内测试失败:

  • storageState未生效,受保护路由超时
  • 退出登录按钮处于禁用状态,确认localStorage中header token项未正确设置

相关配置文件

playwright_tests/auth.setup.js

import { test as setup, expect } from '@playwright/test';

const authFile = 'playwright/.auth/user.json';

setup('authenticate', async ({ page }) => {
  // Perform authentication steps.
  await page.goto('/');
  await page.setViewportSize({ width: 1920, height: 1080 });
  await page.getByRole('button', { name: 'Sign in' }).click();
  await page.waitForURL('/login');
  await page.setViewportSize({ width: 1920, height: 1080 });
  await page.getByLabel('Username').click();
  await page.getByLabel('Username').fill('user');
  await page.getByLabel('Password', { exact: true }).click();
  await page.getByLabel('Password', { exact: true }).fill('password');
  await page.getByLabel('Password', { exact: true }).press('Enter');
  // Wait until the page receives the cookies.
  //
  // Sometimes login flow sets cookies in the process of several redirects.
  // Wait for the final URL to ensure that the cookies are actually set.
  await page.waitForURL('/');
  // End of authentication steps.

  await page.context().storageState({ path: authFile });
});

playwright.config.js

// @ts-check
const { defineConfig, devices } = require('@playwright/test');
// import process
const process = require('process');

/**
 * Read environment variables from file.
 * https://github.com/motdotla/dotenv
 */
// require('dotenv').config();

/**
 * @see https://playwright.dev/docs/test-configuration
 */
module.exports = defineConfig({
  testDir: './playwright_tests',
  outputDir: 'playwright/test_results',
  /* Run tests in files in parallel */
  fullyParallel: true,
  /* Fail the build on CI if you accidentally left test.only in the source code. */
  forbidOnly: !!process.env.CI,
  /* Retry on CI only */
  retries: process.env.CI ? 2 : 0,
  /* Opt out of parallel tests on CI. */
  workers: process.env.CI ? 1 : undefined,
  /* Reporter to use. See https://playwright.dev/docs/test-reporters */
  reporter: [
    [
      'html',
      { outputFolder: 'playwright_results/playwright_report', open: 'never' },
    ],
    [
      'junit',
      { outputFile: 'playwright_results/playwright_report/reports.xml' },
    ],
  ],
  /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
  use: {
    /* Base URL to use in actions like `await page.goto('/')`. */
    baseURL: process.env.FRONTEND_URL,


    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
    trace: 'on-first-retry',
  },

  /* Configure projects for major browsers */
  projects: [
    // Setup project
    { name: 'setup', testMatch: /.*\.setup\.js/ },
    {
      name: 'chromium',
      use: { 
        ...devices['Desktop Chrome'],
        // Use prepared auth state.
        storageState: 'playwright/.auth/user.json',
      },
      dependencies: ['setup']
    },

    {
      name: 'firefox',
      use: { 
        ...devices['Desktop Firefox'],
        // Use prepared auth state.
        storageState: 'playwright/.auth/user.json',
      },
      dependencies: ['setup']
    },

本地生成的storageState示例(playwright/.auth/user.json)

{
  "cookies": [],
  "origins": [
    {
      "origin": "http://localhost:8080",
      "localStorage": [
        {
          "name": "header",
          "value": "3c9cf469144b01c34eb09dfb9fbfa09b19dc4139"
        }
      ]
    }
  ]
}

排查与解决步骤

1. 修复origin不匹配问题

本地storageState中的origin是http://localhost:8080,但CI环境的FRONTEND_URL通常是域名或其他地址,导致Playwright无法匹配origin,无法注入localStorage。

解决:

  • 在CI流水线中添加步骤,替换storageState里的origin为当前环境的FRONTEND_URL:
    # GitLab CI配置片段
    stages:
      - test
    playwright_test:
      script:
        - npm install
        - npx playwright install --with-deps
        - npx playwright test --project=setup
        - sed -i "s|http://localhost:8080|$FRONTEND_URL|g" playwright/.auth/user.json
        - npx playwright test --project=chromium
    

2. 确保登录后localStorage已写入

部分应用会异步写入localStorage,仅等待URL跳转可能不足以确保token已生成。修改auth.setup.js,添加登录成功验证与等待:

// 登录步骤后添加:
// 验证退出按钮已启用,确认登录状态
await expect(page.getByRole('button', { name: 'Sign out' })).toBeEnabled();
// 强制等待异步写入完成(按需调整时长)
await page.waitForTimeout(1000);
await page.context().storageState({ path: authFile });

3. 验证CI中storageState文件的正确性

在setup步骤末尾添加日志,确认生成的storageState内容:

const fs = require('fs');
console.log('Generated storageState content:', fs.readFileSync(authFile, 'utf8'));

查看CI日志,确认文件包含header token且origin与CI环境匹配。

4. 调试localStorage注入情况

在测试脚本中添加调试代码,打印当前页面的localStorage内容:

test('verify auth state', async ({ page }) => {
  await page.goto('/');
  const headerToken = await page.evaluate(() => localStorage.getItem('header'));
  console.log('Current header token:', headerToken);
  expect(headerToken).not.toBeNull();
});

通过CI日志确认token是否存在,定位问题环节。


内容的提问来源于stack exchange,提问作者jaycarn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 18:33:18