Angular.js + nw.js + webpack + karma + jasmine如何测试

时间:2022-08-24 22:30:02

I have a nw.js native application with angular.js inside. My app bundled with webpack and contains native node.js modules. My entry point is index.js file that I organized like this:

我有一个带有angular.js的nw.js本机应用程序。我的应用程序与webpack捆绑在一起,包含本机node.js模块。我的入口点是我组织的index.js文件:

var gui = require('nw.gui');
var angular = require('angular');
require('./app.css');

// other modules

var myApp = angular.module('myApp', [
    'ngRaven',
    'ngMaterial',
    'ngMessages'
]).constant(
    'fs', require('fs')
)

require('./services')(myApp);
require('./directives')(myApp);
require('./factories')(myApp);
require('./filters')(myApp);
require('./controllers')(myApp);
require('./app.js')(myApp);

My webpack config looks like this:

我的webpack配置如下所示:

const path = require('path');

const config = {
    entry: [
        './app/index.js'
    ],
    output: {
        path: path.resolve(__dirname, 'app'),
        filename: 'bundle.js'
    },
    devtool: "source-map",
    target: 'node-webkit',
    module:{
        // css, html loaders
    },
    node: {
        os: true,
        fs: true,
        child_process: true,
        __dirname: true,
        __filename: true
    }
};

module.exports = config;

So every dependency include Node.js native modules like fs, path, child_process bundled in one big file bundle.js that i include in html and then package my nw.js app. So my app structure looks like:

因此,每个依赖包括Node.js本机模块,如fs,path,child_process捆绑在一个大文件bundle.js中,我包含在html中,然后打包我的nw.js应用程序。所以我的app结构如下:

my_project:
--app
----controllers
------welcome
--------welcome.js // Page controller
--------welcome.html // Page HTML
------index.js // here I include each page controller
----app.js // My angular app initialization
----index.js // here I include all dependencies 

I'm trying to run tests with this structure. I tried karma+jasmine, karma+mocha, tried different configurations, my last one looks like:

我正在尝试使用这种结构运行测试。我尝试了业力+茉莉,业力+摩卡,尝试了不同的配置,我的最后一个看起来像:

module.exports = function (config) {
    config.set({
        basePath: '',
        frameworks: ['jasmine'],
        files: [
            'app/bundle.js',
            'app/**/*spec.js'
        ],
        exclude: [],
        preprocessors: {
            'app/bundle.js': ['webpack']
        },
        reporters: ['progress'],
        port: 9876,
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: true,
        browsers: ['ChromeHeadlessNoSandbox'],
        customLaunchers: {
            ChromeHeadlessNoSandbox: {
                base: 'ChromeHeadless',
                flags: ['--no-sandbox']
            }
        },
        singleRun: true,

        webpack: {
            // you don't need to specify the entry option because
            // karma watches the test entry points
            // webpack watches dependencies

            // ... remainder of webpack configuration (or import)
        },

        webpackMiddleware: {
            // webpack-dev-middleware configuration
            // i.e.
            noInfo: true,
            // and use stats to turn off verbose output
            stats: {
                // options i.e.
                chunks: false
            }
        }
    });
};

But my tests still not see the angular application.

但我的测试仍然没有看到角度应用。

describe('Welcome page', function() {
    beforeEach(angular.mock.module('WelcomePageCtrl'));
});

P.S I don't require exactly karma and jasminne, so any solution will be appreciated. I just want to cover my project with tests

P.S我不需要确切的业力和jasminne,所以任何解决方案将不胜感激。我只想用测试来覆盖我的项目

1 个解决方案

#1


3  

I have gone through something similar myself. I don't think you need the bundle.js for your tests.

我自己经历过类似的事情。我认为您的测试不需要bundle.js。

Here is how would do it:

这是怎么做的:

I assume your controller/service/etc implementation is as follows:

我假设你的控制器/服务/ etc实现如下:

    /* app/controller/welcome.js */
    module.exports = function(app) {
        return app.controller("MyCtrl", function($scope) {
            $scope.name = "lebouf";
        });
    };

I like my test code to sit right beside the code I'm testing (Welcome.spec.js in the same directory as Welcome.js). That test code would look like so:

我喜欢我的测试代码坐在我正在测试的代码旁边(Welcome.spec.js在与Welcome.js相同的目录中)。那个测试代码看起来像这样:

/* app/controller/welcome.spec.js */
beforeEach(function() {
    var app = angular.module("myApp", []); //module definition
    require("./welcome")(app);
});
beforeEach(mockModule("myApp"));

describe("MyCtrl", () => {
    var scope = {};
    beforeEach(mockInject(function($controller) {
        $controller("MyCtrl", {
            $scope: scope
        });
    }));

    it("has name in its scope", function() {
        expect(scope.name).to.equal("not lebouf"); //the test will fail
    });
});

Except, this is an angular controller we're testing and it's not that simple. We need the angular object itself. So lets set it up. I'll explain why it is done how it is done next:

除此之外,这是一个我们正在测试的角度控制器,并不是那么简单。我们需要角度物体本身。所以让我们进行设置。我将解释为什么要完成下一步的工作:

/* test-setup.js */
const jsdom = require("jsdom").jsdom; //v5.6.1
const chai = require("chai");

global.document = jsdom("<html><head></head><body></body></html>", {});
global.window = document.defaultView;
global.window.mocha = true;
global.window.beforeEach = beforeEach;
global.window.afterEach = afterEach;

require("angular/angular");
require("angular-mocks");

global.angular = window.angular;
global.mockInject = angular.mock.inject;
global.mockModule = angular.mock.module;
global.expect = chai.expect;

console.log("ALL SET");

And we'll run the tests as:

我们将运行测试:

node_modules/.bin/mocha ./init.js app/**/*.spec.js
#or preferably as `npm test` by copying the abev statement into package.json

extra info

Here is how init.js is setup as is:

以下是init.js的设置方式:

  1. jsdom: f you require("angular/angular") you'll see that it needs a window instance. jsdom can create documents and windows and so on without a web browser!
  2. jsdom:你需要(“angular / angular”)你会发现它需要一个窗口实例。没有网络浏览器,jsdom可以创建文档和窗口等!

  3. window.mocha: we need angular-mocks to populate our angular with the necessary utilities. But if you look at the code you'll notice that window.mocha || window.jasmine needs to be true. Thats whywindow.mocha = true`
  4. window.mocha:我们需要角度模拟来填充我们的角度与必要的实用程序。但是如果你看一下代码,你就会注意到window.mocha || window.jasmine必须是真的。这就是为什么windowwind.mocha = true`

  5. window.beforeEach, window.afterEach: the same reason as above; because angular-mocks.js demands it.
  6. window.beforeEach,window.afterEach:与上述相同的原因;因为angular-mocks.js要求它。

  7. I set some global variables that I plan to use commonly in my tests: angular, expect, mockInject, mockModule.
  8. 我设置了一些我打算在我的测试中常用的全局变量:angular,expect,mockInject,mockModule。

Also these may provide some additional information:

这些也可能提供一些额外的信息:

#1


3  

I have gone through something similar myself. I don't think you need the bundle.js for your tests.

我自己经历过类似的事情。我认为您的测试不需要bundle.js。

Here is how would do it:

这是怎么做的:

I assume your controller/service/etc implementation is as follows:

我假设你的控制器/服务/ etc实现如下:

    /* app/controller/welcome.js */
    module.exports = function(app) {
        return app.controller("MyCtrl", function($scope) {
            $scope.name = "lebouf";
        });
    };

I like my test code to sit right beside the code I'm testing (Welcome.spec.js in the same directory as Welcome.js). That test code would look like so:

我喜欢我的测试代码坐在我正在测试的代码旁边(Welcome.spec.js在与Welcome.js相同的目录中)。那个测试代码看起来像这样:

/* app/controller/welcome.spec.js */
beforeEach(function() {
    var app = angular.module("myApp", []); //module definition
    require("./welcome")(app);
});
beforeEach(mockModule("myApp"));

describe("MyCtrl", () => {
    var scope = {};
    beforeEach(mockInject(function($controller) {
        $controller("MyCtrl", {
            $scope: scope
        });
    }));

    it("has name in its scope", function() {
        expect(scope.name).to.equal("not lebouf"); //the test will fail
    });
});

Except, this is an angular controller we're testing and it's not that simple. We need the angular object itself. So lets set it up. I'll explain why it is done how it is done next:

除此之外,这是一个我们正在测试的角度控制器,并不是那么简单。我们需要角度物体本身。所以让我们进行设置。我将解释为什么要完成下一步的工作:

/* test-setup.js */
const jsdom = require("jsdom").jsdom; //v5.6.1
const chai = require("chai");

global.document = jsdom("<html><head></head><body></body></html>", {});
global.window = document.defaultView;
global.window.mocha = true;
global.window.beforeEach = beforeEach;
global.window.afterEach = afterEach;

require("angular/angular");
require("angular-mocks");

global.angular = window.angular;
global.mockInject = angular.mock.inject;
global.mockModule = angular.mock.module;
global.expect = chai.expect;

console.log("ALL SET");

And we'll run the tests as:

我们将运行测试:

node_modules/.bin/mocha ./init.js app/**/*.spec.js
#or preferably as `npm test` by copying the abev statement into package.json

extra info

Here is how init.js is setup as is:

以下是init.js的设置方式:

  1. jsdom: f you require("angular/angular") you'll see that it needs a window instance. jsdom can create documents and windows and so on without a web browser!
  2. jsdom:你需要(“angular / angular”)你会发现它需要一个窗口实例。没有网络浏览器,jsdom可以创建文档和窗口等!

  3. window.mocha: we need angular-mocks to populate our angular with the necessary utilities. But if you look at the code you'll notice that window.mocha || window.jasmine needs to be true. Thats whywindow.mocha = true`
  4. window.mocha:我们需要角度模拟来填充我们的角度与必要的实用程序。但是如果你看一下代码,你就会注意到window.mocha || window.jasmine必须是真的。这就是为什么windowwind.mocha = true`

  5. window.beforeEach, window.afterEach: the same reason as above; because angular-mocks.js demands it.
  6. window.beforeEach,window.afterEach:与上述相同的原因;因为angular-mocks.js要求它。

  7. I set some global variables that I plan to use commonly in my tests: angular, expect, mockInject, mockModule.
  8. 我设置了一些我打算在我的测试中常用的全局变量:angular,expect,mockInject,mockModule。

Also these may provide some additional information:

这些也可能提供一些额外的信息: