Testing dynamically named inputs inside ng-repeat using $setViewValue() #5125
Description
Hi!
I cross posted this in stack overflow - I hope that isn't bad manners.
I am trying to test a directive that dynamically adds form inputs to a page using ng-repeat. The code runs fine in the browser but trying to test it with Jasmine I discovered what seems (to me) to be a bug or at least weird behaviour in Angular.
I'd expect to be able to set the view value on an input using
form.questions.answer1.$setViewValue();
but in my tests when I console log the form.questions object I get this:
form.questions.answer{{ question.questionId }}
i.e. The index of the object hasn't been parsed (although the html is output correctly).
Is there any other way of triggering the ng-change event? I have tried setting the value of the input using jQuery (inside my test) but although it successfully changes the value it doesn't fire off the ng-change event.
plunker (check the contents of your console to see what I mean.).
My code:
app.directive('repeatedInputs', function(){
var template ='<div ng-form name="questions">'+
'<div ng-repeat="(key, question) in questions" >' +
'<span id="question{{ question.questionId }}">{{ question.questionText }}</span>'+
'<span><input type="text" name="answer{{ question.questionId }}"' +
' id="answer{{question.questionId}}"' +
' ng-model="question.answer" ng-change="change()"/></span>' +
'</div>' +
'</div>';
return {
template: template,
scope: {
answers: '=',
singleAnswer: '='
},
/**
* Links the directive to the view.
*
* @param {object} scope
* Reference to the directive scope.
*
* @param {object} elm
* Reference to the directive element.
*/
link: function (scope, element) {
scope.questions = [
{
questionId: '1',
questionText: 'What is your name?',
answer: null
},
{
questionId: '2',
questionText: 'What is your quest?',
answer: null
},
{
questionId: '3',
questionText: 'What is your favourite colour?',
answer: null
}
];
scope.change = function () {
for (var i in scope.questions) {
scope.answers[i] = scope.questions[i].answer;
}
};
}
};
});
Here is my spec file:
describe('repeating inputs directive', function () {
var element, scope, $compile;
beforeEach(function(){
module('plunker');
inject(function ($rootScope, _$compile_) {
scope = $rootScope.$new();
scope.theAnswers = [];
scope.singleAnswer = null;
element = angular.element(
'<form name="form">'
+'<div repeated-inputs answers="theAnswers" single-answer="singleAnswer">'
+'</div></form>'
);
$compile = _$compile_;
$compile(element)(scope);
scope.$apply();
})
});
it('should store the input from the answers in the parent scope',
function () {
// I want to do this
//scope.form.questions.answer1.$setViewValue('Ben');
// but inside the object, the answers name field is not being parsed
// I am expecting the path to the answer to look like this:
// scope.form.questions.answer1
// instead it looks like this:
// scope.form.questions.answer{{ question.questionId }}
console.log(scope.form.questions);
expect(scope.theAnswers[0]).toEqual('Ben');
});
});