Cypress测试用例执行后如何重置window.location.href
问题背景
测试点击操作后会更新window.location.href的UI组件时,存在测试用例间地址污染问题:
- 第一个测试用例可正常运行
- 第二个测试用例启动时,地址为前一个测试中UI修改后的地址,导致用例无法从正确页面启动
- 测试初始地址为自动生成,不能在测试开头硬编码地址重置,需要可在
afterEach钩子中执行的通用重置方案,让浏览器地址恢复到测试启动时的初始状态
现有测试代码
it.only('should send asynchronous analytics event after provider selection click', () => { rewire$useFlag(() => true); cy.location().then((location) => console.log('window !!')); const analyticsAsyncStub = cy.stub().as('sendAnalyticsAsyncStub'); rewire$sendAnalyticsAsync(analyticsAsyncStub); // hack浏览器检测,保证 provider 选项可正常渲染 cy.window().then(($window) => { console.log('window !!', $window.location.href); ($window as any).chrome = {}; ($window as any).chrome.runtime = { sendMessage() { 'mock function'; }, }; }); mountFixtureWithProviders({ children: <ProviderSelection flagsConfig={defaultFlags} /> }); cyGetByTestId('provider--metaMask').click(); cy.get('@sendAnalyticsAsyncStub').should( 'have.been.calledWithMatch', analyticsUtilsModule.createButtonEvent(ButtonEventName.providerSelectionPressed), ); });
mountFixtureWithProviders 函数代码
export const mountFixtureWithProviders = ({ children, mountInsideVisualMock = true, setErrorLog = () => ({}), renderErrorScreens, }: { children: ReactNode; mountInsideVisualMock?: boolean; setErrorLog?: SetErrorLog; renderErrorScreens?: boolean; }) => { const RouterMockedChildren = () => <MemoryRouter>{children}</MemoryRouter>; const ProvidedChildren = () => renderErrorScreens ? ( <DemoAppToRenderErrorMessages> <RouterMockedChildren /> </DemoAppToRenderErrorMessages> ) : ( <LinkUiCoreContext.Provider value={{ setErrorLog, imageResizerServiceUrl: DEV_IMAGE_RESIZER_SERVICE_URL }}> <RouterMockedChildren /> </LinkUiCoreContext.Provider> ); return mount(mountInsideVisualMock ? linkPageVisualMock({ children: <ProvidedChildren /> }) : <ProvidedChildren />); };
解决方案
缓存初始地址+afterEach统一重置
在测试套件外层缓存组件测试的默认初始地址,每个用例执行完后自动跳转回初始地址即可,不需要硬编码固定地址:
// 写在describe块的最外层作用域 let initialTestHref; // 套件首次启动时缓存初始地址 before(() => { cy.window().then(win => { initialTestHref = win.location.href; }); }); // 每个用例执行完成后重置地址 afterEach(() => { cy.visit(initialTestHref); });
说明:Cypress组件测试模式下,cy.visit()支持跳转回内存中的默认测试页地址,不会触发跨域错误。
无历史栈残留的重置方式
如果不希望在浏览器历史栈中留下跳转记录,可以替换为location.replace方法做重置:
afterEach(() => { cy.window().then(win => { win.location.replace(initialTestHref); }); });
补充说明
从提供的挂载函数代码看,组件外层包裹的是React Router的MemoryRouter,正常情况下内存路由不会修改真实浏览器的window.location.href,出现地址污染是因为组件内部直接操作了window.location做跳转,上述全局重置方案不需要修改组件业务逻辑,即可完全隔离用例间的地址影响。
内容的提问来源于stack exchange,提问作者daniel blythe
相关产品推荐
相关产品推荐

