我正在寻找一种测试事件的方法。就像主题标题一样,我的堆栈是 RequireJs + Karma + Jasmine。我不想使用 jQuery 或任何非必要的外部库。
我在导航栏中使用了 icon-utils 代码: 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);
}
}
};
});
并对其进行测试:
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)
});
})
})
现在有我要测试的nabar.js
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");
});
}
);
});
是的,我需要测试所选 dom 元素的类是否在单击时发生变化:
define(['navbar'], function(navBar) {
describe('test navBar', function () {
it('should toggle is-active class on click ', function() {
});
})
})
我花了很多时间寻找好的解决方案,但我找不到任何有用的东西。我需要找到一种方法将事件侦听器从 navbar.js 附加到 dom 元素,并检查是否触发了事件以及是否切换了 is-active 类。
此外,由于测试纯 Js 的良好来源并不多,我将不胜感激每一条有助于我保持良好实践和编写质量测试的提示。
如果有帮助的话,还有我的 karma.conf.js:
// 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,
})
}
答案 0 :(得分:0)
问题在于 navbar
模块在定义自身时附加了事件侦听器。
我在之前的工作中遇到过类似的问题。
有两种可能的解决方案。
第一个非常简单,它不需要更改 navbar
模块的代码,但需要在测试模块中进行一些修改。
这是伪代码:
define(function() {
beforeEach(function(done) {
document.body.innerHtml = 'put your html here'
require(['navbar'], function() {
done() // RequireJS is async so we need to give Jasmine information that the beforeEach section is finished
})
})
beforeEach((done) => {
document.body.innerHtml = ''
require.undef('navbar')
})
describe('test navBar', function () {
it('should toggle is-active class on click ', function() {
// trigger click
// do assertions
});
})
})
第二种方法需要更改模块的代码。您可以返回一个允许按需附加侦听器的函数,而不是在定义模块时附加事件侦听器。
模块代码:
define('navbar', ['icon-utils'], function (iconUtils) {
return () => {
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");
});
}
);
});
});
测试会容易得多:
define(['navbar'], function(navbar) {
beforeEach((done) => {
document.body.innerHtml = ''
})
describe('test navBar', function () {
it('should toggle is-active class on click ', function() {
document.body.innerHtml = 'put your html here'
navbar()
// trigger click
// do assertions
});
})
})