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:
""
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 globalangular
variable that is visible to angular-mocks.You can check this by running this at the top of one of your tests:
To work around this you just need to use the global
angular
variable in your tests.src/__test__/all-in-one.test.js:
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.And then your test works as expected for me:
For reference, here is the full app and test:
src/app/app.module.js:
src/__test__/app.test.js:
I ran into the same baffling behavior a couple years later and I wanted to share what I found
If you transpile the test using babel and look at the imports you will find something similar to the following
_interopRequireWildcard
currently has the following implementationIn short it creates a new object and copies all the properties from the imported object. This is why
angular === window.angular
isfalse
. It also explains whyangular.mock
isn't defined, it didn't exist when_interopRequireWildcard
made a copy of the moduleGiven that there are a couple additional ways to solve the problem in addition to the accepted answer
Instead of using
import * as angular from 'angular'
usingimport angular from 'angular'
should avoid the behavior because_interopRequireDefault
does not return a different object. (However, if you are using TypeScript it may not resolve the types for 'angular' correctly with this method)Another option would be to import angular twice: