与Node.js相比,浏览器(在本例中为Chrome)中的URL
对象的行为不同。结果,我得到了在Node中运行时通过的测试,但是行为在浏览器中不匹配。
为了演示,这是一个简单的parseURL
函数,该函数尝试从字符串中解析URL。如果无法正确解析,则会返回一个URL,该URL等于使用提供的字符串进行的Google搜索。
function parseURL(query) {
const formattedQuery = query.includes('://') ? query : `http://${query}`;
try {
return new URL(formattedQuery);
} catch (err) {
return new URL(`https://www.google.com/search?q=${encodeURIComponent(query)}`);
}
}
还有一个简单的Jest测试,以演示该功能的预期工作方式:
describe('parseURL', () => {
it('accepts valid URL string', () => {
expect(parseURL('https://example.com')).toEqual(
new URL('https://example.com')
);
});
it('prepends protocol when missing', () => {
expect(parseURL('example.com')).toEqual(
new URL('http://example.com')
);
});
it('converts search queries', () => {
expect(parseURL('example.com lol jk')).toEqual(
new URL('https://www.google.com/search?q=example.com+lol+jk')
);
});
});
前两个测试对Node.js和浏览器都具有匹配的行为。太好了!
尽管浏览器内部行为不匹配,但是第三项测试仍通过了Node.js。具体来说,在Node.js中调用new URL('http://example.com lol jk')
时,会引发错误。但是在浏览器中,不会引发任何错误,而是返回一个URL对象:
{
href: "http://example.com%20lol%20jk/",
origin: "http://example.com%20lol%20jk",
protocol: "http:",
username: "",
password: "",
hash: "",
host: "example.com%20lol%20jk",
hostname: "example.com%20lol%20jk",
href: "http://example.com%20lol%20jk/",
origin: "http://example.com%20lol%20jk",
password: "",
pathname: "/",
port: "",
protocol: "http:",
search: "",
searchParams: URLSearchParams {},
username: ""
}
当使用这样的对象时,如何确定我的测试能够反映浏览器中实际发生的事情?
答案 0 :(得分:2)
问题在于URL
在实现之间不一致。
这是预期的行为
new URL('http://example.com lol jk')
引发错误,它不是有效的URL。可以在Node.js和Firefox中正确实现,但不能在Chrome(此处称为“浏览器”)中正确实现。
在Jest中依靠Node.js实现是安全的。如果生产中需要一致性,则{URL
必须替换为符合规范的实现whatwg-url
。