我们可以直接对 HTML 嵌入式 JavaScript 函数进行单元测试吗?

Can we directly unit test HTML embedded JavaScript functions?

假设我们有一个嵌入了JavaScript的网页,如index.html,如下所示:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
  <meta charset="utf-8" />

  <title>Cypress - Testing the Tester</title>

  <script>/*<![CDATA[*/  
    function foo() {
      return "bar";
    }

    function outputMessage(message) {
      document.querySelector("output").innerHTML += message + "<br />";
    }

    window.addEventListener("pageshow", function(){
      outputMessage(foo());
    });

  /*]]>*/</script>

</head>
<body>
  <h1>Cypress - Testing the Tester</h1>
  <output></output>
</body>
</html>

在页面显示(例如加载)中,这会在 <output></output>.

中插入字符串“bar”

如果my_cypress_spec.js是:

describe('The Home Page Tests', () => {
  it('Test HTML embedded JavaScript function', () => {
    // Assumes, e.g. "baseUrl": "http://127.0.0.1:5500" set in cypress.json
    cy.visit('index.html'); 
    expect(foo()).to.equal("bar");
  }); 
});

然后在赛普拉斯测试运行器中我得到一个“ReferenceError ... foo is not defined”。也就是说,赛普拉斯似乎无法识别 foo() 函数。

有没有办法让 Cypress 直接对 foo() 函数进行单元测试?也就是说,不依赖 ES6/ES2015 export/imports(上面的重构将 foo() 放在它自己的 JavaScript 文件中,然后 my_cypress_spec.js 导入它)?

正在尝试 我的 my_cypress_spec.js 变成:

describe('The Home Page Tests', () => {
  it('Test HTML embedded JavaScript function', () => {
    // Assumes, e.g. "baseUrl": "http://127.0.0.1:5500" set in cypress.json
    cy.visit('index.html'); 
    cy.window().then(win => {
      expect(win.foo()).to.eq('bar');
    });
  }); 
});

我收到错误“TypeError ... win.foo 不是一个函数”。

我不确定如果您使用更复杂的应用程序(例如使用 Angular 或 React 创建的应用程序),这将适用于何种程度。这些框架具有专门用于单元测试的测试工具。

对于您提供的原始 JS 示例,这很容易,因为 foo() 附加到 AUT 的 window。

cy.window().then(win => {
  expect(win.foo()).to.eq('bar')
})

Fody 的回答有效。所以,完整的 my_cypress_spec.js 可以变成这样的:

describe('The Home Page Tests', () => {
  it('Test HTML embedded JavaScript function', () => {
    // Assumes, e.g. "baseUrl": "http://127.0.0.1:5500" set in cypress.json
    cy.visit('index.html'); 
    cy.window().then(win => {
      expect(win.foo()).to.eq('bar');
    });
  }); 
});

但是,我收到“TypeError ... win.foo is not a function”的原因是因为在我机器上的 index.html 中(不是上面最初发布的那样)我有一个开幕 <script type="module">。将其改回 <script> 使测试通过。

因此,为了完整起见,我将其标记为“答案”,同时指出来自@Fody 和@jonrsharpe 的见解。