javascript - 如何测试使用 jest 操作 DOM 的普通 js 代码

标签 javascript unit-testing async-await mocking jestjs

// get submit button and add event listener to it
const submitBtn = document.getElementById("submit");
if(submitBtn){
submitBtn.addEventListener('click', loginFunction)
}
//call back function
function loginFunction(e){
    e.preventDefault();
    //  the data to post
    const data = {
        email: document.getElementById("email").value,
        password: document.getElementById("password").value,
    };

    //  post the data to db via fetch
    fetch("https://store-manager-api-app-v2.herokuapp.com/api/v2/auth/login",{
    headers: {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin':'*',
        'Access-Control-Request-Method': '*'
    },
    method:"POST",
    mode: "cors",
    body: JSON.stringify(data)

    }).then(function(response){return response.json()})
    .then(function(response){
        localStorage.setItem('token', response.token);
        if (response.Message === "User logged in successfully!"){
            // redirect to index page
            document.getElementById("notify").innerHTML =`<div class="isa_success">
                               <i class="fa fa-check"></i>
     ${response.Message}
    </div>`;
        window.location.assign('../HTML/index.html')
        }
        else{
            let notify = document.getElementById("notify");
            notify.innerHTML =`<div class="isa_info">
                        <i class="fa fa-info-circle"></i>
                        ${response.Message}
                         </div>`
        }

    })
}

这是我的 login.js 文件,它监听提交按钮,然后执行提取以登录用户。

下面是我的login.test.js 文件..这是对login.js 的测试,但它不起作用。我尝试将 await Promise.resolve.then() 更改为 jest.UseFakeTimers() 但它不起作用。有人知道它为什么不起作用以及可能的解决方案吗?

describe('login',() => {
    let fetchMock;
    let assignMock;

    beforeEach(() => {
        document.body.innerHTML +=`
        <div id="notify">
          </div>
        <form id="signin">
          <input type="email" id="email" value="<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a4d0c1d7d0e4c3c9c5cdc88ac7cbc9" rel="noreferrer noopener nofollow">[email protected]</a>">
          <input type="password"  id="password" value ="test1234">
          <input type="submit" id="submit">
        </form>`;
        fetchMock = jest.spyOn(global,'fetch');
        fetchMock.mockImplementation(() =>Promise.resolve ({
            json: () => Promise.resolve({Message:"User logged in successfully!"})
        }));
        assignMock = jest.spyOn(window.location , "assign");
        assignMock.mockImplementation(() =>{});
        require('../UI/js/login');
    });
    afterEach(() => {
        fetchMock.mockRestore();
        assignMock.mockRestore();
        jest.resetModules()
    });
    it('fetch data and change the content of #notify', async function() {
        document.getElementById('submit').click();
        expect(fetchMock).toHaveBeenCalledTimes(1);
        const fetchArgs = fetchMock.mock.calls[0];
        expect(fetchArgs[0]).toBe('https://store-manager-api-app-v2.herokuapp.com/api/v2/auth/login');
        expect(fetchArgs[1]).toEqual({
            method: "POST",
            headers: {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin':'*',
                'Access-Control-Request-Method': '*'
            },
            mode: "cors",
            body: JSON.stringify({
                email: '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2551405651654248444c490b464a48" rel="noreferrer noopener nofollow">[email protected]</a>',
                password: "test1234"
            })

        });
     await Promise.resolve().then();
     expect(document.getElementById('notify').innerHTML).toBe(`<div class="isa_success">
<i class="fa fa-check"></i>
    User logged in successfully!
     </div>`);
       expect(assignMock).toHaveBeenCalledTimes(1);
       expect(assignMock.mock.calls[0][0]).toBe("../HTML/index.html");
    });


});

这是我遇到的错误:

Error: expect(received).toBe(expected) // Object.is equality

Expected: "<div class=\"isa_success\">
<i class=\"fa fa-check\"></i>
    User logged in successfully!
     </div>"
Received: "
          "

Difference:

- Expected
+ Received

- <div class="isa_success">
- <i class="fa fa-check"></i>
-     User logged in successfully!
-      </div>
+ 
+            <Click to see difference>


      45 |         });
      46 |      await Promise.resolve().then();
    > 47 |      expect(document.getElementById('notify').innerHTML).toBe(`<div class="isa_success">
         |                                                          ^
      48 | <i class="fa fa-check"></i>
      49 |     User logged in successfully!
      50 |      </div>`);

      at Object.toBe (__tests__/login.test.js:47:58)
      at tryCatch (node_modules/regenerator-runtime/runtime.js:62:40)
      at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:296:22)
      at Generator.prototype.(anonymous function) [as next] (node_modules/regenerator-runtime/runtime.js:114:21)
      at step (__tests__/login.test.js:3:191)
      at __tests__/login.test.js:3:361

最佳答案

解决方案相当简单。我只需添加一个 await Promise.resolve.then() 行即可使其工作:

    describe('login',() => {
        let fetchMock;
        let assignMock;

        beforeEach(() => {
            document.body.innerHTML +=`
            <div id="notify">
              </div>
            <form id="signin">
              <input type="email" id="email" value="<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7a0e1f090e3a1d171b131654191517" rel="noreferrer noopener nofollow">[email protected]</a>">
              <input type="password"  id="password" value ="test1234">
              <input type="submit" id="submit">
            </form>`;
            fetchMock = jest.spyOn(global,'fetch');
            fetchMock.mockImplementation(() =>Promise.resolve ({
                json: () => Promise.resolve({Message:"User logged in successfully!"})
            }));
            assignMock = jest.spyOn(window.location , "assign");
            assignMock.mockImplementation(() =>{});
            require('../UI/js/login');
        });
        afterEach(() => {
            fetchMock.mockRestore();
            assignMock.mockRestore();
            jest.resetModules()
        });
        it('fetch data and change the content of #notify', async function() {
            document.getElementById('submit').click();
            expect(fetchMock).toHaveBeenCalledTimes(1);
            const fetchArgs = fetchMock.mock.calls[0];
            expect(fetchArgs[0]).toBe('https://store-manager-api-app-v2.herokuapp.com/api/v2/auth/login');
            expect(fetchArgs[1]).toEqual({
                method: "POST",
                headers: {
                    'Content-Type': 'application/json',
                    'Access-Control-Allow-Origin':'*',
                    'Access-Control-Request-Method': '*'
                },
                mode: "cors",
                body: JSON.stringify({
                    email: '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b5c1d0c6c1f5d2d8d4dcd99bd6dad8" rel="noreferrer noopener nofollow">[email protected]</a>',
                    password: "test1234"
                })

            });
         await Promise.resolve().then();
         await Promise.resolve().then(); //on adding this the test passes
         expect(document.getElementById('notify').innerHTML).toBe(`<div class="isa_success">
    <i class="fa fa-check"></i>
        User logged in successfully!
         </div>`);
           expect(assignMock).toHaveBeenCalledTimes(1);
           expect(assignMock.mock.calls[0][0]).toBe("../HTML/index.html");
        });


});

关于javascript - 如何测试使用 jest 操作 DOM 的普通 js 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53514939/

相关文章:

javascript - https ://graph. facebook.com/me/albums 有时什么都不返回

c++ - 有没有办法在不需要 stdafx.h 的情况下在 C++ 中使用预编译头文件?

entity-framework - EF6 alpha 异步等待实体存储过程/函数导入?

kotlin - 为什么 'await' 会阻塞 kotlin 中的线程?

javascript - 更改组合框中第一个滚动中可见的元素数

javascript - 装订铁页和和

PhpUnit 测试 stub 方法多次返回

java - 排序列表上的 AssertEquals 总是返回 false

javascript - 如何在 Koa.js 应用程序的验收测试中使用 ES2016 (ES7) async/await?

javascript - 如何使用 Material-UI 将排版主题默认值应用于常规标签?