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

如何在Playwright中Mock chrome.storage.sync.get完成扩展测试?

解决Playwright中Mock chrome.storage.sync.get无效的问题

问题根源

你的mock代码未生效,核心原因是页面上下文与扩展上下文相互隔离:page.addInitScript是注入到普通页面的执行上下文,但你的扩展代码(比如内容脚本)运行在独立的扩展沙箱上下文中,导致mock无法覆盖到扩展里的chrome.storage对象。

解决方案

方案1:针对内容脚本上下文注入Mock

如果你的业务代码是扩展的内容脚本,需要将mock注入到内容脚本的专属上下文,可通过context.addInitScript指定target: 'content'实现:

test('MyTest', async ({ context, page }) => {
  // 向所有内容脚本上下文注入mock逻辑
  await context.addInitScript({
    target: 'content',
    content: `
      const mockStorageData = { data: 'storedData' };
      // 对齐原生chrome.storage.sync.get的参数逻辑
      chrome.storage.sync.get = (keys, callback) => {
        let result = {};
        // 处理不同类型的keys参数
        if (typeof keys === 'string') {
          result[keys] = mockStorageData[keys];
        } else if (Array.isArray(keys)) {
          keys.forEach(key => {
            result[key] = mockStorageData[key];
          });
        } else if (typeof keys === 'object') {
          Object.keys(keys).forEach(key => {
            result[key] = mockStorageData[key] ?? keys[key];
          });
        } else {
          result = mockStorageData;
        }
        // 同时支持回调和Promise两种调用方式
        if (typeof callback === 'function') {
          callback(result);
          return;
        }
        return Promise.resolve(result);
      };
    `
  });

  await page.goto('https://www.myWebsite.com/');
  const result = page.locator("#data");
  await expect(result).toContainText('storedData');
});

方案2:模拟完整的Chrome Storage API

如果你的代码依赖chrome.storage的更多特性(比如存储修改、监听变化),可以模拟更完整的API实现:

await context.addInitScript({
  target: 'content',
  content: `
    const mockStorage = {
      sync: {
        data: 'storedData',
        get: function(keys, callback) {
          let res = {};
          // 兼容各种参数场景
          if (keys === null || keys === undefined) {
            res = { ...this };
          } else if (typeof keys === 'string') {
            res[keys] = this[keys];
          } else if (Array.isArray(keys)) {
            keys.forEach(k => res[k] = this[k]);
          } else if (typeof keys === 'object') {
            for (const k in keys) {
              res[k] = this[k] ?? keys[k];
            }
          }
          // 支持回调和Promise
          if (callback) {
            callback(res);
            return;
          }
          return Promise.resolve(res);
        },
        // 可选:模拟set方法
        set: function(data, callback) {
          Object.assign(this, data);
          if (callback) callback();
          return Promise.resolve();
        }
      }
    };
    // 替换全局chrome.storage对象
    chrome.storage = mockStorage;
  `
});

方案3:针对后台脚本的Mock

如果你的chrome.storage调用是在扩展后台脚本中,需要通过Playwright的extension fixture获取后台页面,再注入mock:

test('MyTest', async ({ extension, page }) => {
  const backgroundPage = await extension.backgroundPage();
  await backgroundPage.addInitScript(() => {
    const mockData = { data: 'storedData' };
    chrome.storage.sync.get = async (keys) => {
      if (keys === 'data') return mockData;
      return {};
    };
  });

  await page.goto('https://www.myWebsite.com/');
  const result = page.locator("#data");
  await expect(result).toContainText('storedData');
});

关键注意事项

  • 确保mock的get函数完全对齐原生API的参数规则:支持字符串、数组、对象作为keys,同时兼容回调和Promise两种调用方式,否则业务代码可能因参数不匹配无法获取数据。
  • 明确代码运行的上下文:页面上下文、内容脚本上下文、后台脚本上下文相互隔离,mock必须注入到对应上下文才会生效。
  • 确认扩展已正确加载:使用Playwright Web扩展夹具时,需保证启动上下文时已正确加载扩展,避免因chrome对象不存在导致的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:08:29