Commit a9aa5894a1fc1bb78101e52eb04152a7c24f8f5b

Authored by Ábner Oliveira
2 parents 23d29ed1 90add01a
Exists in master and in 1 other branch dev-fixes

merge with master

@@ -33,7 +33,8 @@ @@ -33,7 +33,8 @@
33 "angular-translate-handler-log": "^2.10.0", 33 "angular-translate-handler-log": "^2.10.0",
34 "angular-dynamic-locale": "^0.1.30", 34 "angular-dynamic-locale": "^0.1.30",
35 "angular-i18n": "^1.5.0", 35 "angular-i18n": "^1.5.0",
36 - "angular-load": "^0.4.1" 36 + "angular-load": "^0.4.1",
  37 + "angular-translate-interpolation-messageformat": "^2.10.0"
37 }, 38 },
38 "devDependencies": { 39 "devDependencies": {
39 "angular-mocks": "~1.5.0" 40 "angular-mocks": "~1.5.0"
@@ -48,6 +48,7 @@ gulp.task('html', ['inject', 'partials'], function () { @@ -48,6 +48,7 @@ gulp.task('html', ['inject', 'partials'], function () {
48 .pipe($.replace('/languages/', noosferoThemePrefix + 'languages/')) 48 .pipe($.replace('/languages/', noosferoThemePrefix + 'languages/'))
49 .pipe($.replace('bower_components/angular-i18n/', noosferoThemePrefix + 'locale/angular-i18n/')) 49 .pipe($.replace('bower_components/angular-i18n/', noosferoThemePrefix + 'locale/angular-i18n/'))
50 .pipe($.replace('bower_components/moment/', noosferoThemePrefix + 'locale/moment/')) 50 .pipe($.replace('bower_components/moment/', noosferoThemePrefix + 'locale/moment/'))
  51 + .pipe($.replace('bower_components/messageformat/', noosferoThemePrefix + 'locale/messageformat/'))
51 .pipe($.sourcemaps.init()) 52 .pipe($.sourcemaps.init())
52 .pipe($.ngAnnotate()) 53 .pipe($.ngAnnotate())
53 .pipe($.uglify({ preserveComments: $.uglifySaveLicense })).on('error', conf.errorHandler('Uglify')) 54 .pipe($.uglify({ preserveComments: $.uglifySaveLicense })).on('error', conf.errorHandler('Uglify'))
@@ -88,6 +89,7 @@ gulp.task('locale', function () { @@ -88,6 +89,7 @@ gulp.task('locale', function () {
88 return gulp.src([ 89 return gulp.src([
89 path.join("bower_components/angular-i18n", '*.js'), 90 path.join("bower_components/angular-i18n", '*.js'),
90 path.join("bower_components/moment/locale", '*.js'), 91 path.join("bower_components/moment/locale", '*.js'),
  92 + path.join("bower_components/messageformat/locale", '*.js'),
91 ], {base: 'bower_components/'}) 93 ], {base: 'bower_components/'})
92 .pipe(gulp.dest(path.join(conf.paths.dist, '/locale/'))); 94 .pipe(gulp.dest(path.join(conf.paths.dist, '/locale/')));
93 }); 95 });
src/app/cms/cms.component.spec.ts
@@ -9,8 +9,9 @@ describe("Components", () => { @@ -9,8 +9,9 @@ describe("Components", () => {
9 let articleServiceMock: any; 9 let articleServiceMock: any;
10 let profileServiceMock: any; 10 let profileServiceMock: any;
11 let $state: any; 11 let $state: any;
12 - let sweetAlert: any;  
13 let profile = { id: 1 }; 12 let profile = { id: 1 };
  13 + let notification: any;
  14 +
14 15
15 beforeEach(inject((_$rootScope_: ng.IRootScopeService, _$q_: ng.IQService) => { 16 beforeEach(inject((_$rootScope_: ng.IRootScopeService, _$q_: ng.IQService) => {
16 $rootScope = _$rootScope_; 17 $rootScope = _$rootScope_;
@@ -19,7 +20,7 @@ describe("Components", () => { @@ -19,7 +20,7 @@ describe("Components", () => {
19 20
20 beforeEach(() => { 21 beforeEach(() => {
21 $state = jasmine.createSpyObj("$state", ["transitionTo"]); 22 $state = jasmine.createSpyObj("$state", ["transitionTo"]);
22 - sweetAlert = jasmine.createSpyObj("SweetAlert", ["swal"]); 23 + notification = jasmine.createSpyObj("notification", ["success"]);
23 profileServiceMock = jasmine.createSpyObj("profileServiceMock", ["getCurrentProfile"]); 24 profileServiceMock = jasmine.createSpyObj("profileServiceMock", ["getCurrentProfile"]);
24 articleServiceMock = jasmine.createSpyObj("articleServiceMock", ["create"]); 25 articleServiceMock = jasmine.createSpyObj("articleServiceMock", ["create"]);
25 26
@@ -34,7 +35,7 @@ describe("Components", () => { @@ -34,7 +35,7 @@ describe("Components", () => {
34 }); 35 });
35 36
36 it("create an article in the current profile when save", done => { 37 it("create an article in the current profile when save", done => {
37 - let component: Cms = new Cms(articleServiceMock, profileServiceMock, $state, sweetAlert); 38 + let component: Cms = new Cms(articleServiceMock, profileServiceMock, $state, notification);
38 component.save(); 39 component.save();
39 $rootScope.$apply(); 40 $rootScope.$apply();
40 expect(profileServiceMock.getCurrentProfile).toHaveBeenCalled(); 41 expect(profileServiceMock.getCurrentProfile).toHaveBeenCalled();
@@ -43,11 +44,11 @@ describe("Components", () => { @@ -43,11 +44,11 @@ describe("Components", () => {
43 }); 44 });
44 45
45 it("got to the new article page and display an alert when saving sucessfully", done => { 46 it("got to the new article page and display an alert when saving sucessfully", done => {
46 - let component: Cms = new Cms(articleServiceMock, profileServiceMock, $state, sweetAlert); 47 + let component: Cms = new Cms(articleServiceMock, profileServiceMock, $state, notification);
47 component.save(); 48 component.save();
48 $rootScope.$apply(); 49 $rootScope.$apply();
49 expect($state.transitionTo).toHaveBeenCalledWith("main.profile.page", { page: "path", profile: "profile" }); 50 expect($state.transitionTo).toHaveBeenCalledWith("main.profile.page", { page: "path", profile: "profile" });
50 - expect(sweetAlert.swal).toHaveBeenCalled(); 51 + expect(notification.success).toHaveBeenCalled();
51 done(); 52 done();
52 }); 53 });
53 54
src/app/cms/cms.component.ts
@@ -2,37 +2,33 @@ import {StateConfig, Component, Inject, provide} from 'ng-forward'; @@ -2,37 +2,33 @@ import {StateConfig, Component, Inject, provide} from 'ng-forward';
2 import {Profile} from "./../models/interfaces"; 2 import {Profile} from "./../models/interfaces";
3 import {ArticleService} from "../../lib/ng-noosfero-api/http/article.service"; 3 import {ArticleService} from "../../lib/ng-noosfero-api/http/article.service";
4 import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service"; 4 import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service";
  5 +import {Notification} from "../components/notification/notification.component";
5 6
6 @Component({ 7 @Component({
7 selector: 'cms', 8 selector: 'cms',
8 templateUrl: "app/cms/cms.html", 9 templateUrl: "app/cms/cms.html",
9 providers: [ 10 providers: [
10 provide('articleService', { useClass: ArticleService }), 11 provide('articleService', { useClass: ArticleService }),
11 - provide('profileService', { useClass: ProfileService }) 12 + provide('profileService', { useClass: ProfileService }),
  13 + provide('notification', { useClass: Notification })
12 ] 14 ]
13 }) 15 })
14 -@Inject(ArticleService, ProfileService, "$state", "SweetAlert") 16 +@Inject(ArticleService, ProfileService, "$state", Notification)
15 export class Cms { 17 export class Cms {
16 18
17 article: any = {}; 19 article: any = {};
18 20
19 constructor(private articleService: ArticleService, 21 constructor(private articleService: ArticleService,
20 private profileService: ProfileService, 22 private profileService: ProfileService,
21 - private $state: ng.ui.IStateService, private SweetAlert: any) { } 23 + private $state: ng.ui.IStateService,
  24 + private notification: Notification) { }
22 25
23 save() { 26 save() {
24 - this.profileService.getCurrentProfile().then((profile: Profile) => {  
25 - return this.articleService.create(this.article, <any>profile);  
26 - }).then((result: noosfero.RestResult<noosfero.Article>) => {  
27 - console.log('RESULT', result);  
28 - let resultData: noosfero.Article = <noosfero.Article>result.data;  
29 - this.$state.transitionTo('main.profile.page', { page: resultData.path, profile: resultData.profile.identifier });  
30 - this.SweetAlert.swal({  
31 - title: "Good job!",  
32 - text: "Article saved!",  
33 - type: "success",  
34 - timer: 1000  
35 - }); 27 + this.profileService.getCurrentProfile().then((profile: noosfero.Profile) => {
  28 + return this.articleService.create(this.article, profile);
  29 + }).then((response: restangular.IResponse) => {
  30 + this.$state.transitionTo('main.profile.page', { page: response.data.article.path, profile: response.data.article.profile.identifier });
  31 + this.notification.success("Good job!", "Article saved!");
36 }); 32 });
37 } 33 }
38 34
src/app/components/language-selector/language-selector.component.spec.ts
1 -import {TestComponentBuilder, ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder';  
2 -import {Pipe, Input, provide, Component} from 'ng-forward'; 1 +import {ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder';
  2 +import {provide} from 'ng-forward';
3 3
4 import {LanguageSelector} from './language-selector.component'; 4 import {LanguageSelector} from './language-selector.component';
5 5
6 import * as helpers from "../../../spec/helpers"; 6 import * as helpers from "../../../spec/helpers";
7 7
8 -const tcb = new TestComponentBuilder();  
9 -  
10 -const htmlTemplate: string = '<language-selector></language-selector>';  
11 -  
12 describe("Components", () => { 8 describe("Components", () => {
13 9
14 describe("Language Selector Component", () => { 10 describe("Language Selector Component", () => {
15 11
16 beforeEach(angular.mock.module("templates")); 12 beforeEach(angular.mock.module("templates"));
17 13
18 - @Component({  
19 - selector: 'test-container-component',  
20 - template: htmlTemplate,  
21 - directives: [LanguageSelector],  
22 - providers: [  
23 - provide('$translate', {  
24 - useValue: helpers.mocks.$translate  
25 - }),  
26 - provide('tmhDynamicLocale', {  
27 - useValue: helpers.mocks.tmhDynamicLocale  
28 - }),  
29 - provide('amMoment', {  
30 - useValue: helpers.mocks.amMoment  
31 - }),  
32 - provide('angularLoad', {  
33 - useValue: helpers.mocks.angularLoad  
34 - })  
35 - ].concat(helpers.provideFilters("translateFilter"))  
36 - })  
37 - class BlockContainerComponent { }  
38 -  
39 - it("set available languages when change language", () => { 14 + let buildComponent = (): Promise<ComponentFixture> => {
  15 + return helpers.quickCreateComponent({
  16 + template: "<language-selector></language-selector>",
  17 + directives: [LanguageSelector],
  18 + providers: [
  19 + provide('$translate', {
  20 + useValue: helpers.mocks.$translate
  21 + }),
  22 + provide('tmhDynamicLocale', {
  23 + useValue: helpers.mocks.tmhDynamicLocale
  24 + }),
  25 + provide('amMoment', {
  26 + useValue: helpers.mocks.amMoment
  27 + }),
  28 + provide('angularLoad', {
  29 + useValue: helpers.mocks.angularLoad
  30 + })
  31 + ].concat(helpers.provideFilters("translateFilter"))
  32 + });
  33 + }
  34 +
  35 + it("set available languages when change language", (done) => {
40 let component: LanguageSelector = new LanguageSelector( 36 let component: LanguageSelector = new LanguageSelector(
41 <any>helpers.mocks.$translate, 37 <any>helpers.mocks.$translate,
42 <any>helpers.mocks.tmhDynamicLocale, 38 <any>helpers.mocks.tmhDynamicLocale,
@@ -47,11 +43,35 @@ describe(&quot;Components&quot;, () =&gt; { @@ -47,11 +43,35 @@ describe(&quot;Components&quot;, () =&gt; {
47 expect(component.availableLanguages).toBeNull(); 43 expect(component.availableLanguages).toBeNull();
48 component.changeLanguage('en'); 44 component.changeLanguage('en');
49 expect(component.availableLanguages).toBeDefined(); 45 expect(component.availableLanguages).toBeDefined();
  46 + done();
50 }); 47 });
51 48
52 - it("display language options", () => {  
53 - helpers.createComponentFromClass(BlockContainerComponent).then(fixture => { 49 + it("display language options", (done) => {
  50 + buildComponent().then(fixture => {
54 expect(fixture.debugElement.queryAll('li.language').length).toEqual(2); 51 expect(fixture.debugElement.queryAll('li.language').length).toEqual(2);
  52 + done();
  53 + });
  54 + });
  55 +
  56 + it("change the language", (done) => {
  57 + buildComponent().then(fixture => {
  58 + let component: LanguageSelector = fixture.debugElement.componentViewChildren[0].componentInstance;
  59 + let $q = fixture.debugElement.getLocal("$q");
  60 + let loadScripPromise = $q.defer();
  61 + loadScripPromise.resolve();
  62 + component["angularLoad"].loadScript = jasmine.createSpy("loadScript").and.returnValue(loadScripPromise.promise);
  63 + component["tmhDynamicLocale"].set = jasmine.createSpy("set");
  64 + component["tmhDynamicLocale"].get = jasmine.createSpy("get").and.returnValue("en");
  65 + component["$translate"].use = jasmine.createSpy("use");
  66 +
  67 + component.changeLanguage('pt');
  68 + fixture.debugElement.getLocal("$rootScope").$digest();
  69 +
  70 + expect(component["angularLoad"].loadScript).toHaveBeenCalledWith("/bower_components/moment/locale/pt.js");
  71 + expect(component["angularLoad"].loadScript).toHaveBeenCalledWith("/bower_components/messageformat/locale/pt.js");
  72 + expect(component["tmhDynamicLocale"].set).toHaveBeenCalledWith("pt");
  73 + expect(component["$translate"].use).toHaveBeenCalledWith("pt");
  74 + done();
55 }); 75 });
56 }); 76 });
57 77
src/app/components/language-selector/language-selector.component.ts
@@ -14,6 +14,7 @@ export class LanguageSelector { @@ -14,6 +14,7 @@ export class LanguageSelector {
14 private amMoment: any, 14 private amMoment: any,
15 private angularLoad: any) { 15 private angularLoad: any) {
16 16
  17 + this.configAvailableLanguages();
17 this.changeLanguage(tmhDynamicLocale.get() || $translate.use()); 18 this.changeLanguage(tmhDynamicLocale.get() || $translate.use());
18 } 19 }
19 20
@@ -24,14 +25,20 @@ export class LanguageSelector { @@ -24,14 +25,20 @@ export class LanguageSelector {
24 changeLanguage(language: string) { 25 changeLanguage(language: string) {
25 this.changeMomentLocale(language); 26 this.changeMomentLocale(language);
26 this.tmhDynamicLocale.set(language); 27 this.tmhDynamicLocale.set(language);
27 - this.$translate.use(language).then((lang) => {  
28 - this.availableLanguages = {  
29 - "en": this.$translate.instant("language.en"),  
30 - "pt": this.$translate.instant("language.pt")  
31 - }; 28 + this.angularLoad.loadScript(`/bower_components/messageformat/locale/${language}.js`).then(() => {
  29 + return this.$translate.use(language);
  30 + }).then(() => {
  31 + this.configAvailableLanguages();
32 }); 32 });
33 } 33 }
34 34
  35 + private configAvailableLanguages() {
  36 + this.availableLanguages = {
  37 + "en": this.$translate.instant("language.en"),
  38 + "pt": this.$translate.instant("language.pt")
  39 + };
  40 + }
  41 +
35 private changeMomentLocale(language: string) { 42 private changeMomentLocale(language: string) {
36 let localePromise = Promise.resolve(); 43 let localePromise = Promise.resolve();
37 if (language != "en") { 44 if (language != "en") {
src/app/components/noosfero-activities/activity/new_friendship.html
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <timeline-heading> 5 <timeline-heading>
6 <h4 class="timeline-title"> 6 <h4 class="timeline-title">
7 <a ui-sref="main.profile.info({profile: ctrl.activity.user.identifier})"><strong ng-bind="ctrl.activity.user.name"></strong></a> 7 <a ui-sref="main.profile.info({profile: ctrl.activity.user.identifier})"><strong ng-bind="ctrl.activity.user.name"></strong></a>
8 - <span> {{"activities.new_friendship.description" | translate:{friends: ctrl.activity.params.friend_name.length} }} </span> 8 + <span> {{"activities.new_friendship.description" | translate:{friends: ctrl.activity.params.friend_name.length}:"messageformat" }} </span>
9 <span class="comma-separated"> 9 <span class="comma-separated">
10 <a class="separated-item" ui-sref="main.profile.info({profile: ctrl.activity.params.friend_url[$index].profile})" ng-repeat="friend in ctrl.activity.params.friend_name"> 10 <a class="separated-item" ui-sref="main.profile.info({profile: ctrl.activity.params.friend_url[$index].profile})" ng-repeat="friend in ctrl.activity.params.friend_name">
11 <strong ng-bind="friend"></strong> 11 <strong ng-bind="friend"></strong>
src/app/components/notification/notification.component.spec.ts 0 → 100644
@@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
  1 +import {TestComponentBuilder, ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder';
  2 +import {Pipe, Input, provide, Component} from 'ng-forward';
  3 +
  4 +import * as helpers from "../../../spec/helpers";
  5 +
  6 +import {Notification} from "./notification.component";
  7 +
  8 +const tcb = new TestComponentBuilder();
  9 +
  10 +describe("Components", () => {
  11 +
  12 + describe("Profile Image Component", () => {
  13 +
  14 + beforeEach(angular.mock.module("templates"));
  15 +
  16 + it("use the default message when call notification component without a specific message", done => {
  17 + let sweetAlert = jasmine.createSpyObj("sweetAlert", ["swal"]);
  18 + sweetAlert.swal = jasmine.createSpy("swal");
  19 +
  20 + let component: Notification = new Notification(<any>helpers.mocks.$log, <any>sweetAlert, <any>helpers.mocks.$translate);
  21 + component.httpError(500, {});
  22 + expect(sweetAlert.swal).toHaveBeenCalledWith(jasmine.objectContaining({
  23 + text: Notification.DEFAULT_HTTP_ERROR_MESSAGE,
  24 + type: "error"
  25 + }));
  26 + done();
  27 + });
  28 +
  29 + it("use the default message when call notification component without error data", done => {
  30 + let sweetAlert = jasmine.createSpyObj("sweetAlert", ["swal"]);
  31 + sweetAlert.swal = jasmine.createSpy("swal");
  32 +
  33 + let component: Notification = new Notification(<any>helpers.mocks.$log, <any>sweetAlert, <any>helpers.mocks.$translate);
  34 + component.httpError(500, null);
  35 + expect(sweetAlert.swal).toHaveBeenCalledWith(jasmine.objectContaining({
  36 + text: Notification.DEFAULT_HTTP_ERROR_MESSAGE,
  37 + type: "error"
  38 + }));
  39 + done();
  40 + });
  41 +
  42 + it("display a success message when call notification success", done => {
  43 + let sweetAlert = jasmine.createSpyObj("sweetAlert", ["swal"]);
  44 + sweetAlert.swal = jasmine.createSpy("swal");
  45 +
  46 + let component: Notification = new Notification(<any>helpers.mocks.$log, <any>sweetAlert, <any>helpers.mocks.$translate);
  47 + component.success("title", "message", 1000);
  48 + expect(sweetAlert.swal).toHaveBeenCalledWith(jasmine.objectContaining({
  49 + type: "success"
  50 + }));
  51 + done();
  52 + });
  53 +
  54 + it("set the default timer in success messages", done => {
  55 + let sweetAlert = jasmine.createSpyObj("sweetAlert", ["swal"]);
  56 + sweetAlert.swal = jasmine.createSpy("swal");
  57 +
  58 + let component: Notification = new Notification(<any>helpers.mocks.$log, <any>sweetAlert, <any>helpers.mocks.$translate);
  59 + component.success("title", "message");
  60 + expect(sweetAlert.swal).toHaveBeenCalledWith(jasmine.objectContaining({
  61 + type: "success",
  62 + timer: Notification.DEFAULT_SUCCESS_TIMER
  63 + }));
  64 + done();
  65 + });
  66 + });
  67 +});
src/app/components/notification/notification.component.ts 0 → 100644
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +import {Injectable, Inject} from "ng-forward";
  2 +
  3 +@Injectable()
  4 +@Inject("$log", "SweetAlert", "$translate")
  5 +export class Notification {
  6 +
  7 + constructor(
  8 + private $log: ng.ILogService,
  9 + private SweetAlert: any,
  10 + private $translate: angular.translate.ITranslateService
  11 + ) { }
  12 +
  13 + public static DEFAULT_HTTP_ERROR_TITLE = "notification.http-error.default.title";
  14 + public static DEFAULT_HTTP_ERROR_MESSAGE = "notification.http-error.default.message";
  15 + public static DEFAULT_SUCCESS_TIMER = 1000;
  16 +
  17 + httpError(status: number, data: any): boolean {
  18 + this.$log.debug(status, data);
  19 +
  20 + let message = (data || {}).message || Notification.DEFAULT_HTTP_ERROR_MESSAGE;
  21 + this.SweetAlert.swal({
  22 + title: this.$translate.instant(Notification.DEFAULT_HTTP_ERROR_TITLE),
  23 + text: this.$translate.instant(message),
  24 + type: "error"
  25 + });
  26 + return true; // return true to indicate that the error was already handled
  27 + }
  28 +
  29 + success(title: string, text: string, timer: number = Notification.DEFAULT_SUCCESS_TIMER) {
  30 + this.SweetAlert.swal({
  31 + title: title,
  32 + text: text,
  33 + type: "success",
  34 + timer: timer
  35 + });
  36 + }
  37 +
  38 +}
src/app/content-viewer/content-viewer-actions.component.spec.ts 0 → 100644
@@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
  1 +import {providers} from 'ng-forward/cjs/testing/providers';
  2 +
  3 +import {Input, Component, provide} from 'ng-forward';
  4 +
  5 +import * as helpers from "../../spec/helpers";
  6 +
  7 +import {ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder';
  8 +import {ContentViewerActions} from './content-viewer-actions.component';
  9 +
  10 +// this htmlTemplate will be re-used between the container components in this spec file
  11 +const htmlTemplate: string = '<content-viewer-actions [article]="ctrl.article" [profile]="ctrl.profile"></content-viewer-actions>';
  12 +
  13 +describe('Content Viewer Actions Component', () => {
  14 +
  15 + beforeEach(() => {
  16 +
  17 + angular.mock.module("templates");
  18 +
  19 + providers((provide: any) => {
  20 + return <any>[
  21 + provide('ProfileService', {
  22 + useValue: helpers.mocks.profileService
  23 + })
  24 + ];
  25 + });
  26 + });
  27 +
  28 + let buildComponent = (): Promise<ComponentFixture> => {
  29 + return helpers.quickCreateComponent({
  30 + providers: [
  31 + helpers.provideEmptyObjects('Restangular'),
  32 + helpers.provideFilters('translateFilter')
  33 + ],
  34 + directives: [ContentViewerActions],
  35 + template: htmlTemplate
  36 + });
  37 + };
  38 +
  39 + it('renders content viewer actions directive', (done: Function) => {
  40 + buildComponent().then((fixture: ComponentFixture) => {
  41 + expect(fixture.debugElement.query('content-viewer-actions').length).toEqual(1);
  42 +
  43 + done();
  44 + });
  45 + });
  46 +
  47 + it('check if profile was loaded', (done: Function) => {
  48 + let profile: any = {
  49 + id: 1,
  50 + identifier: 'the-profile-test',
  51 + type: 'Person'
  52 + };
  53 +
  54 + helpers.mocks.profileService.getCurrentProfile = () => {
  55 + return helpers.mocks.promiseResultTemplate(profile);
  56 + };
  57 +
  58 + buildComponent().then((fixture: ComponentFixture) => {
  59 + let contentViewerComp: ContentViewerActions = fixture.debugElement.componentViewChildren[0].componentInstance;
  60 +
  61 + expect(contentViewerComp.profile).toEqual(jasmine.objectContaining(profile));
  62 +
  63 + done();
  64 + });
  65 + });
  66 +
  67 +});
src/app/content-viewer/content-viewer-actions.component.ts
1 import {Component, Inject, provide} from "ng-forward"; 1 import {Component, Inject, provide} from "ng-forward";
2 import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service"; 2 import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service";
3 3
4 -import {Profile} from "./../models/interfaces";  
5 -  
6 @Component({ 4 @Component({
7 selector: "content-viewer-actions", 5 selector: "content-viewer-actions",
8 templateUrl: "app/content-viewer/navbar-actions.html", 6 templateUrl: "app/content-viewer/navbar-actions.html",
@@ -11,11 +9,11 @@ import {Profile} from &quot;./../models/interfaces&quot;; @@ -11,11 +9,11 @@ import {Profile} from &quot;./../models/interfaces&quot;;
11 @Inject(ProfileService) 9 @Inject(ProfileService)
12 export class ContentViewerActions { 10 export class ContentViewerActions {
13 11
14 - article: any;  
15 - profile: any; 12 + article: noosfero.Article;
  13 + profile: noosfero.Profile;
16 14
17 constructor(profileService: ProfileService) { 15 constructor(profileService: ProfileService) {
18 - profileService.getCurrentProfile().then((profile: Profile) => { 16 + profileService.getCurrentProfile().then((profile: noosfero.Profile) => {
19 this.profile = profile; 17 this.profile = profile;
20 }); 18 });
21 } 19 }
src/app/content-viewer/content-viewer.component.spec.ts 0 → 100644
@@ -0,0 +1,90 @@ @@ -0,0 +1,90 @@
  1 +import {providers} from 'ng-forward/cjs/testing/providers';
  2 +
  3 +import {Input, Component, provide} from 'ng-forward';
  4 +
  5 +import * as helpers from "../../spec/helpers";
  6 +
  7 +import {ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder';
  8 +import {ContentViewer} from './content-viewer.component';
  9 +
  10 +// this htmlTemplate will be re-used between the container components in this spec file
  11 +const htmlTemplate: string = '<content-viewer [article]="ctrl.article" [profile]="ctrl.profile"></content-viewer>';
  12 +
  13 +describe('Content Viewer Component', () => {
  14 +
  15 + let stateParamsService: any;
  16 +
  17 + //loading the templates
  18 + beforeEach(() => {
  19 + angular.mock.module("templates");
  20 +
  21 + stateParamsService = { page: 1 };
  22 +
  23 + providers((provide: any) => {
  24 + return <any>[
  25 + provide('ArticleService', {
  26 + useValue: helpers.mocks.articleService
  27 + }),
  28 + provide('ProfileService', {
  29 + useValue: helpers.mocks.profileService
  30 + }),
  31 + // TODO: Como criar um mock do atributo "page" de stateParams
  32 + provide('$stateParams', {
  33 + useValue: stateParamsService
  34 + })
  35 + ]
  36 + });
  37 + });
  38 +
  39 + let buildComponent = (): Promise<ComponentFixture> => {
  40 + return helpers.quickCreateComponent({
  41 + providers: [
  42 + helpers.provideEmptyObjects('Restangular')
  43 + ],
  44 + directives: [ContentViewer],
  45 + template: htmlTemplate
  46 + });
  47 + };
  48 +
  49 + it('renders content viewer directive', (done: Function) => {
  50 + buildComponent().then((fixture: ComponentFixture) => {
  51 + expect(fixture.debugElement.query('content-viewer').length).toEqual(1);
  52 +
  53 + done();
  54 + })
  55 + });
  56 +
  57 + it('check if article was loaded', (done: Function) => {
  58 + var article: any = {
  59 + id: 1,
  60 + title: 'The article test'
  61 + };
  62 + var profile: any = {
  63 + id: 1,
  64 + identifier: 'the-profile-test',
  65 + type: 'Person'
  66 + };
  67 +
  68 + helpers.mocks.profileService.getCurrentProfile = () => {
  69 + return helpers.mocks.promiseResultTemplate(profile);
  70 + };
  71 +
  72 + helpers.mocks.articleService.getByProfile = (id: number, params: any) => {
  73 + return helpers.mocks.promiseResultTemplate({
  74 + data: {
  75 + article: article
  76 + }
  77 + });
  78 + };
  79 +
  80 +
  81 + buildComponent().then((fixture: ComponentFixture) => {
  82 + let contentViewerComp: ContentViewer = fixture.debugElement.componentViewChildren[0].componentInstance;
  83 +
  84 + expect(contentViewerComp.profile).toEqual(jasmine.objectContaining(profile));
  85 + expect(contentViewerComp.article).toEqual(jasmine.objectContaining(article));
  86 +
  87 + done();
  88 + });
  89 + });
  90 +});
src/app/content-viewer/content-viewer.component.ts
@@ -21,14 +21,14 @@ export class ContentViewer { @@ -21,14 +21,14 @@ export class ContentViewer {
21 article: noosfero.Article = null; 21 article: noosfero.Article = null;
22 22
23 @Input() 23 @Input()
24 - profile: Profile = null; 24 + profile: noosfero.Profile = null;
25 25
26 constructor(private articleService: ArticleService, private profileService: ProfileService, private $log: ng.ILogService, private $stateParams: angular.ui.IStateParamsService) { 26 constructor(private articleService: ArticleService, private profileService: ProfileService, private $log: ng.ILogService, private $stateParams: angular.ui.IStateParamsService) {
27 this.activate(); 27 this.activate();
28 } 28 }
29 29
30 activate() { 30 activate() {
31 - this.profileService.getCurrentProfile().then((profile: Profile) => { 31 + this.profileService.getCurrentProfile().then((profile: noosfero.Profile) => {
32 this.profile = profile; 32 this.profile = profile;
33 return this.articleService.getByProfile(<any>this.profile, { path: this.$stateParams["page"] }); 33 return this.articleService.getByProfile(<any>this.profile, { path: this.$stateParams["page"] });
34 }).then((result: noosfero.RestResult<noosfero.Article>) => { 34 }).then((result: noosfero.RestResult<noosfero.Article>) => {
src/app/index.config.ts
@@ -29,6 +29,7 @@ function configTranslation($translateProvider: angular.translate.ITranslateProvi @@ -29,6 +29,7 @@ function configTranslation($translateProvider: angular.translate.ITranslateProvi
29 prefix: '/languages/', 29 prefix: '/languages/',
30 suffix: '.json' 30 suffix: '.json'
31 }); 31 });
  32 + $translateProvider.addInterpolation('$translateMessageFormatInterpolation');
32 $translateProvider.useMissingTranslationHandlerLog(); 33 $translateProvider.useMissingTranslationHandlerLog();
33 $translateProvider.preferredLanguage('en'); 34 $translateProvider.preferredLanguage('en');
34 $translateProvider.useSanitizeValueStrategy('escape'); 35 $translateProvider.useSanitizeValueStrategy('escape');
src/app/index.run.ts
1 import {Session} from "./components/auth/session"; 1 import {Session} from "./components/auth/session";
  2 +import {Notification} from "./components/notification/notification.component";
2 3
3 /** @ngInject */ 4 /** @ngInject */
4 -export function noosferoAngularRunBlock($log: ng.ILogService, Restangular: restangular.IService, Session: Session) {  
5 - Restangular.addFullRequestInterceptor((element: any, operation: string, route: string, url: string, headers: string) => { 5 +export function noosferoAngularRunBlock(
  6 + $log: ng.ILogService,
  7 + Restangular: restangular.IService,
  8 + Session: Session,
  9 + Notification: Notification
  10 +) {
  11 +
  12 + Restangular.addFullRequestInterceptor((element: any, operation: string, route: string, url: string, headers: string) => {
6 if (Session.currentUser()) { 13 if (Session.currentUser()) {
7 (<any>headers)["Private-Token"] = Session.currentUser().private_token; 14 (<any>headers)["Private-Token"] = Session.currentUser().private_token;
8 } 15 }
9 return <any>{ headers: <any>headers }; 16 return <any>{ headers: <any>headers };
10 }); 17 });
  18 + Restangular.setErrorInterceptor((response: restangular.IResponse, deferred: ng.IDeferred<any>) => {
  19 + // return false to break the promise chain and don't call catch
  20 + return !Notification.httpError(response.status, response.data);
  21 + });
11 } 22 }
12 -  
src/app/main/main.component.ts
@@ -17,6 +17,7 @@ import {DateFormat} from &quot;../components/noosfero/date-format/date-format.filter&quot; @@ -17,6 +17,7 @@ import {DateFormat} from &quot;../components/noosfero/date-format/date-format.filter&quot;
17 17
18 import {AuthService} from "./../components/auth/auth_service"; 18 import {AuthService} from "./../components/auth/auth_service";
19 import {Session} from "./../components/auth/session"; 19 import {Session} from "./../components/auth/session";
  20 +import {Notification} from "./../components/notification/notification.component";
20 21
21 22
22 import {Navbar} from "../components/navbar/navbar"; 23 import {Navbar} from "../components/navbar/navbar";
@@ -41,7 +42,7 @@ export class MainContent { @@ -41,7 +42,7 @@ export class MainContent {
41 MainBlock, RecentDocumentsBlock, Navbar, ProfileImageBlock, 42 MainBlock, RecentDocumentsBlock, Navbar, ProfileImageBlock,
42 MembersBlock, NoosferoTemplate, DateFormat, RawHTMLBlock 43 MembersBlock, NoosferoTemplate, DateFormat, RawHTMLBlock
43 ], 44 ],
44 - providers: [AuthService, Session] 45 + providers: [AuthService, Session, Notification]
45 }) 46 })
46 @StateConfig([ 47 @StateConfig([
47 { 48 {
src/app/profile-info/profile-info.component.ts
@@ -11,17 +11,17 @@ import {ProfileService} from &quot;../../lib/ng-noosfero-api/http/profile.service&quot;; @@ -11,17 +11,17 @@ import {ProfileService} from &quot;../../lib/ng-noosfero-api/http/profile.service&quot;;
11 @Inject(ProfileService) 11 @Inject(ProfileService)
12 export class ProfileInfo { 12 export class ProfileInfo {
13 13
14 - activities: any  
15 - profile: any 14 + activities: any;
  15 + profile: noosfero.Profile;
16 16
17 constructor(private profileService: ProfileService) { 17 constructor(private profileService: ProfileService) {
18 this.activate(); 18 this.activate();
19 } 19 }
20 20
21 activate() { 21 activate() {
22 - this.profileService.getCurrentProfile().then((profile: Profile) => { 22 + this.profileService.getCurrentProfile().then((profile: noosfero.Profile) => {
23 this.profile = profile; 23 this.profile = profile;
24 - return this.profileService.getActivities(this.profile.id); 24 + return this.profileService.getActivities(<number>this.profile.id);
25 }).then((response: restangular.IResponse) => { 25 }).then((response: restangular.IResponse) => {
26 this.activities = response.data.activities; 26 this.activities = response.data.activities;
27 }); 27 });
src/app/profile/profile-home.component.ts
1 import {StateConfig, Component, Inject, provide} from 'ng-forward'; 1 import {StateConfig, Component, Inject, provide} from 'ng-forward';
2 2
3 -import {Profile} from "./../models/interfaces";  
4 import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service"; 3 import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service";
5 4
6 @Component({ 5 @Component({
@@ -11,12 +10,12 @@ import {ProfileService} from &quot;../../lib/ng-noosfero-api/http/profile.service&quot;; @@ -11,12 +10,12 @@ import {ProfileService} from &quot;../../lib/ng-noosfero-api/http/profile.service&quot;;
11 @Inject(ProfileService, "$state") 10 @Inject(ProfileService, "$state")
12 export class ProfileHome { 11 export class ProfileHome {
13 12
14 - profile: Profile; 13 + profile: noosfero.Profile;
15 14
16 constructor(profileService: ProfileService, $state: ng.ui.IStateService) { 15 constructor(profileService: ProfileService, $state: ng.ui.IStateService) {
17 - profileService.getCurrentProfile().then((profile: Profile) => { 16 + profileService.getCurrentProfile().then((profile: noosfero.Profile) => {
18 this.profile = profile; 17 this.profile = profile;
19 - return profileService.getHomePage(this.profile.id, { fields: 'path' }); 18 + return profileService.getHomePage(<number>this.profile.id, { fields: 'path' });
20 }).then((response: restangular.IResponse) => { 19 }).then((response: restangular.IResponse) => {
21 if (response.data.article) { 20 if (response.data.article) {
22 $state.transitionTo('main.profile.page', { page: response.data.article.path, profile: this.profile.identifier }, { location: false }); 21 $state.transitionTo('main.profile.page', { page: response.data.article.path, profile: this.profile.identifier }, { location: false });
src/app/profile/profile.component.spec.ts
@@ -7,6 +7,7 @@ describe(&quot;Components&quot;, () =&gt; { @@ -7,6 +7,7 @@ describe(&quot;Components&quot;, () =&gt; {
7 let $rootScope: ng.IRootScopeService; 7 let $rootScope: ng.IRootScopeService;
8 let $q: ng.IQService; 8 let $q: ng.IQService;
9 let profileServiceMock: any; 9 let profileServiceMock: any;
  10 + let notificationMock: any;
10 let $stateParams: any; 11 let $stateParams: any;
11 12
12 beforeEach(inject((_$rootScope_: ng.IRootScopeService, _$q_: ng.IQService) => { 13 beforeEach(inject((_$rootScope_: ng.IRootScopeService, _$q_: ng.IQService) => {
@@ -17,6 +18,7 @@ describe(&quot;Components&quot;, () =&gt; { @@ -17,6 +18,7 @@ describe(&quot;Components&quot;, () =&gt; {
17 beforeEach(() => { 18 beforeEach(() => {
18 $stateParams = jasmine.createSpyObj("$stateParams", ["profile"]); 19 $stateParams = jasmine.createSpyObj("$stateParams", ["profile"]);
19 profileServiceMock = jasmine.createSpyObj("profileServiceMock", ["setCurrentProfileByIdentifier", "getBoxes"]); 20 profileServiceMock = jasmine.createSpyObj("profileServiceMock", ["setCurrentProfileByIdentifier", "getBoxes"]);
  21 + notificationMock = jasmine.createSpyObj("notificationMock", ["httpError"]);
20 22
21 let profileResponse = $q.defer(); 23 let profileResponse = $q.defer();
22 profileResponse.resolve({ id: 1 }); 24 profileResponse.resolve({ id: 1 });
@@ -28,7 +30,7 @@ describe(&quot;Components&quot;, () =&gt; { @@ -28,7 +30,7 @@ describe(&quot;Components&quot;, () =&gt; {
28 }); 30 });
29 31
30 it("get the profile and store in profile service", done => { 32 it("get the profile and store in profile service", done => {
31 - let component: Profile = new Profile(profileServiceMock, $stateParams); 33 + let component: Profile = new Profile(profileServiceMock, $stateParams, notificationMock);
32 $rootScope.$apply(); 34 $rootScope.$apply();
33 expect(profileServiceMock.setCurrentProfileByIdentifier).toHaveBeenCalled(); 35 expect(profileServiceMock.setCurrentProfileByIdentifier).toHaveBeenCalled();
34 expect(component.profile).toEqual({ id: 1 }); 36 expect(component.profile).toEqual({ id: 1 });
@@ -36,11 +38,26 @@ describe(&quot;Components&quot;, () =&gt; { @@ -36,11 +38,26 @@ describe(&quot;Components&quot;, () =&gt; {
36 }); 38 });
37 39
38 it("get the profile boxes", done => { 40 it("get the profile boxes", done => {
39 - let component: Profile = new Profile(profileServiceMock, $stateParams); 41 + let component: Profile = new Profile(profileServiceMock, $stateParams, notificationMock);
40 $rootScope.$apply(); 42 $rootScope.$apply();
41 expect(profileServiceMock.getBoxes).toHaveBeenCalled(); 43 expect(profileServiceMock.getBoxes).toHaveBeenCalled();
42 expect(component.boxes).toEqual([{ id: 2 }]); 44 expect(component.boxes).toEqual([{ id: 2 }]);
43 done(); 45 done();
44 }); 46 });
  47 +
  48 + it("display notification error when the profile wasn't found", done => {
  49 + let profileResponse = $q.defer();
  50 + profileResponse.reject();
  51 + profileServiceMock.setCurrentProfileByIdentifier = jasmine.createSpy("setCurrentProfileByIdentifier").and.returnValue(profileResponse.promise);
  52 +
  53 + let component: Profile = new Profile(profileServiceMock, $stateParams, notificationMock);
  54 + $rootScope.$apply();
  55 +
  56 + expect(profileServiceMock.setCurrentProfileByIdentifier).toHaveBeenCalled();
  57 + expect(notificationMock.httpError).toHaveBeenCalled();
  58 + expect(component.profile).toBeUndefined();
  59 + done();
  60 + });
  61 +
45 }); 62 });
46 }); 63 });
src/app/profile/profile.component.ts
@@ -6,14 +6,16 @@ import {ContentViewer} from &quot;../content-viewer/content-viewer.component&quot;; @@ -6,14 +6,16 @@ import {ContentViewer} from &quot;../content-viewer/content-viewer.component&quot;;
6 import {ContentViewerActions} from "../content-viewer/content-viewer-actions.component"; 6 import {ContentViewerActions} from "../content-viewer/content-viewer-actions.component";
7 import {NoosferoActivities} from "../components/noosfero-activities/activities.component"; 7 import {NoosferoActivities} from "../components/noosfero-activities/activities.component";
8 import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service"; 8 import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service";
9 -  
10 -import * as noosferoModels from "./../models/interfaces"; 9 +import {Notification} from "../components/notification/notification.component";
11 10
12 @Component({ 11 @Component({
13 selector: 'profile', 12 selector: 'profile',
14 templateUrl: "app/profile/profile.html", 13 templateUrl: "app/profile/profile.html",
15 directives: [NoosferoActivities], 14 directives: [NoosferoActivities],
16 - providers: [provide('profileService', { useClass: ProfileService })] 15 + providers: [
  16 + provide('profileService', { useClass: ProfileService }),
  17 + provide('notification', { useClass: Notification })
  18 + ]
17 }) 19 })
18 @StateConfig([ 20 @StateConfig([
19 { 21 {
@@ -72,15 +74,17 @@ import * as noosferoModels from &quot;./../models/interfaces&quot;; @@ -72,15 +74,17 @@ import * as noosferoModels from &quot;./../models/interfaces&quot;;
72 @Inject(ProfileService, "$stateParams") 74 @Inject(ProfileService, "$stateParams")
73 export class Profile { 75 export class Profile {
74 76
75 - boxes: noosferoModels.Box[];  
76 - profile: noosferoModels.Profile; 77 + boxes: noosfero.Box[];
  78 + profile: noosfero.Profile;
77 79
78 - constructor(profileService: ProfileService, $stateParams: ng.ui.IStateParamsService) {  
79 - profileService.setCurrentProfileByIdentifier($stateParams["profile"]).then((profile: noosferoModels.Profile) => { 80 + constructor(profileService: ProfileService, $stateParams: ng.ui.IStateParamsService, notification: Notification) {
  81 + profileService.setCurrentProfileByIdentifier($stateParams["profile"]).then((profile: noosfero.Profile) => {
80 this.profile = profile; 82 this.profile = profile;
81 - return profileService.getBoxes(this.profile.id); 83 + return profileService.getBoxes(<number>this.profile.id);
82 }).then((response: restangular.IResponse) => { 84 }).then((response: restangular.IResponse) => {
83 this.boxes = response.data.boxes; 85 this.boxes = response.data.boxes;
  86 + }).catch(() => {
  87 + notification.httpError(404, { message: "Profile not found!" });
84 }); 88 });
85 } 89 }
86 } 90 }
src/languages/en.json
@@ -12,10 +12,12 @@ @@ -12,10 +12,12 @@
12 "profile.wall": "Profile Wall", 12 "profile.wall": "Profile Wall",
13 "activities.create_article.description": "has published on", 13 "activities.create_article.description": "has published on",
14 "activities.add_member_in_community.description": "has joined the community", 14 "activities.add_member_in_community.description": "has joined the community",
15 - "activities.new_friendship.description": "has made {{friends}} new friend(s):", 15 + "activities.new_friendship.description": "has made {friends, plural, one{one new friend} other{# new friends}}:",
16 "auth.title": "Login", 16 "auth.title": "Login",
17 "auth.form.login": "Login / Email address", 17 "auth.form.login": "Login / Email address",
18 "auth.form.password": "Password", 18 "auth.form.password": "Password",
19 "auth.form.login_button": "Login", 19 "auth.form.login_button": "Login",
20 - "navbar.content_viewer_actions.new_post": "New Post" 20 + "navbar.content_viewer_actions.new_post": "New Post",
  21 + "notification.http-error.default.message": "Something went wrong!",
  22 + "notification.http-error.default.title": "Oops..."
21 } 23 }
src/languages/pt.json
@@ -12,10 +12,12 @@ @@ -12,10 +12,12 @@
12 "profile.wall": "Mural do Perfil", 12 "profile.wall": "Mural do Perfil",
13 "activities.create_article.description": "publicou em", 13 "activities.create_article.description": "publicou em",
14 "activities.add_member_in_community.description": "entrou na comunidade", 14 "activities.add_member_in_community.description": "entrou na comunidade",
15 - "activities.new_friendship.description": "fez {{friends}} novo(s) amigo(s):", 15 + "activities.new_friendship.description": "fez {friends, plural, one{um novo amigo} other{# novos amigos}}:",
16 "auth.title": "Login", 16 "auth.title": "Login",
17 "auth.form.login": "Login / Email", 17 "auth.form.login": "Login / Email",
18 "auth.form.password": "Senha", 18 "auth.form.password": "Senha",
19 "auth.form.login_button": "Login", 19 "auth.form.login_button": "Login",
20 - "navbar.content_viewer_actions.new_post": "Novo Artigo" 20 + "navbar.content_viewer_actions.new_post": "Novo Artigo",
  21 + "notification.http-error.default.message": "Algo deu errado!",
  22 + "notification.http-error.default.title": "Oops..."
21 } 23 }
src/lib/ng-noosfero-api/http/profile.service.spec.ts
@@ -24,8 +24,17 @@ describe(&quot;Services&quot;, () =&gt; { @@ -24,8 +24,17 @@ describe(&quot;Services&quot;, () =&gt; {
24 it("should return profile by its identifier", (done) => { 24 it("should return profile by its identifier", (done) => {
25 let identifier = 'profile1'; 25 let identifier = 'profile1';
26 $httpBackend.expectGET(`/api/v1/profiles?identifier=${identifier}`).respond(200, [{ name: "profile1" }]); 26 $httpBackend.expectGET(`/api/v1/profiles?identifier=${identifier}`).respond(200, [{ name: "profile1" }]);
27 - profileService.getByIdentifier(identifier).then((response: restangular.IResponse) => {  
28 - expect(response.data[0]).toEqual({ name: "profile1" }); 27 + profileService.getByIdentifier(identifier).then((profile: noosfero.Profile) => {
  28 + expect(profile).toEqual({ name: "profile1" });
  29 + done();
  30 + });
  31 + $httpBackend.flush();
  32 + });
  33 +
  34 + it("should reject the promise if the profile wasn't found", (done) => {
  35 + let identifier = 'profile1';
  36 + $httpBackend.expectGET(`/api/v1/profiles?identifier=${identifier}`).respond(200, []);
  37 + profileService.getByIdentifier(identifier).catch(() => {
29 done(); 38 done();
30 }); 39 });
31 $httpBackend.flush(); 40 $httpBackend.flush();
@@ -63,11 +72,11 @@ describe(&quot;Services&quot;, () =&gt; { @@ -63,11 +72,11 @@ describe(&quot;Services&quot;, () =&gt; {
63 72
64 it("should resolve the current profile", (done) => { 73 it("should resolve the current profile", (done) => {
65 let profile = { id: 1, identifier: "profile1" }; 74 let profile = { id: 1, identifier: "profile1" };
66 - profileService.getCurrentProfile().then((currentProfile: Profile) => { 75 + profileService.getCurrentProfile().then((currentProfile: noosfero.Profile) => {
67 expect(currentProfile).toEqual(currentProfile); 76 expect(currentProfile).toEqual(currentProfile);
68 done(); 77 done();
69 }); 78 });
70 - profileService.setCurrentProfile(<Profile>profile); 79 + profileService.setCurrentProfile(<any>profile);
71 $rootScope.$apply(); 80 $rootScope.$apply();
72 }); 81 });
73 82
@@ -84,9 +93,9 @@ describe(&quot;Services&quot;, () =&gt; { @@ -84,9 +93,9 @@ describe(&quot;Services&quot;, () =&gt; {
84 it("should find the profile by identifier, set and resolve the current profile", (done) => { 93 it("should find the profile by identifier, set and resolve the current profile", (done) => {
85 let identifier = 'profile1'; 94 let identifier = 'profile1';
86 $httpBackend.expectGET(`/api/v1/profiles?identifier=${identifier}`).respond(200, [{ name: "profile1" }]); 95 $httpBackend.expectGET(`/api/v1/profiles?identifier=${identifier}`).respond(200, [{ name: "profile1" }]);
87 - profileService.setCurrentProfileByIdentifier(identifier).then((profile: Profile) => { 96 + profileService.setCurrentProfileByIdentifier(identifier).then((profile: noosfero.Profile) => {
88 expect(profile).toEqual({ name: "profile1" }); 97 expect(profile).toEqual({ name: "profile1" });
89 - profileService.getCurrentProfile().then((profile: Profile) => { 98 + profileService.getCurrentProfile().then((profile: noosfero.Profile) => {
90 expect(profile).toEqual({ name: "profile1" }); 99 expect(profile).toEqual({ name: "profile1" });
91 done(); 100 done();
92 }); 101 });
src/lib/ng-noosfero-api/http/profile.service.ts
@@ -5,7 +5,7 @@ import {Profile} from &quot;../../../app/models/interfaces&quot;; @@ -5,7 +5,7 @@ import {Profile} from &quot;../../../app/models/interfaces&quot;;
5 @Inject("Restangular", "$q") 5 @Inject("Restangular", "$q")
6 export class ProfileService { 6 export class ProfileService {
7 7
8 - private _currentProfilePromise: ng.IDeferred<Profile>; 8 + private _currentProfilePromise: ng.IDeferred<noosfero.Profile>;
9 9
10 constructor(private restangular: restangular.IService, private $q: ng.IQService) { 10 constructor(private restangular: restangular.IService, private $q: ng.IQService) {
11 this.resetCurrentProfile(); 11 this.resetCurrentProfile();
@@ -15,18 +15,18 @@ export class ProfileService { @@ -15,18 +15,18 @@ export class ProfileService {
15 this._currentProfilePromise = this.$q.defer(); 15 this._currentProfilePromise = this.$q.defer();
16 } 16 }
17 17
18 - getCurrentProfile(): ng.IPromise<Profile> { 18 + getCurrentProfile(): ng.IPromise<noosfero.Profile> {
19 return this._currentProfilePromise.promise; 19 return this._currentProfilePromise.promise;
20 } 20 }
21 21
22 - setCurrentProfile(profile: Profile) { 22 + setCurrentProfile(profile: noosfero.Profile) {
23 this._currentProfilePromise.resolve(profile); 23 this._currentProfilePromise.resolve(profile);
24 } 24 }
25 25
26 setCurrentProfileByIdentifier(identifier: string) { 26 setCurrentProfileByIdentifier(identifier: string) {
27 this.resetCurrentProfile(); 27 this.resetCurrentProfile();
28 - return this.getByIdentifier(identifier).then((response: restangular.IResponse) => {  
29 - this.setCurrentProfile(response.data[0]); 28 + return this.getByIdentifier(identifier).then((profile: noosfero.Profile) => {
  29 + this.setCurrentProfile(profile);
30 return this.getCurrentProfile(); 30 return this.getCurrentProfile();
31 }); 31 });
32 } 32 }
@@ -35,8 +35,14 @@ export class ProfileService { @@ -35,8 +35,14 @@ export class ProfileService {
35 return this.get(profileId).customGET("home_page", params); 35 return this.get(profileId).customGET("home_page", params);
36 } 36 }
37 37
38 - getByIdentifier(identifier: string): restangular.IPromise<any> {  
39 - return this.restangular.one('profiles').get({ identifier: identifier }); 38 + getByIdentifier(identifier: string): ng.IPromise<noosfero.Profile> {
  39 + let p = this.restangular.one('profiles').get({ identifier: identifier });
  40 + return p.then((response: restangular.IResponse) => {
  41 + if (response.data.length === 0) {
  42 + return this.$q.reject(p);
  43 + }
  44 + return response.data[0];
  45 + });
40 } 46 }
41 47
42 getProfileMembers(profileId: number, params?: any): restangular.IPromise<any> { 48 getProfileMembers(profileId: number, params?: any): restangular.IPromise<any> {
src/lib/ng-noosfero-api/interfaces/box.ts 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +namespace noosfero {
  2 + export interface Box {
  3 + id: number;
  4 + position: number;
  5 + }
  6 +}
0 \ No newline at end of file 7 \ No newline at end of file
src/spec/mocks.ts
@@ -38,6 +38,32 @@ export var mocks = { @@ -38,6 +38,32 @@ export var mocks = {
38 authService: { 38 authService: {
39 logout: () => { } 39 logout: () => { }
40 }, 40 },
  41 + articleService: {
  42 + getByProfile: (profileId: number, params?: any) => {
  43 + return {
  44 + then: (func?: Function) => {
  45 + if (func) func({
  46 + data: {
  47 + article: null
  48 + }
  49 + });
  50 + }
  51 + };
  52 + },
  53 + getChildren: (articleId: number, params?: any) => {
  54 + return {
  55 + then: (func?: Function) => { if (func) func(); }
  56 + };
  57 + }
  58 + },
  59 + profileService: {
  60 + getCurrentProfile: (profile: any) => {
  61 + return mocks.promiseResultTemplate({
  62 + profile: profile
  63 + });
  64 + },
  65 + instant: () => { }
  66 + },
41 sessionWithCurrentUser: (user: any) => { 67 sessionWithCurrentUser: (user: any) => {
42 return { 68 return {
43 currentUser: () => { return user; } 69 currentUser: () => { return user; }
@@ -45,11 +71,9 @@ export var mocks = { @@ -45,11 +71,9 @@ export var mocks = {
45 }, 71 },
46 $translate: { 72 $translate: {
47 use: (lang?: string) => { 73 use: (lang?: string) => {
48 - return {  
49 - then: (func?: any) => { if (func) func() }  
50 - } 74 + return lang ? Promise.resolve(lang) : "en";
51 }, 75 },
52 - instant: () => { } 76 + instant: (text: string) => { return text }
53 }, 77 },
54 tmhDynamicLocale: { 78 tmhDynamicLocale: {
55 get: () => { }, 79 get: () => { },
@@ -60,9 +84,18 @@ export var mocks = { @@ -60,9 +84,18 @@ export var mocks = {
60 }, 84 },
61 angularLoad: { 85 angularLoad: {
62 loadScript: (script?: string) => { 86 loadScript: (script?: string) => {
63 - return {  
64 - then: (func?: any) => { if (func) func() }  
65 - } 87 + return Promise.resolve();
66 } 88 }
  89 + },
  90 + promiseResultTemplate: (response?: {}) => {
  91 +
  92 + return {
  93 + then: (func?: (response: any) => void) => {
  94 + if (func) { return func(response); }
  95 + }
  96 + };
  97 + },
  98 + $log: {
  99 + debug: () => { }
67 } 100 }
68 }; 101 };