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

Playwright中Basic Auth无法存入storageState致测试失败求助

问题:Playwright复用Basic Auth失败,Setup通过但测试用例报错

搭建Playwright项目时,尝试通过项目依赖复用Basic Auth用于测试,Setup测试始终通过,但示例测试用例报错:page.goto: net::ERR_INVALID_AUTH_CREDENTIALS at https://the-internet.herokuapp.com/basic_auth。

相关代码

配置文件

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

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

/**
 * @see https://playwright.dev/docs/test-configuration
 */
module.exports = defineConfig({
  testDir: './tests',
  /* 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',
  /* 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: 'https://the-internet.herokuapp.com/basic_auth',

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

  /* Configure projects for major browsers */
  projects: [
    {
      name: 'setup',
      testDir: './',
      testMatch: 'globalSetup.js'
    },
    {
      name: 'testrun',
      dependencies: ['setup'],
      use: { storageState: './LoginAuth.json' }
    },
],
}

globalSetup代码

test('setup', async ({ page }) => {
    const authHeaders = 'Basic ' + Buffer.from('admin:admin').toString('base64');
    await page.setExtraHTTPHeaders({ Authorization : authHeaders })
    await page.goto('');
    await expect(page.getByText('Congratulations!')).toBeVisible();
    await page.context().storageState({ path: './LoginAuth.json' })
})

测试用例

test('new fckn test', async ({page}) => {
  await page.goto('');

  await expect(page.getByText('Congratulations!')).toBeVisible();
})

问题原因

storageState 只会存储Cookie、LocalStorage等浏览器存储数据,不会保存你通过setExtraHTTPHeaders设置的Authorization请求头。Setup测试中直接设置了请求头所以能成功,但测试用例读取storageState后并没有继承这个请求头,导致认证失败。

解决方案

方法一:在测试项目全局配置HTTP头

直接在testrun项目的配置中添加extraHTTPHeaders,让所有测试自动携带认证头:

// 配置文件中testrun项目部分修改为
{
  name: 'testrun',
  dependencies: ['setup'],
  use: {
    storageState: './LoginAuth.json',
    extraHTTPHeaders: {
      'Authorization': 'Basic ' + Buffer.from('admin:admin').toString('base64')
    }
  }
},

方法二:利用Playwright原生HTTP认证机制(推荐)

在globalSetup中创建带有Basic Auth的context,Playwright会将认证信息存入storageState,测试用例读取后自动复用:

修改globalSetup.js:

test('setup', async ({ browser }) => {
  // 创建携带Basic Auth的context
  const context = await browser.newContext({
    httpCredentials: {
      username: 'admin',
      password: 'admin'
    }
  });
  const page = await context.newPage();
  await page.goto('');
  await expect(page.getByText('Congratulations!')).toBeVisible();
  // 保存context状态到文件
  await context.storageState({ path: './LoginAuth.json' });
  await context.close();
});

配置文件无需额外修改,testrun项目只需读取storageState即可自动携带认证信息。

方法三:在测试用例中直接设置认证

如果需要灵活控制,可以在测试用例中给当前context设置HTTP凭据:

test('new fckn test', async ({page, context}) => {
  await context.setHTTPCredentials({
    username: 'admin',
    password: 'admin'
  });
  await page.goto('');
  await expect(page.getByText('Congratulations!')).toBeVisible();
});

内容的提问来源于stack exchange,提问作者Otis von Lilien

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 04:50:18