Commit d14121298f31300970fed97c1216414bbcdb5037
Exists in
master
and in
1 other branch
Merge branch 'ngforward' of softwarepublico.gov.br:noosfero-themes/angular-theme into ngforward
Showing
261 changed files
with
3984 additions
and
3345 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 261 files displayed.
.vscode/settings.json
@@ -3,7 +3,9 @@ | @@ -3,7 +3,9 @@ | ||
3 | "files.exclude": { | 3 | "files.exclude": { |
4 | "**/.git": true, | 4 | "**/.git": true, |
5 | "**/.DS_Store": true, | 5 | "**/.DS_Store": true, |
6 | - "src/app/*.js": false | 6 | + "src/**/*.js": true, |
7 | + "src/**/*.js.map": true, | ||
8 | + "coverage": true | ||
7 | }, | 9 | }, |
8 | "editor.fontSize": 14, | 10 | "editor.fontSize": 14, |
9 | "typescript.useCodeSnippetsOnMethodSuggest": true | 11 | "typescript.useCodeSnippetsOnMethodSuggest": true |
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +let replace = require("replace"); | ||
2 | + | ||
3 | +import * as path from "path"; | ||
4 | + | ||
5 | +let wrong_jqlite_d_ts_file = path.join(__dirname, "../node_modules/ng-forward/cjs/util/jqlite-extensions.d.ts"); | ||
6 | + | ||
7 | +replace({ | ||
8 | + regex: /import JQuery from \".\/\";/, | ||
9 | + replacement: "", | ||
10 | + paths: [wrong_jqlite_d_ts_file], | ||
11 | + sillent: false | ||
12 | +}); | ||
13 | + |
package.json
@@ -4,21 +4,23 @@ | @@ -4,21 +4,23 @@ | ||
4 | "dependencies": { | 4 | "dependencies": { |
5 | "angular": "^1.5.0", | 5 | "angular": "^1.5.0", |
6 | "angular-mock": "^1.0.0", | 6 | "angular-mock": "^1.0.0", |
7 | - "moment": "^2.11.2" | 7 | + "moment": "^2.11.2", |
8 | + "ng-forward": "0.0.1-alpha.12" | ||
8 | }, | 9 | }, |
9 | "scripts": { | 10 | "scripts": { |
10 | "build": "webpack; gulp build", | 11 | "build": "webpack; gulp build", |
11 | "webpack": "webpack", | 12 | "webpack": "webpack", |
13 | + "karma": "concurrently \"webpack -w\" \"karma start\"", | ||
12 | "docs": "gulp ngdocs; static-server docs", | 14 | "docs": "gulp ngdocs; static-server docs", |
13 | - "karma": "karma", | ||
14 | "coverage": "karma start --single-run; npm run remap-coverage", | 15 | "coverage": "karma start --single-run; npm run remap-coverage", |
15 | "remap-coverage": "ts-node --project ./dev-scripts ./dev-scripts/remapCoverage.ts", | 16 | "remap-coverage": "ts-node --project ./dev-scripts ./dev-scripts/remapCoverage.ts", |
16 | "test-single": "karma start --single-run", | 17 | "test-single": "karma start --single-run", |
17 | "test-and-coverage": "karma start & npm run remap-coverage", | 18 | "test-and-coverage": "karma start & npm run remap-coverage", |
18 | "test": "webpack -w --test", | 19 | "test": "webpack -w --test", |
19 | - "postinstall": "npm install -g bower && bower install && typings install && cd dev-scripts && typings install", | 20 | + "postinstall": "npm install -g bower; bower install; typings install; npm run fix-jqlite; cd dev-scripts; typings install", |
20 | "start": "concurrently \"webpack -w\" \"gulp serve\"", | 21 | "start": "concurrently \"webpack -w\" \"gulp serve\"", |
21 | - "generate-indexes": "ts-node --project ./dev-scripts ./dev-scripts/generate-index-modules.ts" | 22 | + "generate-indexes": "ts-node --project ./dev-scripts ./dev-scripts/generate-index-modules.ts", |
23 | + "fix-jqlite": "ts-node --project ./dev-scripts dev-scripts/fix-jqlite.ts" | ||
22 | }, | 24 | }, |
23 | "devDependencies": { | 25 | "devDependencies": { |
24 | "browser-sync": "~2.9.11", | 26 | "browser-sync": "~2.9.11", |
@@ -71,7 +73,6 @@ | @@ -71,7 +73,6 @@ | ||
71 | "karma-webpack": "^1.7.0", | 73 | "karma-webpack": "^1.7.0", |
72 | "lodash": "~3.10.1", | 74 | "lodash": "~3.10.1", |
73 | "main-bower-files": "~2.9.0", | 75 | "main-bower-files": "~2.9.0", |
74 | - "ng-forward": "0.0.1-alpha.12", | ||
75 | "on-build-webpack": "^0.1.0", | 76 | "on-build-webpack": "^0.1.0", |
76 | "phantomjs": "~1.9.18", | 77 | "phantomjs": "~1.9.18", |
77 | "phantomjs-polyfill": "0.0.2", | 78 | "phantomjs-polyfill": "0.0.2", |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +/* Module Index Entry - generated using the script npm run generate-index */ |
@@ -0,0 +1,108 @@ | @@ -0,0 +1,108 @@ | ||
1 | + | ||
2 | +import {Input, provide, Component} from 'ng-forward'; | ||
3 | +import {ArticleViewComponent, ArticleDefaultViewComponent} from './article-default-view.component'; | ||
4 | + | ||
5 | +import {createComponentFromClass, quickCreateComponent} from "../../spec/helpers"; | ||
6 | + | ||
7 | +// this htmlTemplate will be re-used between the container components in this spec file | ||
8 | +const htmlTemplate: string = '<noosfero-article [article]="ctrl.article" [profile]="ctrl.profile"></noosfero-article>'; | ||
9 | + | ||
10 | + | ||
11 | +describe("Components", () => { | ||
12 | + | ||
13 | + describe("ArticleView Component", () => { | ||
14 | + | ||
15 | + // the karma preprocessor html2js transform the templates html into js files which put | ||
16 | + // the templates to the templateCache into the module templates | ||
17 | + // we need to load the module templates here as the template for the | ||
18 | + // component Noosfero ArtileView will be load on our tests | ||
19 | + beforeEach(angular.mock.module("templates")); | ||
20 | + | ||
21 | + it("renders the default component when no specific component is found", (done: Function) => { | ||
22 | + // Creating a container component (ArticleContainerComponent) to include | ||
23 | + // the component under test (ArticleView) | ||
24 | + @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [ArticleViewComponent] }) | ||
25 | + class ArticleContainerComponent { | ||
26 | + article = { type: 'anyArticleType' }; | ||
27 | + profile = { name: 'profile-name' }; | ||
28 | + constructor() { | ||
29 | + } | ||
30 | + } | ||
31 | + | ||
32 | + createComponentFromClass(ArticleContainerComponent).then((fixture) => { | ||
33 | + // and here we can inspect and run the test assertions | ||
34 | + | ||
35 | + // gets the children component of ArticleContainerComponent | ||
36 | + let articleView: ArticleViewComponent = fixture.debugElement.componentViewChildren[0].componentInstance; | ||
37 | + | ||
38 | + // and checks if the article View rendered was the Default Article View | ||
39 | + expect(articleView.constructor.prototype).toEqual(ArticleDefaultViewComponent.prototype); | ||
40 | + | ||
41 | + // done needs to be called (it isn't really needed, as we can read in | ||
42 | + // here (https://github.com/ngUpgraders/ng-forward/blob/master/API.md#createasync) | ||
43 | + // because createAsync in ng-forward is not really async, but as the intention | ||
44 | + // here is write tests in angular 2 ways, this is recommended | ||
45 | + done(); | ||
46 | + }); | ||
47 | + | ||
48 | + }); | ||
49 | + | ||
50 | + it("receives the article and profile as inputs", (done: Function) => { | ||
51 | + | ||
52 | + // Creating a container component (ArticleContainerComponent) to include | ||
53 | + // the component under test (ArticleView) | ||
54 | + @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [ArticleViewComponent] }) | ||
55 | + class ArticleContainerComponent { | ||
56 | + article = { type: 'anyArticleType' }; | ||
57 | + profile = { name: 'profile-name' }; | ||
58 | + constructor() { | ||
59 | + } | ||
60 | + } | ||
61 | + | ||
62 | + // uses the TestComponentBuilder instance to initialize the component | ||
63 | + createComponentFromClass(ArticleContainerComponent).then((fixture) => { | ||
64 | + // and here we can inspect and run the test assertions | ||
65 | + let articleView: ArticleViewComponent = fixture.debugElement.componentViewChildren[0].componentInstance; | ||
66 | + | ||
67 | + // assure the article object inside the ArticleView matches | ||
68 | + // the provided through the parent component | ||
69 | + expect(articleView.article.type).toEqual("anyArticleType"); | ||
70 | + expect(articleView.profile.name).toEqual("profile-name"); | ||
71 | + | ||
72 | + // done needs to be called (it isn't really needed, as we can read in | ||
73 | + // here (https://github.com/ngUpgraders/ng-forward/blob/master/API.md#createasync) | ||
74 | + // because createAsync in ng-forward is not really async, but as the intention | ||
75 | + // here is write tests in angular 2 ways, this is recommended | ||
76 | + done(); | ||
77 | + }); | ||
78 | + }); | ||
79 | + | ||
80 | + | ||
81 | + it("renders a article view which matches to the article type", done => { | ||
82 | + // NoosferoTinyMceArticle component created to check if it will be used | ||
83 | + // when a article with type 'TinyMceArticle' is provided to the noosfero-article (ArticleView) | ||
84 | + // *** Important *** - the selector is what ng-forward uses to define the name of the directive provider | ||
85 | + @Component({ selector: 'noosfero-tiny-mce-article', template: "<h1>TinyMceArticle</h1>" }) | ||
86 | + class TinyMceArticleView { | ||
87 | + @Input() article: any; | ||
88 | + @Input() profile: any; | ||
89 | + } | ||
90 | + | ||
91 | + // Creating a container component (ArticleContainerComponent) to include our NoosferoTinyMceArticle | ||
92 | + @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [ArticleViewComponent, TinyMceArticleView] }) | ||
93 | + class CustomArticleType { | ||
94 | + article = { type: 'TinyMceArticle' }; | ||
95 | + profile = { name: 'profile-name' }; | ||
96 | + constructor() { | ||
97 | + } | ||
98 | + } | ||
99 | + createComponentFromClass(CustomArticleType).then(fixture => { | ||
100 | + let myComponent: CustomArticleType = fixture.componentInstance; | ||
101 | + expect(myComponent.article.type).toEqual("TinyMceArticle"); | ||
102 | + expect(fixture.debugElement.componentViewChildren[0].text()).toEqual("TinyMceArticle"); | ||
103 | + done(); | ||
104 | + }); | ||
105 | + }); | ||
106 | + | ||
107 | + }); | ||
108 | +}); | ||
0 | \ No newline at end of file | 109 | \ No newline at end of file |
@@ -0,0 +1,57 @@ | @@ -0,0 +1,57 @@ | ||
1 | +import { bundle, Input, Inject, Component, Directive } from 'ng-forward'; | ||
2 | +import {ArticleBlogComponent} from "./types/blog/blog.component"; | ||
3 | + | ||
4 | +/** | ||
5 | + * @ngdoc controller | ||
6 | + * @name ArticleDefaultView | ||
7 | + * @description | ||
8 | + * A default view for Noosfero Articles. If the specific article view is | ||
9 | + * not implemented, then this view is used. | ||
10 | + */ | ||
11 | +@Component({ | ||
12 | + selector: 'noosfero-default-article', | ||
13 | + templateUrl: 'app/article/article.html' | ||
14 | +}) | ||
15 | +export class ArticleDefaultViewComponent { | ||
16 | + | ||
17 | + @Input() article: noosfero.Article; | ||
18 | + @Input() profile: noosfero.Profile; | ||
19 | + | ||
20 | +} | ||
21 | + | ||
22 | +/** | ||
23 | + * @ngdoc controller | ||
24 | + * @name ArticleView | ||
25 | + * @description | ||
26 | + * A dynamic view for articles. It uses the article type to replace | ||
27 | + * the default template with the custom article directive. | ||
28 | + */ | ||
29 | +@Component({ | ||
30 | + selector: 'noosfero-article', | ||
31 | + template: 'not-used', | ||
32 | + directives: [ArticleDefaultViewComponent, ArticleBlogComponent] | ||
33 | +}) | ||
34 | +@Inject("$element", "$scope", "$injector", "$compile") | ||
35 | +export class ArticleViewComponent { | ||
36 | + | ||
37 | + @Input() article: noosfero.Article; | ||
38 | + @Input() profile: noosfero.Profile; | ||
39 | + directiveName: string; | ||
40 | + | ||
41 | + ngOnInit() { | ||
42 | + let specificDirective = 'noosfero' + this.article.type; | ||
43 | + this.directiveName = "noosfero-default-article"; | ||
44 | + if (this.$injector.has(specificDirective + 'Directive')) { | ||
45 | + this.directiveName = specificDirective.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); | ||
46 | + } | ||
47 | + this.$element.replaceWith(this.$compile('<' + this.directiveName + ' [article]="ctrl.article" [profile]="ctrl.profile"></' + this.directiveName + '>')(this.$scope)); | ||
48 | + } | ||
49 | + | ||
50 | + constructor( | ||
51 | + private $element: any, | ||
52 | + private $scope: ng.IScope, | ||
53 | + private $injector: ng.auto.IInjectorService, | ||
54 | + private $compile: ng.ICompileService) { | ||
55 | + | ||
56 | + } | ||
57 | +} |
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +<div class="article"> | ||
2 | + <div class="page-header"> | ||
3 | + <h3 ng-bind="ctrl.article.title"></h3> | ||
4 | + </div> | ||
5 | + | ||
6 | + <div class="sub-header clearfix"> | ||
7 | + <div class="page-info pull-right small text-muted"> | ||
8 | + <span class="time"> | ||
9 | + <i class="fa fa-clock-o"></i> <span am-time-ago="ctrl.article.created_at | dateFormat"></span> | ||
10 | + </span> | ||
11 | + <span class="author" ng-if="ctrl.article.author"> | ||
12 | + <i class="fa fa-user"></i> | ||
13 | + <a ui-sref="main.profile.home({profile: ctrl.article.author.identifier})"> | ||
14 | + <span class="author-name" ng-bind="ctrl.article.author.name"></span> | ||
15 | + </a> | ||
16 | + </span> | ||
17 | + </div> | ||
18 | + </div> | ||
19 | + | ||
20 | + <div class="page-body"> | ||
21 | + <div ng-bind-html="ctrl.article.body"></div> | ||
22 | + </div> | ||
23 | +</div> |
@@ -0,0 +1,55 @@ | @@ -0,0 +1,55 @@ | ||
1 | +import {quickCreateComponent} from "../../spec/helpers"; | ||
2 | +import {BasicEditorComponent} from "./basic-editor.component"; | ||
3 | + | ||
4 | + | ||
5 | +describe("Article BasicEditor", () => { | ||
6 | + | ||
7 | + let $rootScope: ng.IRootScopeService; | ||
8 | + let $q: ng.IQService; | ||
9 | + let articleServiceMock: any; | ||
10 | + let profileServiceMock: any; | ||
11 | + let $state: any; | ||
12 | + let profile = { id: 1 }; | ||
13 | + let notification: any; | ||
14 | + | ||
15 | + | ||
16 | + beforeEach(inject((_$rootScope_: ng.IRootScopeService, _$q_: ng.IQService) => { | ||
17 | + $rootScope = _$rootScope_; | ||
18 | + $q = _$q_; | ||
19 | + })); | ||
20 | + | ||
21 | + beforeEach(() => { | ||
22 | + $state = jasmine.createSpyObj("$state", ["transitionTo"]); | ||
23 | + notification = jasmine.createSpyObj("notification", ["success"]); | ||
24 | + profileServiceMock = jasmine.createSpyObj("profileServiceMock", ["getCurrentProfile"]); | ||
25 | + articleServiceMock = jasmine.createSpyObj("articleServiceMock", ["createInProfile"]); | ||
26 | + | ||
27 | + let getCurrentProfileResponse = $q.defer(); | ||
28 | + getCurrentProfileResponse.resolve(profile); | ||
29 | + | ||
30 | + let articleCreate = $q.defer(); | ||
31 | + articleCreate.resolve({ data: { path: "path", profile: { identifier: "profile" } } }); | ||
32 | + | ||
33 | + profileServiceMock.getCurrentProfile = jasmine.createSpy("getCurrentProfile").and.returnValue(getCurrentProfileResponse.promise); | ||
34 | + articleServiceMock.createInProfile = jasmine.createSpy("createInProfile").and.returnValue(articleCreate.promise); | ||
35 | + }); | ||
36 | + | ||
37 | + it("create an article in the current profile when save", done => { | ||
38 | + let component: BasicEditorComponent = new BasicEditorComponent(articleServiceMock, profileServiceMock, $state, notification); | ||
39 | + component.save(); | ||
40 | + $rootScope.$apply(); | ||
41 | + expect(profileServiceMock.getCurrentProfile).toHaveBeenCalled(); | ||
42 | + expect(articleServiceMock.createInProfile).toHaveBeenCalledWith(profile, component.article); | ||
43 | + done(); | ||
44 | + }); | ||
45 | + | ||
46 | + it("got to the new article page and display an alert when saving sucessfully", done => { | ||
47 | + let component: BasicEditorComponent = new BasicEditorComponent(articleServiceMock, profileServiceMock, $state, notification); | ||
48 | + component.save(); | ||
49 | + $rootScope.$apply(); | ||
50 | + expect($state.transitionTo).toHaveBeenCalledWith("main.profile.page", { page: "path", profile: "profile" }); | ||
51 | + expect(notification.success).toHaveBeenCalled(); | ||
52 | + done(); | ||
53 | + }); | ||
54 | + | ||
55 | +}); |
@@ -0,0 +1,35 @@ | @@ -0,0 +1,35 @@ | ||
1 | +import {StateConfig, Component, Inject, provide} from 'ng-forward'; | ||
2 | +import {ArticleService} from "../../lib/ng-noosfero-api/http/article.service"; | ||
3 | +import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service"; | ||
4 | +import {NotificationService} from "../shared/services/notification.service.ts"; | ||
5 | + | ||
6 | +@Component({ | ||
7 | + selector: 'article-basic-editor', | ||
8 | + templateUrl: "app/article/basic-editor.html", | ||
9 | + providers: [ | ||
10 | + provide('articleService', { useClass: ArticleService }), | ||
11 | + provide('profileService', { useClass: ProfileService }), | ||
12 | + provide('notification', { useClass: NotificationService }) | ||
13 | + ] | ||
14 | +}) | ||
15 | +@Inject(ArticleService, ProfileService, "$state", NotificationService) | ||
16 | +export class BasicEditorComponent { | ||
17 | + | ||
18 | + article: noosfero.Article = <noosfero.Article>{}; | ||
19 | + | ||
20 | + constructor(private articleService: ArticleService, | ||
21 | + private profileService: ProfileService, | ||
22 | + private $state: ng.ui.IStateService, | ||
23 | + private notification: NotificationService) { } | ||
24 | + | ||
25 | + save() { | ||
26 | + this.profileService.getCurrentProfile().then((profile: noosfero.Profile) => { | ||
27 | + return this.articleService.createInProfile(profile, this.article); | ||
28 | + }).then((response: noosfero.RestResult<noosfero.Article>) => { | ||
29 | + let article = (<noosfero.Article>response.data); | ||
30 | + this.$state.transitionTo('main.profile.page', { page: article.path, profile: article.profile.identifier }); | ||
31 | + this.notification.success("Good job!", "Article saved!"); | ||
32 | + }); | ||
33 | + } | ||
34 | + | ||
35 | +} |
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +<form> | ||
2 | + <div class="form-group"> | ||
3 | + <label for="titleInput">Title</label> | ||
4 | + <input type="text" class="form-control" id="titleInput" placeholder="title" ng-model="vm.article.name"> | ||
5 | + </div> | ||
6 | + <div class="form-group"> | ||
7 | + <label for="bodyInput">Text</label> | ||
8 | + <textarea class="form-control" id="bodyInput" rows="10" ng-model="vm.article.body"></textarea> | ||
9 | + </div> | ||
10 | + <button type="submit" class="btn btn-default" ng-click="vm.save()">Save</button> | ||
11 | +</form> |
src/app/article/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/article/content-viewer/content-viewer-actions.component.ts
0 → 100644
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +import {Component, Inject, provide} from "ng-forward"; | ||
2 | +import {ProfileService} from "../../../lib/ng-noosfero-api/http/profile.service"; | ||
3 | + | ||
4 | +@Component({ | ||
5 | + selector: "content-viewer-actions", | ||
6 | + templateUrl: "app/article/content-viewer/navbar-actions.html", | ||
7 | + providers: [provide('profileService', { useClass: ProfileService })] | ||
8 | +}) | ||
9 | +@Inject(ProfileService) | ||
10 | +export class ContentViewerActions { | ||
11 | + | ||
12 | + article: noosfero.Article; | ||
13 | + profile: noosfero.Profile; | ||
14 | + | ||
15 | + constructor(profileService: ProfileService) { | ||
16 | + profileService.getCurrentProfile().then((profile: noosfero.Profile) => { | ||
17 | + this.profile = profile; | ||
18 | + }); | ||
19 | + } | ||
20 | +} |
src/app/article/content-viewer/content-viewer.component.spec.ts
0 → 100644
@@ -0,0 +1,88 @@ | @@ -0,0 +1,88 @@ | ||
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 {ContentViewerComponent} 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: [ContentViewerComponent], | ||
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 | + let article: any = { | ||
59 | + id: 1, | ||
60 | + title: 'The article test' | ||
61 | + }; | ||
62 | + let 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.getArticleByProfileAndPath = (profile: noosfero.Profile, path: string) => { | ||
73 | + return helpers.mocks.promiseResultTemplate({ | ||
74 | + data: article | ||
75 | + }); | ||
76 | + }; | ||
77 | + | ||
78 | + | ||
79 | + buildComponent().then((fixture: ComponentFixture) => { | ||
80 | + let contentViewerComp: ContentViewerComponent = fixture.debugElement.componentViewChildren[0].componentInstance; | ||
81 | + | ||
82 | + expect(contentViewerComp.profile).toEqual(profile); | ||
83 | + expect(contentViewerComp.article).toEqual(article); | ||
84 | + | ||
85 | + done(); | ||
86 | + }); | ||
87 | + }); | ||
88 | +}); |
src/app/article/content-viewer/content-viewer.component.ts
0 → 100644
@@ -0,0 +1,38 @@ | @@ -0,0 +1,38 @@ | ||
1 | +import {ArticleViewComponent} from "./../article-default-view.component"; | ||
2 | +import {Input, Component, StateConfig, Inject, provide} from "ng-forward"; | ||
3 | + | ||
4 | +import {ArticleBlogComponent} from "./../types/blog/blog.component"; | ||
5 | +import {ArticleService} from "../../../lib/ng-noosfero-api/http/article.service"; | ||
6 | +import {ProfileService} from "../../../lib/ng-noosfero-api/http/profile.service"; | ||
7 | + | ||
8 | +@Component({ | ||
9 | + selector: "content-viewer", | ||
10 | + templateUrl: "app/article/content-viewer/page.html", | ||
11 | + directives: [ArticleBlogComponent, ArticleViewComponent], | ||
12 | + providers: [ | ||
13 | + provide('articleService', { useClass: ArticleService }), | ||
14 | + provide('profileService', { useClass: ProfileService }) | ||
15 | + ] | ||
16 | +}) | ||
17 | +@Inject(ArticleService, ProfileService, "$log", "$stateParams") | ||
18 | +export class ContentViewerComponent { | ||
19 | + | ||
20 | + @Input() | ||
21 | + article: noosfero.Article = null; | ||
22 | + | ||
23 | + @Input() | ||
24 | + profile: noosfero.Profile = null; | ||
25 | + | ||
26 | + constructor(private articleService: ArticleService, private profileService: ProfileService, private $log: ng.ILogService, private $stateParams: angular.ui.IStateParamsService) { | ||
27 | + this.activate(); | ||
28 | + } | ||
29 | + | ||
30 | + activate() { | ||
31 | + this.profileService.getCurrentProfile().then((profile: noosfero.Profile) => { | ||
32 | + this.profile = profile; | ||
33 | + return this.articleService.getArticleByProfileAndPath(this.profile, this.$stateParams["page"]); | ||
34 | + }).then((result: noosfero.RestResult<any>) => { | ||
35 | + this.article = <noosfero.Article>result.data; | ||
36 | + }); | ||
37 | + } | ||
38 | +} |
@@ -0,0 +1,7 @@ | @@ -0,0 +1,7 @@ | ||
1 | +<ul class="nav navbar-nav"> | ||
2 | + <li ng-show="vm.profile"> | ||
3 | + <a href="#" role="button" ui-sref="main.profile.cms({profile: vm.profile.identifier})"> | ||
4 | + <i class="fa fa-file fa-fw fa-lg"></i> {{"navbar.content_viewer_actions.new_post" | translate}} | ||
5 | + </a> | ||
6 | + </li> | ||
7 | +</ul> |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +<noosfero-article ng-if="vm.article" [article]="vm.article" [profile]="vm.profile"></noosfero-article> |
@@ -0,0 +1,129 @@ | @@ -0,0 +1,129 @@ | ||
1 | +import { | ||
2 | +providers | ||
3 | +} from 'ng-forward/cjs/testing/providers'; | ||
4 | + | ||
5 | +import { | ||
6 | +Input, | ||
7 | +Component | ||
8 | +} from 'ng-forward'; | ||
9 | +import { | ||
10 | +ArticleBlogComponent | ||
11 | +} from './blog.component'; | ||
12 | + | ||
13 | +import { | ||
14 | +createComponentFromClass, | ||
15 | +quickCreateComponent, | ||
16 | +provideEmptyObjects, | ||
17 | +createProviderToValue, | ||
18 | +provideFilters | ||
19 | +} from "../../../../spec/helpers.ts"; | ||
20 | + | ||
21 | +// this htmlTemplate will be re-used between the container components in this spec file | ||
22 | +const htmlTemplate: string = '<noosfero-blog [article]="ctrl.article" [profile]="ctrl.profile"></noosfero-blog>'; | ||
23 | + | ||
24 | +describe("Blog Component", () => { | ||
25 | + | ||
26 | + function promiseResultTemplate(response?: {}) { | ||
27 | + let thenFuncEmpty = (func: Function) => { | ||
28 | + // does nothing | ||
29 | + }; | ||
30 | + if (response) { | ||
31 | + return { | ||
32 | + then: (func: (response: any) => void) => { | ||
33 | + func(response); | ||
34 | + } | ||
35 | + }; | ||
36 | + } else { | ||
37 | + return { | ||
38 | + then: (func: (response: any) => void) => { | ||
39 | + // does nothing | ||
40 | + } | ||
41 | + }; | ||
42 | + } | ||
43 | + } | ||
44 | + | ||
45 | + let articleService = { | ||
46 | + getChildren: (article_id: number, filters: {}) => { | ||
47 | + return promiseResultTemplate(null); | ||
48 | + } | ||
49 | + }; | ||
50 | + | ||
51 | + @Component({ | ||
52 | + selector: 'test-container-component', | ||
53 | + template: htmlTemplate, | ||
54 | + directives: [ArticleBlogComponent], | ||
55 | + providers: [ | ||
56 | + provideEmptyObjects('Restangular'), | ||
57 | + createProviderToValue('ArticleService', articleService), | ||
58 | + provideFilters('truncateFilter') | ||
59 | + ] | ||
60 | + }) | ||
61 | + class BlogContainerComponent { | ||
62 | + article = { | ||
63 | + type: 'anyArticleType' | ||
64 | + }; | ||
65 | + profile = { | ||
66 | + name: 'profile-name' | ||
67 | + }; | ||
68 | + } | ||
69 | + | ||
70 | + beforeEach(() => { | ||
71 | + | ||
72 | + // the karma preprocessor html2js transform the templates html into js files which put | ||
73 | + // the templates to the templateCache into the module templates | ||
74 | + // we need to load the module templates here as the template for the | ||
75 | + // component Noosfero ArtileView will be load on our tests | ||
76 | + angular.mock.module("templates"); | ||
77 | + | ||
78 | + providers((provide: any) => { | ||
79 | + return <any>[ | ||
80 | + provide('ArticleService', { | ||
81 | + useValue: articleService | ||
82 | + }) | ||
83 | + ]; | ||
84 | + }); | ||
85 | + }); | ||
86 | + | ||
87 | + it("renders the blog content", (done: Function) => { | ||
88 | + | ||
89 | + createComponentFromClass(BlogContainerComponent).then((fixture) => { | ||
90 | + | ||
91 | + expect(fixture.debugElement.query('div.blog').length).toEqual(1); | ||
92 | + | ||
93 | + done(); | ||
94 | + }); | ||
95 | + }); | ||
96 | + | ||
97 | + it("verify the blog data", (done: Function) => { | ||
98 | + | ||
99 | + let articles = [{ | ||
100 | + id: 1, | ||
101 | + title: 'The article test' | ||
102 | + }]; | ||
103 | + | ||
104 | + let result = { data: articles, headers: (name: string) => { return 1; } }; | ||
105 | + | ||
106 | + // defining a mock result to articleService.getChildren method | ||
107 | + articleService.getChildren = (article_id: number, filters: {}) => { | ||
108 | + return promiseResultTemplate(result); | ||
109 | + }; | ||
110 | + | ||
111 | + createComponentFromClass(BlogContainerComponent).then((fixture) => { | ||
112 | + | ||
113 | + // gets the children component of BlogContainerComponent | ||
114 | + let articleBlog: BlogContainerComponent = fixture.debugElement.componentViewChildren[0].componentInstance; | ||
115 | + | ||
116 | + // check if the component property are the provided by the mocked articleService | ||
117 | + let post = { | ||
118 | + id: 1, | ||
119 | + title: 'The article test' | ||
120 | + }; | ||
121 | + expect((<any>articleBlog)["posts"][0]).toEqual(jasmine.objectContaining(post)); | ||
122 | + expect((<any>articleBlog)["totalPosts"]).toEqual(1); | ||
123 | + | ||
124 | + done(); | ||
125 | + }); | ||
126 | + | ||
127 | + }); | ||
128 | + | ||
129 | +}); | ||
0 | \ No newline at end of file | 130 | \ No newline at end of file |
@@ -0,0 +1,47 @@ | @@ -0,0 +1,47 @@ | ||
1 | +import {Component, Input, Inject} from "ng-forward"; | ||
2 | + | ||
3 | +import {ArticleService} from "../../../../lib/ng-noosfero-api/http/article.service"; | ||
4 | + | ||
5 | +/** | ||
6 | + * @ngdoc controller | ||
7 | + * @name ArticleBlog | ||
8 | + * @description | ||
9 | + * An specific {@link ArticleView} for Blog articles. | ||
10 | + */ | ||
11 | +@Component({ | ||
12 | + selector: "noosfero-blog", | ||
13 | + templateUrl: "app/article/types/blog/blog.html" | ||
14 | +}) | ||
15 | +@Inject(ArticleService) | ||
16 | +export class ArticleBlogComponent { | ||
17 | + | ||
18 | + @Input() article: noosfero.Article; | ||
19 | + @Input() profile: noosfero.Profile; | ||
20 | + | ||
21 | + private posts: noosfero.Article[]; | ||
22 | + private perPage: number = 3; | ||
23 | + private currentPage: number; | ||
24 | + private totalPosts: number = 0; | ||
25 | + | ||
26 | + constructor(private articleService: ArticleService) { } | ||
27 | + | ||
28 | + ngOnInit() { | ||
29 | + this.loadPage(); | ||
30 | + } | ||
31 | + | ||
32 | + loadPage() { | ||
33 | + let filters = { | ||
34 | + content_type: "TinyMceArticle", | ||
35 | + per_page: this.perPage, | ||
36 | + page: this.currentPage | ||
37 | + }; | ||
38 | + | ||
39 | + this.articleService | ||
40 | + .getChildren(this.article, filters) | ||
41 | + .then((result: noosfero.RestResult<noosfero.Article[]>) => { | ||
42 | + this.totalPosts = <number>result.headers("total"); | ||
43 | + this.posts = result.data; | ||
44 | + }); | ||
45 | + } | ||
46 | + | ||
47 | +} |
@@ -0,0 +1,24 @@ | @@ -0,0 +1,24 @@ | ||
1 | +<div class="blog"> | ||
2 | + <div class="blog-cover" ng-show="ctrl.article.image"> | ||
3 | + <img ng-src="{{ctrl.article.image.url}}" class="img-responsive"> | ||
4 | + <h3 ng-bind="ctrl.article.title"></h3> | ||
5 | + </div> | ||
6 | + | ||
7 | + <div class="page-header" ng-show="!ctrl.article.image"> | ||
8 | + <h3 ng-bind="ctrl.article.title"></h3> | ||
9 | + </div> | ||
10 | + | ||
11 | + <div> | ||
12 | + <div ng-repeat="child in ctrl.posts | orderBy: 'created_at':true"> | ||
13 | + <div class="page-header"> | ||
14 | + <a class="title" ui-sref="main.profile.page({profile: ctrl.profile.identifier, page: child.path})"><h4 ng-bind="child.title"></h4></a> | ||
15 | + <div class="post-lead" ng-bind-html="child.body | truncate: 500: '...': true"></div> | ||
16 | + </div> | ||
17 | + </div> | ||
18 | + </div> | ||
19 | + | ||
20 | + <pagination ng-model="ctrl.currentPage" total-items="ctrl.totalPosts" class="pagination-sm center-block" | ||
21 | + boundary-links="true" items-per-page="ctrl.perPage" ng-change="ctrl.loadPage()" | ||
22 | + first-text="«" last-text="»" previous-text="‹" next-text="›"> | ||
23 | + </pagination> | ||
24 | +</div> |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/cms/cms.component.spec.ts
@@ -1,54 +0,0 @@ | @@ -1,54 +0,0 @@ | ||
1 | -import {quickCreateComponent} from "../../spec/helpers"; | ||
2 | -import {Cms} from "./cms.component"; | ||
3 | - | ||
4 | -describe("Components", () => { | ||
5 | - describe("Cms Component", () => { | ||
6 | - | ||
7 | - let $rootScope: ng.IRootScopeService; | ||
8 | - let $q: ng.IQService; | ||
9 | - let articleServiceMock: any; | ||
10 | - let profileServiceMock: any; | ||
11 | - let $state: any; | ||
12 | - let notification: any; | ||
13 | - | ||
14 | - beforeEach(inject((_$rootScope_: ng.IRootScopeService, _$q_: ng.IQService) => { | ||
15 | - $rootScope = _$rootScope_; | ||
16 | - $q = _$q_; | ||
17 | - })); | ||
18 | - | ||
19 | - beforeEach(() => { | ||
20 | - $state = jasmine.createSpyObj("$state", ["transitionTo"]); | ||
21 | - notification = jasmine.createSpyObj("notification", ["success"]); | ||
22 | - profileServiceMock = jasmine.createSpyObj("profileServiceMock", ["getCurrentProfile"]); | ||
23 | - articleServiceMock = jasmine.createSpyObj("articleServiceMock", ["create"]); | ||
24 | - | ||
25 | - let getCurrentProfileResponse = $q.defer(); | ||
26 | - getCurrentProfileResponse.resolve({ id: 1 }); | ||
27 | - | ||
28 | - let articleCreate = $q.defer(); | ||
29 | - articleCreate.resolve({ data: { article: { path: "path", profile: { identifier: "profile" } } } }); | ||
30 | - | ||
31 | - profileServiceMock.getCurrentProfile = jasmine.createSpy("getCurrentProfile").and.returnValue(getCurrentProfileResponse.promise); | ||
32 | - articleServiceMock.create = jasmine.createSpy("create").and.returnValue(articleCreate.promise); | ||
33 | - }); | ||
34 | - | ||
35 | - it("create an article in the current profile when save", done => { | ||
36 | - let component: Cms = new Cms(articleServiceMock, profileServiceMock, $state, notification); | ||
37 | - component.save(); | ||
38 | - $rootScope.$apply(); | ||
39 | - expect(profileServiceMock.getCurrentProfile).toHaveBeenCalled(); | ||
40 | - expect(articleServiceMock.create).toHaveBeenCalledWith(1, component.article); | ||
41 | - done(); | ||
42 | - }); | ||
43 | - | ||
44 | - it("got to the new article page and display an alert when saving sucessfully", done => { | ||
45 | - let component: Cms = new Cms(articleServiceMock, profileServiceMock, $state, notification); | ||
46 | - component.save(); | ||
47 | - $rootScope.$apply(); | ||
48 | - expect($state.transitionTo).toHaveBeenCalledWith("main.profile.page", { page: "path", profile: "profile" }); | ||
49 | - expect(notification.success).toHaveBeenCalled(); | ||
50 | - done(); | ||
51 | - }); | ||
52 | - | ||
53 | - }); | ||
54 | -}); |
src/app/cms/cms.component.ts
@@ -1,35 +0,0 @@ | @@ -1,35 +0,0 @@ | ||
1 | -import {StateConfig, Component, Inject, provide} from 'ng-forward'; | ||
2 | -import {Profile} from "./../models/interfaces"; | ||
3 | -import {ArticleService} from "../../lib/ng-noosfero-api/http/article.service"; | ||
4 | -import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service"; | ||
5 | -import {Notification} from "../components/notification/notification.component"; | ||
6 | - | ||
7 | -@Component({ | ||
8 | - selector: 'cms', | ||
9 | - templateUrl: "app/cms/cms.html", | ||
10 | - providers: [ | ||
11 | - provide('articleService', { useClass: ArticleService }), | ||
12 | - provide('profileService', { useClass: ProfileService }), | ||
13 | - provide('notification', { useClass: Notification }) | ||
14 | - ] | ||
15 | -}) | ||
16 | -@Inject(ArticleService, ProfileService, "$state", Notification) | ||
17 | -export class Cms { | ||
18 | - | ||
19 | - article: any = {}; | ||
20 | - | ||
21 | - constructor(private articleService: ArticleService, | ||
22 | - private profileService: ProfileService, | ||
23 | - private $state: ng.ui.IStateService, | ||
24 | - private notification: Notification) { } | ||
25 | - | ||
26 | - save() { | ||
27 | - this.profileService.getCurrentProfile().then((profile: Profile) => { | ||
28 | - return this.articleService.create(profile.id, this.article); | ||
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!"); | ||
32 | - }); | ||
33 | - } | ||
34 | - | ||
35 | -} |
src/app/cms/cms.html
@@ -1,11 +0,0 @@ | @@ -1,11 +0,0 @@ | ||
1 | -<form> | ||
2 | - <div class="form-group"> | ||
3 | - <label for="titleInput">Title</label> | ||
4 | - <input type="text" class="form-control" id="titleInput" placeholder="title" ng-model="vm.article.name"> | ||
5 | - </div> | ||
6 | - <div class="form-group"> | ||
7 | - <label for="bodyInput">Text</label> | ||
8 | - <textarea class="form-control" id="bodyInput" rows="10" ng-model="vm.article.body"></textarea> | ||
9 | - </div> | ||
10 | - <button type="submit" class="btn btn-default" ng-click="vm.save()">Save</button> | ||
11 | -</form> |
src/app/cms/index.ts
src/app/components/auth/auth_controller.spec.ts
@@ -1,33 +0,0 @@ | @@ -1,33 +0,0 @@ | ||
1 | -import {AuthController} from "./auth_controller"; | ||
2 | -import {AuthService} from "./auth_service"; | ||
3 | - | ||
4 | -describe("Controllers", () => { | ||
5 | - | ||
6 | - | ||
7 | - describe("AuthController", () => { | ||
8 | - | ||
9 | - it("calls authenticate on AuthService when login called", () => { | ||
10 | - | ||
11 | - // creating a Mock AuthService | ||
12 | - let AuthServiceMock: AuthService = jasmine.createSpyObj("AuthService", ["login"]); | ||
13 | - | ||
14 | - // pass AuthServiceMock into the constructor | ||
15 | - let authController = new AuthController(null, null, AuthServiceMock); | ||
16 | - | ||
17 | - // setup of authController -> set the credentials instance property | ||
18 | - let credentials = { username: "username", password: "password" }; | ||
19 | - | ||
20 | - authController.credentials = credentials; | ||
21 | - | ||
22 | - // calls the authController login method | ||
23 | - authController.login(); | ||
24 | - | ||
25 | - // checks if the method login of the injected AuthService has been called | ||
26 | - expect(AuthServiceMock.login).toHaveBeenCalledWith(credentials); | ||
27 | - | ||
28 | - }); | ||
29 | - | ||
30 | - | ||
31 | - | ||
32 | - }); | ||
33 | -}); |
src/app/components/auth/auth_controller.ts
@@ -1,21 +0,0 @@ | @@ -1,21 +0,0 @@ | ||
1 | -import {Credentials} from "./../../models/interfaces"; | ||
2 | -import {AuthService} from "./auth_service"; | ||
3 | - | ||
4 | -export class AuthController { | ||
5 | - | ||
6 | - static $inject = ["$log", "$stateParams", "AuthService"]; | ||
7 | - | ||
8 | - constructor( | ||
9 | - private $log: ng.ILogService, | ||
10 | - private $stateParams: any, | ||
11 | - private AuthService: AuthService | ||
12 | - ) { | ||
13 | - | ||
14 | - } | ||
15 | - | ||
16 | - credentials: Credentials; | ||
17 | - | ||
18 | - login() { | ||
19 | - this.AuthService.login(this.credentials); | ||
20 | - } | ||
21 | -} |
src/app/components/auth/auth_events.ts
@@ -1,11 +0,0 @@ | @@ -1,11 +0,0 @@ | ||
1 | -export interface IAuthEvents { | ||
2 | - loginSuccess: string; | ||
3 | - loginFailed: string; | ||
4 | - logoutSuccess: string; | ||
5 | -} | ||
6 | - | ||
7 | -export const AUTH_EVENTS: IAuthEvents = { | ||
8 | - loginSuccess: "auth-login-success", | ||
9 | - loginFailed: "auth-login-failed", | ||
10 | - logoutSuccess: "auth-logout-success" | ||
11 | -}; | ||
12 | \ No newline at end of file | 0 | \ No newline at end of file |
src/app/components/auth/auth_service.spec.ts
@@ -1,82 +0,0 @@ | @@ -1,82 +0,0 @@ | ||
1 | - | ||
2 | - | ||
3 | -import {AuthService, AUTH_EVENTS} from "./"; | ||
4 | -import {User, Credentials} from "./../../models/interfaces"; | ||
5 | - | ||
6 | -describe("Services", () => { | ||
7 | - | ||
8 | - | ||
9 | - describe("Auth Service", () => { | ||
10 | - | ||
11 | - let $httpBackend: ng.IHttpBackendService; | ||
12 | - let authService: AuthService; | ||
13 | - let credentials: Credentials; | ||
14 | - let $rootScope: ng.IRootScopeService; | ||
15 | - let user: User; | ||
16 | - | ||
17 | - beforeEach(angular.mock.module("noosferoApp", ($translateProvider: angular.translate.ITranslateProvider) => { | ||
18 | - $translateProvider.translations('en', {}); | ||
19 | - })); | ||
20 | - | ||
21 | - beforeEach(inject((_$httpBackend_: ng.IHttpBackendService, _$rootScope_: ng.IRootScopeService, _AuthService_: AuthService) => { | ||
22 | - $httpBackend = _$httpBackend_; | ||
23 | - authService = _AuthService_; | ||
24 | - $rootScope = _$rootScope_; | ||
25 | - | ||
26 | - user = <User>{ | ||
27 | - id: 1, | ||
28 | - login: "user" | ||
29 | - }; | ||
30 | - })); | ||
31 | - | ||
32 | - | ||
33 | - describe("Succesffull login", () => { | ||
34 | - | ||
35 | - beforeEach(() => { | ||
36 | - credentials = { username: "user", password: "password" }; | ||
37 | - | ||
38 | - $httpBackend.expectPOST("/api/v1/login", "login=user&password=password").respond(200, { user: user }); | ||
39 | - }); | ||
40 | - | ||
41 | - it("should return loggedUser", (done) => { | ||
42 | - authService.login(credentials).then((loggedUser) => { | ||
43 | - expect(loggedUser).toBeDefined(); | ||
44 | - done(); | ||
45 | - }); | ||
46 | - $httpBackend.flush(); | ||
47 | - expect($httpBackend.verifyNoOutstandingRequest()); | ||
48 | - }); | ||
49 | - | ||
50 | - | ||
51 | - it("should emit event loggin successful with user logged data", () => { | ||
52 | - | ||
53 | - authService.login(credentials); | ||
54 | - | ||
55 | - let eventEmmited: boolean = false; | ||
56 | - $rootScope.$on(AUTH_EVENTS.loginSuccess, (event: ng.IAngularEvent, userThroughEvent: User) => { | ||
57 | - eventEmmited = true; | ||
58 | - expect(userThroughEvent).toEqual(user) | ||
59 | - }); | ||
60 | - | ||
61 | - $httpBackend.flush(); | ||
62 | - | ||
63 | - expect(eventEmmited).toBeTruthy(AUTH_EVENTS.loginSuccess + " was not emmited!"); | ||
64 | - }); | ||
65 | - | ||
66 | - it("should return the current logged in user", () => { | ||
67 | - authService.login(credentials); | ||
68 | - $httpBackend.flush(); | ||
69 | - let actual: User = authService.currentUser(); | ||
70 | - expect(actual).toEqual(user, "The returned user must be present"); | ||
71 | - }); | ||
72 | - | ||
73 | - it("should not return the current user after logout", () => { | ||
74 | - authService.logout(); | ||
75 | - let actual: any = authService.currentUser(); | ||
76 | - expect(actual).toEqual(undefined, "The returned user must not be defined"); | ||
77 | - }); | ||
78 | - }); | ||
79 | - | ||
80 | - | ||
81 | - }); | ||
82 | -}); |
src/app/components/auth/auth_service.ts
@@ -1,69 +0,0 @@ | @@ -1,69 +0,0 @@ | ||
1 | -import {Injectable, Inject} from "ng-forward"; | ||
2 | - | ||
3 | -import {Credentials, NoosferoRootScope, User, UserResponse} from "./../../models/interfaces"; | ||
4 | -import {Session} from "./session"; | ||
5 | - | ||
6 | -import {AUTH_EVENTS, IAuthEvents} from "./auth_events"; | ||
7 | - | ||
8 | -@Injectable() | ||
9 | -@Inject("$q", "$http", "$rootScope", "Session", "$log", "AUTH_EVENTS") | ||
10 | -export class AuthService { | ||
11 | - | ||
12 | - constructor(private $q: ng.IQService, | ||
13 | - private $http: ng.IHttpService, | ||
14 | - private $rootScope: NoosferoRootScope, | ||
15 | - private session: Session, | ||
16 | - private $log: ng.ILogService, | ||
17 | - private auth_events: IAuthEvents) { | ||
18 | - | ||
19 | - } | ||
20 | - | ||
21 | - loginFromCookie() { | ||
22 | - let url: string = '/api/v1/login_from_cookie'; | ||
23 | - return this.$http.post(url, null).then(this.loginSuccessCallback.bind(this), this.loginFailedCallback.bind(this)); | ||
24 | - } | ||
25 | - | ||
26 | - | ||
27 | - private loginSuccessCallback(response: ng.IHttpPromiseCallbackArg<UserResponse>) { | ||
28 | - this.$log.debug('AuthService.login [SUCCESS] response', response); | ||
29 | - let currentUser: User = this.session.create(response.data); | ||
30 | - this.$rootScope.currentUser = currentUser; | ||
31 | - this.$rootScope.$broadcast(this.auth_events.loginSuccess, currentUser); | ||
32 | - return currentUser; | ||
33 | - } | ||
34 | - | ||
35 | - login(credentials: Credentials): ng.IPromise<User> { | ||
36 | - let url = '/api/v1/login'; | ||
37 | - let encodedData = 'login=' + credentials.username + '&password=' + credentials.password; | ||
38 | - return this.$http.post(url, encodedData).then(this.loginSuccessCallback.bind(this), this.loginFailedCallback.bind(this)); | ||
39 | - } | ||
40 | - | ||
41 | - private loginFailedCallback(response: ng.IHttpPromiseCallbackArg<any>): any { | ||
42 | - this.$log.debug('AuthService.login [FAIL] response', response); | ||
43 | - this.$rootScope.$broadcast(this.auth_events.loginFailed); | ||
44 | - // return $q.reject(response); | ||
45 | - return null; | ||
46 | - } | ||
47 | - | ||
48 | - public logout() { | ||
49 | - this.session.destroy(); | ||
50 | - this.$rootScope.currentUser = undefined; | ||
51 | - this.$rootScope.$broadcast(this.auth_events.logoutSuccess); | ||
52 | - this.$http.jsonp('/account/logout'); // FIXME logout from noosfero to sync login state | ||
53 | - } | ||
54 | - | ||
55 | - public isAuthenticated() { | ||
56 | - return !!this.session.currentUser(); | ||
57 | - } | ||
58 | - | ||
59 | - public currentUser(): User { | ||
60 | - return this.session.currentUser(); | ||
61 | - } | ||
62 | - | ||
63 | - public isAuthorized(authorizedRoles: string | string[]) { | ||
64 | - if (!angular.isArray(authorizedRoles)) { | ||
65 | - authorizedRoles = [<string>authorizedRoles]; | ||
66 | - } | ||
67 | - return (this.isAuthenticated() && authorizedRoles.indexOf(this.session.currentUser().userRole) !== -1); | ||
68 | - } | ||
69 | -} | ||
70 | \ No newline at end of file | 0 | \ No newline at end of file |
src/app/components/auth/index.ts
src/app/components/auth/login.html
@@ -1,16 +0,0 @@ | @@ -1,16 +0,0 @@ | ||
1 | -<div class="modal-header"> | ||
2 | - <h3 class="modal-title">{{"auth.title" | translate}}</h3> | ||
3 | -</div> | ||
4 | -<div class="modal-body"> | ||
5 | - <form> | ||
6 | - <div class="form-group"> | ||
7 | - <label for="exampleInputEmail1">{{"auth.form.login" | translate}}</label> | ||
8 | - <input type="text" class="form-control" id="exampleInputEmail1" placeholder="Login / Email" ng-model="vm.credentials.username"> | ||
9 | - </div> | ||
10 | - <div class="form-group"> | ||
11 | - <label for="exampleInputPassword1">{{"auth.form.password" | translate}}</label> | ||
12 | - <input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password" ng-model="vm.credentials.password"> | ||
13 | - </div> | ||
14 | - <button type="submit" class="btn btn-default" ng-click="vm.login()">{{"auth.form.login_button" | translate}}</button> | ||
15 | - </form> | ||
16 | -</div> |
src/app/components/auth/session.ts
@@ -1,27 +0,0 @@ | @@ -1,27 +0,0 @@ | ||
1 | -import {Injectable, Inject} from "ng-forward"; | ||
2 | -import {UserResponse, User, INoosferoLocalStorage} from "./../../models/interfaces"; | ||
3 | - | ||
4 | -@Injectable() | ||
5 | -@Inject("$localStorage", "$log") | ||
6 | -export class Session { | ||
7 | - | ||
8 | - constructor(private $localStorage: INoosferoLocalStorage, private $log: ng.ILogService) { | ||
9 | - | ||
10 | - } | ||
11 | - | ||
12 | - create(data: UserResponse): User { | ||
13 | - this.$localStorage.currentUser = data.user; | ||
14 | - this.$log.debug('User session created.', this.$localStorage.currentUser); | ||
15 | - return this.$localStorage.currentUser; | ||
16 | - }; | ||
17 | - | ||
18 | - destroy() { | ||
19 | - delete this.$localStorage.currentUser; | ||
20 | - this.$log.debug('User session destroyed.'); | ||
21 | - }; | ||
22 | - | ||
23 | - currentUser(): User { | ||
24 | - return this.$localStorage.currentUser; | ||
25 | - }; | ||
26 | - | ||
27 | -} | ||
28 | \ No newline at end of file | 0 | \ No newline at end of file |
src/app/components/auth/session_spec.ts
@@ -1,49 +0,0 @@ | @@ -1,49 +0,0 @@ | ||
1 | -import {Component} from "ng-forward"; | ||
2 | -import {Session} from "./"; | ||
3 | -import {fixtures, createComponentFromClass, createProviderToValue} from "./../../../spec/helpers"; | ||
4 | -import {UserResponse, User, INoosferoLocalStorage} from "./../../models/interfaces"; | ||
5 | - | ||
6 | - | ||
7 | -describe("Services", () => { | ||
8 | - | ||
9 | - | ||
10 | - describe("Session Service", () => { | ||
11 | - | ||
12 | - let $localStorage: INoosferoLocalStorage = null; | ||
13 | - let $log: any; | ||
14 | - | ||
15 | - beforeEach(() => { | ||
16 | - $localStorage = <INoosferoLocalStorage>{ currentUser: null }; | ||
17 | - $log = jasmine.createSpyObj('$log', ['debug']); | ||
18 | - }); | ||
19 | - | ||
20 | - it("method 'create()' saves the current user on $localstorage service", () => { | ||
21 | - let session = new Session($localStorage, $log); | ||
22 | - let userResponse = <UserResponse>{ | ||
23 | - user: fixtures.user | ||
24 | - }; | ||
25 | - session.create(userResponse); | ||
26 | - expect($localStorage.currentUser).toEqual(userResponse.user); | ||
27 | - }); | ||
28 | - | ||
29 | - it("method 'destroy()' clean the currentUser on $localstorage", () => { | ||
30 | - let session = new Session($localStorage, $log); | ||
31 | - let userResponse = <UserResponse>{ | ||
32 | - user: fixtures.user | ||
33 | - }; | ||
34 | - $localStorage.currentUser = fixtures.user; | ||
35 | - session.destroy(); | ||
36 | - expect($localStorage.currentUser).toBeUndefined(); | ||
37 | - }); | ||
38 | - | ||
39 | - it("method 'currentUser()' returns the user recorded on $localstorage service", () => { | ||
40 | - let session = new Session($localStorage, $log); | ||
41 | - let userResponse = <UserResponse>{ | ||
42 | - user: fixtures.user | ||
43 | - }; | ||
44 | - $localStorage.currentUser = fixtures.user; | ||
45 | - expect(session.currentUser()).toEqual($localStorage.currentUser); | ||
46 | - }); | ||
47 | - }); | ||
48 | - | ||
49 | -}); | ||
50 | \ No newline at end of file | 0 | \ No newline at end of file |
src/app/components/index.ts
@@ -1 +0,0 @@ | @@ -1 +0,0 @@ | ||
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/language-selector/language-selector.component.spec.ts
@@ -1,46 +0,0 @@ | @@ -1,46 +0,0 @@ | ||
1 | -import {ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder'; | ||
2 | -import {provide} from 'ng-forward'; | ||
3 | - | ||
4 | -import {LanguageSelector} from './language-selector.component'; | ||
5 | - | ||
6 | -import * as helpers from "../../../spec/helpers"; | ||
7 | - | ||
8 | -describe("Components", () => { | ||
9 | - | ||
10 | - describe("Language Selector Component", () => { | ||
11 | - | ||
12 | - beforeEach(angular.mock.module("templates")); | ||
13 | - | ||
14 | - let translatorService: any; | ||
15 | - | ||
16 | - let buildComponent = (): Promise<ComponentFixture> => { | ||
17 | - translatorService = jasmine.createSpyObj("translatorService", ["availableLanguages", "currentLanguage"]) | ||
18 | - return helpers.quickCreateComponent({ | ||
19 | - template: "<language-selector></language-selector>", | ||
20 | - directives: [LanguageSelector], | ||
21 | - providers: [ | ||
22 | - provide('TranslatorService', { | ||
23 | - useValue: translatorService | ||
24 | - }) | ||
25 | - ].concat(helpers.provideFilters("translateFilter")) | ||
26 | - }); | ||
27 | - } | ||
28 | - | ||
29 | - it("display language options", (done) => { | ||
30 | - buildComponent().then(fixture => { | ||
31 | - fixture.debugElement.getLocal("$rootScope").$apply(); | ||
32 | - expect(fixture.debugElement.queryAll('li.language').length).toEqual(2); | ||
33 | - done(); | ||
34 | - }); | ||
35 | - }); | ||
36 | - | ||
37 | - it("call the translator service when change the language", (done) => { | ||
38 | - let translatorService = jasmine.createSpyObj("translatorService", ["changeLanguage"]); | ||
39 | - let languageSelector = new LanguageSelector(<any>translatorService); | ||
40 | - languageSelector.changeLanguage("en"); | ||
41 | - expect(translatorService.changeLanguage).toHaveBeenCalledWith("en"); | ||
42 | - done(); | ||
43 | - }); | ||
44 | - | ||
45 | - }); | ||
46 | -}); |
src/app/components/language-selector/language-selector.component.ts
@@ -1,24 +0,0 @@ | @@ -1,24 +0,0 @@ | ||
1 | -import {Component, Inject} from "ng-forward"; | ||
2 | -import {TranslatorService} from "../translator/translator.service"; | ||
3 | - | ||
4 | -@Component({ | ||
5 | - selector: "language-selector", | ||
6 | - templateUrl: "app/components/language-selector/language-selector.html" | ||
7 | -}) | ||
8 | -@Inject(TranslatorService) | ||
9 | -export class LanguageSelector { | ||
10 | - | ||
11 | - constructor(private translatorService: TranslatorService) { } | ||
12 | - | ||
13 | - currentLanguage() { | ||
14 | - return this.translatorService.currentLanguage(); | ||
15 | - } | ||
16 | - | ||
17 | - changeLanguage(language: string) { | ||
18 | - this.translatorService.changeLanguage(language); | ||
19 | - } | ||
20 | - | ||
21 | - availableLanguages() { | ||
22 | - return this.translatorService.availableLanguages; | ||
23 | - } | ||
24 | -} |
src/app/components/language-selector/language-selector.html
@@ -1,13 +0,0 @@ | @@ -1,13 +0,0 @@ | ||
1 | -<li class="dropdown profile-menu" dropdown> | ||
2 | - <a href="#" class="dropdown-toggle" aria-expanded="false" dropdown-toggle> | ||
3 | - <span>{{"language.selector" | translate}}</span> <b class="caret"></b> | ||
4 | - </a> | ||
5 | - <ul class="dropdown-menu" dropdown-menu> | ||
6 | - <li ng-repeat="(language, description) in ctrl.availableLanguages()" | ||
7 | - class="language language-{{language}}" ng-class="{'active': language==ctrl.currentLanguage()}"> | ||
8 | - <a href="#" ng-click="ctrl.changeLanguage(language)"> | ||
9 | - {{description}} | ||
10 | - </a> | ||
11 | - </li> | ||
12 | - </ul> | ||
13 | -</li> |
src/app/components/navbar/index.ts
src/app/components/navbar/navbar.directive.spec.js
@@ -1,45 +0,0 @@ | @@ -1,45 +0,0 @@ | ||
1 | -(function() { | ||
2 | - 'use strict'; | ||
3 | - | ||
4 | - describe('directive navbar', function() { | ||
5 | - var vm; | ||
6 | - var el; | ||
7 | - var AUTH_EVENTS; | ||
8 | - var $state; | ||
9 | - | ||
10 | - beforeEach(module('angular')); | ||
11 | - beforeEach(inject(function($compile, $rootScope, $httpBackend, _AUTH_EVENTS_, _$state_) { | ||
12 | - $state = _$state_; | ||
13 | - AUTH_EVENTS = _AUTH_EVENTS_; | ||
14 | - $httpBackend.when('POST','/api/v1/login_from_cookie').respond({}); | ||
15 | - | ||
16 | - el = angular.element('<acme-navbar></acme-navbar>'); | ||
17 | - | ||
18 | - $compile(el)($rootScope.$new()); | ||
19 | - $rootScope.$digest(); | ||
20 | - vm = el.isolateScope().vm; | ||
21 | - })); | ||
22 | - | ||
23 | - it('should be compiled', function() { | ||
24 | - expect(el.html()).not.toEqual(null); | ||
25 | - }); | ||
26 | - | ||
27 | - it('should have isolate scope object with instanciate members', function() { | ||
28 | - expect(vm).toEqual(jasmine.any(Object)); | ||
29 | - expect(vm.currentUser).toEqual(undefined); | ||
30 | - }); | ||
31 | - | ||
32 | - it('should reload current state after login', function() { | ||
33 | - spyOn($state, 'go'); | ||
34 | - el.isolateScope().$broadcast(AUTH_EVENTS.loginSuccess, {}); | ||
35 | - expect($state.go).toHaveBeenCalled(); | ||
36 | - }); | ||
37 | - | ||
38 | - it('should open login when not logged in', function() { | ||
39 | - spyOn(vm, 'openLogin'); | ||
40 | - vm.activate(); | ||
41 | - expect(vm.openLogin).toHaveBeenCalled(); | ||
42 | - }); | ||
43 | - | ||
44 | - }); | ||
45 | -})(); |
src/app/components/navbar/navbar.html
@@ -1,49 +0,0 @@ | @@ -1,49 +0,0 @@ | ||
1 | -<nav class="navbar navbar-static-top navbar-inverse"> | ||
2 | - <div class="container-fluid"> | ||
3 | - <div class="navbar-header"> | ||
4 | - <button type="button" class="navbar-toggle collapsed" ng-click="isCollapsed = !isCollapsed"> | ||
5 | - <span class="sr-only">{{"navbar.toggle_menu" | translate}}</span> | ||
6 | - <span class="icon-bar"></span> | ||
7 | - <span class="icon-bar"></span> | ||
8 | - <span class="icon-bar"></span> | ||
9 | - </button> | ||
10 | - <a class="navbar-brand" ui-sref="main"> | ||
11 | - <span class="noosfero-logo"><img src="assets/images/logo-noosfero.png"></span> {{"noosfero.name" | translate}} | ||
12 | - </a> | ||
13 | - </div> | ||
14 | - | ||
15 | - <div class="collapse navbar-collapse" id="navbar-collapse" collapse="isCollapsed"> | ||
16 | - <ul class="nav navbar-nav"> | ||
17 | - </ul> | ||
18 | - | ||
19 | - <ul class="nav navbar-nav navbar-right"> | ||
20 | - <li ng-show="!ctrl.currentUser"> | ||
21 | - <a ng-href="#" ng-click="ctrl.openLogin()">{{"navbar.login" | translate}}</a> | ||
22 | - </li> | ||
23 | - | ||
24 | - <li class="dropdown profile-menu" ng-show="ctrl.currentUser" dropdown> | ||
25 | - <a href="#" class="dropdown-toggle" aria-expanded="false" dropdown-toggle> | ||
26 | - <noosfero-profile-image [profile]="ctrl.currentUser.person" class="profile-image"></noosfero-profile-image> | ||
27 | - <span ng-bind="ctrl.currentUser.person.name"></span> <b class="caret"></b> | ||
28 | - </a> | ||
29 | - <ul class="dropdown-menu" dropdown-menu> | ||
30 | - <li> | ||
31 | - <a ui-sref="main.profile.info({profile: ctrl.currentUser.person.identifier})"><i class="fa fa-fw fa-user"></i> {{"navbar.profile" | translate}}</a> | ||
32 | - </li> | ||
33 | - <li> | ||
34 | - <a target="_self" ui-sref="main.profile.settings({profile: ctrl.currentUser.person.identifier})"><i class="fa fa-fw fa-gear"></i> {{"navbar.settings" | translate}}</a> | ||
35 | - </li> | ||
36 | - <li class="divider"></li> | ||
37 | - <li> | ||
38 | - <a href="#" ng-click="ctrl.logout()"><i class="fa fa-fw fa-power-off"></i> {{"navbar.logout" | translate}}</a> | ||
39 | - </li> | ||
40 | - </ul> | ||
41 | - </li> | ||
42 | - </ul> | ||
43 | - <ul class="nav navbar-nav navbar-right"> | ||
44 | - <language-selector class="nav navbar-nav navbar-right"></language-selector> | ||
45 | - </ul> | ||
46 | - <div ui-view="actions"></div> | ||
47 | - </div> | ||
48 | - </div> | ||
49 | -</nav> |
src/app/components/navbar/navbar.scss
@@ -1,31 +0,0 @@ | @@ -1,31 +0,0 @@ | ||
1 | -.navbar { | ||
2 | - | ||
3 | - .container-fluid { | ||
4 | - padding-right: 12%; | ||
5 | - padding-left: 12%; | ||
6 | - @media (max-width: 978px) { | ||
7 | - padding-right: 2%; | ||
8 | - padding-left: 2%; | ||
9 | - } | ||
10 | - | ||
11 | - .navbar-brand { | ||
12 | - .noosfero-logo img { | ||
13 | - height: 35px; | ||
14 | - } | ||
15 | - } | ||
16 | - | ||
17 | - .navbar-nav { | ||
18 | - .profile-menu .profile-image { | ||
19 | - img { | ||
20 | - height: 30px; | ||
21 | - width: 30px; | ||
22 | - display: inline-block; | ||
23 | - @extend .img-circle; | ||
24 | - } | ||
25 | - i { | ||
26 | - font-size: 1.7em; | ||
27 | - } | ||
28 | - } | ||
29 | - } | ||
30 | - } | ||
31 | -} |
src/app/components/navbar/navbar.spec.ts
@@ -1,188 +0,0 @@ | @@ -1,188 +0,0 @@ | ||
1 | -import * as helpers from "./../../../spec/helpers"; | ||
2 | -import {Navbar} from "./navbar"; | ||
3 | -import {AUTH_EVENTS} from "./../auth"; | ||
4 | -import {User} from "./../../models/interfaces"; | ||
5 | -import {Injectable, Provider, provide} from "ng-forward"; | ||
6 | - | ||
7 | -import {ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder'; | ||
8 | - | ||
9 | -import {Session, AuthService, AuthController, IAuthEvents} from "./../auth"; | ||
10 | - | ||
11 | - | ||
12 | -describe("Components", () => { | ||
13 | - | ||
14 | - describe("Navbar Component", () => { | ||
15 | - | ||
16 | - let user: User = null; | ||
17 | - let scope: any; | ||
18 | - let $rootScope: ng.IRootScopeService; | ||
19 | - | ||
20 | - let modalInstance: any; | ||
21 | - let $modal: any; | ||
22 | - let authService: any; | ||
23 | - let stateService: any; | ||
24 | - let sessionService: Session; | ||
25 | - | ||
26 | - let provideFunc = provide; | ||
27 | - | ||
28 | - // before Each -> loading mocks on locals variables | ||
29 | - beforeEach(() => { | ||
30 | - user = <User>{ | ||
31 | - id: 1, | ||
32 | - login: "user" | ||
33 | - }; | ||
34 | - scope = helpers.mocks.scopeWithEvents; | ||
35 | - modalInstance = helpers.mocks.modalInstance; | ||
36 | - $modal = helpers.mocks.$modal; | ||
37 | - authService = helpers.mocks.authService; | ||
38 | - stateService = jasmine.createSpyObj("$state", ["go"]); | ||
39 | - sessionService = <any>helpers.mocks.sessionWithCurrentUser(user); | ||
40 | - }); | ||
41 | - | ||
42 | - | ||
43 | - // loading the templates | ||
44 | - beforeEach(angular.mock.module("templates")); | ||
45 | - | ||
46 | - | ||
47 | - // this function allow build the fixture of the container component | ||
48 | - // and is reused in each test | ||
49 | - // The main idea behing not prebuild it on a general beforeEach block is | ||
50 | - // to allow tests configure the mock services accordilly their own needs | ||
51 | - let buildComponent = (): Promise<ComponentFixture> => { | ||
52 | - return helpers.quickCreateComponent({ | ||
53 | - providers: [ | ||
54 | - provide('$modal', { | ||
55 | - useValue: $modal | ||
56 | - }), | ||
57 | - provide('AuthService', { | ||
58 | - useValue: authService | ||
59 | - }), | ||
60 | - helpers.provideEmptyObjects('moment'), | ||
61 | - provide('$state', { | ||
62 | - useValue: stateService | ||
63 | - }), | ||
64 | - provide("$scope", { | ||
65 | - useValue: scope | ||
66 | - }), | ||
67 | - provide('Session', { | ||
68 | - useValue: sessionService | ||
69 | - }), | ||
70 | - provide('AUTH_EVENTS', { | ||
71 | - useValue: { | ||
72 | - AUTH_EVENTS | ||
73 | - } | ||
74 | - }), | ||
75 | - provide('TranslatorService', { | ||
76 | - useValue: helpers.mocks.translatorService | ||
77 | - }) | ||
78 | - ].concat(helpers.provideFilters("translateFilter")), | ||
79 | - directives: [Navbar], | ||
80 | - template: '<acme-navbar></acme-navbar>' | ||
81 | - }); | ||
82 | - } | ||
83 | - | ||
84 | - | ||
85 | - it('should get the loggedIn user', (done: Function) => { | ||
86 | - buildComponent().then((fixture: ComponentFixture) => { | ||
87 | - let navbarInstance: Navbar = fixture.debugElement.componentViewChildren[0].componentInstance; | ||
88 | - expect(navbarInstance).toBeDefined(); | ||
89 | - expect(navbarInstance["currentUser"]).toEqual(user); | ||
90 | - done(); | ||
91 | - }); | ||
92 | - }); | ||
93 | - | ||
94 | - it('should open on click', (done: Function) => { | ||
95 | - spyOn($modal, "open"); | ||
96 | - buildComponent().then((fixture: ComponentFixture) => { | ||
97 | - let navbarComp: Navbar = <Navbar>fixture.debugElement.componentViewChildren[0].componentInstance; | ||
98 | - navbarComp.openLogin(); | ||
99 | - expect($modal.open).toHaveBeenCalled(); | ||
100 | - expect($modal.open).toHaveBeenCalledWith({ | ||
101 | - templateUrl: 'app/components/auth/login.html', | ||
102 | - controller: AuthController, | ||
103 | - controllerAs: 'vm', | ||
104 | - bindToController: true | ||
105 | - }); | ||
106 | - done(); | ||
107 | - }); | ||
108 | - }); | ||
109 | - | ||
110 | - it('should logout', (done: Function) => { | ||
111 | - buildComponent().then((fixture: ComponentFixture) => { | ||
112 | - let navbarComp: Navbar = <Navbar>fixture.debugElement.componentViewChildren[0].componentInstance; | ||
113 | - spyOn(authService, "logout"); | ||
114 | - try { | ||
115 | - navbarComp.logout(); | ||
116 | - expect(authService.logout).toHaveBeenCalled(); | ||
117 | - done(); | ||
118 | - } catch (e) { | ||
119 | - console.error(e); | ||
120 | - fail(e.message); | ||
121 | - done(); | ||
122 | - } | ||
123 | - }); | ||
124 | - }); | ||
125 | - | ||
126 | - | ||
127 | - it('should not activate user when logged in', (done: Function) => { | ||
128 | - buildComponent().then((fixture: ComponentFixture) => { | ||
129 | - let navbarComp: Navbar = <Navbar>fixture.debugElement.componentViewChildren[0].componentInstance; | ||
130 | - spyOn(navbarComp, "openLogin"); | ||
131 | - navbarComp.activate(); | ||
132 | - expect((<any>navbarComp.openLogin).calls.count()).toBe(0); | ||
133 | - done(); | ||
134 | - }); | ||
135 | - }); | ||
136 | - | ||
137 | - it('should activate when user not logged in', (done: Function) => { | ||
138 | - spyOn(sessionService, 'currentUser').and.returnValue(null); | ||
139 | - buildComponent().then((fixture: ComponentFixture) => { | ||
140 | - let navbarComp: Navbar = <Navbar>fixture.debugElement.componentViewChildren[0].componentInstance; | ||
141 | - spyOn(navbarComp, "openLogin"); | ||
142 | - navbarComp.activate(); | ||
143 | - expect(navbarComp.openLogin).toHaveBeenCalled(); | ||
144 | - done(); | ||
145 | - }); | ||
146 | - }); | ||
147 | - | ||
148 | - | ||
149 | - it('closes the modal after login', (done: Function) => { | ||
150 | - modalInstance = jasmine.createSpyObj("modalInstance", ["close"]); | ||
151 | - modalInstance.close = jasmine.createSpy("close"); | ||
152 | - | ||
153 | - $modal.open = () => { | ||
154 | - return modalInstance; | ||
155 | - }; | ||
156 | - | ||
157 | - buildComponent().then((fixture: ComponentFixture) => { | ||
158 | - let navbarComp: Navbar = <Navbar>fixture.debugElement.componentViewChildren[0].componentInstance; | ||
159 | - let localScope: ng.IScope = navbarComp["$scope"]; | ||
160 | - | ||
161 | - navbarComp.openLogin(); | ||
162 | - localScope.$emit(AUTH_EVENTS.loginSuccess); | ||
163 | - expect(modalInstance.close).toHaveBeenCalled(); | ||
164 | - done(); | ||
165 | - }); | ||
166 | - }); | ||
167 | - | ||
168 | - it('updates current user on logout', (done: Function) => { | ||
169 | - buildComponent().then((fixture: ComponentFixture) => { | ||
170 | - let navbarComp: Navbar = <Navbar>fixture.debugElement.componentViewChildren[0].componentInstance; | ||
171 | - let localScope: ng.IScope = navbarComp["$scope"]; | ||
172 | - | ||
173 | - // init navbar currentUser with some user | ||
174 | - navbarComp["currentUser"] = user; | ||
175 | - | ||
176 | - // changes the current User to return null, | ||
177 | - // and emmit the 'logoutSuccess' event | ||
178 | - // just what happens when user logsout | ||
179 | - sessionService.currentUser = () => { return null; }; | ||
180 | - localScope.$emit(AUTH_EVENTS.logoutSuccess); | ||
181 | - expect(navbarComp["currentUser"]).toBeNull(); | ||
182 | - done(); | ||
183 | - }); | ||
184 | - }); | ||
185 | - | ||
186 | - | ||
187 | - }); | ||
188 | -}); |
src/app/components/navbar/navbar.ts
@@ -1,67 +0,0 @@ | @@ -1,67 +0,0 @@ | ||
1 | -import {Component, Inject} from "ng-forward"; | ||
2 | -import {LanguageSelector} from "../language-selector/language-selector.component"; | ||
3 | - | ||
4 | - | ||
5 | -import {Session, AuthService, AuthController, IAuthEvents, AUTH_EVENTS} from "./../auth"; | ||
6 | -import {User} from "./../../models/interfaces"; | ||
7 | - | ||
8 | -@Component({ | ||
9 | - selector: "acme-navbar", | ||
10 | - templateUrl: "app/components/navbar/navbar.html", | ||
11 | - directives: [LanguageSelector], | ||
12 | - providers: [AuthService, Session] | ||
13 | -}) | ||
14 | -@Inject("$modal", AuthService, "Session", "$scope", "$state") | ||
15 | -export class Navbar { | ||
16 | - | ||
17 | - private currentUser: User; | ||
18 | - private modalInstance: any = null; | ||
19 | - /** | ||
20 | - * | ||
21 | - */ | ||
22 | - constructor( | ||
23 | - private $modal: any, | ||
24 | - private authService: AuthService, | ||
25 | - private session: Session, | ||
26 | - private $scope: ng.IScope, | ||
27 | - private $state: ng.ui.IStateService | ||
28 | - ) { | ||
29 | - this.currentUser = this.session.currentUser(); | ||
30 | - | ||
31 | - this.$scope.$on(AUTH_EVENTS.loginSuccess, () => { | ||
32 | - if (this.modalInstance) { | ||
33 | - this.modalInstance.close(); | ||
34 | - this.modalInstance = null; | ||
35 | - } | ||
36 | - | ||
37 | - this.$state.go(this.$state.current, {}, { reload: true }); // TODO move to auth | ||
38 | - }); | ||
39 | - | ||
40 | - this.$scope.$on(AUTH_EVENTS.logoutSuccess, () => { | ||
41 | - this.currentUser = this.session.currentUser(); | ||
42 | - }); | ||
43 | - } | ||
44 | - | ||
45 | - openLogin() { | ||
46 | - this.modalInstance = this.$modal.open({ | ||
47 | - templateUrl: 'app/components/auth/login.html', | ||
48 | - controller: AuthController, | ||
49 | - controllerAs: 'vm', | ||
50 | - bindToController: true | ||
51 | - }); | ||
52 | - }; | ||
53 | - | ||
54 | - logout() { | ||
55 | - this.authService.logout(); | ||
56 | - this.$state.go(this.$state.current, {}, { reload: true }); // TODO move to auth | ||
57 | - }; | ||
58 | - | ||
59 | - | ||
60 | - | ||
61 | - activate() { | ||
62 | - if (!this.currentUser) { | ||
63 | - this.openLogin(); | ||
64 | - } | ||
65 | - } | ||
66 | - | ||
67 | -} |
src/app/components/noosfero-activities/activities.component.spec.ts
@@ -1,36 +0,0 @@ | @@ -1,36 +0,0 @@ | ||
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | ||
2 | -import {Pipe, Input, provide, Component} from 'ng-forward'; | ||
3 | -import {provideFilters} from '../../../spec/helpers'; | ||
4 | - | ||
5 | -import {NoosferoActivities} from './activities.component'; | ||
6 | - | ||
7 | -const tcb = new TestComponentBuilder(); | ||
8 | - | ||
9 | -const htmlTemplate: string = '<noosfero-activities [activities]="ctrl.activities"></noosfero-activities>'; | ||
10 | - | ||
11 | - | ||
12 | -describe("Components", () => { | ||
13 | - | ||
14 | - describe("Noosfero Activities", () => { | ||
15 | - | ||
16 | - beforeEach(angular.mock.module("templates")); | ||
17 | - | ||
18 | - @Component({ | ||
19 | - selector: 'test-container-component', | ||
20 | - template: htmlTemplate, | ||
21 | - directives: [NoosferoActivities], | ||
22 | - providers: provideFilters("truncateFilter", "stripTagsFilter", "translateFilter") | ||
23 | - }) | ||
24 | - class BlockContainerComponent { | ||
25 | - activities = [{ name: "activity1", verb: "create_article" }, { name: "activity2", verb: "create_article" }]; | ||
26 | - } | ||
27 | - | ||
28 | - it("render a noosfero activity tag for each activity", done => { | ||
29 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | ||
30 | - expect(fixture.debugElement.queryAll("noosfero-activity").length).toEqual(2); | ||
31 | - done(); | ||
32 | - }); | ||
33 | - }); | ||
34 | - }); | ||
35 | - | ||
36 | -}); |
src/app/components/noosfero-activities/activities.component.ts
@@ -1,27 +0,0 @@ | @@ -1,27 +0,0 @@ | ||
1 | -import {Component, Input} from "ng-forward"; | ||
2 | -import {NoosferoActivity} from "./activity/activity.component"; | ||
3 | -import {Activity} from "../../models/interfaces"; | ||
4 | - | ||
5 | -/** | ||
6 | - * @ngdoc controller | ||
7 | - * @name NoosferoActivities | ||
8 | - * @description | ||
9 | - * The controller responsible to retreive profile activities. | ||
10 | - */ | ||
11 | - | ||
12 | -@Component({ | ||
13 | - selector: "noosfero-activities", | ||
14 | - templateUrl: 'app/components/noosfero-activities/activities.html', | ||
15 | - directives: [NoosferoActivity] | ||
16 | -}) | ||
17 | -export class NoosferoActivities { | ||
18 | - | ||
19 | - /** | ||
20 | - * @ngdoc property | ||
21 | - * @propertyOf NoosferoActivities | ||
22 | - * @name activities | ||
23 | - * @returns {Activity[]} An array of {@link Activity}. | ||
24 | - */ | ||
25 | - @Input() activities: Activity[]; | ||
26 | - | ||
27 | -} |
src/app/components/noosfero-activities/activities.html
src/app/components/noosfero-activities/activities.scss
src/app/components/noosfero-activities/activity/activity.component.spec.ts
@@ -1,38 +0,0 @@ | @@ -1,38 +0,0 @@ | ||
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | ||
2 | -import {Pipe, Input, provide, Component} from 'ng-forward'; | ||
3 | -import {provideFilters} from '../../../../spec/helpers'; | ||
4 | - | ||
5 | -import {NoosferoActivity} from './activity.component'; | ||
6 | - | ||
7 | -const tcb = new TestComponentBuilder(); | ||
8 | - | ||
9 | -const htmlTemplate: string = '<noosfero-activity [activity]="ctrl.activity"></noosfero-activity>'; | ||
10 | - | ||
11 | - | ||
12 | -describe("Components", () => { | ||
13 | - | ||
14 | - describe("Noosfero Activity", () => { | ||
15 | - | ||
16 | - beforeEach(angular.mock.module("templates")); | ||
17 | - | ||
18 | - @Component({ | ||
19 | - selector: 'test-container-component', | ||
20 | - template: htmlTemplate, | ||
21 | - directives: [NoosferoActivity], | ||
22 | - providers: provideFilters("truncateFilter", "stripTagsFilter", "translateFilter") | ||
23 | - }) | ||
24 | - class BlockContainerComponent { | ||
25 | - activity = { name: "activity1", verb: "create_article" }; | ||
26 | - } | ||
27 | - | ||
28 | - it("render the specific template for an activity verb", done => { | ||
29 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | ||
30 | - let component: NoosferoActivity = fixture.debugElement.componentViewChildren[0].componentInstance; | ||
31 | - expect(component.getActivityTemplate()).toEqual('app/components/noosfero-activities/activity/create_article.html'); | ||
32 | - expect(fixture.debugElement.queryAll(".activity.create_article").length).toEqual(1); | ||
33 | - done(); | ||
34 | - }); | ||
35 | - }); | ||
36 | - }); | ||
37 | - | ||
38 | -}); |
src/app/components/noosfero-activities/activity/activity.component.ts
@@ -1,16 +0,0 @@ | @@ -1,16 +0,0 @@ | ||
1 | -import {Component, Input} from "ng-forward"; | ||
2 | -import {Activity} from "../../../models/interfaces"; | ||
3 | - | ||
4 | -@Component({ | ||
5 | - selector: "noosfero-activity", | ||
6 | - templateUrl: 'app/components/noosfero-activities/activity/activity.html' | ||
7 | -}) | ||
8 | -export class NoosferoActivity { | ||
9 | - | ||
10 | - @Input() activity: Activity; | ||
11 | - | ||
12 | - getActivityTemplate() { | ||
13 | - return 'app/components/noosfero-activities/activity/' + this.activity.verb + '.html'; | ||
14 | - } | ||
15 | - | ||
16 | -} |
src/app/components/noosfero-activities/activity/activity.html
src/app/components/noosfero-activities/activity/add_member_in_community.html
@@ -1,13 +0,0 @@ | @@ -1,13 +0,0 @@ | ||
1 | -<timeline-badge class="info"> | ||
2 | - <i class="fa fa-user-plus"></i> | ||
3 | -</timeline-badge> | ||
4 | -<timeline-panel> | ||
5 | - <timeline-heading> | ||
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> | ||
8 | - <span> {{"activities.add_member_in_community.description" | translate}}</span> | ||
9 | - </h4> | ||
10 | - <p><small class="text-muted"><i class="fa fa-clock-o"></i> <span am-time-ago="ctrl.activity.created_at | dateFormat"></span></small></p> | ||
11 | - </timeline-heading> | ||
12 | - <div class="timeline-body"></div> | ||
13 | -</timeline-panel> |
src/app/components/noosfero-activities/activity/create_article.html
@@ -1,26 +0,0 @@ | @@ -1,26 +0,0 @@ | ||
1 | -<timeline-badge class="success"> | ||
2 | - <i class="fa fa-file-text"></i> | ||
3 | -</timeline-badge> | ||
4 | -<timeline-panel> | ||
5 | - <timeline-heading> | ||
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> | ||
8 | - <span> {{"activities.create_article.description" | translate}} </span> | ||
9 | - <a ui-sref="main.profile.info({profile: ctrl.activity.target.article.profile.identifier})"> | ||
10 | - <strong ng-bind="ctrl.activity.target.article.profile.name"></strong></span> | ||
11 | - </a> | ||
12 | - </h4> | ||
13 | - <p><small class="text-muted"><i class="fa fa-clock-o"></i> <span am-time-ago="ctrl.activity.created_at | dateFormat"></span></small></p> | ||
14 | - </timeline-heading> | ||
15 | - <div class="timeline-body"> | ||
16 | - <div class="article"> | ||
17 | - <div class="title"> | ||
18 | - <a ui-sref="main.profile.page({profile: ctrl.activity.target.article.profile.identifier, page: ctrl.activity.target.article.path})" | ||
19 | - ng-bind="ctrl.activity.target.article.title"></a> | ||
20 | - </div> | ||
21 | - <div class="lead small"> | ||
22 | - <div ng-bind-html="ctrl.activity.target.article.body | stripTags | truncate: 100 : '...': true"></div> | ||
23 | - </div> | ||
24 | - </div> | ||
25 | - </div> | ||
26 | -</timeline-panel> |
src/app/components/noosfero-activities/activity/index.ts
@@ -1 +0,0 @@ | @@ -1 +0,0 @@ | ||
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/noosfero-activities/activity/new_friendship.html
@@ -1,18 +0,0 @@ | @@ -1,18 +0,0 @@ | ||
1 | -<timeline-badge class="info"> | ||
2 | - <i class="fa fa-user-plus"></i> | ||
3 | -</timeline-badge> | ||
4 | -<timeline-panel> | ||
5 | - <timeline-heading> | ||
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> | ||
8 | - <span> {{"activities.new_friendship.description" | translate:{friends: ctrl.activity.params.friend_name.length}:"messageformat" }} </span> | ||
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"> | ||
11 | - <strong ng-bind="friend"></strong> | ||
12 | - </a> | ||
13 | - </span> | ||
14 | - </h4> | ||
15 | - <p><small class="text-muted"><i class="fa fa-clock-o"></i> <span am-time-ago="ctrl.activity.created_at | dateFormat"></span></small></p> | ||
16 | - </timeline-heading> | ||
17 | - <div class="timeline-body"></div> | ||
18 | -</timeline-panel> |
src/app/components/noosfero-activities/index.ts
@@ -1 +0,0 @@ | @@ -1 +0,0 @@ | ||
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/noosfero-articles/article/article.html
@@ -1,23 +0,0 @@ | @@ -1,23 +0,0 @@ | ||
1 | -<div class="article"> | ||
2 | - <div class="page-header"> | ||
3 | - <h3 ng-bind="ctrl.article.title"></h3> | ||
4 | - </div> | ||
5 | - | ||
6 | - <div class="sub-header clearfix"> | ||
7 | - <div class="page-info pull-right small text-muted"> | ||
8 | - <span class="time"> | ||
9 | - <i class="fa fa-clock-o"></i> <span am-time-ago="ctrl.article.created_at | dateFormat"></span> | ||
10 | - </span> | ||
11 | - <span class="author" ng-if="ctrl.article.author"> | ||
12 | - <i class="fa fa-user"></i> | ||
13 | - <a ui-sref="main.profile.home({profile: ctrl.article.author.identifier})"> | ||
14 | - <span class="author-name" ng-bind="ctrl.article.author.name"></span> | ||
15 | - </a> | ||
16 | - </span> | ||
17 | - </div> | ||
18 | - </div> | ||
19 | - | ||
20 | - <div class="page-body"> | ||
21 | - <div ng-bind-html="ctrl.article.body"></div> | ||
22 | - </div> | ||
23 | -</div> |
src/app/components/noosfero-articles/article/article.scss
src/app/components/noosfero-articles/article/article_view.spec.ts
@@ -1,108 +0,0 @@ | @@ -1,108 +0,0 @@ | ||
1 | - | ||
2 | -import {Input, provide, Component} from 'ng-forward'; | ||
3 | -import {ArticleView, ArticleDefaultView} from './article_view'; | ||
4 | - | ||
5 | -import {createComponentFromClass, quickCreateComponent} from "../../../../spec/helpers"; | ||
6 | - | ||
7 | -// this htmlTemplate will be re-used between the container components in this spec file | ||
8 | -const htmlTemplate: string = '<noosfero-article [article]="ctrl.article" [profile]="ctrl.profile"></noosfero-article>'; | ||
9 | - | ||
10 | - | ||
11 | -describe("Components", () => { | ||
12 | - | ||
13 | - describe("ArticleView Component", () => { | ||
14 | - | ||
15 | - // the karma preprocessor html2js transform the templates html into js files which put | ||
16 | - // the templates to the templateCache into the module templates | ||
17 | - // we need to load the module templates here as the template for the | ||
18 | - // component Noosfero ArtileView will be load on our tests | ||
19 | - beforeEach(angular.mock.module("templates")); | ||
20 | - | ||
21 | - it("renders the default component when no specific component is found", (done: Function) => { | ||
22 | - // Creating a container component (ArticleContainerComponent) to include | ||
23 | - // the component under test (ArticleView) | ||
24 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [ArticleView] }) | ||
25 | - class ArticleContainerComponent { | ||
26 | - article = { type: 'anyArticleType' }; | ||
27 | - profile = { name: 'profile-name' }; | ||
28 | - constructor() { | ||
29 | - } | ||
30 | - } | ||
31 | - | ||
32 | - createComponentFromClass(ArticleContainerComponent).then((fixture) => { | ||
33 | - // and here we can inspect and run the test assertions | ||
34 | - | ||
35 | - // gets the children component of ArticleContainerComponent | ||
36 | - let articleView: ArticleView = fixture.debugElement.componentViewChildren[0].componentInstance; | ||
37 | - | ||
38 | - // and checks if the article View rendered was the Default Article View | ||
39 | - expect(articleView.constructor.prototype).toEqual(ArticleDefaultView.prototype); | ||
40 | - | ||
41 | - // done needs to be called (it isn't really needed, as we can read in | ||
42 | - // here (https://github.com/ngUpgraders/ng-forward/blob/master/API.md#createasync) | ||
43 | - // because createAsync in ng-forward is not really async, but as the intention | ||
44 | - // here is write tests in angular 2 ways, this is recommended | ||
45 | - done(); | ||
46 | - }); | ||
47 | - | ||
48 | - }); | ||
49 | - | ||
50 | - it("receives the article and profile as inputs", (done: Function) => { | ||
51 | - | ||
52 | - // Creating a container component (ArticleContainerComponent) to include | ||
53 | - // the component under test (ArticleView) | ||
54 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [ArticleView] }) | ||
55 | - class ArticleContainerComponent { | ||
56 | - article = { type: 'anyArticleType' }; | ||
57 | - profile = { name: 'profile-name' }; | ||
58 | - constructor() { | ||
59 | - } | ||
60 | - } | ||
61 | - | ||
62 | - // uses the TestComponentBuilder instance to initialize the component | ||
63 | - createComponentFromClass(ArticleContainerComponent).then((fixture) => { | ||
64 | - // and here we can inspect and run the test assertions | ||
65 | - let articleView: ArticleView = fixture.debugElement.componentViewChildren[0].componentInstance; | ||
66 | - | ||
67 | - // assure the article object inside the ArticleView matches | ||
68 | - // the provided through the parent component | ||
69 | - expect(articleView.article.type).toEqual("anyArticleType"); | ||
70 | - expect(articleView.profile.name).toEqual("profile-name"); | ||
71 | - | ||
72 | - // done needs to be called (it isn't really needed, as we can read in | ||
73 | - // here (https://github.com/ngUpgraders/ng-forward/blob/master/API.md#createasync) | ||
74 | - // because createAsync in ng-forward is not really async, but as the intention | ||
75 | - // here is write tests in angular 2 ways, this is recommended | ||
76 | - done(); | ||
77 | - }); | ||
78 | - }); | ||
79 | - | ||
80 | - | ||
81 | - it("renders a article view which matches to the article type", done => { | ||
82 | - // NoosferoTinyMceArticle component created to check if it will be used | ||
83 | - // when a article with type 'TinyMceArticle' is provided to the noosfero-article (ArticleView) | ||
84 | - // *** Important *** - the selector is what ng-forward uses to define the name of the directive provider | ||
85 | - @Component({ selector: 'noosfero-tiny-mce-article', template: "<h1>TinyMceArticle</h1>" }) | ||
86 | - class TinyMceArticleView { | ||
87 | - @Input() article: any; | ||
88 | - @Input() profile: any; | ||
89 | - } | ||
90 | - | ||
91 | - // Creating a container component (ArticleContainerComponent) to include our NoosferoTinyMceArticle | ||
92 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [ArticleView, TinyMceArticleView] }) | ||
93 | - class CustomArticleType { | ||
94 | - article = { type: 'TinyMceArticle' }; | ||
95 | - profile = { name: 'profile-name' }; | ||
96 | - constructor() { | ||
97 | - } | ||
98 | - } | ||
99 | - createComponentFromClass(CustomArticleType).then(fixture => { | ||
100 | - let myComponent: CustomArticleType = fixture.componentInstance; | ||
101 | - expect(myComponent.article.type).toEqual("TinyMceArticle"); | ||
102 | - expect(fixture.debugElement.componentViewChildren[0].text()).toEqual("TinyMceArticle"); | ||
103 | - done(); | ||
104 | - }); | ||
105 | - }); | ||
106 | - | ||
107 | - }); | ||
108 | -}); | ||
109 | \ No newline at end of file | 0 | \ No newline at end of file |
src/app/components/noosfero-articles/article/article_view.ts
@@ -1,57 +0,0 @@ | @@ -1,57 +0,0 @@ | ||
1 | -import { bundle, Input, Inject, Component, Directive } from 'ng-forward'; | ||
2 | -import {ArticleBlog} from "../blog/blog.component"; | ||
3 | - | ||
4 | -/** | ||
5 | - * @ngdoc controller | ||
6 | - * @name ArticleDefaultView | ||
7 | - * @description | ||
8 | - * A default view for Noosfero Articles. If the specific article view is | ||
9 | - * not implemented, then this view is used. | ||
10 | - */ | ||
11 | -@Component({ | ||
12 | - selector: 'noosfero-default-article', | ||
13 | - templateUrl: 'app/components/noosfero-articles/article/article.html' | ||
14 | -}) | ||
15 | -export class ArticleDefaultView { | ||
16 | - | ||
17 | - @Input() article: any; | ||
18 | - @Input() profile: any; | ||
19 | - | ||
20 | -} | ||
21 | - | ||
22 | -/** | ||
23 | - * @ngdoc controller | ||
24 | - * @name ArticleView | ||
25 | - * @description | ||
26 | - * A dynamic view for articles. It uses the article type to replace | ||
27 | - * the default template with the custom article directive. | ||
28 | - */ | ||
29 | -@Component({ | ||
30 | - selector: 'noosfero-article', | ||
31 | - template: 'not-used', | ||
32 | - directives: [ArticleDefaultView, ArticleBlog] | ||
33 | -}) | ||
34 | -@Inject("$element", "$scope", "$injector", "$compile") | ||
35 | -export class ArticleView { | ||
36 | - | ||
37 | - @Input() article: any; | ||
38 | - @Input() profile: any; | ||
39 | - directiveName: string; | ||
40 | - | ||
41 | - ngOnInit() { | ||
42 | - let specificDirective = 'noosfero' + this.article.type; | ||
43 | - this.directiveName = "noosfero-default-article"; | ||
44 | - if (this.$injector.has(specificDirective + 'Directive')) { | ||
45 | - this.directiveName = specificDirective.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); | ||
46 | - } | ||
47 | - this.$element.replaceWith(this.$compile('<' + this.directiveName + ' [article]="ctrl.article" [profile]="ctrl.profile"></' + this.directiveName + '>')(this.$scope)); | ||
48 | - } | ||
49 | - | ||
50 | - constructor( | ||
51 | - private $element: any, | ||
52 | - private $scope: ng.IScope, | ||
53 | - private $injector: ng.auto.IInjectorService, | ||
54 | - private $compile: ng.ICompileService) { | ||
55 | - | ||
56 | - } | ||
57 | -} |
src/app/components/noosfero-articles/article/index.ts
src/app/components/noosfero-articles/blog/blog.component.spec.ts
@@ -1,132 +0,0 @@ | @@ -1,132 +0,0 @@ | ||
1 | -import { | ||
2 | - providers | ||
3 | -} from 'ng-forward/cjs/testing/providers'; | ||
4 | - | ||
5 | -import { | ||
6 | - Input, | ||
7 | - Component | ||
8 | -} from 'ng-forward'; | ||
9 | -import { | ||
10 | - ArticleBlog | ||
11 | -} from './blog.component'; | ||
12 | - | ||
13 | -import { | ||
14 | - createComponentFromClass, | ||
15 | - quickCreateComponent, | ||
16 | - provideEmptyObjects, | ||
17 | - createProviderToValue, | ||
18 | - provideFilters | ||
19 | -} from "../../../../spec/helpers.ts"; | ||
20 | - | ||
21 | -// this htmlTemplate will be re-used between the container components in this spec file | ||
22 | -const htmlTemplate: string = '<noosfero-blog [article]="ctrl.article" [profile]="ctrl.profile"></noosfero-blog>'; | ||
23 | - | ||
24 | -describe("Blog Component", () => { | ||
25 | - | ||
26 | - function promiseResultTemplate(response ? : {}) { | ||
27 | - let thenFuncEmpty = (func: Function) => { | ||
28 | - // does nothing | ||
29 | - }; | ||
30 | - if (response) { | ||
31 | - return { | ||
32 | - then: (func: (response: any) => void) => { | ||
33 | - func(response); | ||
34 | - } | ||
35 | - }; | ||
36 | - } else { | ||
37 | - return { | ||
38 | - then: (func: (response: any) => void) => { | ||
39 | - // does nothing | ||
40 | - } | ||
41 | - }; | ||
42 | - } | ||
43 | - } | ||
44 | - | ||
45 | - let articleService = { | ||
46 | - getChildren: (article_id: number, filters: {}) => { | ||
47 | - return promiseResultTemplate(null); | ||
48 | - } | ||
49 | - }; | ||
50 | - | ||
51 | - @Component({ | ||
52 | - selector: 'test-container-component', | ||
53 | - template: htmlTemplate, | ||
54 | - directives: [ArticleBlog], | ||
55 | - providers: [ | ||
56 | - provideEmptyObjects('Restangular'), | ||
57 | - createProviderToValue('ArticleService', articleService), | ||
58 | - provideFilters('truncateFilter') | ||
59 | - ] | ||
60 | - }) | ||
61 | - class BlogContainerComponent { | ||
62 | - article = { | ||
63 | - type: 'anyArticleType' | ||
64 | - }; | ||
65 | - profile = { | ||
66 | - name: 'profile-name' | ||
67 | - }; | ||
68 | - } | ||
69 | - | ||
70 | - beforeEach(() => { | ||
71 | - | ||
72 | - // the karma preprocessor html2js transform the templates html into js files which put | ||
73 | - // the templates to the templateCache into the module templates | ||
74 | - // we need to load the module templates here as the template for the | ||
75 | - // component Noosfero ArtileView will be load on our tests | ||
76 | - angular.mock.module("templates") | ||
77 | - | ||
78 | - providers((provide: any) => { | ||
79 | - return <any > [ | ||
80 | - provide('ArticleService', { | ||
81 | - useValue: articleService | ||
82 | - }) | ||
83 | - ] | ||
84 | - }); | ||
85 | - }); | ||
86 | - | ||
87 | - it("renders the blog content", (done: Function) => { | ||
88 | - | ||
89 | - createComponentFromClass(BlogContainerComponent).then((fixture) => { | ||
90 | - | ||
91 | - expect(fixture.debugElement.query('div.blog').length).toEqual(1); | ||
92 | - | ||
93 | - done(); | ||
94 | - }); | ||
95 | - }); | ||
96 | - | ||
97 | - it("verify the blog data", (done: Function) => { | ||
98 | - | ||
99 | - // defining a mock result to articleService.getChildren method | ||
100 | - articleService.getChildren = (article_id: number, filters: {}) => { | ||
101 | - return promiseResultTemplate({ | ||
102 | - headers: (headerName: string) => { | ||
103 | - return 1; | ||
104 | - }, | ||
105 | - data: < any > { | ||
106 | - articles: [{ | ||
107 | - id: 1, | ||
108 | - title: 'The article test' | ||
109 | - }] | ||
110 | - } | ||
111 | - }); | ||
112 | - }; | ||
113 | - | ||
114 | - createComponentFromClass(BlogContainerComponent).then((fixture) => { | ||
115 | - | ||
116 | - // gets the children component of BlogContainerComponent | ||
117 | - let articleBlog: BlogContainerComponent = fixture.debugElement.componentViewChildren[0].componentInstance; | ||
118 | - | ||
119 | - // check if the component property are the provided by the mocked articleService | ||
120 | - let post = { | ||
121 | - id: 1, | ||
122 | - title: 'The article test' | ||
123 | - }; | ||
124 | - expect(( < any > articleBlog)["posts"][0]).toEqual(jasmine.objectContaining(post)); | ||
125 | - expect(( < any > articleBlog)["totalPosts"]).toEqual(1); | ||
126 | - | ||
127 | - done(); | ||
128 | - }); | ||
129 | - | ||
130 | - }); | ||
131 | - | ||
132 | -}); | ||
133 | \ No newline at end of file | 0 | \ No newline at end of file |
src/app/components/noosfero-articles/blog/blog.component.ts
@@ -1,48 +0,0 @@ | @@ -1,48 +0,0 @@ | ||
1 | -import {Component, Input, Inject} from "ng-forward"; | ||
2 | - | ||
3 | -import {Article, Profile} from "./../../../models/interfaces"; | ||
4 | -import {ArticleService} from "../../../../lib/ng-noosfero-api/http/article.service"; | ||
5 | - | ||
6 | -/** | ||
7 | - * @ngdoc controller | ||
8 | - * @name ArticleBlog | ||
9 | - * @description | ||
10 | - * An specific {@link ArticleView} for Blog articles. | ||
11 | - */ | ||
12 | -@Component({ | ||
13 | - selector: "noosfero-blog", | ||
14 | - templateUrl: "app/components/noosfero-articles/blog/blog.html" | ||
15 | -}) | ||
16 | -@Inject(ArticleService) | ||
17 | -export class ArticleBlog { | ||
18 | - | ||
19 | - @Input() article: Article; | ||
20 | - @Input() profile: Profile; | ||
21 | - | ||
22 | - private posts: any[]; | ||
23 | - private perPage: number = 3; | ||
24 | - private currentPage: number; | ||
25 | - private totalPosts: number = 0; | ||
26 | - | ||
27 | - constructor(private articleService: ArticleService) { } | ||
28 | - | ||
29 | - ngOnInit() { | ||
30 | - this.loadPage(); | ||
31 | - } | ||
32 | - | ||
33 | - loadPage() { | ||
34 | - let filters = { | ||
35 | - content_type: "TinyMceArticle", | ||
36 | - per_page: this.perPage, | ||
37 | - page: this.currentPage | ||
38 | - }; | ||
39 | - | ||
40 | - this.articleService | ||
41 | - .getChildren(this.article.id, filters) | ||
42 | - .then((response: restangular.IResponse) => { | ||
43 | - this.totalPosts = <number>(<any>response.headers("total")); | ||
44 | - this.posts = response.data.articles; | ||
45 | - }); | ||
46 | - } | ||
47 | - | ||
48 | -} |
src/app/components/noosfero-articles/blog/blog.html
@@ -1,24 +0,0 @@ | @@ -1,24 +0,0 @@ | ||
1 | -<div class="blog"> | ||
2 | - <div class="blog-cover" ng-show="ctrl.article.image"> | ||
3 | - <img ng-src="{{ctrl.article.image.url}}" class="img-responsive"> | ||
4 | - <h3 ng-bind="ctrl.article.title"></h3> | ||
5 | - </div> | ||
6 | - | ||
7 | - <div class="page-header" ng-show="!ctrl.article.image"> | ||
8 | - <h3 ng-bind="ctrl.article.title"></h3> | ||
9 | - </div> | ||
10 | - | ||
11 | - <div> | ||
12 | - <div ng-repeat="child in ctrl.posts | orderBy: 'created_at':true"> | ||
13 | - <div class="page-header"> | ||
14 | - <a class="title" ui-sref="main.profile.page({profile: ctrl.profile.identifier, page: child.path})"><h4 ng-bind="child.title"></h4></a> | ||
15 | - <div class="post-lead" ng-bind-html="child.body | truncate: 500: '...': true"></div> | ||
16 | - </div> | ||
17 | - </div> | ||
18 | - </div> | ||
19 | - | ||
20 | - <pagination ng-model="ctrl.currentPage" total-items="ctrl.totalPosts" class="pagination-sm center-block" | ||
21 | - boundary-links="true" items-per-page="ctrl.perPage" ng-change="ctrl.loadPage()" | ||
22 | - first-text="«" last-text="»" previous-text="‹" next-text="›"> | ||
23 | - </pagination> | ||
24 | -</div> |
src/app/components/noosfero-articles/blog/blog.scss
src/app/components/noosfero-articles/blog/index.ts
src/app/components/noosfero-articles/index.ts
@@ -1 +0,0 @@ | @@ -1 +0,0 @@ | ||
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/noosfero-blocks/block.component.spec.ts
@@ -1,91 +0,0 @@ | @@ -1,91 +0,0 @@ | ||
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | ||
2 | -import {Input, provide, Component} from 'ng-forward'; | ||
3 | - | ||
4 | -import {Block} from './block.component'; | ||
5 | - | ||
6 | -const tcb = new TestComponentBuilder(); | ||
7 | - | ||
8 | -const htmlTemplate: string = '<noosfero-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-block>'; | ||
9 | - | ||
10 | -describe("Components", () => { | ||
11 | - describe("Block Component", () => { | ||
12 | - | ||
13 | - // the karma preprocessor html2js transform the templates html into js files which put | ||
14 | - // the templates to the templateCache into the module templates | ||
15 | - // we need to load the module templates here as the template for the | ||
16 | - // component Block will be load on our tests | ||
17 | - beforeEach(angular.mock.module("templates")); | ||
18 | - | ||
19 | - it("receives the block and the owner as inputs", done => { | ||
20 | - | ||
21 | - // Creating a container component (BlockContainerComponent) to include | ||
22 | - // the component under test (Block) | ||
23 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [Block] }) | ||
24 | - class BlockContainerComponent { | ||
25 | - block = { type: 'Block' }; | ||
26 | - owner = { name: 'profile-name' }; | ||
27 | - constructor() { | ||
28 | - } | ||
29 | - } | ||
30 | - | ||
31 | - // uses the TestComponentBuilder instance to initialize the component | ||
32 | - tcb | ||
33 | - .createAsync(BlockContainerComponent).then(fixture => { | ||
34 | - // and here we can inspect and run the test assertions | ||
35 | - let myComponent: Block = fixture.componentInstance; | ||
36 | - | ||
37 | - // assure the block object inside the Block matches | ||
38 | - // the provided through the parent component | ||
39 | - expect(myComponent.block.type).toEqual("Block"); | ||
40 | - expect(myComponent.owner.name).toEqual("profile-name"); | ||
41 | - done(); | ||
42 | - }); | ||
43 | - }); | ||
44 | - | ||
45 | - | ||
46 | - it("renders a component which matches to the block type", done => { | ||
47 | - // CustomBlock component created to check if it will be used | ||
48 | - // when a block with type 'CustomBlock' is provided to the noosfero-block (Block) | ||
49 | - // *** Important *** - the selector is what ng-forward uses to define the name of the directive provider | ||
50 | - @Component({ selector: 'noosfero-custom-block', template: "<h1>My Custom Block</h1>" }) | ||
51 | - class CustomBlock { | ||
52 | - @Input() block: any; | ||
53 | - @Input() owner: any; | ||
54 | - } | ||
55 | - | ||
56 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [Block, CustomBlock] }) | ||
57 | - class CustomBlockType { | ||
58 | - block = { type: 'CustomBlock' }; | ||
59 | - owner = { name: 'profile-name' }; | ||
60 | - constructor() { | ||
61 | - } | ||
62 | - } | ||
63 | - tcb | ||
64 | - .createAsync(CustomBlockType).then(fixture => { | ||
65 | - let myComponent: CustomBlockType = fixture.componentInstance; | ||
66 | - expect(myComponent.block.type).toEqual("CustomBlock"); | ||
67 | - expect(fixture.debugElement.componentViewChildren[0].text()).toEqual("My Custom Block"); | ||
68 | - done(); | ||
69 | - }); | ||
70 | - }); | ||
71 | - | ||
72 | - | ||
73 | - it("renders the default block when hasn't defined a block type", done => { | ||
74 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [Block] }) | ||
75 | - class CustomBlockType { | ||
76 | - block: any = { type: null }; | ||
77 | - owner: any = { name: 'profile-name' }; | ||
78 | - constructor() { | ||
79 | - } | ||
80 | - } | ||
81 | - tcb | ||
82 | - .createAsync(CustomBlockType).then(fixture => { | ||
83 | - let myComponent: CustomBlockType = fixture.componentInstance; | ||
84 | - expect(myComponent.block.type).toBeNull(); | ||
85 | - expect(!!fixture.debugElement.nativeElement.querySelector("noosfero-default-block")).toBeTruthy(); | ||
86 | - done(); | ||
87 | - }); | ||
88 | - }); | ||
89 | - | ||
90 | - }); | ||
91 | -}); | ||
92 | \ No newline at end of file | 0 | \ No newline at end of file |
src/app/components/noosfero-blocks/block.component.ts
@@ -1,20 +0,0 @@ | @@ -1,20 +0,0 @@ | ||
1 | -import { Input, Inject, Component } from 'ng-forward'; | ||
2 | - | ||
3 | -@Component({ | ||
4 | - selector: 'noosfero-block', | ||
5 | - template: '<div></div>' | ||
6 | -}) | ||
7 | -@Inject("$element", "$scope", "$injector", "$compile") | ||
8 | -export class Block { | ||
9 | - | ||
10 | - @Input() block: any; | ||
11 | - @Input() owner: any; | ||
12 | - | ||
13 | - ngOnInit() { | ||
14 | - let blockName = (this.block && this.block.type) ? this.block.type.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() : "default-block"; | ||
15 | - this.$element.replaceWith(this.$compile('<noosfero-' + blockName + ' [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-' + blockName + '>')(this.$scope)); | ||
16 | - } | ||
17 | - | ||
18 | - constructor(private $element: any, private $scope: ng.IScope, private $injector: ng.auto.IInjectorService, private $compile: ng.ICompileService) { | ||
19 | - } | ||
20 | -} |
src/app/components/noosfero-blocks/block.scss
src/app/components/noosfero-blocks/index.ts
src/app/components/noosfero-blocks/link-list/index.ts
src/app/components/noosfero-blocks/link-list/link-list.component.spec.ts
@@ -1,65 +0,0 @@ | @@ -1,65 +0,0 @@ | ||
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | ||
2 | -import {Pipe, Input, provide, Component} from 'ng-forward'; | ||
3 | -import {provideFilters} from '../../../../spec/helpers'; | ||
4 | - | ||
5 | -import {LinkListBlock} from './link-list.component'; | ||
6 | - | ||
7 | -const tcb = new TestComponentBuilder(); | ||
8 | - | ||
9 | -const htmlTemplate: string = '<noosfero-link-list-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-link-list-block>'; | ||
10 | - | ||
11 | - | ||
12 | -describe("Components", () => { | ||
13 | - | ||
14 | - describe("Link List Block Component", () => { | ||
15 | - | ||
16 | - beforeEach(angular.mock.module("templates")); | ||
17 | - | ||
18 | - it("receives the block and the owner as inputs", done => { | ||
19 | - | ||
20 | - // Creating a container component (BlockContainerComponent) to include | ||
21 | - // the component under test (Block) | ||
22 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [LinkListBlock] }) | ||
23 | - class BlockContainerComponent { | ||
24 | - block = { type: 'Block' }; | ||
25 | - owner = { name: 'profile-name' }; | ||
26 | - constructor() { | ||
27 | - } | ||
28 | - } | ||
29 | - | ||
30 | - // uses the TestComponentBuilder instance to initialize the component | ||
31 | - //.overrideView(LinkListBlock, { template: 'asdasdasd', pipes: [NoosferoTemplate] }) | ||
32 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | ||
33 | - // and here we can inspect and run the test assertions | ||
34 | - let myComponent: LinkListBlock = fixture.componentInstance; | ||
35 | - | ||
36 | - // assure the block object inside the Block matches | ||
37 | - // the provided through the parent component | ||
38 | - expect(myComponent.block.type).toEqual("Block"); | ||
39 | - expect(myComponent.owner.name).toEqual("profile-name"); | ||
40 | - done(); | ||
41 | - }); | ||
42 | - }); | ||
43 | - | ||
44 | - | ||
45 | - it("display links stored in block settings", done => { | ||
46 | - | ||
47 | - @Component({ | ||
48 | - selector: 'test-container-component', | ||
49 | - template: htmlTemplate, | ||
50 | - directives: [LinkListBlock], | ||
51 | - providers: provideFilters("noosferoTemplateFilter") | ||
52 | - }) | ||
53 | - class CustomBlockType { | ||
54 | - block: any = { settings: { links: [{ name: 'link1', address: 'address1' }, { name: 'link2', address: 'address2' }] } }; | ||
55 | - owner: any = { name: 'profile-name' }; | ||
56 | - } | ||
57 | - tcb.createAsync(CustomBlockType).then(fixture => { | ||
58 | - expect(fixture.debugElement.queryAll(".link-list-block a").length).toEqual(2); | ||
59 | - done(); | ||
60 | - }); | ||
61 | - }); | ||
62 | - | ||
63 | - }); | ||
64 | - | ||
65 | -}); | ||
66 | \ No newline at end of file | 0 | \ No newline at end of file |
src/app/components/noosfero-blocks/link-list/link-list.component.ts
@@ -1,20 +0,0 @@ | @@ -1,20 +0,0 @@ | ||
1 | -import {Component, Input} from "ng-forward"; | ||
2 | - | ||
3 | -@Component({ | ||
4 | - selector: "noosfero-link-list-block", | ||
5 | - templateUrl: "app/components/noosfero-blocks/link-list/link-list.html" | ||
6 | -}) | ||
7 | -export class LinkListBlock { | ||
8 | - | ||
9 | - @Input() block: any; | ||
10 | - @Input() owner: any; | ||
11 | - | ||
12 | - links: any; | ||
13 | - | ||
14 | - ngOnInit() { | ||
15 | - if (this.block && this.block.settings) { | ||
16 | - this.links = this.block.settings.links; | ||
17 | - } | ||
18 | - } | ||
19 | - | ||
20 | -} |
src/app/components/noosfero-blocks/link-list/link-list.html
src/app/components/noosfero-blocks/link-list/link-list.scss
@@ -1,34 +0,0 @@ | @@ -1,34 +0,0 @@ | ||
1 | -.icon-event { | ||
2 | - @extend .fa-calendar; | ||
3 | -} | ||
4 | -.icon-photos { | ||
5 | - @extend .fa-photo; | ||
6 | -} | ||
7 | -.icon-edit { | ||
8 | - @extend .fa-edit; | ||
9 | -} | ||
10 | -.icon-ok { | ||
11 | - @extend .fa-check; | ||
12 | -} | ||
13 | -.icon-send { | ||
14 | - @extend .fa-send-o; | ||
15 | -} | ||
16 | -.icon-menu-people { | ||
17 | - @extend .fa-user; | ||
18 | -} | ||
19 | -.icon-forum { | ||
20 | - @extend .fa-users; | ||
21 | -} | ||
22 | -.icon-new { | ||
23 | - @extend .fa-file-o; | ||
24 | -} | ||
25 | -.icon-save { | ||
26 | - @extend .fa-save; | ||
27 | -} | ||
28 | - | ||
29 | -.link-list-block { | ||
30 | - a i { | ||
31 | - line-height: 25px; | ||
32 | - color: #949494; | ||
33 | - } | ||
34 | -} |
src/app/components/noosfero-blocks/main-block/index.ts
@@ -1 +0,0 @@ | @@ -1 +0,0 @@ | ||
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/noosfero-blocks/main-block/main-block.component.spec.ts
@@ -1,41 +0,0 @@ | @@ -1,41 +0,0 @@ | ||
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | ||
2 | -import {Input, provide, Component, StateConfig} from 'ng-forward'; | ||
3 | - | ||
4 | -import {MainBlock} from './main-block.component'; | ||
5 | -import {NoosferoApp} from '../../../index.module'; | ||
6 | - | ||
7 | -const tcb = new TestComponentBuilder(); | ||
8 | - | ||
9 | -const htmlTemplate: string = '<noosfero-main-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-main-block>'; | ||
10 | - | ||
11 | -describe("Components", () => { | ||
12 | - describe("Main Block Component", () => { | ||
13 | - | ||
14 | - // the karma preprocessor html2js transform the templates html into js files which put | ||
15 | - // the templates to the templateCache into the module templates | ||
16 | - // we need to load the module templates here as the template for the | ||
17 | - // component Block will be load on our tests | ||
18 | - beforeEach(angular.mock.module("templates")); | ||
19 | - | ||
20 | - it("check if the main block has a tag with ui-view attribute", done => { | ||
21 | - | ||
22 | - // Creating a container component (BlockContainerComponent) to include | ||
23 | - // the component under test (Block) | ||
24 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [MainBlock] }) | ||
25 | - class BlockContainerComponent { | ||
26 | - } | ||
27 | - | ||
28 | - // uses the TestComponentBuilder instance to initialize the component | ||
29 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | ||
30 | - // and here we can inspect and run the test assertions | ||
31 | - //let myComponent: MainBlock = fixture.componentInstance; | ||
32 | - | ||
33 | - // assure the block object inside the Block matches | ||
34 | - // the provided through the parent component | ||
35 | - expect(fixture.debugElement.queryAll('[ui-view="mainBlockContent"]').length).toEqual(1) | ||
36 | - done(); | ||
37 | - }); | ||
38 | - }); | ||
39 | - | ||
40 | - }); | ||
41 | -}); | ||
42 | \ No newline at end of file | 0 | \ No newline at end of file |
src/app/components/noosfero-blocks/main-block/main-block.component.ts
@@ -1,10 +0,0 @@ | @@ -1,10 +0,0 @@ | ||
1 | -import {Component, Input} from 'ng-forward' | ||
2 | -import {Block} from '../block.component'; | ||
3 | - | ||
4 | -@Component({ | ||
5 | - selector: 'noosfero-main-block', | ||
6 | - templateUrl: 'app/components/noosfero-blocks/main-block/main-block.html' | ||
7 | -}) | ||
8 | -export class MainBlock { | ||
9 | - | ||
10 | -} |
src/app/components/noosfero-blocks/main-block/main-block.html
@@ -1 +0,0 @@ | @@ -1 +0,0 @@ | ||
1 | -<div ui-view="mainBlockContent" autoscroll></div> |
src/app/components/noosfero-blocks/members-block/index.ts
@@ -1 +0,0 @@ | @@ -1 +0,0 @@ | ||
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/noosfero-blocks/members-block/members-block.component.spec.ts
@@ -1,53 +0,0 @@ | @@ -1,53 +0,0 @@ | ||
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | ||
2 | -import {Provider, Input, provide, Component} from 'ng-forward'; | ||
3 | - | ||
4 | -import {MembersBlock} from './members-block.component'; | ||
5 | - | ||
6 | -const htmlTemplate: string = '<noosfero-members-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-members-block>'; | ||
7 | - | ||
8 | -const tcb = new TestComponentBuilder(); | ||
9 | - | ||
10 | -describe("Components", () => { | ||
11 | - describe("Members Block Component", () => { | ||
12 | - | ||
13 | - beforeEach(angular.mock.module("templates")); | ||
14 | - | ||
15 | - let state = jasmine.createSpyObj("state", ["go"]); | ||
16 | - let providers = [ | ||
17 | - new Provider('truncateFilter', { useValue: () => { } }), | ||
18 | - new Provider('stripTagsFilter', { useValue: () => { } }), | ||
19 | - new Provider('$state', { useValue: state }), | ||
20 | - new Provider('ProfileService', { | ||
21 | - useValue: { | ||
22 | - getProfileMembers: (profileId: number, filters: any): any => { | ||
23 | - return Promise.resolve({ data: { people: [{ identifier: "person1" }] } }); | ||
24 | - } | ||
25 | - } | ||
26 | - }), | ||
27 | - ]; | ||
28 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [MembersBlock], providers: providers }) | ||
29 | - class BlockContainerComponent { | ||
30 | - block = { type: 'Block', settings: {} }; | ||
31 | - owner = { name: 'profile-name' }; | ||
32 | - constructor() { | ||
33 | - } | ||
34 | - } | ||
35 | - | ||
36 | - it("get members of the block owner", done => { | ||
37 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | ||
38 | - let block: MembersBlock = fixture.debugElement.componentViewChildren[0].componentInstance; | ||
39 | - expect(block.members).toEqual([{ identifier: "person1" }]); | ||
40 | - done(); | ||
41 | - }); | ||
42 | - }); | ||
43 | - | ||
44 | - it("render the profile image for each member", done => { | ||
45 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | ||
46 | - fixture.debugElement.getLocal("$rootScope").$apply(); | ||
47 | - expect(fixture.debugElement.queryAll("noosfero-profile-image").length).toEqual(1); | ||
48 | - done(); | ||
49 | - }); | ||
50 | - }); | ||
51 | - | ||
52 | - }); | ||
53 | -}); | ||
54 | \ No newline at end of file | 0 | \ No newline at end of file |
src/app/components/noosfero-blocks/members-block/members-block.component.ts
@@ -1,25 +0,0 @@ | @@ -1,25 +0,0 @@ | ||
1 | -import {Input, Inject, Component} from "ng-forward"; | ||
2 | -import {ProfileService} from "../../../../lib/ng-noosfero-api/http/profile.service"; | ||
3 | - | ||
4 | -@Component({ | ||
5 | - selector: "noosfero-members-block", | ||
6 | - templateUrl: 'app/components/noosfero-blocks/members-block/members-block.html', | ||
7 | -}) | ||
8 | -@Inject(ProfileService) | ||
9 | -export class MembersBlock { | ||
10 | - | ||
11 | - @Input() block: any; | ||
12 | - @Input() owner: any; | ||
13 | - | ||
14 | - members: any = []; | ||
15 | - | ||
16 | - constructor(private profileService: ProfileService) { | ||
17 | - | ||
18 | - } | ||
19 | - | ||
20 | - ngOnInit() { | ||
21 | - this.profileService.getProfileMembers(this.owner.id, { per_page: 6 }).then((response: any) => { | ||
22 | - this.members = response.data.people; | ||
23 | - }); | ||
24 | - } | ||
25 | -} |
src/app/components/noosfero-blocks/members-block/members-block.html
src/app/components/noosfero-blocks/members-block/members-block.scss
@@ -1,17 +0,0 @@ | @@ -1,17 +0,0 @@ | ||
1 | -.members-block { | ||
2 | - .member { | ||
3 | - img, i.profile-image { | ||
4 | - width: 60px; | ||
5 | - } | ||
6 | - img { | ||
7 | - display: inline-block; | ||
8 | - vertical-align: top; | ||
9 | - } | ||
10 | - i.profile-image { | ||
11 | - text-align: center; | ||
12 | - background-color: #889DB1; | ||
13 | - color: #F1F1F1; | ||
14 | - font-size: 4.5em; | ||
15 | - } | ||
16 | - } | ||
17 | -} |
src/app/components/noosfero-blocks/profile-image-block/profile-image-block.component.spec.ts
@@ -1,46 +0,0 @@ | @@ -1,46 +0,0 @@ | ||
1 | -import {TestComponentBuilder, ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder'; | ||
2 | -import {Pipe, Input, provide, Component} from 'ng-forward'; | ||
3 | - | ||
4 | -import {ProfileImageBlock} from './profile-image-block.component'; | ||
5 | - | ||
6 | -import * as helpers from "./../../../../spec/helpers"; | ||
7 | - | ||
8 | -const tcb = new TestComponentBuilder(); | ||
9 | - | ||
10 | -const htmlTemplate: string = '<noosfero-profile-image-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-profile-image-block>'; | ||
11 | - | ||
12 | -describe("Components", () => { | ||
13 | - | ||
14 | - describe("Profile Image Block Component", () => { | ||
15 | - | ||
16 | - beforeEach(angular.mock.module("templates")); | ||
17 | - | ||
18 | - @Component({ | ||
19 | - selector: 'test-container-component', | ||
20 | - template: htmlTemplate, | ||
21 | - directives: [ProfileImageBlock], | ||
22 | - providers: helpers.provideFilters("translateFilter") | ||
23 | - }) | ||
24 | - class BlockContainerComponent { | ||
25 | - block = { type: 'Block' }; | ||
26 | - owner = { name: 'profile-name' }; | ||
27 | - constructor() { | ||
28 | - } | ||
29 | - } | ||
30 | - | ||
31 | - it("show image if present", () => { | ||
32 | - helpers.tcb.createAsync(BlockContainerComponent).then(fixture => { | ||
33 | - var elProfile = fixture.debugElement.componentViewChildren[0]; | ||
34 | - expect(elProfile.query('div.profile-image-block').length).toEqual(1); | ||
35 | - }); | ||
36 | - }); | ||
37 | - | ||
38 | - it("has link to the profile", () => { | ||
39 | - helpers.tcb.createAsync(BlockContainerComponent).then(fixture => { | ||
40 | - var elProfile = fixture.debugElement.componentViewChildren[0]; | ||
41 | - expect(elProfile.query('a.settings-link').length).toEqual(1); | ||
42 | - }); | ||
43 | - }); | ||
44 | - | ||
45 | - }); | ||
46 | -}); |
src/app/components/noosfero-blocks/profile-image-block/profile-image-block.component.ts
@@ -1,14 +0,0 @@ | @@ -1,14 +0,0 @@ | ||
1 | -import {Inject, Input, Component} from "ng-forward"; | ||
2 | -import {ProfileImage} from "./../../../components/noosfero/profile-image/profile-image.component"; | ||
3 | - | ||
4 | -@Component({ | ||
5 | - selector: "noosfero-profile-image-block", | ||
6 | - templateUrl: 'app/components/noosfero-blocks/profile-image-block/profile-image-block.html', | ||
7 | - directives: [ProfileImage] | ||
8 | -}) | ||
9 | -export class ProfileImageBlock { | ||
10 | - | ||
11 | - @Input() block: any; | ||
12 | - @Input() owner: any; | ||
13 | - | ||
14 | -} |
src/app/components/noosfero-blocks/profile-image-block/profile-image-block.html
@@ -1,6 +0,0 @@ | @@ -1,6 +0,0 @@ | ||
1 | -<div class="center-block text-center profile-image-block"> | ||
2 | - <a ui-sref="main.profile.info({profile: ctrl.owner.identifier})"> | ||
3 | - <noosfero-profile-image [profile]="ctrl.owner"></noosfero-profile-image> | ||
4 | - </a> | ||
5 | - <a class="settings-link" target="_self" ui-sref="main.profile.settings({profile: ctrl.owner.identifier})">{{"blocks.profile_image.control_panel" | translate}}</a> | ||
6 | -</div> |
src/app/components/noosfero-blocks/profile-image-block/profile-image-block.scss
src/app/components/noosfero-blocks/raw-html/raw-html.component.spec.ts
@@ -1,36 +0,0 @@ | @@ -1,36 +0,0 @@ | ||
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | ||
2 | -import {Component} from 'ng-forward'; | ||
3 | - | ||
4 | -import {RawHTMLBlock} from './raw-html.component'; | ||
5 | - | ||
6 | -const tcb = new TestComponentBuilder(); | ||
7 | - | ||
8 | -const htmlTemplate: string = '<noosfero-raw-htmlblock [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-raw-htmlblock>'; | ||
9 | - | ||
10 | -describe("Components", () => { | ||
11 | - | ||
12 | - describe("Raw Html Block Component", () => { | ||
13 | - | ||
14 | - beforeEach(angular.mock.module("templates")); | ||
15 | - beforeEach(angular.mock.module("ngSanitize")); | ||
16 | - | ||
17 | - it("display html stored in block settings", done => { | ||
18 | - | ||
19 | - @Component({ | ||
20 | - selector: 'test-container-component', | ||
21 | - template: htmlTemplate, | ||
22 | - directives: [RawHTMLBlock], | ||
23 | - }) | ||
24 | - class CustomBlockType { | ||
25 | - block: any = { settings: { html: '<em>block content</em>' } }; | ||
26 | - owner: any = { name: 'profile-name' }; | ||
27 | - } | ||
28 | - tcb.createAsync(CustomBlockType).then(fixture => { | ||
29 | - expect(fixture.debugElement.query(".raw-html-block em").text().trim()).toEqual('block content'); | ||
30 | - done(); | ||
31 | - }); | ||
32 | - }); | ||
33 | - | ||
34 | - }); | ||
35 | - | ||
36 | -}); |
src/app/components/noosfero-blocks/raw-html/raw-html.component.ts
@@ -1,18 +0,0 @@ | @@ -1,18 +0,0 @@ | ||
1 | -import {Component, Input} from "ng-forward"; | ||
2 | - | ||
3 | -@Component({ | ||
4 | - selector: "noosfero-raw-htmlblock", | ||
5 | - templateUrl: 'app/components/noosfero-blocks/raw-html/raw-html.html' | ||
6 | -}) | ||
7 | - | ||
8 | -export class RawHTMLBlock { | ||
9 | - | ||
10 | - @Input() block: any; | ||
11 | - @Input() owner: any; | ||
12 | - | ||
13 | - html: string; | ||
14 | - | ||
15 | - ngOnInit() { | ||
16 | - this.html = this.block.settings.html; | ||
17 | - } | ||
18 | -} |
src/app/components/noosfero-blocks/raw-html/raw-html.html
src/app/components/noosfero-blocks/recent-documents/index.ts
@@ -1 +0,0 @@ | @@ -1 +0,0 @@ | ||
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/noosfero-blocks/recent-documents/recent-documents.component.spec.ts
@@ -1,53 +0,0 @@ | @@ -1,53 +0,0 @@ | ||
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | ||
2 | -import {Provider, Input, provide, Component} from 'ng-forward'; | ||
3 | -import {provideFilters} from '../../../../spec/helpers'; | ||
4 | -import {RecentDocumentsBlock} from './recent-documents.component'; | ||
5 | - | ||
6 | -const htmlTemplate: string = '<noosfero-recent-documents-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-recent-documents-block>'; | ||
7 | - | ||
8 | -const tcb = new TestComponentBuilder(); | ||
9 | - | ||
10 | -describe("Components", () => { | ||
11 | - describe("Recent Documents Block Component", () => { | ||
12 | - | ||
13 | - beforeEach(angular.mock.module("templates")); | ||
14 | - | ||
15 | - let state = jasmine.createSpyObj("state", ["go"]); | ||
16 | - let providers = [ | ||
17 | - new Provider('$state', { useValue: state }), | ||
18 | - new Provider('ArticleService', { | ||
19 | - useValue: { | ||
20 | - getByProfile: (profileId: number, filters: any): any => { | ||
21 | - return Promise.resolve({ data: { articles: [{ name: "article1" }] } }); | ||
22 | - } | ||
23 | - } | ||
24 | - }), | ||
25 | - ].concat(provideFilters("truncateFilter", "stripTagsFilter")); | ||
26 | - | ||
27 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [RecentDocumentsBlock], providers: providers }) | ||
28 | - class BlockContainerComponent { | ||
29 | - block = { type: 'Block', settings: {} }; | ||
30 | - owner = { name: 'profile-name' }; | ||
31 | - constructor() { | ||
32 | - } | ||
33 | - } | ||
34 | - | ||
35 | - it("get recent documents from the article service", done => { | ||
36 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | ||
37 | - let recentDocumentsBlock: RecentDocumentsBlock = fixture.debugElement.componentViewChildren[0].componentInstance; | ||
38 | - expect(recentDocumentsBlock.documents).toEqual([{ name: "article1" }]); | ||
39 | - done(); | ||
40 | - }); | ||
41 | - }); | ||
42 | - | ||
43 | - it("go to article page when open a document", done => { | ||
44 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | ||
45 | - let recentDocumentsBlock: RecentDocumentsBlock = fixture.debugElement.componentViewChildren[0].componentInstance; | ||
46 | - recentDocumentsBlock.openDocument({ path: "path", profile: { identifier: "identifier" } }); | ||
47 | - expect(state.go).toHaveBeenCalledWith("main.profile.page", { page: "path", profile: "identifier" }); | ||
48 | - done(); | ||
49 | - }); | ||
50 | - }); | ||
51 | - | ||
52 | - }); | ||
53 | -}); | ||
54 | \ No newline at end of file | 0 | \ No newline at end of file |
src/app/components/noosfero-blocks/recent-documents/recent-documents.component.ts
@@ -1,38 +0,0 @@ | @@ -1,38 +0,0 @@ | ||
1 | -import {Component, Inject, Input} from "ng-forward"; | ||
2 | -import {ArticleService} from "../../../../lib/ng-noosfero-api/http/article.service"; | ||
3 | - | ||
4 | -@Component({ | ||
5 | - selector: "noosfero-recent-documents-block", | ||
6 | - templateUrl: 'app/components/noosfero-blocks/recent-documents/recent-documents.html' | ||
7 | -}) | ||
8 | -@Inject(ArticleService, "$state") | ||
9 | -export class RecentDocumentsBlock { | ||
10 | - | ||
11 | - @Input() block: any; | ||
12 | - @Input() owner: any; | ||
13 | - | ||
14 | - profile: any; | ||
15 | - documents: any; | ||
16 | - | ||
17 | - documentsLoaded: boolean = false; | ||
18 | - | ||
19 | - constructor(private articleService: ArticleService, private $state: any) { | ||
20 | - } | ||
21 | - | ||
22 | - ngOnInit() { | ||
23 | - this.profile = this.owner; | ||
24 | - this.documents = []; | ||
25 | - | ||
26 | - var limit = (this.block && this.block.settings) ? this.block.settings.limit : null || 5; | ||
27 | - //FIXME get all text articles | ||
28 | - this.articleService.getByProfile(this.profile.id, { content_type: 'TinyMceArticle', per_page: limit }).then((response: any) => { | ||
29 | - this.documents = response.data.articles; | ||
30 | - this.documentsLoaded = true; | ||
31 | - }); | ||
32 | - } | ||
33 | - | ||
34 | - openDocument(article: any) { | ||
35 | - this.$state.go("main.profile.page", { page: article.path, profile: article.profile.identifier }); | ||
36 | - } | ||
37 | - | ||
38 | -} |
src/app/components/noosfero-blocks/recent-documents/recent-documents.html
@@ -1,18 +0,0 @@ | @@ -1,18 +0,0 @@ | ||
1 | -<div deckgrid source="ctrl.documents" class="deckgrid"> | ||
2 | - <div class="a-card panel media" ng-click="mother.ctrl.openDocument(card);"> | ||
3 | - <div class="author media-left" ng-show="card.author.image"> | ||
4 | - <img ng-src="{{card.author.image.url}}" class="img-circle"> | ||
5 | - </div> | ||
6 | - <div class="header media-body"> | ||
7 | - <h5 class="title media-heading" ng-bind="card.title"></h5> | ||
8 | - | ||
9 | - <div class="subheader"> | ||
10 | - <span class="time"> | ||
11 | - <i class="fa fa-clock-o"></i> <span am-time-ago="card.created_at | dateFormat"></span> | ||
12 | - </span> | ||
13 | - </div> | ||
14 | - </div> | ||
15 | - <img ng-show="card.image" ng-src="{{card.image.url}}" class="img-responsive article-image"> | ||
16 | - <div class="post-lead" ng-bind-html="card.body | stripTags | truncate: 100: '...': true"></div> | ||
17 | - </div> | ||
18 | -</div> |