如何使用 DOM 测试 angularjs 组件
How to test angularjs component with DOM
我正在尝试熟悉测试 AngularJS 应用程序。
虽然测试组件逻辑或多或少是清楚的,但我在 html 模板和模型绑定方面遇到了麻烦,因为我想测试 html 与控制器逻辑的绑定。
测试是运行 by karma 在真实浏览器中,所以测试环境支持DOM。
看起来不可能,不是吗?
describe('sign-up', function () {
angular.mock.module('myApp');
angular.mock.inject(function($componentController, $rootScope, $document) {
let scope = $rootScope.$new();
let signUp = $componentController('signUp', {$scope: scope});
console.log(`signup = ${signUp}`);
for (let [k,v] of signUp) {
// there is no field signUp.firstName
// but inside the controller code referencing
// this.firstName is working
console.log(`signup.${k} = ${v}`);
}
// jquery cannot find #firstName node
// $('#firstName').val('dan') gets the same outcome
$document.find('#firstName').val('dan');
expect($document.find('#firstName').val()).toBe('dan');
// without DOM form submission is not possible
});
});
});
控制器组件:
angular.
module('myApp').
component('signUp', {
templateUrl: template,
controller: [
function () {
this.form = {};
var self = this;
}]});
模板:
<form novalidate name="$ctrl.form" >
<div class="form-group">
<input type="text" class="form-control"
ng-model="$ctrl.firstName"
required
name="firstName"
id="firstName"
/>
</div>
</form>
您需要创建并编译元素:
let element = angular.element('<sign-up></sign-up>');
const $compile = $injector.get('$compile');
element = $compile(element)($scope);
controller = element.controller('signUp');
P.S。 $document.find('#firstName')
不会 return 任何东西,因为你不在任何地方添加这个元素。使用 element.find
代替
您可以使用 $compile
service to test your component templates ($componentController
creates instances of component controllers without creating any markup, even $compile
will not attach it to $document
, so you have to use angular.element
检查您的模板)。
这是您的组件的一个工作示例:
angular.module('myApp', [])
.component('signUp', {
template: '<form novalidate name="$ctrl.form" >\n' +
' <div class="form-group">\n' +
' <input type="text" class="form-control"\n' +
' ng-model="$ctrl.firstName"\n' +
' required\n' +
' name="firstName"\n' +
' id="firstName"\n' +
' />\n' +
' </div>\n' +
' </form>',
controller: 'SignUpController'
})
.controller('SignUpController', [function myComponentController() {
var ctrl = this;
ctrl.form = {};
}]);
/*
TESTS GO HERE
*/
describe('Testing a component controller', function() {
beforeEach(module('myApp', function ($provide) {
}));
beforeEach(inject(function ($injector) {
}));
describe('with $compile', function () {
var element;
var scope;
var controller;
beforeEach(inject(function ($rootScope, $compile) {
scope = $rootScope.$new();
element = angular.element('<sign-up></sign-up>');
element = $compile(element)(scope);
controller = element.controller('signUp');
console.log(element);
scope.$apply();
}));
it('should render template', function () {
expect(element.find('input').val()).toBe('');
controller.firstName = 'Dan';
scope.$apply();
expect(element.find('input').val()).toBe('Dan');
});
})
});
.as-console-wrapper {
height:0;
}
<!DOCTYPE html>
<html>
<head>
<!-- jasmine -->
<script src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.8.0/jasmine.js"></script>
<!-- jasmine's html reporting code and css -->
<script src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.8.0/jasmine-html.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.8.0/jasmine.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.8.0/boot.js"></script>
<!-- angular itself -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.js"></script>
<!-- angular's testing helpers -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular-mocks.js"></script>
</head>
<body>
<!-- bootstrap jasmine! -->
<script>
var jasmineEnv = jasmine.getEnv();
// Tell it to add an Html Reporter
// this will add detailed HTML-formatted results
// for each spec ran.
jasmineEnv.addReporter(new jasmine.HtmlReporter());
// Execute the tests!
jasmineEnv.execute();
</script>
</body>
</html>
我正在尝试熟悉测试 AngularJS 应用程序。 虽然测试组件逻辑或多或少是清楚的,但我在 html 模板和模型绑定方面遇到了麻烦,因为我想测试 html 与控制器逻辑的绑定。
测试是运行 by karma 在真实浏览器中,所以测试环境支持DOM。
看起来不可能,不是吗?
describe('sign-up', function () {
angular.mock.module('myApp');
angular.mock.inject(function($componentController, $rootScope, $document) {
let scope = $rootScope.$new();
let signUp = $componentController('signUp', {$scope: scope});
console.log(`signup = ${signUp}`);
for (let [k,v] of signUp) {
// there is no field signUp.firstName
// but inside the controller code referencing
// this.firstName is working
console.log(`signup.${k} = ${v}`);
}
// jquery cannot find #firstName node
// $('#firstName').val('dan') gets the same outcome
$document.find('#firstName').val('dan');
expect($document.find('#firstName').val()).toBe('dan');
// without DOM form submission is not possible
});
});
});
控制器组件:
angular.
module('myApp').
component('signUp', {
templateUrl: template,
controller: [
function () {
this.form = {};
var self = this;
}]});
模板:
<form novalidate name="$ctrl.form" >
<div class="form-group">
<input type="text" class="form-control"
ng-model="$ctrl.firstName"
required
name="firstName"
id="firstName"
/>
</div>
</form>
您需要创建并编译元素:
let element = angular.element('<sign-up></sign-up>');
const $compile = $injector.get('$compile');
element = $compile(element)($scope);
controller = element.controller('signUp');
P.S。 $document.find('#firstName')
不会 return 任何东西,因为你不在任何地方添加这个元素。使用 element.find
代替
您可以使用 $compile
service to test your component templates ($componentController
creates instances of component controllers without creating any markup, even $compile
will not attach it to $document
, so you have to use angular.element
检查您的模板)。
这是您的组件的一个工作示例:
angular.module('myApp', [])
.component('signUp', {
template: '<form novalidate name="$ctrl.form" >\n' +
' <div class="form-group">\n' +
' <input type="text" class="form-control"\n' +
' ng-model="$ctrl.firstName"\n' +
' required\n' +
' name="firstName"\n' +
' id="firstName"\n' +
' />\n' +
' </div>\n' +
' </form>',
controller: 'SignUpController'
})
.controller('SignUpController', [function myComponentController() {
var ctrl = this;
ctrl.form = {};
}]);
/*
TESTS GO HERE
*/
describe('Testing a component controller', function() {
beforeEach(module('myApp', function ($provide) {
}));
beforeEach(inject(function ($injector) {
}));
describe('with $compile', function () {
var element;
var scope;
var controller;
beforeEach(inject(function ($rootScope, $compile) {
scope = $rootScope.$new();
element = angular.element('<sign-up></sign-up>');
element = $compile(element)(scope);
controller = element.controller('signUp');
console.log(element);
scope.$apply();
}));
it('should render template', function () {
expect(element.find('input').val()).toBe('');
controller.firstName = 'Dan';
scope.$apply();
expect(element.find('input').val()).toBe('Dan');
});
})
});
.as-console-wrapper {
height:0;
}
<!DOCTYPE html>
<html>
<head>
<!-- jasmine -->
<script src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.8.0/jasmine.js"></script>
<!-- jasmine's html reporting code and css -->
<script src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.8.0/jasmine-html.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.8.0/jasmine.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/jasmine/2.8.0/boot.js"></script>
<!-- angular itself -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.js"></script>
<!-- angular's testing helpers -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular-mocks.js"></script>
</head>
<body>
<!-- bootstrap jasmine! -->
<script>
var jasmineEnv = jasmine.getEnv();
// Tell it to add an Html Reporter
// this will add detailed HTML-formatted results
// for each spec ran.
jasmineEnv.addReporter(new jasmine.HtmlReporter());
// Execute the tests!
jasmineEnv.execute();
</script>
</body>
</html>