0

我有一个模式登录视图,我正在用 Jasmine 进行测试。我在测试登录按钮重定向时遇到了一个令人讨厌的问题。我已经将重定向放在一个方法中,以便我可以模拟它并测试调用,但是当我触发登录按钮上的点击事件时,间谍似乎被忽略了。

这是我正在测试的视图...

define(['ministry', 'models/m-auth', 'helpers/cookie-manager', 'text!templates/modals/login.html', 'jquery.custom'],
function (Ministry, Authentication, CookieManager, TemplateSource) {
    var loginView = Ministry.SimpleView.extend({

        name: 'Login',

        el: "#popupLoginWrapper",

        template: Handlebars.compile(TemplateSource),

        events: {
            'submit #loginForm': 'signIn'
        },

        redirectToOrigin: function () {
            // TODO: Change location to member home when implemented
            location.href = '/#/jqm';
        },

        signIn: function (e) {
            var that = this;

            e.preventDefault();

            // As we have no input yet log in manually using the auth model...
            var authData = new Authentication.Request({
                requestSource: $('#requestSource').text(),
                apiKey: $('#apiKey').text(),
                username: '*****',
                password: '*****'
            });

            // This saves the login details, generating a session if necessary, then creates a cookie that lasts for 1 hour
            authData.save(authData.attributes, {                    
                success: function () {
                    if (authData.generatedHash !== undefined && authData.generatedHash !== null && authData.generatedHash !== '')
                        CookieManager.CreateSession(authData.generatedHash);
                        that.redirectToOrigin();
                }
            });
        },
    });

    return loginView;
});

(它目前使用硬编码帐户登录 - 连接实际控件是下一项工作)。这是有问题的测试(为了简单起见,我将所有前后都合并到测试中)......

        var buildAndRenderView = function (viewObject) {
            viewObject.render();
            $('#jasmineSpecTestArea').append(viewObject.el);
            return viewObject;
        };

        it("signs in when the 'Sign In' button is clicked", function () {
            spyOn(objUt, 'redirectToOrigin').andCallFake(Helper.DoNothing);
            spyOn(Backbone.Model.prototype, 'save').andCallFake(function (attributes, params) {
                params.success();
            });

            $('body').append('<div id="jasmineSpecTestArea"></div>');
            $('#jasmineSpecTestArea').append('<section id="popupLoginWrapper"></section>');
            objUt = new View();
            buildAndRenderView(objUt);

            objUt.$('#loginForm button').click();

            expect(objUt.redirectToOrigin).toHaveBeenCalled();

            $('#jasmineSpecTestArea').remove();
        });

一些简短的理由:我将绝大多数视图作为独立组件进行处理,然后在称为区域(以 Marionette 为模型)的自定义视图变体中呈现 - 我通常发现这是一个很好的整洁实践,可以帮助我跟踪什么位于应用程序中的位置,与给定“空间”中的内容分开。此策略似乎不适用于诸如此类的花哨模式,因此渲染发生在隐藏的现有 DOM 元素中,然后移动到该区域中,因此需要将代码附加 'popupLoginWrapper' 到测试区域.

如果我直接使用空事件参数调用登录方法,上述相同的测试也会失败。Jasmine 给了我以下错误“错误:预期是间谍,但得到了功能。” (这是有道理的,因为它调用的是 redirectToOrigin 的实际实现而不是 spy。

我有类似的测试通过了,问题似乎与 params.success() 的触发有关,但这是测试所必需的。

附加:禁用测试后,我发现此问题会影响此模式的大多数测试。通过单步执行,我可以看到在某些情况下应用了 spy 并执行了 spy 代码,但随后似乎触发了真正的成功调用。

4

1 回答 1

0

我似乎已经解决了这个问题 - 我不确定如何解决;几天后我刚刚完全接近它 - 测试现在看起来像这样......

            var buildAndRenderView = function (viewObject) {
                viewObject.render();
                $('#jasmineSpecTestArea').append(viewObject.el);
                viewObject.postRender();
                return viewObject;
            };

               it("signs in when the 'Sign In' button is clicked", function () {
                    $('body').append('<div id="jasmineSpecTestArea"></div>');
                    $('#jasmineSpecTestArea').append('<section id="popupLoginWrapper"></section>');
                    objUt = new View();
                    spyOn(objUt, 'redirectToOrigin').andCallFake(Helper.DoNothing);
                    spyOn(objUt, 'displayError').andCallFake(Helper.DoNothing);
                    spyOn(Backbone.Model.prototype, 'save').andCallFake(function (attributes, params) {
                        params.success();
                    });

                    objUt = buildAndRenderView(objUt);
                    objUt.$('#loginForm button').click();

                    expect(objUt.redirectToOrigin).toHaveBeenCalled();
                    expect(objUt.displayError).not.toHaveBeenCalled();
                    $('#jasmineSpecTestArea').remove();
                });

displayError 调用是添加的,因为我从最初的问题开始就包装了错误警报机制,所以并不是特别相关。在修复测试后,我将一些变量集拆分为 postRender,因此这也不相关。

问题似乎是调用 buildAndRenderView 方法而没有将返回值设置为对象。通过改变这个...

buildAndRenderView(objUt);

到...

objUt = buildAndRenderView(objUt);

问题自行解决。

于 2013-08-14T09:13:14.870 回答