Node.js和浏览器之间的测试行为有所不同

时间:2018-09-02 22:38:35

标签: javascript node.js browser jestjs

与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: ""
}

当使用这样的对象时,如何确定我的测试能够反映浏览器中实际发生的事情?

1 个答案:

答案 0 :(得分:2)

问题在于URL在实现之间不一致。

这是预期的行为

new URL('http://example.com lol jk')

引发错误,它不是有效的URL。可以在Node.js和Firefox中正确实现,但不能在Chrome(此处称为“浏览器”)中正确实现。

在Jest中依靠Node.js实现是安全的。如果生产中需要一致性,则{URL必须替换为符合规范的实现whatwg-url