To solve the test I had to create my directive.
First of all I created the module that all my directives would have to use.
var directives = angular.module('backlogsReader.directives', []);
And then I wrote my roadmap-preview Directive.
var roadmapPreview = angular.module('backlogsReader.directives'); roadmapPreview .directive('roadmapPreview', function () { return { restrict: 'E', replace: true, scope: { roadmap: '=roadmap' }, templateUrl: 'relativeToTheApplicationRootUrl/roadmapPreview.html' }; });
I decided that this directive should have to work only as an html Element
... return { restrict: 'E', replace: true, scope: { roadmap: '=roadmap' }, templateUrl: 'relativeToTheApplicationRootUrl/roadmapPreview.html' }; ...
and that my custom tag <roadmap-preview> should have had to be removed with the content of my template.
... return { restrict: 'E', replace: true, scope: { roadmap: '=roadmap' }, templateUrl: 'relativeToTheApplicationRootUrl/roadmapPreview.html' }; ...
I defined that the scope (a concept similar to MVC ViewModel in this case) of the directive should have to be passed through an attribute named “roadmap”.
... return { restrict: 'E', replace: true, scope: { roadmap: '=roadmap' }, templateUrl: 'relativeToTheApplicationRootUrl/roadmapPreview.html' }; ...
At the end I set the url of the html template of this directive.
... return { restrict: 'E', replace: true, scope: { roadmap: '=roadmap' }, templateUrl: 'relativeToTheApplicationRootUrl/roadmapPreview.html' }; ...
Inside my template html I could refer to the scope using the word “roadmap” that I defined above and I could access it and its properties using a “double curly brackets” notation.
<div class="roadmap-preview"> <div class="where-are-you pos-{{roadmap.whereAreYou.month}}-{{roadmap.whereAreYou.weekOfTheMonth}}" tooltip="where are you!"></div> <release-detail release="release" ng-repeat="release in roadmap.releases"></release-detail> <div class="street"></div> <div class="roadmap-q q-1">Q1</div> <div class="roadmap-q q-2">Q2</div> <div class="roadmap-q q-3">Q3</div> <div class="roadmap-q q-4">Q4</div> </div>
With this implementation of my directive, all test passed.
Few words about <release-detail>
:
At that time I didn’t need to know exactly the content of a release, I only needed to have a release-detail for every release in my roadmap so it was enough to iterate through all my releases and to pass the release content to my release-detail directive.
... <release-detail release="release" ng-repeat="release in roadmap.releases"></release-detail> ...
Obviously even if my test passed, my task wasn’t solved, so I wrote the test for the release-detail.
Exactly like I did for the roadmap-preview I just listed what I wanted
describe('', function () { describe('When the release is compiled', function () { it('it should have a name', function () { }); it('it should have a flag', function () { }); it('it should have the position in the timeline', function () { }); }); });
Then I setup the test defining a mock of data and I wrote my expectations.
describe('', function () { describe('When the release is compiled', function () { var scope; var el; beforeEach(function() { scope = rootScope.$new(); scope.stub = { estimated: { month: '2', weekOfTheMonth: '4' }, name: "myname" }; el = compile('<release-detail release="stub"></release-detail>')(scope); scope.$digest(); }); it('it should have a name', function () { var release = el; expect(release.attr('title')).toContain('myname'); }); it('it should have a flag', function () { var release = el; expect(release.find('.flag').length).toBe(1); }); it('it should have the position in the timeline', function () { var release = el; expect(release.hasClass('pos-2-4')).toBeTruthy(); }); }); });
To make things work, I preloaded in the first describe() my template in the same way I did for the roadmap-preview.
describe('', function () { var compile; var rootScope; beforeEach(module('backlogsReader.directives')); beforeEach(inject(function ($compile, $rootScope, $templateCache) { compile = $compile; rootScope = $rootScope; var roadmapPreviewTemplate = null; $.ajax({ type: 'GET', async: false, url: 'relativeToTestUrl/releaseDetail.html', success: function (html) { roadmapPreviewTemplate = html; } }); $templateCache.put("relativeToTheApplicationRootUrl/releaseDetail.html", roadmapPreviewTemplate); })); ... });
Here the file complete:
describe('', function () { var compile; var rootScope; beforeEach(module('backlogsReader.directives')); beforeEach(inject(function ($compile, $rootScope, $templateCache) { compile = $compile; rootScope = $rootScope; var roadmapPreviewTemplate = null; $.ajax({ type: 'GET', async: false, url: 'relativeToTestUrl/releaseDetail.html', success: function (html) { roadmapPreviewTemplate = html; } }); $templateCache.put("relativeToTheApplicationRootUrl/releaseDetail.html", roadmapPreviewTemplate); })); describe('When the release is compiled', function () { var scope; var el; beforeEach(function() { scope = rootScope.$new(); scope.stub = { estimated: { month: '2', weekOfTheMonth: '4' }, name: "myname" }; el = compile('<release-detail release="stub"></release-detail>')(scope); scope.$digest(); }); it('it should have a name', function () { var release = el; expect(release.attr('title')).toContain('myname'); }); it('it should have a flag', function () { var release = el; expect(release.find('.flag').length).toBe(1); }); it('it should have the position in the timeline', function () { var release = el; expect(release.hasClass('pos-2-4')).toBeTruthy(); }); }); });
Obviously all my test failed
I started creating my directive
var releaseDetail = angular.module('backlogsReader.directives'); releaseDetail .directive('releaseDetail', function () { return { restrict: 'E', replace: true, scope: { release: '=release' }, templateUrl: 'relativeToTheApplicationRootUrl/releaseDetail.html' }; });
The logic was the same I used creating roadmap-preview.
And the html template wasn’t more complicated
<div class="release pos-{{release.estimated.month}}-{{release.estimated.weekOfTheMonth}}" title="{{release.name}}"> <div class="flag"></div> </div>
I run my test and they worked.
So that was the situation at the end of my session:
I put in place my directive and after few stylesheet I finally had:
Pingback: Backlog Aggregator: Roadmap Feedback (part one) | Agile. Angular/Js. Asp.NET & TDD