Я в процессе обновления нашего внешнего модуля AngularJS. Как только я обновил наш Webpack и Karma-Webpack, я начал получать ошибку неизвестного провайдера.
Я хотел бы использовать ng-strict-di
, но когда я добавляю это в наше приложение, все работает нормально. Таким образом, проблема существует только в модульных тестах.
Я разбил это, так что проще. В приведенном мной примере проблема возникает, когда я пытаюсь внедрить $filter
в мой модульный тест.
Раздел зависимостей package.json
{
"dependencies": {
"angular": "1.7.5",
"angular-resource": "1.7.5",
"jquery": "3.2.1",
"karma-sourcemap-loader": "^0.3.7",
"moment": "2.15.2",
"moment-timezone": "0.5.23",
"ngstorage": "^0.3.11",
"platform": "1.3.3"
},
"devDependencies": {
"@types/angular": "1.6.3",
"@types/angular-resource": "^1.5.8",
"@types/google-maps": "^3.2.0",
"@types/jasmine": "~2.5.54",
"@types/jquery": "^2.0.51",
"@types/moment": "^2.13.0",
"@types/moment-timezone": "^0.2.34",
"@types/ngstorage": "^0.3.35",
"@types/platform": "^1.3.0",
"angular-mocks": "1.7.5",
"del": "^1.2.1",
"gulp": "^3.9.1",
"gulp-angular-templatecache": "^1.9.1",
"gulp-concat": "^2.6.1",
"gulp-debug": "^2.1.2",
"gulp-exit": "0.0.2",
"gulp-filter": "^2.0.2",
"gulp-inject": "^4.3.2",
"gulp-install": "^0.6.0",
"gulp-jshint": "^1.12.0",
"gulp-jshint-xml-file-reporter": "^0.3.3",
"gulp-load-plugins": "^0.8.1",
"gulp-plumber": "^0.6.6",
"gulp-sort": "^2.0.0",
"gulp-tslint": "^7.1.0",
"gulp-typescript": "^3.1.6",
"gulp-uglify": "^1.5.4",
"gulp-useref": "^1.3.0",
"gulp-util": "^3.0.8",
"gulp-wrap": "^0.10.1",
"istanbul-instrumenter-loader": "^3.0.1",
"jasmine": "^2.10.2",
"karma": "^4.0.1",
"karma-chrome-launcher": "^2.0.0",
"karma-coverage": "^1.1.2",
"karma-coverage-istanbul-reporter": "^2.0.5",
"karma-jasmine": "^2.0.1",
"karma-junit-reporter": "^1.2.0",
"karma-phantomjs-launcher": "^1.0.4",
"karma-webpack": "^4.0.2",
"require-dir": "^0.3.2",
"run-sequence": "^1.2.2",
"source-map-support": "^0.4.14",
"ts-loader": "^6.2.1",
"tslint": "^4.5.1",
"tslint-loader": "^3.6.0",
"typescript": "3.4.3",
"uglifyjs-webpack-plugin": "^2.2.0",
"webpack": "^4.41.2",
"webpack-stream": "^5.2.1",
"yargs": "^7.0.2"
}
}
Webpack.config
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const LoaderOptionsPlugin = require("webpack/lib/LoaderOptionsPlugin");
let libraryName = "shared-angular-services";
let plugins = []
outputFile = libraryName + ".min.js";
module.exports = {
mode: "production",
context: __dirname + "/app",
entry: "./index.ts",
devtool: "source-map",
//devtool: 'inline-source-map',
resolve: {
// Add '.ts' and '.tsx' as a resolvable extension.
extensions: [".ts", ".tsx", ".js"]
},
module: {
rules: [
/*{
test: /\.tsx?$/,
enforce: 'pre',
loader: "tslint-loader",
exclude: /(node_modules|bower_components)/
}, */ {
// all files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'
test: /\.tsx?$/,
loader: "ts-loader",
exclude: /(node_modules)/
}
]
},
plugins: plugins,
output: {
library: libraryName,
path: __dirname + "/target",
filename: outputFile,
// export itself to umd
libraryTarget: "umd",
umdNamedDefine: true
},
optimization: {
minimizer: [new UglifyJsPlugin()]
},
node: {
fs: "empty"
},
externals: {
angular: "angular",
"angular-resource": "angular-resource",
ngstorage: "ngstorage",
jQuery: "jquery",
lodash: "lodash",
moment: "moment",
"moment-timezone": "moment-timezone",
platform: "platform"
},
stats: {
warningsFilter: /System.import/
}
};
Karma-Webpack Config
var path = require('path');
var webpackConfig = require('../../webpack.config');
webpackConfig.resolve = webpackConfig.resolve || {};
webpackConfig.resolve.modules = webpackConfig.resolve.modules || [];
webpackConfig.resolve.modules.push('node_modules');
webpackConfig.module.rules.push({
test: /\.[tj]+sx?$/,
loader: 'istanbul-instrumenter-loader',
exclude: [
/node_modules/
],
enforce: 'post',
options: {
esModules: true
}
});
var entry = path.resolve(webpackConfig.context, webpackConfig.entry);
var preprocessors = {};
preprocessors[entry] = ['webpack', 'coverage', 'sourcemap'];
preprocessors["test/karma/**/*.ts"] = ['webpack'];
preprocessors["test/karma/**/*.js"] = ['webpack'];
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'],
webpack: webpackConfig,
webpackMiddleware: {
stats: "errors-only",
noInfo: true,
logLevel: "error"
},
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: preprocessors,
// list of files / patterns to load in the browser
files: [
"node_modules/angular/angular.js",
"node_modules/angular-resource/angular-resource.js",
"node_modules/moment/moment.js",
"node_modules/moment-timezone/moment-timezone.js",
"node_modules/lodash/lodash.js",
"node_modules/platform/platform.js",
"node_modules/ngstorage/ngStorage.js",
"node_modules/jquery/dist/jquery.js",
"node_modules/angular-mocks/angular-mocks.js",
entry,
"test/karma/filter/join-by.pipe.spec.ts",
"test/karma/model/sometest.spec.ts"
//test
],
mime: {'text/x-typescript': ['ts', 'tsx']},
// list of files to exclude
exclude: [
"test/karma/**/*conf.js",
'target/**/*.min.js'
],
reporters: ['dots', 'junit', 'coverage-istanbul'],
// the default configuration
junitReporter: {
outputDir: 'target/testResults',
outputFile: 'test-results.xml'
},
coverageIstanbulReporter: {
// reports can be any that are listed here: https://github.com/istanbuljs/istanbul-reports/tree/590e6b0089f67b723a1fdf57bc7ccc080ff189d7/lib
reports: ['html', 'cobertura', 'text-summary'],
// base output directory. If you include %browser% in the path it will be replaced with the karma browser name
dir: "target/testResults/coverage/",
// if using webpack and pre-loaders, work around webpack breaking the source path
fixWebpackSourcePaths: true,
// stop istanbul outputting messages like `File [${filename}] ignored, nothing could be mapped`
skipFilesWithNoCoverage: true,
// Most reporters accept additional config options. You can pass these through the `report-config` option
'report-config': {
// all options available at: https://github.com/istanbuljs/istanbul-reports/blob/590e6b0089f67b723a1fdf57bc7ccc080ff189d7/lib/html/index.js#L135-L137
html: {
// outputs the report in ./coverage/html
subdir: 'html'
}
},
// enforce percentage thresholds
// anything under these percentages will cause karma to fail with an exit code of 1 if not running in watch mode
thresholds: {
statements: 1,
lines: 1,
branches: 1,
functions: 1
}
},
// 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_ERROR,
// 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: ['Chrome'],
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true
});
};
Модульный тест
import * as angular from "angular";
import { JoinByFilter } from "../../../app/filter/join-by.pipe";
describe("Join By Filter Test", function() {
let joinByFilter;
let value;
let $filter;
beforeEach(function() {
(angular as any).mock.module("angular-filter");
(angular as any).mock.inject((_$filter_) => {
$filter = _$filter_;
});
joinByFilter = new JoinByFilter();
});
it( "Should register itself with Angular", function() {
expect($filter("JoinByFilter")).toBeTruthy();
});
})
Окончательная ошибка
Error: [$injector:unpr] Unknown provider: nProvider <- n
https://errors.angularjs.org/1.7.5/$injector/unpr?p0=nProvider%20%3C-%20n
at node_modules/angular/angular.js:138:12
at node_modules/angular/angular.js:4905:19
at Object.getService [as get] (node_modules/angular/angular.js:5065:32)
at node_modules/angular/angular.js:4910:45
at getService (node_modules/angular/angular.js:5065:32)
at injectionArgs (node_modules/angular/angular.js:5090:58)
at Object.invoke (node_modules/angular/angular.js:5114:18)
at UserContext.WorkFn (node_modules/angular-mocks/angular-mocks.js:3459:20)
at Object.window.inject.angular.mock.inject (node_modules/angular-mocks/angular-mocks.js:3429:42)
at UserContext.<anonymous> (test/karma/filter/join-by.pipe.spec.js:1:7888)
at <Jasmine>
at Object.window.inject.angular.mock.inject (node_modules/angular-mocks/angular-mocks.js:3422:25)
at UserContext.<anonymous> (test/karma/filter/join-by.pipe.spec.js:1:7888)
at <Jasmine>
TypeError: t is not a function
at <Jasmine>
at UserContext.<anonymous> (test/karma/filter/join-by.pipe.spec.js:1:8050)
at <Jasmine>
Я замечаю, что она имеет тенденциюразбить на angular.mock.inject
Есть мысли? Заранее спасибо.