浏览器中的URL
对象(在本例中为Chrome(与Node.js的行为不同。 结果,我得到了在 Node 中运行时通过的测试,但行为在浏览器中不匹配。
为了演示,下面是一个简单的parseURL
函数,它尝试从字符串中解析 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: ""
}
我如何确信我的测试反映了使用此类对象时浏览器中实际发生的情况?
问题是URL
在实现之间不一致。
预期行为是
new URL('http://example.com lol jk')
抛出错误,它不是有效的 URL。它在Node.js和Firefox中正确实现,但在Chrome(这里被称为"浏览器"(中没有。
在 Jest 中依赖 Node.js 实现是安全的。如果在生产中需要一致性,则需要将URL
替换为符合规范的实现,whatwg-url
.