JSFiddle showing the problem:
http://jsfiddle.net/ggvfwoeL/3/
I have an Angular application that involves a service for generating threats. The threat generation is done using the nools rule engine. The service exposes a function generateForElement
that returns a promise. The function looks like this (see the JSFiddle for full details):
var Element = function (element) { this.type = element.attributes.type; }
var Threats = function () { this.collection = []; }
function generateForElement(element) {
var threats = new Threats();
var el = new Element(element);
flow.getSession(threats, el).match();
return $q.when(threats.collection);
}
The rule engine is set up so that when you call generateForElement
with an element that is a tm.Process
type, it generates 2 threats. Here is the code that defines the rules (obviously this is much simplified to make the question clearer):
function initialiseFlow() {
return nools.flow('Element threat generation', function (flow) {
flow.rule('Spoofing Threat Rule', [
[Element, 'el', 'el.type == "tm.Process"'],
[Threats, 'threats']
], function (facts) {
facts.threats.collection.push('Spoofing');
});
flow.rule('Tampering Threat Rule', [
[Element, 'el', 'el.type == "tm.Process"'],
[Threats, 'threats']
], function (facts) {
facts.threats.collection.push('Tampering');
});
});
}
When I manually test this in my application I see the 2 threats being generated. But my unit test is failing on this line
expect(threats.length).toEqual(2);
With error
Error: Expected 1 to equal 2.
So it appears that only 1 threat is being generated. The unit test definition is like this:
describe('threatengine service', function () {
var threatengine;
var $rootScope;
beforeEach(function () {
angular.mock.module('app')
angular.mock.inject(function (_$rootScope_, _threatengine_) {
threatengine = _threatengine_;
$rootScope = _$rootScope_;
});
$rootScope.$apply();
});
describe('threat generation tests', function () {
it('process should generate two threats', function () {
var element = { attributes: { type: 'tm.Process' }};
var threats;
threatengine.generateForElement(element).then(function (data) {
threats = data;
});
expect(threats).toBeUndefined();
$rootScope.$apply();
expect(threats).toBeDefined();
expect(threats.length).toEqual(2);
});
});
});
Clearly I am doing something wrong. As I said, when I run the full application I definitely get 2 threats which make me think the fault is either with the unit test, or maybe with how I am handling the promises in my service, but I just can't see it.
Why is my unit test failing?