【问题标题】:Testing events with RequireJs + Karma + Jasmine使用 RequireJs + Karma + Jasmine 测试事件
【发布时间】:2021-02-15 14:34:22
【问题描述】:

我正在尝试寻找一种方法来测试事件。就像在主题标题中一样,我的堆栈是 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,
  })
}

【问题讨论】:

    标签: javascript jasmine requirejs karma-jasmine karma-runner


    【解决方案1】:

    问题在于navbar 模块在定义自身时附加了事件侦听器。

    我在上一份工作中遇到过类似的问题。

    有两种可能的解决方案。

    首先

    第一个,很简单,它不需要更改navbar 模块的代码,但需要对测试模块进行一些修改。

    1. 定义一个没有被测模块作为依赖的测试模块——这很关键
    2. 在测试用例中,将有效的html添加到文档中
    3. 需要测试模块
    4. 触发事件
    5. 检查结果
    6. 拆除 - undef 测试模块并清除文档 html

    这是伪代码:

    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
          });
        })
    })
    

    【讨论】:

      猜你喜欢
      • 2016-03-19
      • 2016-01-14
      • 2016-04-14
      • 2018-11-13
      • 1970-01-01
      • 2014-05-04
      • 1970-01-01
      • 2014-09-20
      • 2013-05-15
      相关资源
      最近更新 更多