history.back 在 Karma 中表现不尽如人意
history.back not behaving as expected in Karma
当我 运行 像这样的基本测试用例时:
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 运行s 在内部 iframe 中进行测试。当我按顺序将前三行粘贴到浏览器的 JavaScript 控制台时,导航按预期工作。因此,在这种情况下,window 的行为与内部 iframe 的行为之间一定存在某些不同之处。
这是 Chrome 上的 Karma 5.1。
有什么想法吗?
问题是 history.back()
API 是异步的
This method is asynchronous. Add a listener for the popstate
event in order to determine when the navigation has completed.
所以导航返回被触发但是测试没有等待它完成并且检查失败。
我们需要通过添加 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();
})
});
});
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();
});
});
});
要自定义后退按钮的行为,请重命名 'should return to previous' 以描述您希望按钮执行的任何操作,并相应地更新测试。
当我 运行 像这样的基本测试用例时:
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 运行s 在内部 iframe 中进行测试。当我按顺序将前三行粘贴到浏览器的 JavaScript 控制台时,导航按预期工作。因此,在这种情况下,window 的行为与内部 iframe 的行为之间一定存在某些不同之处。
这是 Chrome 上的 Karma 5.1。
有什么想法吗?
问题是 history.back()
API 是异步的
This method is asynchronous. Add a listener for the
popstate
event in order to determine when the navigation has completed.
所以导航返回被触发但是测试没有等待它完成并且检查失败。
我们需要通过添加 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();
})
});
});
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();
});
});
});
要自定义后退按钮的行为,请重命名 'should return to previous' 以描述您希望按钮执行的任何操作,并相应地更新测试。