使用Backbone Layoutmanager预编译Handlebar模板,用于Jasmine测试

时间:2012-12-04 18:53:11

标签: javascript unit-testing templates backbone.js jasmine

民间

我们的项目规模迅速扩大,我希望成为一名优秀的JS公民,并在为时已晚之前实施测试。我们正在使用Backbone与Backbone Layoutmanager和Handlebars模板创建我们的前端,我已阅读some excellent博客文章,介绍如何使用Backbone驱动的应用程序测试Jasmine与Jasmine-Jquery和Sinon,所以我决定去那。

但是,我们的设置有点不典型,因为我们正在使用RequireJS模块,使用Layoutmanager扩充Backbone,以及预编译Handlebars模板。我们正在由这些库的创建者异步地预编译模板as is suggested,在我意识到任何类型的异步jQuery / Ajax调用获胜之前,我花费了大量时间来敲打我的头脑。如果您使用Jasmine运行应用程序,则可以正常工作。 试图使$.ajax(...)调用与async: false同步,并没有这样做,并且深入了解Layoutmanager JS源代码,我发现这一切都是异步的。

所以无论如何这就是我最终使预编译工作的结果:

Backbone.LayoutManager.configure({
    manage: false,

    prefix: "app/templates/",

    fetch: function(path) {
        var done;
        var that = this;

        // Concatenate the file extension.
        path = path + ".html";

        runs(function() {
            if (!JST[path]) {
                done = that.async()

                return $.ajax({ url: app.root + path, async: false }).then(
                    //Successhandler
                    function(contents) {
                        JST[path] = Handlebars.compile(contents);
                        JST[path].__compiled__ = true;
                        done(JST[path]);
                    },
                    //Errorhandler
                    function(jqXHR, textStatus, errorThrown) {
                        //Feil ved lasting av template
                        //TODO logg feil på en eller annen måte
                    }
                );
            }
            // If the template hasn't been compiled yet, then compile.
            if (!JST[path].__compiled__) {
                JST[path] = Handlebars.compile(JST[path]);
                JST[path].__compiled__ = true;
            }
        });

        waitsFor(function() {
            return done;
        }, "loading template", 500);
        return JST[path];
    },

    // Override render to use Handlebars
    render: function(template, context) {
        return template(context);
    }

});

解决方案是将异步逻辑包装在runswaitFor中。

现在提出问题: 我不认为这是一个最佳解决方案,因为它迫使我复制app.js只是为了包装异步调用。有没有更好的方法解决这个问题?

如果还不够公平,希望其他人从这篇文章中学习。

1 个答案:

答案 0 :(得分:0)

我还没有找到避免重复app.js的解决方案。但是这个文件很少改变,所以这不是一个真正的问题。 然而,我对上面的异步处理做了一些改进,使其更加健壮:

    waitsFor(function() {
        return JST[path] && JST[path].__compiled__;
    }, "loading template", 1000);
    return JST[path];

然后可以移除行done(JST[path]);

测试现在运行得更稳定,之前由于模板加载不正确,它们有时会失败。

接受这个作为答案。