简体   繁体   English

设置webpack业力和角度模拟

[英]Setting up webpack karma and angular-mocks

I have this problem setting up my webpack. 我有这个问题设置我的webpack。 I'm setting up webpack on an existing project and additionally I'm introducing ES6. 我正在现有项目上设置webpack,另外我正在介绍ES6。 I would like to do it in the 'correct' manner having tests passing after some big change.That's why I need to set karma tests. 我想以“正确”的方式做这件事,经过一些重大改变后测试通过。这就是我需要设置业力测试的原因。 The application is using AngularJS 1, and for the tests I'm using Angular-Mocks (karma setup with Jasmina and PhantomJS). 该应用程序使用的是AngularJS 1,对于测试,我使用的是Angular-Mocks(使用Jasmina和PhantomJS设置karma)。

I went throw a lot of existing solutions how to set up webpack with karama and angular but non of the examples got my tests to work. 我去了很多现有的解决方案如何使用karama和angular设置webpack但是没有示例让我的测试工作。 Basically the problem is with injection and mocking. 基本上问题在于注射和嘲弄。 For instance, I'm getting undefined when trying to inject $rootScope or $backendMock. 例如,我在尝试注入$ rootScope或$ backendMock时未定义。

This is my current setup: 这是我目前的设置:

webpack.config.js webpack.config.js

const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const rootPath = path.resolve(__dirname, "src");
const libsDir = rootPath + "/lib";
const applicationDir = libsDir + "/app";

const plugins =
    [
        new CleanWebpackPlugin('build', {
            root: rootPath,
            verbose: true,
            dry: false
        }),
        new webpack.EnvironmentPlugin({
            PROD_ENV: false
        }),
        new HtmlWebpackPlugin({
            template: 'src/index.tmpl.ejs',
            inject: 'head',
            filename: 'index.html'
        }),
        new ExtractTextPlugin('style/[name].css'),
        new webpack.ProvidePlugin({
            $: "jquery",
            jquery: "jquery",
            "window.jQuery": "jquery",
            jQuery: "jquery"
        })
    ];


module.exports = {
    devtool: 'source-map',
    entry: {
        vendors: libsDir + "/components.js",
        application: applicationDir + "/Application.js",
        browserDetect: applicationDir + "/BrowserDetection.js"
    },
    output: {
        path: __dirname + "/build",
        publicPath: '',
        filename: "[name].bundle.js",
        sourceMapFilename: "[name].bundle.map",
        chunkFilename: '[chunkhash].js'
    },
    module: {
        loaders: [
            {
                test: /\.html$/,
                loader: "ngtemplate-loader!html-loader"
            }, {
                test: /\.(svg|png|jpe?g|ttf|woff2?|eot)$/,
                loader: 'url-loader?limit=10000&name=style/[name].[ext]'
            }, {
                test: /\.(scss|css)$/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    //resolve-url-loader may be chained before sass-loader if necessary
                    use: ['css-loader?minimize', 'resolve-url-loader', 'sass-loader?sourceMap']
                })
            }
        ]
    },
    plugins: plugins,
    node: {
        net: 'empty',
        tls: 'empty',
        //dns: 'empty',
        fs: 'empty'
    }
};

karma.config.js karma.config.js

var webpackConfig = require('./webpack.config');

module.exports = function (config) {
    config.set({

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '',

        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['jasmine'],

        // list of files / patterns to load in the browser
        files: [
            'node_modules/angular/angular.js',
            'node_modules/angular-mocks/angular-mocks.js',
            {pattern: 'tests/karma.entry.js'}
        ],

        // list of files to exclude
        exclude: [],

        // preprocess matching files before serving them to the browser
        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: {
            'tests/karma.entry.js' : ['webpack']
        },

        webpack: webpackConfig,

        webpackMiddleware: {
            stats: "errors-only"
        },

        ngHtml2JsPreprocessor: {
            // setting this option will create only a single module that contains templates
            // from all the files, so you can load them all with module('foo')
            moduleName: 'templates',
            stripPrefix: 'src/'
        },

        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter

        //TEST
        // reporters: ['progress', 'html', 'junit', 'coverage'],

        //TEST
        // coverageReporter: {
        //     dir: 'reports',
        //     reporters: [
        //         {type: 'cobertura', subdir: 'xml', file: 'code-coverage.xml'},
        //         {type: 'html', subdir: 'html'}
        //     ]
        // },

        // the default configuration
        htmlReporter: {
            outputFile: 'reports/html/ui-unit-tests.html'
        },

        junitReporter: {
            outputFile: 'reports/xml/ui-unit-tests.xml'
        },

        // 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_DEBUG,

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

        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['PhantomJS'],

        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: true ,

        plugins: [
            require('karma-webpack'),
            require('karma-jasmine'),
            require('karma-coverage'),
            require('karma-phantomjs-launcher'),
            require('karma-chrome-launcher'),
        ].
    });
};

karma.entry.js karma.entry.js

var testsContext = require.context(".", true, /\.spec\.js/);
testsContext.keys().forEach(testsContext);

No all my tests are in a separate file -> /tests/**/*.spec.js, these are picked up and PhanthomJS is trying to run them. 我的所有测试都没有在一个单独的文件中 - > /tests/**/*.spec.js,这些都被拾取并且PhanthomJS正在尝试运行它们。

This is one tests that I run: 这是我运行的一个测试:

describe('contextmenu', function () {
    var customersEndpoint = '/api/v1/res/customers',
        directiveScope,
        $httpBackendMock,
        contextMenuDomElement,
        compileDirective,
        contextService,
        contextsReturnedFromBackend = [
            {name: "Kjell's Buildings and Stuffz", id: 1},
            {name: "IMA Stats Runners", id: 2},
            {name: "Juice and Gin Inc.", id: 3}
        ];

    beforeEach(angular.mock.module("FES"));
    beforeEach(angular.mock.module("templates"));


    beforeEach(function () {
        angular.mock.inject(function (_$rootScope_, _$compile_, _$httpBackend_, _ContextService_) {
            contextService = _ContextService_;
            $httpBackendMock = _$httpBackend_;

            $httpBackendMock.when('GET', customersEndpoint)
                .respond(contextsReturnedFromBackend);

            compileDirective = function() {
                directiveScope = _$rootScope_.$new();
                contextMenuDomElement = _$compile_(angular.element("<contextmenu></contextmenu>"))(directiveScope);
                directiveScope.$digest();
            };
        });
    });

    describe('on init', function() {
       it('calls the context service to get available contexts and select first item', function() {
           $httpBackendMock.expectGET(customersEndpoint);
           compileDirective();
           $httpBackendMock.flush(); // this returns the $http request that was made on init in the controller
            directiveScope.$digest();
           console.log(directiveScope);
           expect(directiveScope.contexts.length).toBe(3);
           expect(contextMenuDomElement.html()).toContain(contextsReturnedFromBackend[0].name);
       })
    });

    describe('on context clicked', function() {
        it('sets the current context', function() {
            var newContextToSelect = directiveScope.contexts[1];
            directiveScope.onContextClicked(newContextToSelect);
            expect(directiveScope.selectedContext).toBe(newContextToSelect);
        });
    });
});

The error I get are that the $httpBackendMock or directiveScope are undefined. 我得到的错误是$ httpBackendMock或directiveScope未定义。

PhantomJS 2.1.1 (Linux 0.0.0) contextmenu on init calls the context service to get available contexts and select first item FAILED
        forEach@node_modules/angular/angular.js:402:24
        loadModules@node_modules/angular/angular.js:4880:12
        createInjector@node_modules/angular/angular.js:4802:30
        WorkFn@node_modules/angular-mocks/angular-mocks.js:3161:60
        inject@node_modules/angular-mocks/angular-mocks.js:3141:46
        tests/karma.entry.js:165:28
        loaded@http://localhost:9876/context.js:151:17
        node_modules/angular/angular.js:4921:53
        TypeError: undefined is not an object (evaluating '$httpBackendMock.expectGET') in tests/karma.entry.js (line 182)
        tests/karma.entry.js:182:28
        loaded@http://localhost:9876/context.js:151:17
PhantomJS 2.1.1 (Linux 0.0.0) contextmenu on context clicked sets the current context FAILED
        forEach@node_modules/angular/angular.js:402:24
        loadModules@node_modules/angular/angular.js:4880:12
        createInjector@node_modules/angular/angular.js:4802:30
        WorkFn@node_modules/angular-mocks/angular-mocks.js:3161:60
        inject@node_modules/angular-mocks/angular-mocks.js:3141:46
        tests/karma.entry.js:165:28
        loaded@http://localhost:9876/context.js:151:17
        node_modules/angular/angular.js:4921:53
        TypeError: undefined is not an object (evaluating 'directiveScope.contexts') in tests/karma.entry.js (line 194)
        tests/karma.entry.js:194:52
        loaded@http://localhost:9876/context.js:151:17

I'm running Angular 1.6.2, Webpack 2.2.1, Karma-Webpack 2.0.2 and Karma in version 1.5.0. 我正在运行Angular 1.6.2,Webpack 2.2.1,Karma-Webpack 2.0.2和版本1.5.0的Karma。 I'm trying to write my modules in ES6 and transform it in webpack. 我正在尝试在ES6中编写我的模块并在webpack中进行转换。 Can You guys help ? 你们可以帮忙吗? I'm stuck on this for a long time now ;/ I know there are new 'better' solutions to test ES6 modules but I need t 我现在已经坚持了很长时间; /我知道有更新的“更好”的解决方案来测试ES6模块,但我需要

Can you guys please help me here ? 你能帮帮我吗?

This setup can be quite nasty sometimes when AngularJS cannot find required providers. 当AngularJS找不到所需的提供者时,这种设置有时会非常讨厌。 Instead of throwing an error, it just exits, doesn't enter any inject functions and starts the it blocks. 它不会抛出错误,只是退出,不会进入任何inject函数并启动it阻塞。 Consequently, the values you normally get from your $injector are still undefined. 因此,您通常从$injector的值仍未定义。

Have a look at whether you really mocked all required dependencies, either through angular.mock.module('serviceModule') the module that contains them, or through creating and configuring a spy object. 看看你是否真的通过angular.mock.module('serviceModule')包含它们的模块,或者通过创建和配置间谍对象来angular.mock.module('serviceModule')所有必需的依赖项。

angular.mock.module(($provider: ng.auto.IProvideService) => {
  $provider.value('service', jasmine.createSpyObj('service', ['list of accessed modules']);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM