unit-testingcodeceptjs

How to use CodeceptJS to unit-test a JS function


I've set up CodeceptJS for a project and use it to test various end-to-end scenarios.

Now I want to extend the tests-suite to also run unit-tests to verify functionality of custom JS functions.

For example: I have a global object App that has a version attribute. As a first test, I want to confirm that App.version is present and has a value.

My first attempt is a test.js file with the following code:

Feature('Unit Tests');

Scenario('Test App presence', ({ I }) => {
    I.amOnPage('/');

    I.executeScript(function() {return App.version})
        .then(function(value) { I.say(value) } );
});

Problems with this code

  1. The major issue: How can I assert that the App.version is present?
    My script can display the value but does not fail if it's missing
  2. My code is very complex for such a simple test.
    I'm sure there's a cleaner/faster way to perform that test, right?

Solution

  • Here is a solution that works for me:

    Read data from the browser:

    1. I created a custom helper via npx codecept gh and named it BrowserAccess.
    2. The helper function getBrowserData uses this.helpers['Puppeteer'].page.evaluate() to run and return custom code from the browser scope. Documentation for .evaluate()

    Custom assertions:

    1. Install the codeceptjs-assert package, e.g. npm i codeceptjs-assert
    2. Add the AssertWrapper-helper to the codecept-config file. This enables checks like I.assert(a, b)

    Full Code

    codecept.conf.js

    exports.config = {
        helpers: {
            AssertWrapper: {
                require: "codeceptjs-assert"
            },
            BrowserAccess: {
                require: './browseraccess_helper.js'
            },
            ...
        },
        ...
    }
    

    browseraccess_helper.js

    const Helper = require('@codeceptjs/helper');
    
    class BrowserAccess extends Helper {
        async getBrowserData(symbolName) {
            const currentPage = this.helpers['Puppeteer'].page;
            let res;
    
            try {
                res = await currentPage.evaluate((evalVar) => {
                    let res;
                    try {
                        res = eval(evalVar);
                    } catch (e) {
                    }
                    return Promise.resolve(res);
                }, symbolName);
            } catch (err) {
                res = null;
            }
    
            return res;
        }
    }
    

    jsapp_test.js (the test is now async)

    Feature('Unit Tests');
    
    Scenario('Test App presence', async ({ I }) => {
        I.amOnPage('/');
    
        const version = await I.getBrowserData('App.version');
        I.assertOk(version);
    });