Commit 4f1c6294a4a294a566501e075920948ae0c83f1a

Authored by Carlos Purificação
1 parent 99531814

Login block component - initial implementation

src/app/layout/blocks/login-block/login-block.component.spec.ts 0 → 100644
... ... @@ -0,0 +1,108 @@
  1 +import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder';
  2 +import {Injectable, Provider, provide} from "ng-forward";
  3 +import {ComponentTestHelper, createClass} from './../../../../spec/component-test-helper';
  4 +import {ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder';
  5 +import {providers} from 'ng-forward/cjs/testing/providers';
  6 +import {LoginBlockComponent} from './login-block.component';
  7 +import * as helpers from "./../../../../spec/helpers";
  8 +import {SessionService, AuthService, AuthController, IAuthEvents, AUTH_EVENTS} from "./../../../login";
  9 +
  10 +const htmlTemplate: string = '<noosfero-login-block></noosfero-login-block>';
  11 +
  12 +describe("Components", () => {
  13 +
  14 + describe("Login Block Component", () => {
  15 + let helper: ComponentTestHelper<LoginBlockComponent>;
  16 + let person: any = null;
  17 +
  18 + /**
  19 + * Mock objects
  20 + */
  21 + let authService: any = helpers.mocks.authService;
  22 + let user = <noosfero.User>{ person: person };
  23 + let sessionService: any = <any>helpers.mocks.sessionWithCurrentUser(user);
  24 + let state = jasmine.createSpyObj("$state", ["go"]);
  25 + let scope = helpers.mocks.scopeWithEvents;
  26 +
  27 + let providers = [
  28 + new Provider('SessionService', { useValue: sessionService }),
  29 + new Provider('$state', { useValue: state }),
  30 + new Provider('AuthService', { useValue: authService }),
  31 + new Provider('$scope', { useValue: scope })
  32 + ];
  33 +
  34 + beforeEach( angular.mock.module("templates") );
  35 +
  36 + beforeEach( (done: Function) => {
  37 + let cls = createClass({
  38 + template: htmlTemplate,
  39 + directives: [LoginBlockComponent],
  40 + providers: providers,
  41 + properties: {}
  42 + });
  43 + helper = new ComponentTestHelper<LoginBlockComponent>(cls, done);
  44 + });
  45 +
  46 + it("expect person to be null with no logged in user", () => {
  47 + expect(helper.component.currentUser).toBeNull;
  48 + });
  49 +
  50 + it("expect person to be defined when user login", () => {
  51 + // Executes the login method on the component
  52 + doComponentLogin();
  53 + expect(helper.component.currentUser.person).toBe(person);
  54 + });
  55 +
  56 + it("expect person to be null when user logout", () => {
  57 + // First do a login
  58 + doComponentLogin();
  59 + // The logout the user
  60 + doComponentLogout();
  61 + // Check if the current user was cleared
  62 + expect(helper.component.currentUser).toBeNull;
  63 + });
  64 +
  65 + /**
  66 + * Execute the logout method on the target component
  67 + */
  68 + function doComponentLogout() {
  69 + // Create a mock for the AuthService logout method
  70 + spyOn(authService, "logout");
  71 + helper.component.logout();
  72 + expect(authService.logout).toHaveBeenCalled();
  73 + // After the component logout method execution, fire the
  74 + // AuthService event
  75 + simulateLogout();
  76 + }
  77 +
  78 + /**
  79 + * Execute the login method on the target component
  80 + */
  81 + function doComponentLogin() {
  82 + // Create a mock for the AuthService login method
  83 + spyOn(authService, "login");
  84 + helper.component.login();
  85 + expect(authService.login).toHaveBeenCalled();
  86 + // After the component login method execution, fire the
  87 + // AuthService event
  88 + simulateLogin();
  89 + }
  90 +
  91 + /**
  92 + * Simulate the AuthService loginSuccess event
  93 + */
  94 + function simulateLogin() {
  95 + let localScope: ng.IScope = helper.component["$scope"];
  96 + localScope.$emit(AUTH_EVENTS.loginSuccess);
  97 + }
  98 +
  99 + /**
  100 + * Simulate the AuthService logoutSuccess event
  101 + */
  102 + function simulateLogout() {
  103 + let localScope: ng.IScope = helper.component["$scope"];
  104 + localScope.$emit(AUTH_EVENTS.logoutSuccess);
1
  • Me
    Michel Felipe @mfdeveloper

    O uso de $emit para executar callbacks de eventos é uma abordagem do Angular 1.x que deve ser evitada. Ao invés disso, utilize o método EventEmitter.next() ou EventEmitter.emit() como sugerido pelo ng-forward

    Choose File ...   File name...
    Cancel
  105 + }
  106 + });
  107 +
  108 +});
0 109 \ No newline at end of file
... ...
src/app/layout/blocks/login-block/login-block.component.ts 0 → 100644
... ... @@ -0,0 +1,73 @@
  1 +import {Input, Inject, Component} from "ng-forward";
  2 +import {SessionService, AuthService, IAuthEvents, AUTH_EVENTS} from "./../../../login";
  3 +
  4 +/**
  5 + * @ngdoc controller
  6 + * @name layout.blocks.LoginBlockComponent
  7 + * @description
  8 + * The Noosfero block responible for presenting a login form and user status
  9 + */
  10 +@Component({
  11 + selector: "noosfero-login-block",
  12 + templateUrl: 'app/layout/blocks/login-block/login-block.html',
  13 +})
  14 +@Inject("SessionService", "$state", 'AuthService', "$scope")
  15 +export class LoginBlockComponent {
  16 +
  17 + /**
  18 + * @ngdoc property
  19 + * @name currentUser
  20 + * @propertyOf layout.blocks.LoginBlockComponent
  21 + * @description
  22 + * The current loged in user
  23 + */
  24 + currentUser: noosfero.User;
  25 +
  26 + /**
  27 + * @ngdoc property
  28 + * @name credentials
  29 + * @propertyOf layout.blocks.LoginBlockComponent
  30 + * @description
  31 + * The credentials of the currentUser
  32 + */
  33 + credentials: noosfero.Credentials;
  34 +
  35 + constructor(
  36 + private session: SessionService,
  37 + private $state: ng.ui.IStateService,
  38 + private authService: AuthService,
  39 + private $scope: ng.IScope) {
  40 + this.currentUser = this.session.currentUser();
  41 +
  42 + this.$scope.$on(AUTH_EVENTS.loginSuccess, () => {
1
  • Me
    Michel Felipe @mfdeveloper

    O uso de $scope para callback de eventos é uma abordagem do Angular 1.x que deve ser evitada. Ao invés disso, utilize a classe EventEmitter como sugerido pelo ng-forward

    Choose File ...   File name...
    Cancel
  43 + this.currentUser = this.session.currentUser();
  44 + });
  45 +
  46 + this.$scope.$on(AUTH_EVENTS.logoutSuccess, () => {
  47 + this.currentUser = this.session.currentUser();
  48 + });
  49 +
  50 + }
  51 +
  52 + /**
  53 + * @ngdoc method
  54 + * @name login
  55 + * @methodOf layout.blocks.LoginBlockComponent
  56 + * @description
  57 + * Logs in the user using its credentials
  58 + */
  59 + login() {
  60 + this.authService.login(this.credentials);
  61 + }
  62 +
  63 + /**
  64 + * @ngdoc method
  65 + * @name logout
  66 + * @methodOf layout.blocks.LoginBlockComponent
  67 + * @description
  68 + * Logout the user
  69 + */
  70 + logout() {
  71 + this.authService.logout();
  72 + };
  73 +}
... ...
src/app/layout/blocks/login-block/login-block.html 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +<div class="logged-user-info" ng-show="ctrl.currentUser">
  2 + <h4>Logged in as {{ctrl.currentUser.person.identifier}}</h4>
  3 + <ul>
  4 + <li>User since {{ctrl.currentUser.created_at.month}}/{{ctrl.currentUser.created_at.year}}</li>
  5 + <li><a ui-sref="main.profile.info({profile: ctrl.currentUser.person.identifier})">Profile Homepage</a></li>
  6 + </ul>
  7 + <div class="user-actions">
  8 + <a href="#" ng-click="ctrl.logout()"><i class="fa fa-fw fa-power-off"></i> {{"navbar.logout" | translate}}</a>
  9 + </div>
  10 +</div>
  11 +<div class="logged-user-info" ng-show="!ctrl.currentUser">
  12 + <form>
  13 + <div class="form-group">
  14 + <label for="exampleInputEmail1">{{"auth.form.login" | translate}}</label>
  15 + <input type="text" class="form-control" id="exampleInputEmail1" placeholder="Login / Email" ng-model="ctrl.credentials.username">
  16 + </div>
  17 + <div class="form-group">
  18 + <label for="exampleInputPassword1">{{"auth.form.password" | translate}}</label>
  19 + <input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password" ng-model="ctrl.credentials.password">
  20 + </div>
  21 + <button type="submit" class="btn btn-default" ng-click="ctrl.login()">{{"auth.form.login_button" | translate}}</button>
  22 + </form>
  23 +</div>
0 24 \ No newline at end of file
... ...
src/app/login/session.service.ts
... ... @@ -11,13 +11,11 @@ export class SessionService {
11 11  
12 12 create(data: UserResponse): noosfero.User {
13 13 this.$localStorage.currentUser = data.user;
14   - this.$log.debug('User session created.', this.$localStorage.currentUser);
15 14 return this.$localStorage.currentUser;
16 15 };
17 16  
18 17 destroy() {
19 18 delete this.$localStorage.currentUser;
20   - this.$log.debug('User session destroyed.');
21 19 };
22 20  
23 21 currentUser(): noosfero.User {
... ...
src/app/main/main.component.ts
... ... @@ -9,6 +9,7 @@ import {BlockComponent} from &quot;../layout/blocks/block.component&quot;;
9 9 import {EnvironmentComponent} from "../environment/environment.component";
10 10 import {EnvironmentHomeComponent} from "../environment/environment-home.component";
11 11 import {PeopleBlockComponent} from "../layout/blocks/people-block/people-block.component";
  12 +import {LoginBlockComponent} from "../layout/blocks/login-block/login-block.component";
12 13 import {LinkListBlockComponent} from "./../layout/blocks/link-list/link-list.component";
13 14 import {RecentDocumentsBlockComponent} from "../layout/blocks/recent-documents/recent-documents.component";
14 15 import {ProfileImageBlockComponent} from "../layout/blocks/profile-image-block/profile-image-block.component";
... ... @@ -81,7 +82,7 @@ export class EnvironmentContent {
81 82 template: '<div ng-view></div>',
82 83 directives: [
83 84 ArticleBlogComponent, ArticleViewComponent, BoxesComponent, BlockComponent,
84   - EnvironmentComponent, PeopleBlockComponent,
  85 + EnvironmentComponent, PeopleBlockComponent, LoginBlockComponent,
85 86 LinkListBlockComponent, CommunitiesBlockComponent,
86 87 MainBlockComponent, RecentDocumentsBlockComponent, Navbar, ProfileImageBlockComponent,
87 88 MembersBlockComponent, NoosferoTemplate, DateFormat, RawHTMLBlockComponent
... ...
src/spec/component-test-helper.ts
... ... @@ -2,6 +2,7 @@ import { Component } from &quot;ng-forward&quot;;
2 2 import { TestComponentBuilder, ngClass } from 'ng-forward/cjs/testing/test-component-builder';
3 3 import { INgForwardJQuery } from "ng-forward/cjs/util/jqlite-extensions";
4 4 import { ComponentFixture } from 'ng-forward/cjs/testing/test-component-builder';
  5 +import * as helpers from './helpers';
5 6  
6 7 /**
7 8 * @ngdoc object
... ... @@ -135,6 +136,7 @@ export function createClass({
135 136 providers = <any[]>[],
136 137 properties = <any>{}
137 138 }): any {
  139 + providers = providers.concat(helpers.provideFilters("translateFilter"));
138 140 @Component({ selector: 'component-test-helper-container', template, directives, providers })
139 141 class Test {
140 142 constructor() {
... ...
src/spec/mocks.ts
... ... @@ -41,7 +41,8 @@ export var mocks = {
41 41 }
42 42 },
43 43 authService: {
44   - logout: () => { }
  44 + logout: () => { },
1
  45 + login: () => { }
45 46 },
46 47 articleService: {
47 48 getByProfile: (profileId: number, params?: any) => {
... ...