我目前正在使用 Playwright 编写 E2E 测试来模拟关闭并重新打开浏览器选项卡后恢复测验会话。我遇到的问题是,重新打开选项卡后,从 API 检索数据的获取请求会返回
null
,即使 localStorage 数据仍然正确存在。
这是我的完整代码:https://gist.github.com/zpenct/2ef66b86e9eba62aced034991b2313c3
这是完整的场景:
我通过清除并设置
localStorage
中的一些初始值来开始测试,其中包括用户的会话数据(例如当前的问题编号)。
测试将继续回答几个问题,然后关闭浏览器选项卡。
重新打开选项卡时,我希望应用程序从 API 中获取整套问题,并在
localStorage
中保存的特定问题处恢复测验
重要细节:
在
localStorage
中,我只保存当前的问题编号(例如问题3)。
重新打开选项卡后,获取调用应从 API 检索整个问题列表,并且应用程序应显示与保存的问题编号对应的问题(例如,
questions[3]
)。
但是,虽然当前问题编号等
localStorage
值保持不变,但用于检索问题列表的 fetch 调用会返回 null
,导致应用程序无法正确恢复测验。
import { test, expect } from '@playwright/test';
test.describe('Quiz Application - Resume Session', () => {
const user = { username: 'Heoo' };
test('should resume quiz session after closing and reopening the page', async ({ browser }) => {
const context = await browser.newContext();
let page = await context.newPage();
// Step 1: Navigate to the application and set up initial state
await page.goto('http://localhost:5173');
await page.evaluate(() => localStorage.clear());
await page.evaluate((user) => localStorage.setItem("user", JSON.stringify(user)), user);
await page.reload();
// Step 2: Ensure the quiz page is open
const questionSection = page.locator('[data-testid="question-section"]');
await expect(questionSection).toBeVisible();
// Step 3: Answer first two questions
for (let i = 0; i < 2; i++) {
const optionFalse = page.locator('[data-testid="option-false"]');
await optionFalse.click();
await page.waitForTimeout(500); // Add a small delay to ensure state updates
}
// Step 4: Verify we're on the third question
const currentQuestionBefore = page.locator('[data-testid="current-question"]');
await expect(currentQuestionBefore).toHaveText('3/5');
// Step 5: Simulate closing the page
await page.close();
// Step 6: Open a new page in the same context
page = await context.newPage();
await page.goto('http://localhost:5173');
await page.waitForTimeout(4000);
const cq = await page.evaluate(() => localStorage.getItem("currentQuestion"));
const exp = await page.evaluate(() => localStorage.getItem("expirationTime"));
console.log({cq,exp})
// Add a delay to ensure the page has time to load and process localStorage
await page.waitForTimeout(1000);
// Step 7: Ensure the quiz page is open after reopening
await expect(page.locator('[data-testid="question-section"]')).toBeVisible();
// Step 8: Check if the quiz resumed at the correct question
const currentQuestionAfter = page.locator('[data-testid="current-question"]');
await expect(currentQuestionAfter).toHaveText('3/5');
// Step 9: Ensure the quiz is not finished
const latestResult = page.locator('[data-testid="latest-result"]');
await expect(latestResult).not.toBeVisible();
// Step 10: Try answering another question to ensure the quiz is still functional
const optionTrue = page.locator('[data-testid="option-true"]');
await optionTrue.click();
await page.waitForTimeout(500);
// Verify we've moved to the next question
await expect(currentQuestionAfter).toHaveText('4/5');
await context.close();
});
});
localStorage
仍然包含正确的 currentQuestion
值(例如,3
),但检索整套问题的 fetch API 请求会返回 null
,从而导致测验无法正确恢复的不正确状态。为什么 fetch API 在重新打开选项卡后返回
null
,即使 localStorage
包含正确的数据?
此问题是否与重新打开选项卡后如何获取 API 有关?或者在 Playwright 处理浏览器上下文时有什么具体的事情我应该注意吗?
如何确保 fetch 调用正确检索完整的问题集,并且应用程序在正确的问题处恢复?
任何有关如何解决此问题的指导或建议将不胜感激!预先感谢。
如果您概述的所有假设都是正确的,您所描述的问题听起来像是 API 的缺陷。从语法角度来看,您的测试编写正确。
API 是否响应 200 和空正文,或者不同的响应代码?
您确定为您的应用程序建立状态的端点是返回 null 的端点吗?提供有关被测系统实施的更多背景信息可能会更清楚地指出问题。
您是否询问过您正在测试的应用程序的开发人员会话恢复中的预期行为是什么?由于这是一个端到端测试,通常应该足以“做用户会做的事情”,并等待系统允许的延迟量来传递断言,而不询问实现(本地存储、API 有效负载等) )。根据 Playwright 文档的建议:测试用户可见行为