QA challenge Sudoku Solver: running Unit tests involving DOM access and manipulation

Hello.

I coded the following test unit for the second suite:

test('Shows an error for puzzles that are not 81 numbers long', done => {
            const shortStr = '83.9.....6.62.71...9......1945....4.37.4.3..6..';
            const longStr = '..9..5.1.85.4....2432......1...69.83.9.....6.62.71...9......1945....4.37.4.3..6...';
            const errorMsg = 'Error: Expected puzzle to be 81 characters long.';
            const errorDiv = document.getElementById('error-msg');
            const textArea = document.getElementById('text-input');
            Solver.displayMsg(errorDiv)('hidden', '');
            textArea.value = shortStr;
            //Trigger click event
            textArea.dispatchEvent(domEvent);
            document.getElementById('solve-button').click();
            assert.equal(errorDiv.innerText, errorMsg);
            assert.equal(errorDiv.style.visibility, 'visible');
            done();
        });

Solver.displayMsg calls the following function from sudoku-solver.js.

const displayMsg = (elem)=> (visible, msg) => {
        elem.style.visibility = visible;
        elem.innerText = msg;
    }

textArea.dispatchEvent(domEvent) is supposed to initialize textArea with the input bound event. domEvent variable has assigned an event object after a promise in suiteSetup is resolved:

suiteSetup(()=> {
        // Mock the DOM for testing and load Solver
        return JSDOM.fromFile('./views/index.html', {
            runScripts: 'dangerously',
            resources: 'usable'
        })
        .then(dom =>
            new Promise(resolve => {
                dom.window.document.addEventListener('DOMContentLoaded', () => {
                    global.window = dom.window;
                    global.document = dom.window.document;

                  domEvent= new window.Event("input");

                    Solver = require('../public/sudoku-solver');
                    resolve();
                })
            }))
    });

The click event on solve-button element, executes the following callback from sudoku-solver.js:

 const solvePuzzle = () => {
        const {
            value
        } = textArea;
        const errorElem = displayMsg(document.getElementById('error-msg'));
        
        if (value.length !== 81) {

            errorElem('visible', 'Error: Expected puzzle to be 81 characters long.');
            return;
        }
        twoDimArr = createTwoDimensionalArray(value);
        if (!checkSolvable()) {
            errorElem('visible', 'Error: No solution.');
            return;
        }
        if (findSolution()) {
            errorElem('hidden', '');
            globalPuzzleArr = [].concat(...twoDimArr);
            textArea.value = globalPuzzleArr.join('');
            drawOnCells(globalPuzzleArr);
            return;
        }
        return displayMsg('visible', 'Error:No solution found');
    }

However, I can’t get past the assertions. Am I missing something? Even console.log doesn’t show the content in errorDiv. So I’m having a hard time debugging my own test unit.

I run npm run test, which is "cross-env NODE_ENV=test mocha --require @babel/register --recursive --exit --ui tdd tests/" to run the suites by the way.

1 Like

In case someone gets into a similar issue. The solution was actually due to lack of a timeout setting.

cross-env NODE_ENV=test mocha --timeout 5000 --require @babel/register --recursive --exit --ui tdd tests/

A link to my unit tests code. If anybody wants to check out.

Glad you found the problem.

I have a similar problem with the timeout on repl.it. I finished the project recently and it runs and passes all the tests locally, but the DOM mocking has been failing in the suiteSetup() hook of the unit tests on repl.it (saying Error: Timeout of 20000ms exceeded.). I’m just curious as to which deployment platform you used and if you saw any issues like this.

Remove done argument and done(); from your suiteSetup() function in

unit-tests.js

Promise fulfillment is already handled by .then method
.

suiteSetup(()=>
                   {
                     // Mock the DOM for testing and load Solver
                     return JSDOM.fromFile('./views/index.html')
                       .then(function(dom)
                             {
                               global.window = dom.window;
                               global.document = dom.window.document;

                               Solver = require('../public/sudoku-solver.js');
                             });

                   });

Here, a repl.it deployment of your code. You can take a look at the slight change and run tests. These are working as intented.

1 Like

Second set of eyes.

The done() isn’t in my local copy. I tried that as an experiment in the repl.it code and forgot I had it there when I started adjusting the timeouts. And in retrospect, I can’t even remember what I was trying to accomplish with the experiment.

Thanks.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.