当前,我正在为我的项目实施单元测试,并且有一个包含window.location.href
的文件。
我想对此进行测试,这是我的示例代码:
it("method A should work correctly", () => {
const url = "http://dummy.com";
Object.defineProperty(window.location, "href", {
value: url,
writable: true
});
const data = {
id: "123",
name: null
};
window.location.href = url;
wrapper.vm.methodA(data);
expect(window.location.href).toEqual(url);
});
但是我得到这个错误:
TypeError: Cannot redefine property: href
at Function.defineProperty (<anonymous>)
我尝试了一些解决方案,但没有解决。我需要一些提示来帮助我摆脱困境。请帮助。
答案 0 :(得分:26)
基本
URL object与Location object具有许多相同的功能。换句话说,它包含pathname
,search
,hostname
等属性。因此,在大多数情况下,您可以执行以下操作:
delete window.location
window.location = new URL('https://www.example.com')
高级
您还可以嘲笑您可能需要的Location methods,它在URL界面上不存在:
const location = new URL('https://www.example.com')
location.assign = jest.fn()
location.replace = jest.fn()
location.reload = jest.fn()
delete window.location
window.location = location
答案 1 :(得分:9)
您可以尝试:
global.window = Object.create(window);
const url = "http://dummy.com";
Object.defineProperty(window, 'location', {
value: {
href: url
}
});
expect(window.location.href).toEqual(url);
查看有关该问题的笑话问题:
Jest Issue
答案 2 :(得分:6)
2019年的解决方案from GitHub:
delete global.window.location; global.window = Object.create(window); global.window.location = { port: '123', protocol: 'http:', hostname: 'localhost', };
答案 3 :(得分:6)
最好是创建一个新的URL
实例,以便像location.href
一样解析您的字符串,并像{{1}一样更新location
的所有属性。 },.hash
,.search
等
.protocol
答案 4 :(得分:4)
提供的许多示例并未模拟原始Location对象的属性。
我要做的只是用URL替换Location对象(window.location),因为URL包含与Location对象相同的属性,例如“ href”,“ search”,“ hash”,“ host”。
Setter和Getter的工作方式也与Location对象完全相同。
示例:
const realLocation = window.location;
describe('My test', () => {
afterEach(() => {
window.location = realLocation;
});
test('My test func', () => {
// @ts-ignore
delete window.location;
// @ts-ignore
window.location = new URL('http://google.com');
console.log(window.location.href);
// ...
});
});
答案 5 :(得分:2)
我已通过添加writable: true
并将其移至beforeEach
这是我的示例代码:
global.window = Object.create(window);
const url = "http://dummy.com";
Object.defineProperty(window, "location", {
value: {
href: url
},
writable: true
});
答案 6 :(得分:2)
在2020年使用@testing-library/react
处理window.location.assign的示例:
afterEach(cleanup)
beforeEach(() => {
Object.defineProperty(window, 'location', {
writable: true,
value: { assign: jest.fn() }
})
})
答案 7 :(得分:1)
扩展@jabacchetta的解决方案以避免此设置渗入其他测试:
describe("Example", () => {
let location;
beforeEach(() => {
const url = "https://example.com";
location = window.location;
const mockLocation = new URL(url);
mockLocation.replace = jest.fn();
delete window.location;
window.location = mockLocation;
});
afterEach(() => {
window.location = location;
});
});
答案 8 :(得分:0)
可以通过在每次测试中删除此全局变量来重写window.location。
delete global.window.location;
const href = 'http://localhost:3000';
global.window.location = { href };
答案 9 :(得分:0)
根据上述示例和其他示例,这是一个使用jest
的具体示例,可能会帮助某人:
describe('Location tests', () => {
const originalLocation = window.location;
const mockWindowLocation = (newLocation) => {
delete window.location;
window.location = newLocation;
};
const setLocation = (path) =>
mockWindowLocation(
new URL(`https://example.com${path}`)
);
afterEach(() => {
// Restore window.location to not destroy other tests
mockWindowLocation(originalLocation);
});
it('should mock window.location successfully', () => {
setLocation('/private-path');
expect(window.location.href).toEqual(
`https://example.com/private-path`
);
});
});
答案 10 :(得分:0)
您可以尝试一个助手:
const setURL = url => global.jsdom.reconfigure({url});
describe('Test current location', () => {
test('with GET parameter', () => {
setURL('https://test.com?foo=bar');
// ...your test here
});
});
答案 11 :(得分:0)
这对Jest + TypeScript + Next.js有效(如果您使用useRoute().push
const oldWindowLocation = window.location;
beforeAll(() => {
delete window.location;
window.location = { ...oldWindowLocation, assign: jest.fn() };
});
afterAll(() => {
window.location = oldWindowLocation;
});
答案 12 :(得分:0)
JSDOM版本
另一种使用JSDOM的方法,它将提供window.location.href
和window.location
的所有其他属性(例如window.location.search
以获取查询字符串参数)。
import { JSDOM } from 'jsdom';
...
const { window } = new JSDOM('', {
url: 'https://localhost/?testParam=true'
});
delete global.window;
global.window = Object.create(window);
答案 13 :(得分:0)
可能无关紧要。但是对于那些寻求 window.open('url', attribute) 解决方案的人,我在上面的一些评论的帮助下应用了这个:
<script type='application/ld+json'>
{
"@context": "http://schema.org",
"@type": "Invoice",
"accountId": "123-456-789",
"minimumPaymentDue": {
"@type": "PriceSpecification",
"price": "$70.00"
},
"paymentDue": "2015-11-22T08:00:00+00:00",
"paymentStatus": "PaymentAutomaticallyApplied",
"provider": {
"@type": "Organization",
"name": "Mountain View Utilities"
},
"totalPaymentDue": {
"@type": "PriceSpecification",
"price": "$70.00"
}
}
</script>