javascript - jasmine-fixtures - 从未见过的 DOM 变化

标签 javascript unit-testing dom jasmine fixtures

我有两个 RequireJS 模块,一个用于从外部服务获取数据,一个负责将回调传递给第一个模块。

这是第一个非常基本的模块:

define(["jquery"], function($) {

    return {
        /**
         * Retrieves all the companies that do not employs the provided employee
         * @param employeeId ID of the employee
         * @param successCallback callback executed on successful request completion
         * @return matching companies
         */
        fetchCompanies: function(employeeId, successCallback) {
            var url = '/employees/' + employeeId + '/nonEmployers';
            return $.getJSON(url, successCallback);
        }
    };
});

最有趣的是,它会生成一个新的下拉菜单并将其注入(inject)到指定的 DOM 元素中(这是被测试的):

define([
    'jquery',
    'vendor/underscore',
    'modules/non-employers',
    'text!tpl/employeeOption.tpl'], function($, _, nonEmployers, employeeTemplate) {

    var updateCompanies = function(selectedEmployeeId, companyDropDownSelector) {
        nonEmployers.fetchCompanies(selectedEmployeeId, function(data) {
            var template = _.template(employeeTemplate),
                newContents = _.reduce(data, function(string,element) {
                    return string + template({
                        value: element.id,
                        display: element.name
                    });
                }, "<option value='-1'>select a client...</option>\n");
            $(companyDropDownSelector).html(newContents);
        });
    };

    return {
        /**
         * Updates the dropdown identified by companyDropDownSelector
         * with the companies that are non employing the selected employee
         * @param employeeDropDownSelector selector of the employee dropdown
         * @param companyDropDownSelector selector of the company dropdown
         */
        observeEmployees: function(employeeDropDownSelector, companyDropDownSelector) {
            $(employeeDropDownSelector).change(function() {
                var selectedEmployeeId = $(employeeDropDownSelector + " option:selected").val();
                if (selectedEmployeeId > 0) {
                    updateCompanies(selectedEmployeeId, companyDropDownSelector);
                }
            });
        }
    };
});

我正在尝试使用 Jasmine-fixtures 和 waitsFor 来测试最后一个模块,以异步检查设置测试 DOM 结构是否已被修改。但是,总是会超时。

如果您能发现以下测试中的问题,我将不胜感激(要点:https://gist.github.com/fbiville/6223bb346476ca88f55d):

define(["jquery", "modules/non-employers", "modules/pages/activities"], function($, nonEmployers, activities) {
    describe("activities test suite", function() {
        var $form, $employeesDropDown, $companiesDropDown;

        beforeEach(function() {
            $form = affix('form[id=testForm]');
            $employeesDropDown = $form.affix('select[id=employees]');
            $employeesDropDown.affix('option[selected=selected]');
            $employeesDropDown.affix('option[value=1]');
            $companiesDropDown = $form.affix('select[id=companies]');
            $companiesDropDown.affix('option');
        });

        it("should update the company dropdown", function() {
            spyOn(nonEmployers, "fetchCompanies").andCallFake(function(employeeId, callback) {
                callback([{id: 42, name: "ACME"}, {id: 100, name: "OUI"}]);
            });

            activities.observeEmployees('#employees', '#companies');
            $('#employees').trigger('change');

            waitsFor(function() {
                var companiesContents = $('#companies').html(),
                    result = expect(companiesContents).toContain('<option value="42">ACME</option>');

                return result && expect(companiesContents).toContain('<option value="100">OUI</option>');
            }, 'DOM has never been updated', 10000);
        });
    });
});

提前致谢!

罗尔夫

P.S.:将 $(employeeDropDownSelector).change 替换为 $(employeeDropDownSelector).on('change', 和/或包装 activities.observeEmployees 使用 domReady 调用(和 $('#employees').trigger('change');)产生相同的结果

P.P.S.:这个错误是原因 -> SEVERE:runtimeError:message=[指定了一个无效或非法的选择器(选择器:'[id='employees'] :selected' 错误:无效的选择器:*[ id="employees"] *:selected).] sourceName=[http://localhost:59811/src/vendor/require-jquery.js] line=[6002] lineSource=[null] lineOffset=[0]

P.P.P.S.:HtmlUnit 似乎不支持 CSS3 选择器(WTF?),甚至强制使用最新发布的版本,因为 jasmine-maven-plugin 依赖性不会改变任何东西......

有什么办法可以改变 jasmine 插件运行器吗?

最佳答案

好的伙计们。

找到的解决方案:

  1. 升级(如果还没有)到 jasmine-maven-plugin v1.3.1.1(或更高版本)
  2. > configure phantomjs而不是这个糟糕的 HtmlUnit(将 PhantomJS binaries 添加到您的项目中)
  3. 如果您在代码中使用了“:focus”选择器,请注意 this bug , 将其替换为 $(mySelector).get(0) == document.activeElement
  4. 另外,如果代码块位于 waitsFor 之后,请不要忘记用 run(function() {/* expect */}) 包裹你的代码块> 条件。

最后,一切都应该很好。

看看现在考试怎么样:

define(["jquery",
    "modules/nonEmployers",
    "modules/pages/activities"], function($, nonEmployers, activities) {

    describe("activities test suite", function() {
        var $form, $employeesDropDown, $companiesDropDown;

        beforeEach(function() {
            $form = affix('form[id=testForm]');
            $employeesDropDown = $form.affix('select[id=employees]');
            $employeesDropDown.affix('option[selected=selected]');
            $employeesDropDown.affix('option[value=1]');
            $companiesDropDown = $form.affix('select[id=companies]');
            $companiesDropDown.affix('option');

            spyOn(nonEmployers, "fetchCompanies").andCallFake(function(employeeId, callback) {
                callback([{id: 42, name: "ACME"}, {id: 100, name: "OUI"}]);
            });
        });


        it("should update the company dropdown", function() {

            $(document).ready(function() {
                activities.observeEmployees('#employees', '#companies');
                $('#employees option[selected=selected]').removeAttr("selected");
                $('#employees option[value=1]').attr("selected", "selected");
                $('#employees').trigger('change');

                waitsFor(function() {
                    var dropDown = $('#companies').html();
                    return dropDown.indexOf('ACME') > 0 && dropDown.indexOf('OUI') > 0;
                }, 'DOM has never been updated', 500);

                runs(function() {
                    var dropDown = $('#companies').html();
                    expect(dropDown).toContain('<option value="42">ACME</option>');
                    expect(dropDown).toContain('<option value="100">OUI</option>');
                });
            });
        });
    });
});

关于javascript - jasmine-fixtures - 从未见过的 DOM 变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16001190/

相关文章:

javascript - 将变量从 HREF 传递到 Google HTMLSERVICE 应用程序

javascript - TinyMCE:保存内容时我的 HTML 发生了变化。我怎样才能保留我的 HTML?

python - 如何将 `msg` 传递给 unittest.mock 断言方法?

python - 确保 py.test 在 sys.path 中包含应用程序目录

javascript - 使用 jQuery 动态呈现选择框的问题

javascript - 在新窗口中 jquery 函数不起作用

android - 如何从 XML 中获取嵌入的 XML

Javascript 优化 : What tool can condense sequential string concatenations?

javascript - 在 AngularJS 深度过滤方面需要帮助

c# - 在方法中模拟一个对象