当使用 angularjs 进行 运行 业力单元测试时,如何修复 "Cannot use import statement outside a module"?
How to fix "Cannot use import statement outside a module" when running karma unit test with angularjs?
RecordsControllerTest.spec.js
// import RecordsController from '../../public/RecordsController';
import {app} from '../../public/app.js'; // without this gives "Module 'app' is not available! You either misspelled the module name or forgot to load it. "
describe('RecordsController', function() {
//beforeEach(module('app'));
beforeEach(angular.mock.module('app'));
var $controller, $rootScope;
beforeEach(inject(function(_$controller_, _$rootScope_){
// The injector unwraps the underscores (_) from around the parameter names when matching
$controller = _$controller_;
$rootScope = _$rootScope_;
}));
describe('$scope.grade', function() {
it('sets the strength', function() {
var $scope = $rootScope.$new();
/*var controller =*/ $controller('RecordsController', { $scope: $scope });
let grade = $scope.grade(1);
expect(grade).toEqual('small');
});
});
});
package.json
{
"name": "angular-phonecat",
"private": true,
"version": "0.0.0",
"description": "A tutorial application for AngularJS",
"repository": "https://github.com/angular/angular-phonecat",
"license": "MIT",
"dependencies": {
"angular": "1.7.x",
"angular-animate": "1.7.x",
"angular-resource": "1.7.x",
"angular-route": "1.7.x",
"bootstrap": "3.3.x",
"jquery": "3.3.x"
},
"devDependencies": {
"angular-mocks": "1.7.x",
"cpx": "^1.5.0",
"http-server": "^0.11.1",
"jasmine-core": "^3.3.0",
"karma": "^3.1.1",
"karma-chrome-launcher": "^2.2.0",
"karma-firefox-launcher": "^1.1.0",
"karma-jasmine": "^1.1.2",
"protractor": "^5.4.1"
},
"scripts": {
"postinstall": "npm run copy-libs",
"update-deps": "npm update",
"postupdate-deps": "npm run copy-libs",
"copy-libs": "cpx \"node_modules/{angular,angular-*,bootstrap/dist,jquery/dist}/**/*\" app/lib -C",
"prestart": "npm install",
"start": "http-server ./app -a localhost -p 8000 -c-1",
"pretest": "npm install",
"test": "karma start karma.conf.js",
"test-single-run": "npm test -- --single-run",
"preupdate-webdriver": "npm install",
"update-webdriver": "webdriver-manager update",
"preprotractor": "npm run update-webdriver",
"protractor": "protractor e2e-tests/protractor.conf.js"
}
}
app.js
var app = angular.module('app', []);
app.baseUrl = 'http://localhost:8080/';
app.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('//');
$interpolateProvider.endSymbol('//');
});
export {app};
karma.conf.js
//jshint strict: false
// there are more things than needed, could clean up. Same in package.json
module.exports = function(config) {
config.set({
basePath: './app',
files: [
'lib/angular/angular.js',
'lib/angular-animate/angular-animate.js',
'lib/angular-resource/angular-resource.js',
'lib/angular-route/angular-route.js',
'../node_modules/angular-mocks/angular-mocks.js',
'**/*.module.js',
'*!(.module|.spec).js',
'!(lib)/**/*!(.module|.spec).js',
'**/*.spec.js',
'../public/*.js', // works with this because gets real files probably which we test
],
autoWatch: true,
frameworks: ['jasmine'],
browsers: ['Chrome'],
plugins: [
'karma-chrome-launcher',
'karma-jasmine'
]
});
};
RecordsController.js
/*var app = angular.module('app', []);
app.baseUrl = 'http://localhost:8080/';
app.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('//');
$interpolateProvider.endSymbol('//');
});*/
import {app} from './app.js';
app.controller('RecordsController', ['$scope', '$http', function($scope, $http) {
$scope.submit = function () {
console.log($scope);
$http.post( app.baseUrl + 'save', {name: $scope.name, price: $scope.price})
.then(function (response) {
$scope.records.push(response.data)
});
}
$http.get(app.baseUrl + 'list')
.then(function(response) {
$scope.records = response.data;
});
$scope.grade = function(price) {
if (price > 100) {
return 'big';
} else if (price > 50) {
return 'medium';
} else {
return 'small';
}
};
}]);
//export {app};
应用程序有效。如果我没有 app.js 文件但在与 RecordsController.js 相同的文件中定义应用程序 - 单元测试有效。但是当我将代码移动到 app.js - 测试停止工作。这是输出:
npm test -- --single-run
> angular-phonecat@0.0.0 pretest /home/darius/Private/Projects/learning/symfony_angular_docker
> npm install
> angular-phonecat@0.0.0 postinstall /home/darius/Private/Projects/learning/symfony_angular_docker
> npm run copy-libs
> angular-phonecat@0.0.0 copy-libs /home/darius/Private/Projects/learning/symfony_angular_docker
> cpx "node_modules/{angular,angular-*,bootstrap/dist,jquery/dist}/**/*" app/lib -C
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
audited 534 packages in 2.942s
8 packages are looking for funding
run `npm fund` for details
found 10 vulnerabilities (6 low, 3 moderate, 1 high)
run `npm audit fix` to fix them, or `npm audit` for details
> angular-phonecat@0.0.0 test /home/darius/Private/Projects/learning/symfony_angular_docker
> karma start karma.conf.js "--single-run"
27 12 2020 07:58:51.305:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.module.js" does not match any file.
27 12 2020 07:58:51.307:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/*!(.module|.spec).js" does not match any file.
27 12 2020 07:58:51.313:WARN [watcher]: All files matched by "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.spec.js" were excluded or matched by prior matchers.
27 12 2020 07:58:51.325:INFO [karma-server]: Karma v3.1.4 server started at http://0.0.0.0:9876/
27 12 2020 07:58:51.326:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
27 12 2020 07:58:51.329:INFO [launcher]: Starting browser Chrome
27 12 2020 07:58:51.773:INFO [Chrome 87.0.4280 (Linux 0.0.0)]: Connected on socket M3VJxSZLyXP8VAmmAAAA with id 36635738
Chrome 87.0.4280 (Linux 0.0.0) ERROR: 'DEPRECATION:', 'Setting specFilter directly on Env is deprecated and will be removed in a future version of Jasmine, please use the specFilter option in `configure`'
Chrome 87.0.4280 (Linux 0.0.0) ERROR
{
"message": "An error was thrown in afterAll\nSyntaxError: Cannot use import statement outside a module\nSyntaxError: Cannot use import statement outside a module\nSyntaxError: Unexpected token 'export'",
"str": "An error was thrown in afterAll\nSyntaxError: Cannot use import statement outside a module\nSyntaxError: Cannot use import statement outside a module\nSyntaxError: Unexpected token 'export'"
}
Chrome 87.0.4280 (Linux 0.0.0): Executed 0 of 0 ERROR (0.002 secs / 0 secs)
npm ERR! Test failed. See above for more details.
或者您能否推荐教程,其中有导入文件的单元测试示例?
更新
karma.conf.js @tmhao2005 回答后:
//jshint strict: false
// there are more things than needed, could clean up. Same in package.json
module.exports = function(config) {
config.set({
basePath: './app',
files: [
'lib/angular/angular.js',
'lib/angular-animate/angular-animate.js',
'lib/angular-resource/angular-resource.js',
'lib/angular-route/angular-route.js',
'../node_modules/angular-mocks/angular-mocks.js',
'**/*.module.js',
'*!(.module|.spec).js',
'!(lib)/**/*!(.module|.spec).js',
'**/*.spec.js',
'../public/*.js', // works with this because gets real files probably which we test
],
autoWatch: true,
frameworks: ['jasmine'],
browsers: ['Chrome'],
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-webpack',
],
preprocessors: {
// process your `esmodule` syntax of your files
'../public/*.js': ['webpack'],
'**/*.spec.js': ['webpack']
},
webpack: {
// karma watches the test entry points
// (you don't need to specify the entry option)
// webpack watches dependencies
// webpack configuration
},
});
};
现在得到
npm test -- --single-run
> angular-phonecat@0.0.0 pretest /home/darius/Private/Projects/learning/symfony_angular_docker
> npm install
> angular-phonecat@0.0.0 postinstall /home/darius/Private/Projects/learning/symfony_angular_docker
> npm run copy-libs
> angular-phonecat@0.0.0 copy-libs /home/darius/Private/Projects/learning/symfony_angular_docker
> cpx "node_modules/{angular,angular-*,bootstrap/dist,jquery/dist}/**/*" app/lib -C
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules/watchpack/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
audited 786 packages in 3.663s
11 packages are looking for funding
run `npm fund` for details
found 10 vulnerabilities (6 low, 3 moderate, 1 high)
run `npm audit fix` to fix them, or `npm audit` for details
> angular-phonecat@0.0.0 test /home/darius/Private/Projects/learning/symfony_angular_docker
> karma start karma.conf.js "--single-run"
30 12 2020 17:50:53.375:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.module.js" does not match any file.
30 12 2020 17:50:53.377:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/*!(.module|.spec).js" does not match any file.
30 12 2020 17:50:53.384:WARN [watcher]: All files matched by "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.spec.js" were excluded or matched by prior matchers.
⚠ 「wdm」: Hash: d4e94cf661365475ea55
Version: webpack 4.41.1
Time: 57ms
Built at: 2020-12-30 17:50:53
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
ℹ 「wdm」: Compiled with warnings.
30 12 2020 17:50:53.408:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.module.js" does not match any file.
30 12 2020 17:50:53.409:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/*!(.module|.spec).js" does not match any file.
30 12 2020 17:50:53.417:WARN [watcher]: All files matched by "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.spec.js" were excluded or matched by prior matchers.
ℹ 「wdm」: Compiling...
⚠ 「wdm」: Hash: 4b332cf791759062b309
Version: webpack 4.41.1
Time: 18ms
Built at: 2020-12-30 17:50:53
Asset Size Chunks Chunk Names
../public/RecordsController.js 1.48 KiB 1, 2 [emitted] ../public/RecordsController
../public/app.js 1.11 KiB 2 [emitted] ../public/app
Tests/RecordsControllerTest.spec.js 1.45 KiB 0, 2 [emitted] Tests/RecordsControllerTest.spec
Entrypoint Tests/RecordsControllerTest.spec = Tests/RecordsControllerTest.spec.js
Entrypoint ../public/app = ../public/app.js
Entrypoint ../public/RecordsController = ../public/RecordsController.js
[0] ./public/app.js 227 bytes {0} {1} {2} [built]
[1] ./app/Tests/RecordsControllerTest.spec.js 952 bytes {0} [built]
[2] ./public/RecordsController.js 957 bytes {1} [built]
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
ℹ 「wdm」: Compiled with warnings.
30 12 2020 17:50:53.568:INFO [karma-server]: Karma v3.1.4 server started at http://0.0.0.0:9876/
30 12 2020 17:50:53.568:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
30 12 2020 17:50:53.573:INFO [launcher]: Starting browser Chrome
30 12 2020 17:50:53.969:INFO [Chrome 87.0.4280 (Linux 0.0.0)]: Connected on socket xExD5D27bFhOOfMsAAAA with id 98015757
Chrome 87.0.4280 (Linux 0.0.0) ERROR: 'DEPRECATION:', 'Setting specFilter directly on Env is deprecated and will be removed in a future version of Jasmine, please use the specFilter option in `configure`'
Chrome 87.0.4280 (Linux 0.0.0) RecordsController $scope.grade sets the strength FAILED
Error: [$injector:modulerr] Failed to instantiate module app due to:
Error: [$injector:unpr] Unknown provider: e
https://errors.angularjs.org/1.7.9/$injector/modulerr?p0=app&p1=Error%3A%20%5B%24injector%3Aunpr%5D%20Unknown%20provider%3A%20e%0Ahttps%3A%2F%2Ferrors.angularjs.org%2F1.7.9%2F%24injector%2Funpr%3Fp0%3De%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A138%3A12%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A4926%3A19%0A%20%20%20%20at%20getService%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A5086%3A32)%0A%20%20%20%20at%20injectionArgs%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A5111%3A58)%0A%20%20%20%20at%20Object.invoke%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A5135%3A18)%0A%20%20%20%20at%20runInvokeQueue%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A5032%3A35)%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A5042%3A11%0A%20%20%20%20at%20forEach%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A387%3A20)%0A%20%20%20%20at%20loadModules%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A5022%3A5)%0A%20%20%20%20at%20Object.createInjector%20%5Bas%20injector%5D%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A4939%3A19)
at <Jasmine>
at lib/angular/angular.js:138:12
at lib/angular/angular.js:5062:15
at forEach (lib/angular/angular.js:387:20)
at loadModules (lib/angular/angular.js:5022:5)
at Object.createInjector [as injector] (lib/angular/angular.js:4939:19)
at UserContext.WorkFn (/home/darius/Private/Projects/learning/symfony_angular_docker/node_modules/angular-mocks/angular-mocks.js:3449:52)
at <Jasmine>
TypeError: Cannot read property '$new' of undefined
at UserContext.<anonymous> (Tests/RecordsControllerTest.spec.js:1:1385)
at <Jasmine>
Chrome 87.0.4280 (Linux 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.002 secs / 0.008 secs)
npm ERR! Test failed. See above for more details.
更新 2
添加了 $interpolateProvider 作为依赖项,app.js 现在:
var app = angular.module('app', []);
app.baseUrl = 'http://localhost:8080/';
app.config(['$interpolateProvider', function($interpolateProvider) {
$interpolateProvider.startSymbol('//');
$interpolateProvider.endSymbol('//');
}]);
export {app};
添加了开发模式,karma.conf.js现在:
//jshint strict: false
// there are more things than needed, could clean up. Same in package.json
module.exports = function(config) {
config.set({
basePath: './app',
files: [
'lib/angular/angular.js',
'lib/angular-animate/angular-animate.js',
'lib/angular-resource/angular-resource.js',
'lib/angular-route/angular-route.js',
'../node_modules/angular-mocks/angular-mocks.js',
'**/*.module.js',
'*!(.module|.spec).js',
'!(lib)/**/*!(.module|.spec).js',
'**/*.spec.js',
'../public/*.js', // works with this because gets real files probably which we test
],
autoWatch: true,
frameworks: ['jasmine'],
browsers: ['Chrome'],
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-webpack',
],
preprocessors: {
// process your `esmodule` syntax of your files
'../public/*.js': ['webpack'],
'**/*.spec.js': ['webpack']
},
webpack: {
// karma watches the test entry points
// (you don't need to specify the entry option)
// webpack watches dependencies
// webpack configuration.
// dev mode for tests to work
"mode": "development",
},
});
};
现在出现错误:
darius@darius-Vostro-5481:~/Private/Projects/learning/symfony_angular_docker$ npm test -- --single-run
> angular-phonecat@0.0.0 pretest /home/darius/Private/Projects/learning/symfony_angular_docker
> npm install
> angular-phonecat@0.0.0 postinstall /home/darius/Private/Projects/learning/symfony_angular_docker
> npm run copy-libs
> angular-phonecat@0.0.0 copy-libs /home/darius/Private/Projects/learning/symfony_angular_docker
> cpx "node_modules/{angular,angular-*,bootstrap/dist,jquery/dist}/**/*" app/lib -C
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules/watchpack/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
audited 786 packages in 3.714s
11 packages are looking for funding
run `npm fund` for details
found 10 vulnerabilities (6 low, 3 moderate, 1 high)
run `npm audit fix` to fix them, or `npm audit` for details
> angular-phonecat@0.0.0 test /home/darius/Private/Projects/learning/symfony_angular_docker
> karma start karma.conf.js "--single-run"
05 01 2021 17:03:25.368:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.module.js" does not match any file.
05 01 2021 17:03:25.370:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/*!(.module|.spec).js" does not match any file.
05 01 2021 17:03:25.376:WARN [watcher]: All files matched by "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.spec.js" were excluded or matched by prior matchers.
ℹ 「wdm」: Hash: 3879665b411e2fff46cc
Version: webpack 4.41.1
Time: 53ms
Built at: 2021-01-05 17:03:25
ℹ 「wdm」: Compiled successfully.
05 01 2021 17:03:25.396:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.module.js" does not match any file.
05 01 2021 17:03:25.397:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/*!(.module|.spec).js" does not match any file.
05 01 2021 17:03:25.402:WARN [watcher]: All files matched by "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.spec.js" were excluded or matched by prior matchers.
ℹ 「wdm」: Compiling...
ℹ 「wdm」: Hash: bfe70362116b7e4fdf82
Version: webpack 4.41.1
Time: 18ms
Built at: 2021-01-05 17:03:25
Asset Size Chunks Chunk Names
../public/RecordsController.js 5.83 KiB ../public/RecordsController [emitted] ../public/RecordsController
../public/app.js 4.23 KiB ../public/app [emitted] ../public/app
Tests/RecordsControllerTest.spec.js 5.77 KiB Tests/RecordsControllerTest.spec [emitted] Tests/RecordsControllerTest.spec
Entrypoint ../public/app = ../public/app.js
Entrypoint Tests/RecordsControllerTest.spec = Tests/RecordsControllerTest.spec.js
Entrypoint ../public/RecordsController = ../public/RecordsController.js
[./app/Tests/RecordsControllerTest.spec.js] 954 bytes {Tests/RecordsControllerTest.spec} [built]
[./public/RecordsController.js] 958 bytes {../public/RecordsController} [built]
[./public/app.js] 253 bytes {../public/app} {Tests/RecordsControllerTest.spec} {../public/RecordsController} [built]
ℹ 「wdm」: Compiled successfully.
05 01 2021 17:03:25.502:INFO [karma-server]: Karma v3.1.4 server started at http://0.0.0.0:9876/
05 01 2021 17:03:25.503:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
05 01 2021 17:03:25.507:INFO [launcher]: Starting browser Chrome
05 01 2021 17:03:25.963:INFO [Chrome 87.0.4280 (Linux 0.0.0)]: Connected on socket t4Hc0-IijbJd_27rAAAA with id 24424610
Chrome 87.0.4280 (Linux 0.0.0) ERROR: 'DEPRECATION:', 'Setting specFilter directly on Env is deprecated and will be removed in a future version of Jasmine, please use the specFilter option in `configure`'
Chrome 87.0.4280 (Linux 0.0.0) RecordsController $scope.grade sets the strength FAILED
Error: [$controller:ctrlreg] The controller with the name 'RecordsController' is not registered.
https://errors.angularjs.org/1.7.9/$controller/ctrlreg?p0=RecordsController
at lib/angular/angular.js:138:12
at $controller (lib/angular/angular.js:11680:17)
at /home/darius/Private/Projects/learning/symfony_angular_docker/node_modules/angular-mocks/angular-mocks.js:2555:14
at UserContext.eval (webpack:///./app/Tests/RecordsControllerTest.spec.js?:22:34)
at <Jasmine>
Chrome 87.0.4280 (Linux 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.005 secs / 0.01 secs)
npm ERR! Test failed. See above for more details.
更新 3:
我在想 - 也许它没有看到控制器,因为它在没有控制器的情况下导入 app.js?控制器在另一个文件中分配给应用程序。但是测试只是没有看到另一个文件。也许我需要以某种方式从 RecordsController.js 文件中导出控制器?并在测试中导入它?
您正在使用 es6
(也称为 esnext
)模块的代码编写代码,因此如果不配置更多内容,它将无法正常工作。
但您也可以使用 karma-webpack
将您的代码转换为能够 运行 针对浏览器。这里有一些你应该做的事情来添加它:
- 安装需要的包:
npm i -D webpack karma-webpack webpack@4.41.1
// looks like `webpack5` doesn't work with `karma-webpack`
- 将您的
karma.conf.js
配置为使用 karma-webpack
:
preprocessors: {
// process your `esmodule` syntax of your files
'../public/*.js': ['webpack'],
'**/*.spec.js': ['webpack']
},
webpack: {
// karma watches the test entry points
// (you don't need to specify the entry option)
// webpack watches dependencies
// webpack configuration
"mode": "development",
},
plugins: [
// ...
'karma-webpack',
],
经过这么多时间终于在 tmhao2005 答案的帮助下找到了一个可行的解决方案:
app.js
var app = angular.module('app', []);
app.baseUrl = 'http://localhost:8080/';
app.config(['$interpolateProvider', function($interpolateProvider) {
$interpolateProvider.startSymbol('//');
$interpolateProvider.endSymbol('//');
}]);
export {app};
single_page.html.twig
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.9/angular.js"></script>
{# <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>#}
<script type="module" src="RecordsController.js"></script>
</head>
<body ng-app="app" >
<div class="container">
<div ng-controller="RecordsController">
<h1>Records controller</h1> <br>
<div class="row col-md-4">
<form>
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" ng-model="name" id="name">
</div>
<div class="form-group">
<label>Price</label>
<input type="number" class="form-control" ng-model="price" id="price">
</div>
<button type="submit" class="btn btn-primary" ng-click="submit()">Submit</button>
</form>
</div>
<table class="table table-bordered">
<tr>
<th>Id</th>
<th>Name</th>
<th>Price</th>
<th>Size</th>
</tr>
<tr ng-repeat="(key, record) in records">
<td>// record.id //</td>
<td>// record.name //</td>
<td>// record.price //</td>
<td>// grade(record.price) //</td>
</tr>
</table>
<a-great-eye></a-great-eye>
</div> <!-- end records controller -->
</div>
</body>
</html>
RecordsControllerTest.spec.js
import {RecordsController} from '../../public/RecordsController.js';
describe('RecordsController', function() {
var $controller, $rootScope, $http;
beforeEach(inject(function(_$controller_, _$rootScope_, _$http_){
// The injector unwraps the underscores (_) from around the parameter names when matching
$controller = _$controller_;
$rootScope = _$rootScope_;
$http = _$http_;
}));
describe('$scope.grade', function() {
it('sets the strength', function() {
var $scope = $rootScope.$new();
var controller = new RecordsController($scope, $http);
let grade = $scope.grade(1);
expect(grade).toEqual('small');
});
});
});
package.json
{
"name": "angular-phonecat",
"private": true,
"version": "0.0.0",
"description": "A tutorial application for AngularJS",
"repository": "https://github.com/angular/angular-phonecat",
"license": "MIT",
"dependencies": {
"angular": "1.7.x",
"angular-animate": "1.7.x",
"angular-resource": "1.7.x",
"angular-route": "1.7.x",
"bootstrap": "3.3.x",
"jquery": "3.3.x"
},
"devDependencies": {
"angular-mocks": "1.7.x",
"cpx": "^1.5.0",
"http-server": "^0.11.1",
"jasmine-core": "^3.3.0",
"karma": "^3.1.1",
"karma-chrome-launcher": "^2.2.0",
"karma-firefox-launcher": "^1.1.0",
"karma-jasmine": "^1.1.2",
"karma-webpack": "^4.0.2",
"protractor": "^5.4.1",
"webpack": "^4.41.1"
},
"scripts": {
"postinstall": "npm run copy-libs",
"update-deps": "npm update",
"postupdate-deps": "npm run copy-libs",
"copy-libs": "cpx \"node_modules/{angular,angular-*,bootstrap/dist,jquery/dist}/**/*\" app/lib -C",
"prestart": "npm install",
"start": "http-server ./app -a localhost -p 8000 -c-1",
"pretest": "npm install",
"test": "karma start karma.conf.js",
"test-single-run": "npm test -- --single-run",
"preupdate-webdriver": "npm install",
"update-webdriver": "webdriver-manager update",
"preprotractor": "npm run update-webdriver",
"protractor": "protractor e2e-tests/protractor.conf.js"
}
}
RecordsController.js
import {app} from './app.js';
function RecordsController($scope, $http)
{
$scope.submit = function () {
console.log($scope);
$http.post( app.baseUrl + 'save', {name: $scope.name, price: $scope.price})
.then(function (response) {
$scope.records.push(response.data)
});
}
$http.get(app.baseUrl + 'list')
.then(function(response) {
$scope.records = response.data;
});
$scope.grade = function(price) {
if (price > 100) {
return 'big';
} else if (price > 50) {
return 'medium';
} else {
return 'small';
}
};
}
app.controller('RecordsController', RecordsController);
export {RecordsController};
karma.conf.js
//jshint strict: false
// there are more things than needed, could clean up. Same in package.json
module.exports = function(config) {
config.set({
basePath: './app',
files: [
'lib/angular/angular.js',
'lib/angular-animate/angular-animate.js',
'lib/angular-resource/angular-resource.js',
'lib/angular-route/angular-route.js',
'../node_modules/angular-mocks/angular-mocks.js',
'**/*.module.js',
'*!(.module|.spec).js',
'!(lib)/**/*!(.module|.spec).js',
'**/*.spec.js',
'../public/*.js', // works with this because gets real files probably which we test
],
autoWatch: true,
frameworks: ['jasmine'],
browsers: ['Chrome'],
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-webpack',
],
preprocessors: {
// process your `esmodule` syntax of your files
'../public/*.js': ['webpack'],
'**/*.spec.js': ['webpack']
},
webpack: {
// karma watches the test entry points
// (you don't need to specify the entry option)
// webpack watches dependencies
// webpack configuration.
// dev mode for tests to work
"mode": "development",
},
});
};
所以最后一个问题是测试正在导入 app.js 但在 app.js 文件中控制器没有分配给应用程序。它被分配在不同的文件中。但是我无法让测试知道这一点。但是不同的解决方案是将 RecordsController 作为单独的函数。然后甚至不需要模拟应用程序。
我只是不确定
app.controller('RecordsController', RecordsController);
从体系结构的角度来看,在 RecordsController 文件中很好。
RecordsControllerTest.spec.js
// import RecordsController from '../../public/RecordsController';
import {app} from '../../public/app.js'; // without this gives "Module 'app' is not available! You either misspelled the module name or forgot to load it. "
describe('RecordsController', function() {
//beforeEach(module('app'));
beforeEach(angular.mock.module('app'));
var $controller, $rootScope;
beforeEach(inject(function(_$controller_, _$rootScope_){
// The injector unwraps the underscores (_) from around the parameter names when matching
$controller = _$controller_;
$rootScope = _$rootScope_;
}));
describe('$scope.grade', function() {
it('sets the strength', function() {
var $scope = $rootScope.$new();
/*var controller =*/ $controller('RecordsController', { $scope: $scope });
let grade = $scope.grade(1);
expect(grade).toEqual('small');
});
});
});
package.json
{
"name": "angular-phonecat",
"private": true,
"version": "0.0.0",
"description": "A tutorial application for AngularJS",
"repository": "https://github.com/angular/angular-phonecat",
"license": "MIT",
"dependencies": {
"angular": "1.7.x",
"angular-animate": "1.7.x",
"angular-resource": "1.7.x",
"angular-route": "1.7.x",
"bootstrap": "3.3.x",
"jquery": "3.3.x"
},
"devDependencies": {
"angular-mocks": "1.7.x",
"cpx": "^1.5.0",
"http-server": "^0.11.1",
"jasmine-core": "^3.3.0",
"karma": "^3.1.1",
"karma-chrome-launcher": "^2.2.0",
"karma-firefox-launcher": "^1.1.0",
"karma-jasmine": "^1.1.2",
"protractor": "^5.4.1"
},
"scripts": {
"postinstall": "npm run copy-libs",
"update-deps": "npm update",
"postupdate-deps": "npm run copy-libs",
"copy-libs": "cpx \"node_modules/{angular,angular-*,bootstrap/dist,jquery/dist}/**/*\" app/lib -C",
"prestart": "npm install",
"start": "http-server ./app -a localhost -p 8000 -c-1",
"pretest": "npm install",
"test": "karma start karma.conf.js",
"test-single-run": "npm test -- --single-run",
"preupdate-webdriver": "npm install",
"update-webdriver": "webdriver-manager update",
"preprotractor": "npm run update-webdriver",
"protractor": "protractor e2e-tests/protractor.conf.js"
}
}
app.js
var app = angular.module('app', []);
app.baseUrl = 'http://localhost:8080/';
app.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('//');
$interpolateProvider.endSymbol('//');
});
export {app};
karma.conf.js
//jshint strict: false
// there are more things than needed, could clean up. Same in package.json
module.exports = function(config) {
config.set({
basePath: './app',
files: [
'lib/angular/angular.js',
'lib/angular-animate/angular-animate.js',
'lib/angular-resource/angular-resource.js',
'lib/angular-route/angular-route.js',
'../node_modules/angular-mocks/angular-mocks.js',
'**/*.module.js',
'*!(.module|.spec).js',
'!(lib)/**/*!(.module|.spec).js',
'**/*.spec.js',
'../public/*.js', // works with this because gets real files probably which we test
],
autoWatch: true,
frameworks: ['jasmine'],
browsers: ['Chrome'],
plugins: [
'karma-chrome-launcher',
'karma-jasmine'
]
});
};
RecordsController.js
/*var app = angular.module('app', []);
app.baseUrl = 'http://localhost:8080/';
app.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('//');
$interpolateProvider.endSymbol('//');
});*/
import {app} from './app.js';
app.controller('RecordsController', ['$scope', '$http', function($scope, $http) {
$scope.submit = function () {
console.log($scope);
$http.post( app.baseUrl + 'save', {name: $scope.name, price: $scope.price})
.then(function (response) {
$scope.records.push(response.data)
});
}
$http.get(app.baseUrl + 'list')
.then(function(response) {
$scope.records = response.data;
});
$scope.grade = function(price) {
if (price > 100) {
return 'big';
} else if (price > 50) {
return 'medium';
} else {
return 'small';
}
};
}]);
//export {app};
应用程序有效。如果我没有 app.js 文件但在与 RecordsController.js 相同的文件中定义应用程序 - 单元测试有效。但是当我将代码移动到 app.js - 测试停止工作。这是输出:
npm test -- --single-run
> angular-phonecat@0.0.0 pretest /home/darius/Private/Projects/learning/symfony_angular_docker
> npm install
> angular-phonecat@0.0.0 postinstall /home/darius/Private/Projects/learning/symfony_angular_docker
> npm run copy-libs
> angular-phonecat@0.0.0 copy-libs /home/darius/Private/Projects/learning/symfony_angular_docker
> cpx "node_modules/{angular,angular-*,bootstrap/dist,jquery/dist}/**/*" app/lib -C
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
audited 534 packages in 2.942s
8 packages are looking for funding
run `npm fund` for details
found 10 vulnerabilities (6 low, 3 moderate, 1 high)
run `npm audit fix` to fix them, or `npm audit` for details
> angular-phonecat@0.0.0 test /home/darius/Private/Projects/learning/symfony_angular_docker
> karma start karma.conf.js "--single-run"
27 12 2020 07:58:51.305:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.module.js" does not match any file.
27 12 2020 07:58:51.307:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/*!(.module|.spec).js" does not match any file.
27 12 2020 07:58:51.313:WARN [watcher]: All files matched by "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.spec.js" were excluded or matched by prior matchers.
27 12 2020 07:58:51.325:INFO [karma-server]: Karma v3.1.4 server started at http://0.0.0.0:9876/
27 12 2020 07:58:51.326:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
27 12 2020 07:58:51.329:INFO [launcher]: Starting browser Chrome
27 12 2020 07:58:51.773:INFO [Chrome 87.0.4280 (Linux 0.0.0)]: Connected on socket M3VJxSZLyXP8VAmmAAAA with id 36635738
Chrome 87.0.4280 (Linux 0.0.0) ERROR: 'DEPRECATION:', 'Setting specFilter directly on Env is deprecated and will be removed in a future version of Jasmine, please use the specFilter option in `configure`'
Chrome 87.0.4280 (Linux 0.0.0) ERROR
{
"message": "An error was thrown in afterAll\nSyntaxError: Cannot use import statement outside a module\nSyntaxError: Cannot use import statement outside a module\nSyntaxError: Unexpected token 'export'",
"str": "An error was thrown in afterAll\nSyntaxError: Cannot use import statement outside a module\nSyntaxError: Cannot use import statement outside a module\nSyntaxError: Unexpected token 'export'"
}
Chrome 87.0.4280 (Linux 0.0.0): Executed 0 of 0 ERROR (0.002 secs / 0 secs)
npm ERR! Test failed. See above for more details.
或者您能否推荐教程,其中有导入文件的单元测试示例?
更新
karma.conf.js @tmhao2005 回答后:
//jshint strict: false
// there are more things than needed, could clean up. Same in package.json
module.exports = function(config) {
config.set({
basePath: './app',
files: [
'lib/angular/angular.js',
'lib/angular-animate/angular-animate.js',
'lib/angular-resource/angular-resource.js',
'lib/angular-route/angular-route.js',
'../node_modules/angular-mocks/angular-mocks.js',
'**/*.module.js',
'*!(.module|.spec).js',
'!(lib)/**/*!(.module|.spec).js',
'**/*.spec.js',
'../public/*.js', // works with this because gets real files probably which we test
],
autoWatch: true,
frameworks: ['jasmine'],
browsers: ['Chrome'],
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-webpack',
],
preprocessors: {
// process your `esmodule` syntax of your files
'../public/*.js': ['webpack'],
'**/*.spec.js': ['webpack']
},
webpack: {
// karma watches the test entry points
// (you don't need to specify the entry option)
// webpack watches dependencies
// webpack configuration
},
});
};
现在得到
npm test -- --single-run
> angular-phonecat@0.0.0 pretest /home/darius/Private/Projects/learning/symfony_angular_docker
> npm install
> angular-phonecat@0.0.0 postinstall /home/darius/Private/Projects/learning/symfony_angular_docker
> npm run copy-libs
> angular-phonecat@0.0.0 copy-libs /home/darius/Private/Projects/learning/symfony_angular_docker
> cpx "node_modules/{angular,angular-*,bootstrap/dist,jquery/dist}/**/*" app/lib -C
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules/watchpack/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
audited 786 packages in 3.663s
11 packages are looking for funding
run `npm fund` for details
found 10 vulnerabilities (6 low, 3 moderate, 1 high)
run `npm audit fix` to fix them, or `npm audit` for details
> angular-phonecat@0.0.0 test /home/darius/Private/Projects/learning/symfony_angular_docker
> karma start karma.conf.js "--single-run"
30 12 2020 17:50:53.375:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.module.js" does not match any file.
30 12 2020 17:50:53.377:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/*!(.module|.spec).js" does not match any file.
30 12 2020 17:50:53.384:WARN [watcher]: All files matched by "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.spec.js" were excluded or matched by prior matchers.
⚠ 「wdm」: Hash: d4e94cf661365475ea55
Version: webpack 4.41.1
Time: 57ms
Built at: 2020-12-30 17:50:53
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
ℹ 「wdm」: Compiled with warnings.
30 12 2020 17:50:53.408:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.module.js" does not match any file.
30 12 2020 17:50:53.409:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/*!(.module|.spec).js" does not match any file.
30 12 2020 17:50:53.417:WARN [watcher]: All files matched by "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.spec.js" were excluded or matched by prior matchers.
ℹ 「wdm」: Compiling...
⚠ 「wdm」: Hash: 4b332cf791759062b309
Version: webpack 4.41.1
Time: 18ms
Built at: 2020-12-30 17:50:53
Asset Size Chunks Chunk Names
../public/RecordsController.js 1.48 KiB 1, 2 [emitted] ../public/RecordsController
../public/app.js 1.11 KiB 2 [emitted] ../public/app
Tests/RecordsControllerTest.spec.js 1.45 KiB 0, 2 [emitted] Tests/RecordsControllerTest.spec
Entrypoint Tests/RecordsControllerTest.spec = Tests/RecordsControllerTest.spec.js
Entrypoint ../public/app = ../public/app.js
Entrypoint ../public/RecordsController = ../public/RecordsController.js
[0] ./public/app.js 227 bytes {0} {1} {2} [built]
[1] ./app/Tests/RecordsControllerTest.spec.js 952 bytes {0} [built]
[2] ./public/RecordsController.js 957 bytes {1} [built]
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
ℹ 「wdm」: Compiled with warnings.
30 12 2020 17:50:53.568:INFO [karma-server]: Karma v3.1.4 server started at http://0.0.0.0:9876/
30 12 2020 17:50:53.568:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
30 12 2020 17:50:53.573:INFO [launcher]: Starting browser Chrome
30 12 2020 17:50:53.969:INFO [Chrome 87.0.4280 (Linux 0.0.0)]: Connected on socket xExD5D27bFhOOfMsAAAA with id 98015757
Chrome 87.0.4280 (Linux 0.0.0) ERROR: 'DEPRECATION:', 'Setting specFilter directly on Env is deprecated and will be removed in a future version of Jasmine, please use the specFilter option in `configure`'
Chrome 87.0.4280 (Linux 0.0.0) RecordsController $scope.grade sets the strength FAILED
Error: [$injector:modulerr] Failed to instantiate module app due to:
Error: [$injector:unpr] Unknown provider: e
https://errors.angularjs.org/1.7.9/$injector/modulerr?p0=app&p1=Error%3A%20%5B%24injector%3Aunpr%5D%20Unknown%20provider%3A%20e%0Ahttps%3A%2F%2Ferrors.angularjs.org%2F1.7.9%2F%24injector%2Funpr%3Fp0%3De%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A138%3A12%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A4926%3A19%0A%20%20%20%20at%20getService%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A5086%3A32)%0A%20%20%20%20at%20injectionArgs%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A5111%3A58)%0A%20%20%20%20at%20Object.invoke%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A5135%3A18)%0A%20%20%20%20at%20runInvokeQueue%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A5032%3A35)%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A5042%3A11%0A%20%20%20%20at%20forEach%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A387%3A20)%0A%20%20%20%20at%20loadModules%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A5022%3A5)%0A%20%20%20%20at%20Object.createInjector%20%5Bas%20injector%5D%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.js%3F59efdd7db87c914e8c987ccc770455b4feb59f8f%3A4939%3A19)
at <Jasmine>
at lib/angular/angular.js:138:12
at lib/angular/angular.js:5062:15
at forEach (lib/angular/angular.js:387:20)
at loadModules (lib/angular/angular.js:5022:5)
at Object.createInjector [as injector] (lib/angular/angular.js:4939:19)
at UserContext.WorkFn (/home/darius/Private/Projects/learning/symfony_angular_docker/node_modules/angular-mocks/angular-mocks.js:3449:52)
at <Jasmine>
TypeError: Cannot read property '$new' of undefined
at UserContext.<anonymous> (Tests/RecordsControllerTest.spec.js:1:1385)
at <Jasmine>
Chrome 87.0.4280 (Linux 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.002 secs / 0.008 secs)
npm ERR! Test failed. See above for more details.
更新 2
添加了 $interpolateProvider 作为依赖项,app.js 现在:
var app = angular.module('app', []);
app.baseUrl = 'http://localhost:8080/';
app.config(['$interpolateProvider', function($interpolateProvider) {
$interpolateProvider.startSymbol('//');
$interpolateProvider.endSymbol('//');
}]);
export {app};
添加了开发模式,karma.conf.js现在:
//jshint strict: false
// there are more things than needed, could clean up. Same in package.json
module.exports = function(config) {
config.set({
basePath: './app',
files: [
'lib/angular/angular.js',
'lib/angular-animate/angular-animate.js',
'lib/angular-resource/angular-resource.js',
'lib/angular-route/angular-route.js',
'../node_modules/angular-mocks/angular-mocks.js',
'**/*.module.js',
'*!(.module|.spec).js',
'!(lib)/**/*!(.module|.spec).js',
'**/*.spec.js',
'../public/*.js', // works with this because gets real files probably which we test
],
autoWatch: true,
frameworks: ['jasmine'],
browsers: ['Chrome'],
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-webpack',
],
preprocessors: {
// process your `esmodule` syntax of your files
'../public/*.js': ['webpack'],
'**/*.spec.js': ['webpack']
},
webpack: {
// karma watches the test entry points
// (you don't need to specify the entry option)
// webpack watches dependencies
// webpack configuration.
// dev mode for tests to work
"mode": "development",
},
});
};
现在出现错误:
darius@darius-Vostro-5481:~/Private/Projects/learning/symfony_angular_docker$ npm test -- --single-run
> angular-phonecat@0.0.0 pretest /home/darius/Private/Projects/learning/symfony_angular_docker
> npm install
> angular-phonecat@0.0.0 postinstall /home/darius/Private/Projects/learning/symfony_angular_docker
> npm run copy-libs
> angular-phonecat@0.0.0 copy-libs /home/darius/Private/Projects/learning/symfony_angular_docker
> cpx "node_modules/{angular,angular-*,bootstrap/dist,jquery/dist}/**/*" app/lib -C
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules/watchpack/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
audited 786 packages in 3.714s
11 packages are looking for funding
run `npm fund` for details
found 10 vulnerabilities (6 low, 3 moderate, 1 high)
run `npm audit fix` to fix them, or `npm audit` for details
> angular-phonecat@0.0.0 test /home/darius/Private/Projects/learning/symfony_angular_docker
> karma start karma.conf.js "--single-run"
05 01 2021 17:03:25.368:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.module.js" does not match any file.
05 01 2021 17:03:25.370:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/*!(.module|.spec).js" does not match any file.
05 01 2021 17:03:25.376:WARN [watcher]: All files matched by "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.spec.js" were excluded or matched by prior matchers.
ℹ 「wdm」: Hash: 3879665b411e2fff46cc
Version: webpack 4.41.1
Time: 53ms
Built at: 2021-01-05 17:03:25
ℹ 「wdm」: Compiled successfully.
05 01 2021 17:03:25.396:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.module.js" does not match any file.
05 01 2021 17:03:25.397:WARN [watcher]: Pattern "/home/darius/Private/Projects/learning/symfony_angular_docker/app/*!(.module|.spec).js" does not match any file.
05 01 2021 17:03:25.402:WARN [watcher]: All files matched by "/home/darius/Private/Projects/learning/symfony_angular_docker/app/**/*.spec.js" were excluded or matched by prior matchers.
ℹ 「wdm」: Compiling...
ℹ 「wdm」: Hash: bfe70362116b7e4fdf82
Version: webpack 4.41.1
Time: 18ms
Built at: 2021-01-05 17:03:25
Asset Size Chunks Chunk Names
../public/RecordsController.js 5.83 KiB ../public/RecordsController [emitted] ../public/RecordsController
../public/app.js 4.23 KiB ../public/app [emitted] ../public/app
Tests/RecordsControllerTest.spec.js 5.77 KiB Tests/RecordsControllerTest.spec [emitted] Tests/RecordsControllerTest.spec
Entrypoint ../public/app = ../public/app.js
Entrypoint Tests/RecordsControllerTest.spec = Tests/RecordsControllerTest.spec.js
Entrypoint ../public/RecordsController = ../public/RecordsController.js
[./app/Tests/RecordsControllerTest.spec.js] 954 bytes {Tests/RecordsControllerTest.spec} [built]
[./public/RecordsController.js] 958 bytes {../public/RecordsController} [built]
[./public/app.js] 253 bytes {../public/app} {Tests/RecordsControllerTest.spec} {../public/RecordsController} [built]
ℹ 「wdm」: Compiled successfully.
05 01 2021 17:03:25.502:INFO [karma-server]: Karma v3.1.4 server started at http://0.0.0.0:9876/
05 01 2021 17:03:25.503:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
05 01 2021 17:03:25.507:INFO [launcher]: Starting browser Chrome
05 01 2021 17:03:25.963:INFO [Chrome 87.0.4280 (Linux 0.0.0)]: Connected on socket t4Hc0-IijbJd_27rAAAA with id 24424610
Chrome 87.0.4280 (Linux 0.0.0) ERROR: 'DEPRECATION:', 'Setting specFilter directly on Env is deprecated and will be removed in a future version of Jasmine, please use the specFilter option in `configure`'
Chrome 87.0.4280 (Linux 0.0.0) RecordsController $scope.grade sets the strength FAILED
Error: [$controller:ctrlreg] The controller with the name 'RecordsController' is not registered.
https://errors.angularjs.org/1.7.9/$controller/ctrlreg?p0=RecordsController
at lib/angular/angular.js:138:12
at $controller (lib/angular/angular.js:11680:17)
at /home/darius/Private/Projects/learning/symfony_angular_docker/node_modules/angular-mocks/angular-mocks.js:2555:14
at UserContext.eval (webpack:///./app/Tests/RecordsControllerTest.spec.js?:22:34)
at <Jasmine>
Chrome 87.0.4280 (Linux 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.005 secs / 0.01 secs)
npm ERR! Test failed. See above for more details.
更新 3:
我在想 - 也许它没有看到控制器,因为它在没有控制器的情况下导入 app.js?控制器在另一个文件中分配给应用程序。但是测试只是没有看到另一个文件。也许我需要以某种方式从 RecordsController.js 文件中导出控制器?并在测试中导入它?
您正在使用 es6
(也称为 esnext
)模块的代码编写代码,因此如果不配置更多内容,它将无法正常工作。
但您也可以使用 karma-webpack
将您的代码转换为能够 运行 针对浏览器。这里有一些你应该做的事情来添加它:
- 安装需要的包:
npm i -D webpack karma-webpack webpack@4.41.1
// looks like `webpack5` doesn't work with `karma-webpack`
- 将您的
karma.conf.js
配置为使用karma-webpack
:
preprocessors: {
// process your `esmodule` syntax of your files
'../public/*.js': ['webpack'],
'**/*.spec.js': ['webpack']
},
webpack: {
// karma watches the test entry points
// (you don't need to specify the entry option)
// webpack watches dependencies
// webpack configuration
"mode": "development",
},
plugins: [
// ...
'karma-webpack',
],
经过这么多时间终于在 tmhao2005 答案的帮助下找到了一个可行的解决方案:
app.js
var app = angular.module('app', []);
app.baseUrl = 'http://localhost:8080/';
app.config(['$interpolateProvider', function($interpolateProvider) {
$interpolateProvider.startSymbol('//');
$interpolateProvider.endSymbol('//');
}]);
export {app};
single_page.html.twig
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.9/angular.js"></script>
{# <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>#}
<script type="module" src="RecordsController.js"></script>
</head>
<body ng-app="app" >
<div class="container">
<div ng-controller="RecordsController">
<h1>Records controller</h1> <br>
<div class="row col-md-4">
<form>
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" ng-model="name" id="name">
</div>
<div class="form-group">
<label>Price</label>
<input type="number" class="form-control" ng-model="price" id="price">
</div>
<button type="submit" class="btn btn-primary" ng-click="submit()">Submit</button>
</form>
</div>
<table class="table table-bordered">
<tr>
<th>Id</th>
<th>Name</th>
<th>Price</th>
<th>Size</th>
</tr>
<tr ng-repeat="(key, record) in records">
<td>// record.id //</td>
<td>// record.name //</td>
<td>// record.price //</td>
<td>// grade(record.price) //</td>
</tr>
</table>
<a-great-eye></a-great-eye>
</div> <!-- end records controller -->
</div>
</body>
</html>
RecordsControllerTest.spec.js
import {RecordsController} from '../../public/RecordsController.js';
describe('RecordsController', function() {
var $controller, $rootScope, $http;
beforeEach(inject(function(_$controller_, _$rootScope_, _$http_){
// The injector unwraps the underscores (_) from around the parameter names when matching
$controller = _$controller_;
$rootScope = _$rootScope_;
$http = _$http_;
}));
describe('$scope.grade', function() {
it('sets the strength', function() {
var $scope = $rootScope.$new();
var controller = new RecordsController($scope, $http);
let grade = $scope.grade(1);
expect(grade).toEqual('small');
});
});
});
package.json
{
"name": "angular-phonecat",
"private": true,
"version": "0.0.0",
"description": "A tutorial application for AngularJS",
"repository": "https://github.com/angular/angular-phonecat",
"license": "MIT",
"dependencies": {
"angular": "1.7.x",
"angular-animate": "1.7.x",
"angular-resource": "1.7.x",
"angular-route": "1.7.x",
"bootstrap": "3.3.x",
"jquery": "3.3.x"
},
"devDependencies": {
"angular-mocks": "1.7.x",
"cpx": "^1.5.0",
"http-server": "^0.11.1",
"jasmine-core": "^3.3.0",
"karma": "^3.1.1",
"karma-chrome-launcher": "^2.2.0",
"karma-firefox-launcher": "^1.1.0",
"karma-jasmine": "^1.1.2",
"karma-webpack": "^4.0.2",
"protractor": "^5.4.1",
"webpack": "^4.41.1"
},
"scripts": {
"postinstall": "npm run copy-libs",
"update-deps": "npm update",
"postupdate-deps": "npm run copy-libs",
"copy-libs": "cpx \"node_modules/{angular,angular-*,bootstrap/dist,jquery/dist}/**/*\" app/lib -C",
"prestart": "npm install",
"start": "http-server ./app -a localhost -p 8000 -c-1",
"pretest": "npm install",
"test": "karma start karma.conf.js",
"test-single-run": "npm test -- --single-run",
"preupdate-webdriver": "npm install",
"update-webdriver": "webdriver-manager update",
"preprotractor": "npm run update-webdriver",
"protractor": "protractor e2e-tests/protractor.conf.js"
}
}
RecordsController.js
import {app} from './app.js';
function RecordsController($scope, $http)
{
$scope.submit = function () {
console.log($scope);
$http.post( app.baseUrl + 'save', {name: $scope.name, price: $scope.price})
.then(function (response) {
$scope.records.push(response.data)
});
}
$http.get(app.baseUrl + 'list')
.then(function(response) {
$scope.records = response.data;
});
$scope.grade = function(price) {
if (price > 100) {
return 'big';
} else if (price > 50) {
return 'medium';
} else {
return 'small';
}
};
}
app.controller('RecordsController', RecordsController);
export {RecordsController};
karma.conf.js
//jshint strict: false
// there are more things than needed, could clean up. Same in package.json
module.exports = function(config) {
config.set({
basePath: './app',
files: [
'lib/angular/angular.js',
'lib/angular-animate/angular-animate.js',
'lib/angular-resource/angular-resource.js',
'lib/angular-route/angular-route.js',
'../node_modules/angular-mocks/angular-mocks.js',
'**/*.module.js',
'*!(.module|.spec).js',
'!(lib)/**/*!(.module|.spec).js',
'**/*.spec.js',
'../public/*.js', // works with this because gets real files probably which we test
],
autoWatch: true,
frameworks: ['jasmine'],
browsers: ['Chrome'],
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-webpack',
],
preprocessors: {
// process your `esmodule` syntax of your files
'../public/*.js': ['webpack'],
'**/*.spec.js': ['webpack']
},
webpack: {
// karma watches the test entry points
// (you don't need to specify the entry option)
// webpack watches dependencies
// webpack configuration.
// dev mode for tests to work
"mode": "development",
},
});
};
所以最后一个问题是测试正在导入 app.js 但在 app.js 文件中控制器没有分配给应用程序。它被分配在不同的文件中。但是我无法让测试知道这一点。但是不同的解决方案是将 RecordsController 作为单独的函数。然后甚至不需要模拟应用程序。
我只是不确定
app.controller('RecordsController', RecordsController);
从体系结构的角度来看,在 RecordsController 文件中很好。