簡體   English   中英

在 Jest 中測試 XMLHttpRequest onload() 回調功能

[英]Testing XMLHttpRequest onload() callback functionality in Jest

I'm testing some plain HTML and vanilla javascript with Jest and would like to be able to mock the XMLHttpRequest with the exception of the onload() callback function I've defined.

我找到了一些如何模擬整個 XMLHttpRequest 的示例,但我希望能夠模擬除我在代碼中定義的加載 function 之外的所有內容(這就是我要測試的邏輯)。

我想測試的 javascript function 看起來像:

function foo() {
    document.getElementById("loading").style.display = "block";

    var request = new XMLHttpRequest();
    request.open('POST', '/expected/url', true);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    request.send();
    request.onload = function () {
        if (request.status === 200) {
            var array = JSON.parse(request.responseText);
            array.forEach(function (object) {
                // do some stuff
            });

            document.getElementById("loading").style.display = "none";
        }
        else {
            document.getElementById("loading").style.display = "none";
        }
    };
};

module.exports = {
    foo
}

我的測試文件看起來像:

var script = require('../fs/script.js');
const fs = require('fs');
const path = require('path');
const html = fs.readFileSync(path.resolve(__dirname, '../fs/index.html'), 'utf8');

const createMockXHR = responseJSON => {
    const mockXHR = {
        open: jest.fn(),
        send: jest.fn(),
        setRequestHeader: jest.fn(),
        status: 200,
        readyState: 4,
    };
    return mockXHR;
};

describe('Foo', function () {
    const oldXMLHttpRequest = window.XMLHttpRequest;
    let mockXHR = null;

    beforeEach(() => {
        document.documentElement.innerHTML = html.toString();
        mockXHR = createMockXHR();
        window.XMLHttpRequest = jest.fn(() => mockXHR);
    });

    afterEach(() => {
        window.XMLHttpRequest = oldXMLHttpRequest;
        jest.resetModules();
    });

    it('is set, section is collapsed', function () {
        mockXHR.response = '{ "data": "point"}';

        var bar = document.getElementById("bar");
        var elementToCollapse = bar.nextElementSibling;

        script.foo();

        expect(mockXHR.send).toBeCalled();
        expect(mockXHR.onload).toBeCalled();
        // expect some more things
    });
});

我知道上面是錯誤的,因為onload()在我的模擬中的任何地方都沒有定義,但我發現的唯一碎屑是關於我如何能夠做到這一點的會引發錯誤:

const createMockXHR = responseJSON => {
    const mockXHR = {
        open: jest.fn(),
        send: jest.fn().mockImplementation(function () {
            onload = this.onload.bind(this);
            onerror = this.onerror.bind(this);
        }),
        setRequestHeader: jest.fn(),
        status: 200,
        readyState: 4,
    };
    return mockXHR;
};

錯誤:

TypeError: Cannot read properties of undefined (reading 'bind')

      12 |         send: jest.fn().mockImplementation(function () {
    > 13 |             onload = this.onload.bind(this);

雖然沒有從技術上回答這個問題,但我已經解決了我無法測試onload()內聯 function 的問題,方法是將邏輯放在單獨的 function 中並測試:

function foo_logic(request) {
    // the logic
}

function foo() {
    document.getElementById("loading").style.display = "block";

    var request = new XMLHttpRequest();
    request.open('POST', '/expected/url', true);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    request.send();
    request.onload = function () { foo_logic(request) };
};

module.exports = {
    foo_logic,
    foo
}

然后測試:

var script = require('../fs/script.js');
const fs = require('fs');
const path = require('path');
const html = fs.readFileSync(path.resolve(__dirname, '../fs/index.html'), 'utf8');

const createMockXHR = responseJSON => {
    const mockXHR = {
        open: jest.fn(),
        send: jest.fn(),
        setRequestHeader: jest.fn(),
        status: 200,
        readyState: 4,
    };
    return mockXHR;
};

describe('Foo', function () {
    const oldXMLHttpRequest = window.XMLHttpRequest;
    let mockXHR = null;

    beforeEach(() => {
        document.documentElement.innerHTML = html.toString();
        mockXHR = createMockXHR();
        window.XMLHttpRequest = jest.fn(() => mockXHR);
    });

    afterEach(() => {
        window.XMLHttpRequest = oldXMLHttpRequest;
        jest.resetModules();
    });

    it('is set, section is collapsed', function () {
         mockXHR.responseText = JSON.stringify({
            data: "point"
        });

        var bar = document.getElementById("bar");
        var elementToCollapse = bar.nextElementSibling;

        script.foo_logic(mockXHR);

        // expect some things about bar and elementToCollapse
    });
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM