From 6d10324a90f16eccd759ac21919c5390c803f85e Mon Sep 17 00:00:00 2001 From: Carlos Purificacao Date: Thu, 7 Apr 2016 15:20:41 -0300 Subject: [PATCH] People block refactoring. Created component-test-helper --- src/app/layout/blocks/members-block/members-block.component.spec.ts | 43 +++++++++++++++++-------------------------- src/app/layout/blocks/people-block/people-block.component.spec.ts | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------- src/app/layout/blocks/people-block/people-block.component.ts | 2 ++ src/app/layout/blocks/people-block/people-block.html | 2 +- src/app/profile/data/profile-data.component.spec.ts | 2 +- src/spec/component-test-helper.ts | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/spec/mocks.ts | 7 +++++++ 7 files changed, 155 insertions(+), 65 deletions(-) create mode 100644 src/spec/component-test-helper.ts diff --git a/src/app/layout/blocks/members-block/members-block.component.spec.ts b/src/app/layout/blocks/members-block/members-block.component.spec.ts index 4bab067..f6ed115 100644 --- a/src/app/layout/blocks/members-block/members-block.component.spec.ts +++ b/src/app/layout/blocks/members-block/members-block.component.spec.ts @@ -1,7 +1,7 @@ import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; import {Provider, Input, provide, Component} from 'ng-forward'; - import {MembersBlockComponent} from './members-block.component'; +import {ComponentTestHelper, createClass} from './../../../../spec/component-test-helper'; const htmlTemplate: string = ''; @@ -10,13 +10,9 @@ const tcb = new TestComponentBuilder(); describe("Components", () => { describe("Members Block Component", () => { - beforeEach(angular.mock.module("templates")); + let helper: ComponentTestHelper; - let state = jasmine.createSpyObj("state", ["go"]); let providers = [ - new Provider('truncateFilter', { useValue: () => { } }), - new Provider('stripTagsFilter', { useValue: () => { } }), - new Provider('$state', { useValue: state }), new Provider('ProfileService', { useValue: { getProfileMembers: (profileId: number, filters: any): any => { @@ -25,28 +21,23 @@ describe("Components", () => { } }), ]; - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [MembersBlockComponent], providers: providers }) - class BlockContainerComponent { - block = { type: 'Block', settings: {} }; - owner = { name: 'profile-name' }; - constructor() { - } - } - - it("get members of the block owner", done => { - tcb.createAsync(BlockContainerComponent).then(fixture => { - let block: MembersBlockComponent = fixture.debugElement.componentViewChildren[0].componentInstance; - expect(block.members).toEqual([{ identifier: "person1" }]); - done(); - }); + + beforeEach(angular.mock.module("templates")); + + beforeEach( (done) => { + // Custom properties for the component + let properties = { owner: { id: 1 } }; + // Create the component bed for the test. + let cls = createClass(htmlTemplate, [MembersBlockComponent], providers, properties); + helper = new ComponentTestHelper(cls, done); + }); + + it("get members of the block owner", () => { + expect(helper.component.members[0].identifier).toEqual("person1"); }); - it("render the profile image for each member", done => { - tcb.createAsync(BlockContainerComponent).then(fixture => { - fixture.debugElement.getLocal("$rootScope").$apply(); - expect(fixture.debugElement.queryAll("noosfero-profile-image").length).toEqual(1); - done(); - }); + it("render the profile image for each member", () => { + expect(helper.all("noosfero-profile-image").length).toEqual(1); }); }); diff --git a/src/app/layout/blocks/people-block/people-block.component.spec.ts b/src/app/layout/blocks/people-block/people-block.component.spec.ts index 0589614..6b9ecee 100644 --- a/src/app/layout/blocks/people-block/people-block.component.spec.ts +++ b/src/app/layout/blocks/people-block/people-block.component.spec.ts @@ -1,53 +1,69 @@ import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; -import {Provider, Input, provide, Component} from 'ng-forward'; - +import {Provider, provide} from 'ng-forward'; +import {ComponentTestHelper, createClass} from './../../../../spec/component-test-helper'; +import {providers} from 'ng-forward/cjs/testing/providers'; import {PeopleBlockComponent} from './people-block.component'; -const htmlTemplate: string = ''; +import { INgForwardJQuery } from "ng-forward/cjs/util/jqlite-extensions"; -const tcb = new TestComponentBuilder(); +const htmlTemplate: string = ''; describe("Components", () => { - describe("People Block Component", () => { - beforeEach(angular.mock.module("templates")); - - let state = jasmine.createSpyObj("state", ["go"]); - let providers = [ - new Provider('truncateFilter', { useValue: () => { } }), - new Provider('stripTagsFilter', { useValue: () => { } }), - new Provider('$state', { useValue: state }), - new Provider('EnvironmentService', { - useValue: { + describe("People Block Component", () => { + let serviceMock = { getEnvironmentPeople: (filters: any): any => { return Promise.resolve([{ identifier: "person1" }]); } - } - }), - ]; - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [PeopleBlockComponent], providers: providers }) - class BlockContainerComponent { - block = { type: 'Block', settings: {} }; - owner = { name: 'profile-name' }; - constructor() { - } - } - - it("get people of the block owner", done => { - tcb.createAsync(BlockContainerComponent).then(fixture => { - let block: PeopleBlockComponent = fixture.debugElement.componentViewChildren[0].componentInstance; - expect(block.people).toEqual([{ identifier: "person1" }]); - done(); - }); + }; + let providers = [new Provider('EnvironmentService', { useValue: serviceMock })]; + + let helper: ComponentTestHelper; + + beforeEach( angular.mock.module("templates") ); + + /** + * The beforeEach procedure will initialize the helper and parse + * the component according to the given providers. Unfortunetly, in + * this mode, the providers and properties given to the construtor + * can't be overriden. + */ + beforeEach( (done) => { + // Create the component bed for the test. Optionally, this could be done + // in each test if one needs customization of these parameters per test + let cls = createClass(htmlTemplate, [PeopleBlockComponent], providers, {}); + helper = new ComponentTestHelper(cls, done); + }); + + /** + * By default the helper will have the component, with all properties + * ready to be used. Here the mock provider 'EnvironmentService' will + * return the given array with one person. + */ + it("get block with one people", () => { + expect(helper.component.people[0].identifier).toEqual("person1"); }); - it("render the profile image for each person", done => { - tcb.createAsync(BlockContainerComponent).then(fixture => { - fixture.debugElement.getLocal("$rootScope").$apply(); - expect(fixture.debugElement.queryAll("noosfero-profile-image").length).toEqual(1); - done(); - }); + /** + * There are helper functions to access the JQuery DOM like this. + */ + it("render the profile image for each person", () => { + expect(helper.all("noosfero-profile-image").length).toEqual(1); }); + /** + * The main debugElement element is also available + */ + it("render the main noosfero people block", () => { + expect(helper.debugElement.children().length).toEqual(1, "The people-block should have a div children"); + }); + + /** + * Just another example of a JQuery DOM helper function + */ + it("render the noosfero people block div", () => { + let div = helper.findChildren("noosfero-people-block", "div"); + expect(div.className).toBe('people-block', "The class should be people-block"); + }); }); }); \ No newline at end of file diff --git a/src/app/layout/blocks/people-block/people-block.component.ts b/src/app/layout/blocks/people-block/people-block.component.ts index af2cfc1..43d4c50 100644 --- a/src/app/layout/blocks/people-block/people-block.component.ts +++ b/src/app/layout/blocks/people-block/people-block.component.ts @@ -10,6 +10,7 @@ export class PeopleBlockComponent { @Input() block: noosfero.Block; @Input() owner: noosfero.Environment; + private type: string = "people"; people: noosfero.Person[] = []; @@ -21,4 +22,5 @@ export class PeopleBlockComponent { this.people = people; }); } + } diff --git a/src/app/layout/blocks/people-block/people-block.html b/src/app/layout/blocks/people-block/people-block.html index d7c89cf..7f72d92 100644 --- a/src/app/layout/blocks/people-block/people-block.html +++ b/src/app/layout/blocks/people-block/people-block.html @@ -1,4 +1,4 @@ -
+
diff --git a/src/app/profile/data/profile-data.component.spec.ts b/src/app/profile/data/profile-data.component.spec.ts index 9abb416..38deeee 100644 --- a/src/app/profile/data/profile-data.component.spec.ts +++ b/src/app/profile/data/profile-data.component.spec.ts @@ -52,7 +52,7 @@ describe('Profile data component', () => { profileMock.additional_data = { 'Address': 'Street A, Number 102' }; - + buildComponent().then((fixture: ComponentFixture) => { let profileData: ProfileDataComponent = fixture.debugElement.componentViewChildren[0].componentInstance; profileData.profile = profileMock; diff --git a/src/spec/component-test-helper.ts b/src/spec/component-test-helper.ts new file mode 100644 index 0000000..deb9b5a --- /dev/null +++ b/src/spec/component-test-helper.ts @@ -0,0 +1,74 @@ +import { Component } from "ng-forward"; +import { TestComponentBuilder } from 'ng-forward/cjs/testing/test-component-builder'; +import { INgForwardJQuery } from "ng-forward/cjs/util/jqlite-extensions"; +import { ComponentFixture } from 'ng-forward/cjs/testing/test-component-builder'; + +export function createClass(template: any, directives: any, providers: any, properties: any): any { + @Component({ selector: 'component-test-helper-container', template, directives, providers }) + class Test { + constructor() { + Object.keys(properties).forEach((key: any) => { + (this)[key] = properties[key]; + }); + } + } + return Test; +} + +export function rebuild(factory: any, done: any): any { + return new ComponentTestHelper(factory, done); +} + +/** + * Helper class for creating tests. It encapsulates the TestComponentBuilder initialization, + * allowing the test to be DRY. To use, one must declare a beforeEach function in the + * test, and inside construct this object like: + * + * let helper = let helper : ComponentTestHelper; + * beforeEach( (done) => { + * helper = new ComponentTestHelper(cls, tcb); + * } + */ +export class ComponentTestHelper { + + mockComponent: any; + tcb: TestComponentBuilder; + component: any; + debugElement: INgForwardJQuery; + + constructor(mockComponent: any, done: any) { + this.mockComponent = mockComponent; + this.tcb = new TestComponentBuilder(); + this.init(done); + } + + init(done: any): any { + let promisse = this.tcb.createAsync(this.mockComponent) as any; + return promisse.then((fixture: any) => { + // Fire all angular events and parsing + fixture.detectChanges(); + // The main debug element + this.debugElement = fixture.debugElement; + this.component = this.debugElement.componentViewChildren[0].componentInstance; + }).then(() => { + // Force the resolution of components and sync + done(); + }); + } + + /** + * Return all elements matching the given selector + */ + all(selector: string): INgForwardJQuery[] { + return this.debugElement.queryAll(selector); + } + + find(selector: string): INgForwardJQuery { + return this.all(selector)[0]; + } + + findChildren(parentSelector: string, childSelector: string) { + let parentComponent = this.find(parentSelector); + return parentComponent.find(childSelector)[0]; + } +} \ No newline at end of file diff --git a/src/spec/mocks.ts b/src/spec/mocks.ts index 280645d..21a9497 100644 --- a/src/spec/mocks.ts +++ b/src/spec/mocks.ts @@ -72,6 +72,13 @@ export var mocks = { }; } }, + environmentService: { + getEnvironmentPeople: (params: any) => { + return mocks.promiseResultTemplate({ + people: {} + }); + } + }, profileService: { getCurrentProfile: (profile: any) => { return mocks.promiseResultTemplate({ -- libgit2 0.21.2