jeudi 27 septembre 2018

Do I need Mocha if looks like pure JS is enough for me?

I am developing a WebExtension for browsers, and I want to start TDD. Usually, folks without experience in testing of client-side JS just google for a popular framework and stick with it - even without trying to test functions in pure JS. I do not like dependencies - I use anything only if I understand what problem it resolves, I like simplicity. Currently, I do not know why I need any Javascript unit-testing framework. Now I see at popular https://mochajs.org and do not see reasons to use it.

Now my code looks like this:

function unitTests() {  // eslint-disable-line no-unused-vars

(function _prepareRemoving_test() {
    (function _setUp() {
        _testUtils._fillDB();
    })();

    (async function _isUnique() {
        const {itemFeed, isUniqueForUser} = await _prepareRemoving(_testUtils['id']);
        console.assert(itemFeed['hashArticle'] === _testUtils['val']['hashArticle'], itemFeed);
        console.assert(isUniqueForUser === true, isUniqueForUser);
    })();
    _testUtils._addArticleWithDuplicatedHash();
    (async function _isNotUniqueWhenPreviousWithTheSameHash() {
        const {itemFeed, isUniqueForUser} = await _prepareRemoving(_testUtils['id3']);
        console.assert(itemFeed['hashArticle'] === _testUtils['val3']['hashArticle'], itemFeed);
        console.assert(isUniqueForUser === false, isUniqueForUser);
    })();
    (async function _isNotUniqueWhenNextWithTheSameHash() {
        const {itemFeed, isUniqueForUser} = await _prepareRemoving(_testUtils['id2']);
        console.assert(itemFeed['hashArticle'] === _testUtils['val2']['hashArticle'], itemFeed);
        console.assert(isUniqueForUser === false, isUniqueForUser);
    })();

    (function _tearDown() {
        _testUtils._clearDB();
    })();

})();

(function _syncHistory_test() {
    // ===== setup =====
    const fetchOriginal = window.fetch;
    const chromeOriginal = window.chrome;
    // ===== end of setup =====

    (function _added() {
        (function _mock() {
            window.fetch = function() {
                _testUtils._mock(fetch, arguments);
                return fetchOriginal('unitTests/_syncHistory/mockResponses/added.json');
            };
            window._getArticle = function() {
                _testUtils._mock(_getArticle, arguments);
                return Promise.resolve();
            };
            window._persistItemFeed = function() {
                _testUtils._mock(_persistItemFeed, arguments);
            };
            chrome.runtime.sendMessage = function() {
                _testUtils._mock(chrome.runtime.sendMessage, arguments);
            };
            chrome.storage.sync.set = function() {
                _testUtils._mock(chrome.storage.sync.set, arguments);
            };
        })();

        _syncHistory(0, 'myFakeIdToken');

        console.assert(fetch['hasCalls'].length === 1);
        console.assert(fetch['hasCalls'][0][0] === `${stageUrlNew}history?updated=0`);
        console.assert(
            fetch['hasCalls'][0][1]['headers']['Authorization'] = 'myFakeIdToken'
        );

        setTimeout(_ => {  // setTimeout for waiting all callbacks from fetch()
            console.assert(_getArticle['hasCalls'].length === 1);
            console.assert(_getArticle['hasCalls'][0][0] === 1537886629);
            console.assert(
                _persistItemFeed['hasCalls'][0][0] === '1537886629'
            );
            console.assert(
                _persistItemFeed['hasCalls'][0][1] === 'https://example.com/favicon.ico'
            );
            console.assert(
                _persistItemFeed['hasCalls'][0][2] === 'https://example.com/my-article'
            );
            console.assert(
                _persistItemFeed['hasCalls'][0][3] === 'The title of article'
            );
            console.assert(
                _persistItemFeed['hasCalls'][0][4] === false
            );
            console.assert(
                _persistItemFeed['hasCalls'][0][5] === true
            );
            console.assert(
                _persistItemFeed['hasCalls'][0][6] === false
            );
            console.assert(
                _persistItemFeed['hasCalls'][0][7] === '75042f43e7ba2228934f75d96a02f7a1'
            );
            console.assert(
                _persistItemFeed['hasCalls'][0][8] === 1
            );

            console.assert(chrome.runtime.sendMessage['hasCalls'].length === 1);
            console.assert(
                chrome.runtime.sendMessage['hasCalls'][0][0]['fromPopup'] === '_cacheSynced'
            );
            console.assert(
                chrome.runtime.sendMessage['hasCalls'][0][0]['hashArticle'] ===
                    '75042f43e7ba2228934f75d96a02f7a1'
            );
            console.assert(
                chrome.runtime.sendMessage['hasCalls'][0][0]['id'] === '1537886629'
            );
            console.assert(
                chrome.runtime.sendMessage['hasCalls'][0][0]['lenChunks'] === '1'
            );
            console.assert(
                chrome.runtime.sendMessage['hasCalls'][0][0]['idToken'] === 'myFakeIdToken'
            );

            console.assert(
                chrome.storage.sync.set['hasCalls'].length === 1
            );
            console.assert(
                typeof chrome.storage.sync.set['hasCalls'][0][0]['updated'] === 'number'
            );
            console.assert(
                Number.isInteger(chrome.storage.sync.set['hasCalls'][0][0]['updated'])
            );
            console.assert(
                (chrome.storage.sync.set['hasCalls'][0][0]['updated'] + '').length === 10
            );

            _syncHistory(1537886629, 'myFakeIdToken');
            console.assert(fetch['hasCalls'].length === 2);
            console.assert(
                fetch['hasCalls'][1][0] === `${stageUrlNew}history?updated=1537886629`
            );
            console.assert(
                fetch['hasCalls'][1][1]['headers']['Authorization'] = 'myFakeIdToken'
            );

            (function _tearDown() {
                window.fetch = fetchOriginal;
                window.chrome = chromeOriginal;
            })();

        }, 100);
    })();
}

My helper function:

const _testUtils = {  // eslint-disable-line no-unused-vars
    id:  1000000,
    id1: 1111111,
    id2: 2222222,
    id3: 3333333,
    val:  {'hashArticle': '75042f43e7ba2228934f75d96a02f7a0', 'cache': [new Blob(), new Blob()]},
    val1: {'hashArticle': '75042f43e7ba2228934f75d96a02f7a1', 'cache': [new Blob(), new Blob()]},
    val2: {'hashArticle': '75042f43e7ba2228934f75d96a02f7a2', 'cache': [new Blob(), new Blob()]},
    val3: {'hashArticle': '75042f43e7ba2228934f75d96a02f7a2', 'cache': [new Blob(), new Blob()]},

    _fillDB: function() {
        return Promise.all([
            _insertOrReplace(this.id,  this.val),
            _insertOrReplace(this.id1, this.val1),
            _insertOrReplace(this.id2, this.val2)
        ]);
    },
    _addArticleWithDuplicatedHash: function() {
        _insertOrReplace(this.id3, this.val3);
    },
    _clearDB: function() {
        _deleteArticle(this.id);
        _deleteArticle(this.id1);
        _deleteArticle(this.id2);
        _deleteArticle(this.id3);
    },
    _hasCallsify: function(obj) {
        if (!obj['hasCalls']) {
            obj['hasCalls'] = [];
        }
    },
    _mock: function(obj, _arguments) {
        this._hasCallsify(obj);
        obj['hasCalls'].push(_arguments);
    }
};

Aucun commentaire:

Enregistrer un commentaire