如何测试包含i18next实现的Durandal.js viewmodel?

时间:2013-12-19 11:17:41

标签: jasmine durandal i18next

我是Durandal.js和使用Jasmine进行Javascript测试的新手,需要一些帮助。我已经设法使用Karma和Jasmine运行测试环境,但我很难弄清楚如何测试包含i18next依赖项的viewmodel。

以下是我的设置的简要示例:

main.js

requirejs.config({
    paths: {
        'models': 'models',
        'text': '../lib/require/text',
        'durandal': '../lib/durandal/js',
        'plugins': '../lib/durandal/js/plugins',
        'transitions': '../lib/durandal/js/transitions',
        'knockout': '../lib/knockout/knockout-2.3.0',
        'bootstrap': '../lib/bootstrap/js/bootstrap.min',
        'jquery': '../lib/jquery/jquery-1.9.1',
        'i18next': '../lib/i18next/i18next.amd.withJQuery-1.7.1.min'
    }
});

define(['plugins/router', 'durandal/system', 'durandal/app', 'durandal/binder', 'durandal/viewLocator', 'knockout', 'jquery', 'i18next'], function (router, system, app, binder, viewLocator, ko, $, i18n) {    
    app.configurePlugins({
        router: true
    });

    app.start().then(function () {
        // Setup of i18n
        i18n.init({
            detectFromHeaders: false,
            fallbackLng: 'en',
            preload: ['nb', 'en'],
            supportedLngs: ['nb', 'en'],
            resGetPath: 'locales/__lng__.json',
            useCookie: true,
        }, function () {
            binder.binding = function (obj, view) {
                $(view).i18n();
            };

            viewLocator.useConvention();
            app.setRoot('viewmodels/shell');
        });
    });
});

shell.js

define(['plugins/router', 'durandal/app', 'i18next'], function (router, app, i18n) {
    return {
        router: router,
        activate: function () {
            return router.map([
                { route: '', title: i18n.t('pageTitle'), moduleId: 'viewmodels/ViewModel', nav: true }
            ]).buildNavigationModel().mapUnknownRoutes('viewmodels/ViewModel', 'unknown').activate({
                pushState: false,
                hashChange: true
            });
        }
    };
});

test.js (自己的require.js配置)

var tests = [];

for (var file in window.__karma__.files) {
    if (window.__karma__.files.hasOwnProperty(file)) {
        if (/.*\.spec\.js$/.test(file)) {
            tests.push(file);
        }
    }
}

//Workaround for the timestamp issue
for (var file in window.__karma__.files) {
    window.__karma__.files[file.replace(/^\//, '')] = window.__karma__.files[file];
}

require.config({
    baseUrl: 'base',
    paths: {
        'models': 'app/models',
        'viewModels': 'app/viewmodels',
        'specs': 'tests/specs/',
        'text': 'lib/require/text',
        'durandal': 'lib/durandal/js',
        'plugins': 'lib/durandal/js/plugins',
        'transitions': 'lib/durandal/js/transitions',
        'knockout': 'lib/knockout/knockout-2.3.0',
        'jquery': 'lib/jquery/jquery-1.9.1',
        'i18next': 'lib/i18next/i18next.amd.withJQuery-1.7.1.min',
    },

    // ask Require.js to load these files (all our tests)
    deps: tests,

    // start test run, once Require.js is done
    callback: window.__karma__.start
});

karma.conf.js

// Karma configuration

module.exports = function (config) {
    config.set({
        // base path, that will be used to resolve files and exclude
        basePath: '',


        // frameworks to use
        frameworks: ['jasmine', 'requirejs'],


        // list of files / patterns to load in the browser
        files: [
            { pattern: 'lib/jquery/jquery-1.9.1.js', watched: false, included: true, served: true },
            { pattern: 'tests/jasmine/jasmine-jquery.js', watched: false, served: true, included: true },

            { pattern: 'tests/specs/**/*.js', included: false },
            { pattern: 'tests/sinon.js', included: false },
            { pattern: 'lib/**/*.js', included: false, served: true },
            { pattern: 'app/**/*.js', included: false, served: true },

            'tests/test.js',

            //Serve the fixtures
            { pattern: 'app/**/*.html', watched: true, served: true, included: false },
            { pattern: 'app/**/*.json', watched: true, served: true, included: false },
            { pattern: 'tests/**/*.json', watched: true, served: true, included: false }
        ],

        preprocessors: [
            { '**/*.html': '' }
        ],
        // list of files to exclude
        exclude: [
            'foundation/*.js',
            'require.js',
            'init.js',
            'jasmine/jasmine.js',
            'jasmine/jasmine-html.js',
            'node_modules/**/*.html'
        ],


        // test results reporter to use
        // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
        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_INFO,


        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,


        // Start these browsers, currently available:
        // - Chrome
        // - ChromeCanary
        // - Firefox
        // - Opera
        // - Safari (only Mac)
        // - PhantomJS
        // - IE (only Windows)
        browsers: ['PhantomJS'],
        //browsers: ['Chrome', 'Firefox', 'IE'],

        // If browser does not capture in given timeout [ms], kill it
        captureTimeout: 60000,


        // Continuous Integration mode
        // if true, it capture browsers, run tests and exit
        singleRun: false
    });
};

ViewModel(i18next):

define(["i18next"], function (i18n) {
    var pageTitle = i18n.t("pageTitle");

    return {
        pageTitle: pageTitle
    };
});

Spec(i18next)

define(['viewModels/ViewModel'], function (ViewModel) {
    describe("Viewmodel test", function () {
        it("should be testable", function () {
            expect(true).toEqual(true);
        });
        it("should have title", function () {
            expect(ViewModel.pageTitle).not.toBeEmpty();
        });
    });
});

测试跑步者输出

  

PhantomJS 1.9.2(Mac OS X)错误     ReferenceError:找不到变量:initialized     at /Users/xxx/dev/projectXYZ/lib/i18next/i18next.amd.withJQuery-1.7.1.min.js:5   PhantomJS 1.9.2(Mac OS X):执行0 of 0 ERROR(0.312秒/ 0秒)

ViewModel(wo / i18next):

define([], function () {
    var pageTitle = "This is the page title";

    return {
        pageTitle: pageTitle
    };
});

Spec(wo / i18next)

define(['viewModels/ViewModel'], function (ViewModel) {
    describe("Viewmodel test", function () {
        it("should be testable", function () {
            expect(true).toEqual(true);
        });
        it("should have title", function () {
            expect(ViewModel.pageTitle).toEqual("This is the page title");
        });
    });
});

测试跑步者输出(wo / i18next)

  

PhantomJS 1.9.2(Mac OS X):成功执行2 2成功(0.312秒/ 0.164秒)

我想我必须以某种方式初始化i18next,但我不知道如何。

非常感谢任何帮助。

此致

雷米


更新

这就是我最终做的事情:

test.js

'i18next-original': 'lib/i18next/i18next.amd.withJQuery-1.7.1.min',
'i18next': 'tests/i18n-test'

I18N-test.js

define(['i18next-original'], function (i18noriginal) {
'use strict';

i18noriginal.init({
    lng: 'nb',
    detectFromHeaders: false,
    fallbackLng: 'en',
    preload: ['nb', 'en'],
    supportedLngs: ['nb', 'en'],
    resGetPath: 'base/locales/__lng__.json',
    useCookie: false,
    debug: false,
    getAsync: false
});

return i18noriginal;
});

karma.conf.js:

{ pattern: 'tests/i18n-test.js', included: false, served: true },

1 个答案:

答案 0 :(得分:0)

Hallais Remi! 您可以在beforeEach中初始化i18next,如下所示:

define(['viewModels/ViewModel', 'i18next'], function (ViewModel, i18n) {
    describe("Viewmodel test", function () {
        beforeEach(function() {
            var initialized = false;

            runs(function() {
                i18n.init({
                    detectFromHeaders: false,
                    fallbackLng: 'en',
                    preload: ['nb', 'en'],
                    supportedLngs: ['nb', 'en'],
                    resGetPath: 'locales/__lng__.json',
                    useCookie: true
                }, function () { initialized = true; });
            });

            waitsFor(function() {
                return initialized;
            }, 'i18n to initialize', 100);
        });

        it("should be testable", function () {
            expect(true).toEqual(true);
        });
        it("should have title", function () {
            expect(ViewModel.pageTitle).not.toBeEmpty();
        });
    });
});

为了将测试集中在viewModel本身内部的代码上,您可以考虑模拟viewModel中使用的i18n对象。

testr.js可能会帮助您模拟require.js依赖项:https://github.com/medallia/testr.js