Merge Request #29
@@ -19,6 +19,7 @@ describe("Components", () => { | @@ -19,6 +19,7 @@ describe("Components", () => { | ||
19 | describe("Article Default View Component", () => { | 19 | describe("Article Default View Component", () => { |
20 | let helper: ComponentTestHelper<ArticleDefaultViewComponent>; | 20 | let helper: ComponentTestHelper<ArticleDefaultViewComponent>; |
21 | const defaultViewTemplate: string = '<noosfero-default-article [article]="ctrl.article" [profile]="ctrl.profile"></noosfero-default-article>'; | 21 | const defaultViewTemplate: string = '<noosfero-default-article [article]="ctrl.article" [profile]="ctrl.profile"></noosfero-default-article>'; |
22 | + let notificationService = helpers.mocks.notificationService; | ||
22 | let articleService: any = helpers.mocks.articleService; | 23 | let articleService: any = helpers.mocks.articleService; |
23 | let article = <noosfero.Article>{ | 24 | let article = <noosfero.Article>{ |
24 | id: 1, | 25 | id: 1, |
@@ -29,7 +30,8 @@ describe("Components", () => { | @@ -29,7 +30,8 @@ describe("Components", () => { | ||
29 | let state = <ng.ui.IStateService>jasmine.createSpyObj("state", ["go", "transitionTo"]); | 30 | let state = <ng.ui.IStateService>jasmine.createSpyObj("state", ["go", "transitionTo"]); |
30 | let providers = [ | 31 | let providers = [ |
31 | provide('$state', { useValue: state }), | 32 | provide('$state', { useValue: state }), |
32 | - provide('ArticleService', { useValue: articleService }) | 33 | + provide('ArticleService', { useValue: articleService }), |
34 | + helpers.createProviderToValue('NotificationService', notificationService), | ||
33 | ].concat(helpers.provideFilters("translateFilter")); | 35 | ].concat(helpers.provideFilters("translateFilter")); |
34 | 36 | ||
35 | /** | 37 | /** |
@@ -67,13 +69,19 @@ describe("Components", () => { | @@ -67,13 +69,19 @@ describe("Components", () => { | ||
67 | * Execute the delete method on the target component | 69 | * Execute the delete method on the target component |
68 | */ | 70 | */ |
69 | function doDeleteArticle() { | 71 | function doDeleteArticle() { |
72 | + // Create a mock for the notification service confirmation | ||
73 | + spyOn(helper.component.notificationService, 'confirmation').and.callFake(function (params: Function) { | ||
2 |
|
||
74 | + | ||
75 | + }); | ||
70 | // Create a mock for the ArticleService removeArticle method | 76 | // Create a mock for the ArticleService removeArticle method |
71 | - spyOn(helper.component.articleService, 'removeArticle').and.callFake(function(param: noosfero.Article) { | 77 | + spyOn(helper.component.articleService, 'removeArticle').and.callFake(function (param: noosfero.Article) { |
72 | return { | 78 | return { |
73 | - catch: () => {} | 79 | + catch: () => { } |
74 | }; | 80 | }; |
75 | }); | 81 | }); |
76 | helper.component.delete(); | 82 | helper.component.delete(); |
83 | + expect(notificationService.confirmation).toHaveBeenCalled(); | ||
84 | + helper.component.doDelete(); | ||
77 | expect(articleService.removeArticle).toHaveBeenCalled(); | 85 | expect(articleService.removeArticle).toHaveBeenCalled(); |
78 | // After the component delete method execution, fire the | 86 | // After the component delete method execution, fire the |
79 | // ArticleEvent.removed event | 87 | // ArticleEvent.removed event |
@@ -81,9 +89,11 @@ describe("Components", () => { | @@ -81,9 +89,11 @@ describe("Components", () => { | ||
81 | } | 89 | } |
82 | 90 | ||
83 | /** | 91 | /** |
84 | - * Simulate the ArticleService ArticleEvent.removed event | 92 | + * Simulate the Notification Service confirmation and ArticleService |
93 | + * notifyArticleRemovedListeners event | ||
85 | */ | 94 | */ |
86 | function simulateRemovedEvent() { | 95 | function simulateRemovedEvent() { |
96 | + helper.component.notificationService["confirmation"]({ title: "Title", message: "Message" }, () => { }); | ||
87 | helper.component.articleService["notifyArticleRemovedListeners"](article); | 97 | helper.component.articleService["notifyArticleRemovedListeners"](article); |
88 | } | 98 | } |
89 | }); | 99 | }); |
@@ -5,6 +5,7 @@ import {MacroDirective} from "./macro/macro.directive"; | @@ -5,6 +5,7 @@ import {MacroDirective} from "./macro/macro.directive"; | ||
5 | import {ArticleToolbarHotspotComponent} from "../hotspot/article-toolbar-hotspot.component"; | 5 | import {ArticleToolbarHotspotComponent} from "../hotspot/article-toolbar-hotspot.component"; |
6 | import {ArticleContentHotspotComponent} from "../hotspot/article-content-hotspot.component"; | 6 | import {ArticleContentHotspotComponent} from "../hotspot/article-content-hotspot.component"; |
7 | import {ArticleService} from "./../../lib/ng-noosfero-api/http/article.service"; | 7 | import {ArticleService} from "./../../lib/ng-noosfero-api/http/article.service"; |
8 | +import { NotificationService } from "./../shared/services/notification.service"; | ||
8 | 9 | ||
9 | /** | 10 | /** |
10 | * @ngdoc controller | 11 | * @ngdoc controller |
@@ -17,13 +18,13 @@ import {ArticleService} from "./../../lib/ng-noosfero-api/http/article.service"; | @@ -17,13 +18,13 @@ import {ArticleService} from "./../../lib/ng-noosfero-api/http/article.service"; | ||
17 | selector: 'noosfero-default-article', | 18 | selector: 'noosfero-default-article', |
18 | templateUrl: 'app/article/article.html' | 19 | templateUrl: 'app/article/article.html' |
19 | }) | 20 | }) |
20 | -@Inject("$state", ArticleService) | 21 | +@Inject("$state", ArticleService, NotificationService) |
21 | export class ArticleDefaultViewComponent { | 22 | export class ArticleDefaultViewComponent { |
22 | 23 | ||
23 | @Input() article: noosfero.Article; | 24 | @Input() article: noosfero.Article; |
24 | @Input() profile: noosfero.Profile; | 25 | @Input() profile: noosfero.Profile; |
25 | 26 | ||
26 | - constructor(private $state: ng.ui.IStateService, public articleService: ArticleService) { | 27 | + constructor(private $state: ng.ui.IStateService, public articleService: ArticleService, public notificationService: NotificationService) { |
27 | // Subscribe to the Article Removed Event | 28 | // Subscribe to the Article Removed Event |
28 | this.articleService.subscribeToArticleRemoved((article: noosfero.Article) => { | 29 | this.articleService.subscribeToArticleRemoved((article: noosfero.Article) => { |
29 | if (this.article.parent) { | 30 | if (this.article.parent) { |
@@ -31,15 +32,21 @@ export class ArticleDefaultViewComponent { | @@ -31,15 +32,21 @@ export class ArticleDefaultViewComponent { | ||
31 | } else { | 32 | } else { |
32 | this.$state.transitionTo('main.profile.info', { profile: this.article.profile.identifier }); | 33 | this.$state.transitionTo('main.profile.info', { profile: this.article.profile.identifier }); |
33 | } | 34 | } |
35 | + this.notificationService.success({ title: "article.remove.success.title", message: "article.remove.success.message" }); | ||
34 | }); | 36 | }); |
35 | } | 37 | } |
36 | 38 | ||
37 | delete() { | 39 | delete() { |
38 | - this.articleService.removeArticle(this.article).catch((cause: any) => { | ||
39 | - throw new Error(`Problem removing the article: ${cause}`); | 40 | + this.notificationService.confirmation({ title: "article.remove.confirmation.title", message: "article.remove.confirmation.message" }, () => { |
41 | + this.doDelete(); | ||
40 | }); | 42 | }); |
41 | } | 43 | } |
42 | 44 | ||
45 | + doDelete() { | ||
46 | + this.articleService.removeArticle(this.article).catch((cause: any) => { | ||
47 | + throw new Error(`Problem removing the article: ${cause}`); | ||
3 |
|
||
48 | + }); | ||
49 | + } | ||
43 | } | 50 | } |
44 | 51 | ||
45 | /** | 52 | /** |
@@ -56,6 +56,10 @@ | @@ -56,6 +56,10 @@ | ||
56 | "article.basic_editor.cancel": "Cancel", | 56 | "article.basic_editor.cancel": "Cancel", |
57 | "article.basic_editor.success.title": "Good job!", | 57 | "article.basic_editor.success.title": "Good job!", |
58 | "article.basic_editor.success.message": "Article saved!", | 58 | "article.basic_editor.success.message": "Article saved!", |
59 | + "article.remove.success.title": "Good job!", | ||
60 | + "article.remove.success.message": "Article removed!", | ||
61 | + "article.remove.confirmation.title": "Are you sure?", | ||
62 | + "article.remove.confirmation.message": "You will not be able to recover this article!", | ||
59 | "article.basic_editor.visibility": "Visibility", | 63 | "article.basic_editor.visibility": "Visibility", |
60 | "article.basic_editor.visibility.public": "Public", | 64 | "article.basic_editor.visibility.public": "Public", |
61 | "article.basic_editor.visibility.private": "Private", | 65 | "article.basic_editor.visibility.private": "Private", |
@@ -53,6 +53,10 @@ | @@ -53,6 +53,10 @@ | ||
53 | "article.basic_editor.cancel": "Cancelar", | 53 | "article.basic_editor.cancel": "Cancelar", |
54 | "article.basic_editor.success.title": "Bom trabalho!", | 54 | "article.basic_editor.success.title": "Bom trabalho!", |
55 | "article.basic_editor.success.message": "Artigo salvo com sucesso!", | 55 | "article.basic_editor.success.message": "Artigo salvo com sucesso!", |
56 | + "article.remove.success.title": "Bom trabalho!", | ||
1 |
|
||
57 | + "article.remove.success.message": "Artigo removido!", | ||
58 | + "article.remove.confirmation.title": "Tem certeza?", | ||
59 | + "article.remove.confirmation.message": "Não será possível recuperar este artigo!", | ||
56 | "article.basic_editor.visibility": "Visibilidade", | 60 | "article.basic_editor.visibility": "Visibilidade", |
57 | "article.basic_editor.visibility.public": "Público", | 61 | "article.basic_editor.visibility.public": "Público", |
58 | "article.basic_editor.visibility.private": "Privado", | 62 | "article.basic_editor.visibility.private": "Privado", |
@@ -192,6 +192,7 @@ export var mocks: any = { | @@ -192,6 +192,7 @@ export var mocks: any = { | ||
192 | translate: (text: string) => { return text; } | 192 | translate: (text: string) => { return text; } |
193 | }, | 193 | }, |
194 | notificationService: { | 194 | notificationService: { |
195 | - success: () => { } | 195 | + success: () => { }, |
196 | + confirmation: () => { } | ||
196 | } | 197 | } |
197 | }; | 198 | }; |
-
Reassigned to @mfdeveloper
-
Não seria mais indicado utilizar
jasmine.createSpy("confirmation")
oujasmine.createSpyObj("notificationService", ["confirmation"])
como já está amplamente utilizado em outros testes? As diversas formas para implementar coisas muito semelhantes pode causar confusão no futuro. Chegou a conversar rapidamente com @abner sobre isso? -
Não sei direito qual a diferença. Como não estava conseguindo utilizar o jasmine.createSpy, vi isto na documentação do jasmine e utilizei.
-
Se ocorrer um problema, essa mensagem será exibida para o usuário final?
-
Está conforme foi feito nos outros callbacks de serviços. Ach que tem ser feita uma revisão geral de como será o padrão de funcionamento das mensagens de erro.
-
Como esse catch aí é num componente de tela, então deveria estar utilizando o NotificationService para exibir a mensagem de erro para o usuário. Os serviços não devem realmente tratar a exibição de mensagens, mas os componentes de tela devem.
-
As chaves
article.remove.success.title
earticle.remove.confirmation.title
são específicas da tela de artigo? Outras telas não relacionadas com artigo poderão utilizar essas chaves?
67 | 69 | * Execute the delete method on the target component |
68 | 70 | */ |
69 | 71 | function doDeleteArticle() { |
72 | + // Create a mock for the notification service confirmation | |
73 | + spyOn(helper.component.notificationService, 'confirmation').and.callFake(function (params: Function) { | |
2 |
|
33 | 34 | } |
35 | + this.notificationService.success({ title: "article.remove.success.title", message: "article.remove.success.message" }); | |
34 | 36 | }); |
35 | 37 | } |
36 | 38 | |
37 | 39 | delete() { |
38 | - this.articleService.removeArticle(this.article).catch((cause: any) => { | |
39 | - throw new Error(`Problem removing the article: ${cause}`); | |
40 | + this.notificationService.confirmation({ title: "article.remove.confirmation.title", message: "article.remove.confirmation.message" }, () => { | |
41 | + this.doDelete(); | |
40 | 42 | }); |
41 | 43 | } |
42 | 44 | |
45 | + doDelete() { | |
46 | + this.articleService.removeArticle(this.article).catch((cause: any) => { | |
47 | + throw new Error(`Problem removing the article: ${cause}`); | |
3 |
|
53 | 53 | "article.basic_editor.cancel": "Cancelar", |
54 | 54 | "article.basic_editor.success.title": "Bom trabalho!", |
55 | 55 | "article.basic_editor.success.message": "Artigo salvo com sucesso!", |
56 | + "article.remove.success.title": "Bom trabalho!", | |
1 |
|