【问题标题】:history.back not behaving as expected in Karmahistory.back 在 Karma 中的行为不符合预期
【发布时间】:2021-02-26 20:12:42
【问题描述】:

当我运行这样的基本测试用例时:

  fdescribe('Browser back button', () => {

    fit('should return to previous', async () => {

      const originalHref = window.location.href;
      window.history.pushState({}, 'Test', '/test');
      window.history.back();  // This doesn't seem to be working.
      expect(window.location.href).toEqual(originalHref);
    });

我收到错误消息“预期 'http://localhost:9876/test' 等于 'http://localhost:9876/context.html'”。很明显 pushState() 有效,但 back() 无效。

Karma 在内部 iframe 中运行测试。当我将前三行按顺序粘贴到浏览器的 JavaScript 控制台中时,导航按预期工作。所以在这种情况下,窗口的行为和内部 iframe 的行为之间肯定有一些不同。

这是 Chrome 上的 Karma 5.1。

有什么想法吗?

【问题讨论】:

    标签: javascript web iframe karma-runner browser-history


    【解决方案1】:

    问题在于history.back() API 是异步的

    此方法是异步的。为popstate 事件添加监听器以确定导航何时完成。

    因此触发了导航返回但测试不等待它完成并且检查失败。

    我们需要通过添加done 参数将测试转换为异步测试(这是我知道的一种方法,也许还有其他方法)。并使用popstate 事件处理程序等待导航并完成测试。

    fdescribe('Browser back button', () => {
      fit('should return to previous', (done) => {
        const originalHref = window.location.href;
        window.history.pushState({}, 'Test', '/test');
    
        window.history.back(); // gets executed asynchonously
        window.addEventListener('popstate', () => {
          // history.back() is done now
          expect(window.location.href).toEqual(originalHref);
          done();
        })
      });
    });
    

    【讨论】:

    • 完美!非常感谢,我在这个问题上花了好几个小时,正准备用 Selenium 测试我的更改。
    【解决方案2】:

    Vitalii 的答案是最普遍适用的答案,因为它仅依赖于浏览器内置插件。这是 Angular 用户的基本套件,基于他们的代码。

    import { ComponentFixture, TestBed } from '@angular/core/testing';
    
    import { MyComponent } from './my.component';
    import { Location } from '@angular/common';
    
    describe('MyComponent', () => {
      let component: MyComponent;
      let fixture: ComponentFixture<MyComponent>;
    
      beforeEach(async () => {
        await TestBed.configureTestingModule({
            declarations: [ MyComponent ],
          })
          .compileComponents();
      });
    
      beforeEach(() => {
        fixture = TestBed.createComponent(MyComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
      });
    
      it('should create', () => {
        expect(component).toBeTruthy();
      });
    
      fdescribe('Browser back button', () => {
    
        let location: Location;
        let currentUrl: string;
        const previousUrl = '/test';
    
        beforeEach(() => {
          location = TestBed.inject(Location);
          currentUrl = location.normalize(window.location.href);
          location.go(previousUrl);
          location.go(currentUrl);
        });
    
        afterEach(() => location.go(currentUrl));
    
        fit('should return to previous', done => {
          location.subscribe(e => {
            expect(e.url).toEqual(previousUrl);
            done();
          });
          location.back();
        });
      });
    });
    

    要自定义后退按钮的行为,请重命名“应该返回到上一个”以描述您希望按钮执行的任何操作,并相应地更新测试。

    【讨论】:

      猜你喜欢
      • 2018-10-22
      • 1970-01-01
      • 2017-01-27
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-10
      相关资源
      最近更新 更多