i’m trying to find a way to test events. Like in topic title my stack is RequireJs + Karma + Jasmine. I dont want to use jQuery or any not essential external libraries.
There’s icon-utils code i use in my navbar:
icon -utils.js
define('icon-utils', [], function () {
return {
toggleIcon: function (icon, baseIcon, toggledIcon) {
if (baseIcon === icon.getAttribute("data-icon")) {
icon.setAttribute("data-icon", toggledIcon);
} else {
icon.setAttribute("data-icon", baseIcon);
}
}
};
});
And test of it:
define(['icon-utils'], function(iconUtils) {
describe('test iconUtils', function () {
let toggledIcon = 'toggledIcon';
let baseIcon = 'unToggledIcon';
it('should change icon to toggled', function() {
let icon = document.createElement("i");
icon.setAttribute("data-icon", baseIcon)
iconUtils.toggleIcon(icon, baseIcon, toggledIcon);
expect(icon.getAttribute("data-icon")).toEqual(toggledIcon)
});
it('should change icon to unToggled', function() {
let icon = document.createElement("i");
icon.setAttribute("data-icon", toggledIcon)
iconUtils.toggleIcon(icon, baseIcon, toggledIcon);
expect(icon.getAttribute("data-icon")).toEqual(baseIcon)
});
})
})
Now there is my nabar.js i want to test
define('navbar', ['icon-utils'], function (iconUtils) {
Array.from(document.getElementsByClassName("jb-navbar-menu-toggle")).forEach(
(el) => {
el.addEventListener("click", (e) => {
console.log("clicked");
const dropdownIcon = e.currentTarget
.getElementsByClassName("icon")[0]
.getElementsByClassName("material-icons")[0];
document
.getElementById(e.currentTarget.getAttribute("data-target"))
.classList.toggle("is-active");
iconUtils.toggleIcon(dropdownIcon, "more_vert", "close");
});
}
);
});
And yeah i need to test if class of selected dom element is changing on click:
define(['navbar'], function(navBar) {
describe('test navBar', function () {
it('should toggle is-active class on click ', function() {
});
})
})
I spent a lot of time looking for good solution, but i couldn’t find anything helpful. I need to find a way to attach event listener from navbar.js to dom element and check if event was triggered and if is-active class was toggled.
Also as there is not much good sources of testing pure Js i would appreciate every tips that will help me keep good practices and write quality tests.
There is also my karma.conf.js if it is any helpful:
// Karma configuration
// Generated on Tue Feb 09 2021 08:09:01 GMT+0100 (Central European Standard Time)
module.exports = function (config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '../..',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine', 'requirejs'],
// list of files / patterns to load in the browser
files: [
'tests/Ecommerce.Admin.Tests/test-main.js',
{pattern: 'src/Ecommerce.Admin/wwwroot/js/**/*.js', included: false},
{pattern: 'tests/Ecommerce.Admin.Tests/js/**/*.spec.js', included: false},
],
// list of files / patterns to exclude
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_DEBUG,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity,
captureTimeout: 210000,
browserDisconnectTolerance: 3,
browserDisconnectTimeout : 210000,
browserNoActivityTimeout : 210000,
})
}
The problem is that
navbar
module attaches event listeners while defining itself.I had similar problem in my previous job.
There are two possible solutions.
First
First one, is pretty simple, it does not require changing the code of the
navbar
module, but requires some hacks in the test module.Here is pseudo code:
Second
Second method will require changes in the code of the module. Instead of attaching event listeners while defining the module, you can return a function which will allow to attach listeners on demand.
Code for the module:
Testing will be much easier: