This should be a very simple question, I hope... I am an Angular newbie, and a newbie to the whole process of writing tests.
This is my controller:
angular
.module('myModule', [])
.controller('myCtrl', ['$scope', function ($scope) {
$scope.questionIndex = -1;
$scope.text = "Hello world";
}]);
My view (index.html) is as follows:
<div id="text">{{ text }}</div>
This is my test, which is passing fine:
describe('Controller: myCtrl', function () {
// load the controller's module
beforeEach(module('myApp'));
var MainCtrl,
scope;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
MainCtrl = $controller('myCtrl', {
$scope: scope
});
}));
it('should have the initial question index set to -1', function () {
expect(scope.questionIndex).toBe(-1);
});
});
Now I want to write a test to check that the text
element was actually rendered to the page.
How can I do this in Jasmine? Sorry, it's probably a stupid question but I can't figure it out from the documentation.
I'll give you two answers to your question:
First: Testing bindings in your view should probably be done in an end-to-end (E2E) test. And end to end test is used to make sure that the controllers, models and views are working together as expected, along with properly integrating your backend (if you have one). This is where you would test that the given div
has the expected text in it. You can read all about that in the developer guide here. The reason you use an E2E test for this is because the binding isn't truly a responsibility of your controller. The controller handles/manipulates the model. The model is then passed to the view, and it is the view's responsibility to then render the DOM elements using that model. The only reliable way to test your DOM elements is through an E2E test.
Second: It can actually be done in a unit test, but the way to do it isn't exactly pretty. You can do this by using angular's $compile
service. This service is what angular uses to parse through the DOM and turn all bindings/directives/etc into the end product. Here's an example of how that would be done:
var scope, compile, elem;
beforeEach(inject(function ($controller, $rootScope, $compile) {
scope = $rootScope.$new();
compile = $compile;
MainCtrl = $controller('myCtrl', {
$scope: scope
});
}));
it('should set the div content to "' + scope.text + '"', function(){
var html = '<div id="text">{{ text }}</div>';
elem = angular.element(html); // turn html into an element object
compile(elem)(scope); // compile the html
scope.$digest(); // update the scope
expect(elem.text()).toBe(scope.text); //test to see if it was updated.
});
For more info on this second option, please see the detailed tutorial found here. Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With