Backlog Aggregator: Roadmap preview (part two)

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'
		};
	});

In general I prefer to work using one file for each Object, exactly the same way I work in C#

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

tests-release-detail-first-run

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:

tests-release-detail-first-solved

tests-roadmap-preview-first-solved

I put in place my directive and after few stylesheet I finally had:

roadmap-preview

One thought on “Backlog Aggregator: Roadmap preview (part two)

  1. Pingback: Backlog Aggregator: Roadmap Feedback (part one) | Agile. Angular/Js. Asp.NET & TDD

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s