I feel I am missing something crucial in this extremely simplified angular directive unit test:
import * as angular from 'angular'
import 'angular-mocks'
const app = angular.module('my-app', [])
app.directive('myDirective', () => ({
template: 'this does not work either',
link: (scope, element) => { // have also tried compile fn
console.log('This does not log')
element.html('Hi!')
}
}))
describe('myDirective', () => {
var element, scope
beforeEach(app)
beforeEach(inject(($rootScope, $compile) => {
scope = $rootScope.$new()
element = $compile('<my-directive />')(scope)
scope.$digest()
}))
it('should actually do something', () => {
expect(element.html()).toEqual('Hi!')
})
})
When jest runs it appears the directive has not been linked/compiled/whatever
FAIL test/HtmlToPlaintextDirective.spec.js
● myDirective › should actually do something
expect(received).toEqual(expected)
Expected value to equal:
"Hi!"
Received:
""
Load the Angular App beforeEach(module('MyApp')); //3. Describe the object by name describe('compute', function () { var compute; //4. Initialize the filter beforeEach(inject(function ($filter) { compute = $filter('compute', {}); })); //5. Write the test in the it block along with expectations.
AngularJS is written with testability in mind, but it still requires that you do the right thing. We tried to make the right thing easy, but if you ignore these guidelines you may end up with an untestable application.
The jest-preset-angular library will configure Jest and it will also configure the Angular TestBed for you. First, we have to install all the dependencies we need. Secondly, we create a setupJest. ts file in the root and import jest-preset-angular inside of it.
Updated answer:
You're right things don't work as expected when importing everything in a single file.
Digging into things it looks like you're running into some magic that Babel/Jest does to support browser scripts that rely on globals (like AngularJS).
What's happening is that your module's angular
variable is not the same as the global angular
variable that is visible to angular-mocks.
You can check this by running this at the top of one of your tests:
import * as angular from 'angular'
import 'angular-mocks'
console.log(angular === window.angular); // `false` in Jest!
console.log(angular.mock); // undefined
console.log(window.angular.mock); // `{...}` defined
To work around this you just need to use the global angular
variable in your tests.
src/__test__/all-in-one.test.js:
import "angular";
import "angular-mocks";
/*
Work around Jest's window/global mock magic.
Use the global version of `angular` that has been augmented by angular-mocks.
*/
var angular = window.angular;
export var app = angular.module('app', []);
app.directive('myDirective', () => ({
link: (scope, element) => {
console.log('This does log');
scope.content = 'Hi!';
},
template: 'content: {{content}}'
}));
describe('myDirective', function(){
var element;
var scope;
beforeEach(function(){
angular.mock.module(app.name);
});
it('should do something', function(){
inject(function(
$rootScope,
$compile
){
scope = $rootScope.$new();
element = $compile('<my-directive></my-directive>')(scope);
scope.$digest();
});
expect(element.html()).toEqual('content: Hi!');
});
});
Original answer: (This worked because I was accidentally using the global version of angular
inside my test.)
The Angular module under test isn't being initialised correctly in your tests.
Your call to beforeEach(app)
isn't correct.
Instead you need to use angular.mock.module("moduleName")
to initialise your module.
describe('myDirective', () => {
var element, scope
// You need to pass the module name to `angular.mock.module()`
beforeEach(function(){
angular.mock.module(app.name);
});
// Then you can set up and run your tests as normal:
beforeEach(inject(($rootScope, $compile) => {
scope = $rootScope.$new()
element = $compile('<my-directive></my-directive>')(scope)
scope.$digest()
}))
it('should actually do something', () => {
expect(element.html()).toEqual('Hi!')
})
});
And then your test works as expected for me:
PASS src\__test__\app.test.js
myDirective
√ should do something (46ms)
For reference, here is the full app and test:
src/app/app.module.js:
import * as angular from 'angular'
export var app = angular.module('app', []);
app.directive('myDirective', () => ({
link: (scope, element) => {
console.log('This does log');
scope.content = 'Hi!';
},
template: 'content: {{content}}'
}))
src/__test__/app.test.js:
import {app} from "../app/app.module";
import "angular-mocks";
describe('myDirective', function(){
var element;
var scope;
beforeEach(function(){
angular.mock.module(app.name);
});
beforeEach(inject(function(
$rootScope,
$compile
){
scope = $rootScope.$new();
element = $compile('<my-directive></my-directive>')(scope);
scope.$digest();
}));
it('should do something', function(){
expect(element.html()).toEqual('content: Hi!');
});
});
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