Skip to content

Commit

Permalink
refactor(Example): use action creators
Browse files Browse the repository at this point in the history
  • Loading branch information
tja4472 committed Mar 10, 2019
1 parent c80495d commit 52a8470
Show file tree
Hide file tree
Showing 16 changed files with 92 additions and 99 deletions.
26 changes: 9 additions & 17 deletions projects/example-app/src/app/auth/actions/auth-api.actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Action } from '@ngrx/store';
import { ActionsUnion, createAction } from '@ngrx/store';
import { User } from '@example-app/auth/models/user';

export enum AuthApiActionTypes {
Expand All @@ -7,20 +7,12 @@ export enum AuthApiActionTypes {
LoginRedirect = '[Auth/API] Login Redirect',
}

export class LoginSuccess implements Action {
readonly type = AuthApiActionTypes.LoginSuccess;
export const AuthApiActions = {
loginRedirect: () => createAction(AuthApiActionTypes.LoginRedirect),
loginSuccess: (user: User) =>
createAction(AuthApiActionTypes.LoginSuccess, { user }),
loginFailure: (error: any) =>
createAction(AuthApiActionTypes.LoginFailure, { error }),
};

constructor(public payload: { user: User }) {}
}

export class LoginFailure implements Action {
readonly type = AuthApiActionTypes.LoginFailure;

constructor(public payload: { error: any }) {}
}

export class LoginRedirect implements Action {
readonly type = AuthApiActionTypes.LoginRedirect;
}

export type AuthApiActionsUnion = LoginSuccess | LoginFailure | LoginRedirect;
export type AuthApiActions = ActionsUnion<typeof AuthApiActions>;
24 changes: 8 additions & 16 deletions projects/example-app/src/app/auth/actions/auth.actions.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
import { Action } from '@ngrx/store';
import { Action, ActionsUnion, createAction } from '@ngrx/store';

export enum AuthActionTypes {
Logout = '[Auth] Logout',
LogoutConfirmation = '[Auth] Logout Confirmation',
LogoutConfirmationDismiss = '[Auth] Logout Confirmation Dismiss',
}

export class Logout implements Action {
readonly type = AuthActionTypes.Logout;
}

export class LogoutConfirmation implements Action {
readonly type = AuthActionTypes.LogoutConfirmation;
}

export class LogoutConfirmationDismiss implements Action {
readonly type = AuthActionTypes.LogoutConfirmationDismiss;
}
export const AuthActions = {
logout: () => createAction(AuthActionTypes.Logout),
logoutConfirmation: () => createAction(AuthActionTypes.LogoutConfirmation),
logoutConfirmationDismiss: () =>
createAction(AuthActionTypes.LogoutConfirmationDismiss),
};

export type AuthActionsUnion =
| Logout
| LogoutConfirmation
| LogoutConfirmationDismiss;
export type AuthActions = ActionsUnion<typeof AuthActions>;
15 changes: 11 additions & 4 deletions projects/example-app/src/app/auth/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import * as AuthActions from './auth.actions';
import * as AuthApiActions from './auth-api.actions';
import * as LoginPageActions from './login-page.actions';
import { AuthActions, AuthActionTypes } from './auth.actions';
import { AuthApiActions, AuthApiActionTypes } from './auth-api.actions';
import { LoginPageActions, LoginPageActionTypes } from './login-page.actions';

export { AuthActions, AuthApiActions, LoginPageActions };
export {
AuthActions,
AuthActionTypes,
AuthApiActions,
AuthApiActionTypes,
LoginPageActions,
LoginPageActionTypes,
};
13 changes: 6 additions & 7 deletions projects/example-app/src/app/auth/actions/login-page.actions.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { Action } from '@ngrx/store';
import { ActionsUnion, createAction } from '@ngrx/store';
import { Credentials } from '@example-app/auth/models/user';

export enum LoginPageActionTypes {
Login = '[Login Page] Login',
}

export class Login implements Action {
readonly type = LoginPageActionTypes.Login;
export const LoginPageActions = {
login: (credentials: Credentials) =>
createAction(LoginPageActionTypes.Login, { credentials }),
};

constructor(public payload: { credentials: Credentials }) {}
}

export type LoginPageActionsUnion = Login;
export type LoginPageActions = ActionsUnion<typeof LoginPageActions>;
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('Login Page', () => {

it('should dispatch a login event on submit', () => {
const credentials: any = {};
const action = new LoginPageActions.Login({ credentials });
const action = LoginPageActions.login(credentials);

instance.onSubmit(credentials);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ export class LoginPageComponent implements OnInit {
ngOnInit() {}

onSubmit(credentials: Credentials) {
this.store.dispatch(new LoginPageActions.Login({ credentials }));
this.store.dispatch(LoginPageActions.login(credentials));
}
}
26 changes: 13 additions & 13 deletions projects/example-app/src/app/auth/effects/auth.effects.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ describe('AuthEffects', () => {
it('should return an auth.LoginSuccess action, with user information if login succeeds', () => {
const credentials: Credentials = { username: 'test', password: '' };
const user = { name: 'User' } as User;
const action = new LoginPageActions.Login({ credentials });
const completion = new AuthApiActions.LoginSuccess({ user });
const action = LoginPageActions.login(credentials);
const completion = AuthApiActions.loginSuccess(user);

actions$ = hot('-a---', { a: action });
const response = cold('-a|', { a: user });
Expand All @@ -70,10 +70,10 @@ describe('AuthEffects', () => {

it('should return a new auth.LoginFailure if the login service throws', () => {
const credentials: Credentials = { username: 'someOne', password: '' };
const action = new LoginPageActions.Login({ credentials });
const completion = new AuthApiActions.LoginFailure({
error: 'Invalid username or password',
});
const action = LoginPageActions.login(credentials);
const completion = AuthApiActions.loginFailure(
'Invalid username or password'
);
const error = 'Invalid username or password';

actions$ = hot('-a---', { a: action });
Expand All @@ -88,7 +88,7 @@ describe('AuthEffects', () => {
describe('loginSuccess$', () => {
it('should dispatch a RouterNavigation action', (done: any) => {
const user = { name: 'User' } as User;
const action = new AuthApiActions.LoginSuccess({ user });
const action = AuthApiActions.loginSuccess(user);

actions$ = of(action);

Expand All @@ -101,7 +101,7 @@ describe('AuthEffects', () => {

describe('loginRedirect$', () => {
it('should dispatch a RouterNavigation action when auth.LoginRedirect is dispatched', (done: any) => {
const action = new AuthApiActions.LoginRedirect();
const action = AuthApiActions.loginRedirect();

actions$ = of(action);

Expand All @@ -112,7 +112,7 @@ describe('AuthEffects', () => {
});

it('should dispatch a RouterNavigation action when auth.Logout is dispatched', (done: any) => {
const action = new AuthActions.Logout();
const action = AuthActions.logout();

actions$ = of(action);

Expand All @@ -125,8 +125,8 @@ describe('AuthEffects', () => {

describe('logoutConfirmation$', () => {
it('should dispatch a Logout action if dialog closes with true result', () => {
const action = new AuthActions.LogoutConfirmation();
const completion = new AuthActions.Logout();
const action = AuthActions.logoutConfirmation();
const completion = AuthActions.logout();

actions$ = hot('-a', { a: action });
const expected = cold('-b', { b: completion });
Expand All @@ -139,8 +139,8 @@ describe('AuthEffects', () => {
});

it('should dispatch a LogoutConfirmationDismiss action if dialog closes with falsy result', () => {
const action = new AuthActions.LogoutConfirmation();
const completion = new AuthActions.LogoutConfirmationDismiss();
const action = AuthActions.logoutConfirmation();
const completion = AuthActions.logoutConfirmationDismiss();

actions$ = hot('-a', { a: action });
const expected = cold('-b', { b: completion });
Expand Down
26 changes: 12 additions & 14 deletions projects/example-app/src/app/auth/effects/auth.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import { catchError, exhaustMap, map, tap } from 'rxjs/operators';
import {
LoginPageActions,
AuthActions,
AuthActionTypes,
AuthApiActions,
AuthApiActionTypes,
LoginPageActionTypes,
} from '@example-app/auth/actions';
import { Credentials } from '@example-app/auth/models/user';
import { AuthService } from '@example-app/auth/services/auth.service';
Expand All @@ -17,36 +20,33 @@ import { LogoutConfirmationDialogComponent } from '@example-app/auth/components/
export class AuthEffects {
@Effect()
login$ = this.actions$.pipe(
ofType(LoginPageActions.LoginPageActionTypes.Login),
map(action => action.payload.credentials),
ofType(LoginPageActionTypes.Login),
map(action => action.credentials),
exhaustMap((auth: Credentials) =>
this.authService.login(auth).pipe(
map(user => new AuthApiActions.LoginSuccess({ user })),
catchError(error => of(new AuthApiActions.LoginFailure({ error })))
map(AuthApiActions.loginSuccess),
catchError(error => of(AuthApiActions.loginFailure(error)))
)
)
);

@Effect({ dispatch: false })
loginSuccess$ = this.actions$.pipe(
ofType(AuthApiActions.AuthApiActionTypes.LoginSuccess),
ofType(AuthApiActionTypes.LoginSuccess),
tap(() => this.router.navigate(['/']))
);

@Effect({ dispatch: false })
loginRedirect$ = this.actions$.pipe(
ofType(
AuthApiActions.AuthApiActionTypes.LoginRedirect,
AuthActions.AuthActionTypes.Logout
),
ofType(AuthApiActionTypes.LoginRedirect, AuthActionTypes.Logout),
tap(authed => {
this.router.navigate(['/login']);
})
);

@Effect()
logoutConfirmation$ = this.actions$.pipe(
ofType(AuthActions.AuthActionTypes.LogoutConfirmation),
ofType(AuthActionTypes.LogoutConfirmation),
exhaustMap(() => {
const dialogRef = this.dialog.open<
LogoutConfirmationDialogComponent,
Expand All @@ -58,14 +58,12 @@ export class AuthEffects {
}),
map(
result =>
result
? new AuthActions.Logout()
: new AuthActions.LogoutConfirmationDismiss()
result ? AuthActions.logout() : AuthActions.logoutConfirmationDismiss()
)
);

constructor(
private actions$: Actions<LoginPageActions.LoginPageActionsUnion>,
private actions$: Actions<LoginPageActions>,
private authService: AuthService,
private router: Router,
private dialog: MatDialog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('AuthReducer', () => {
describe('LOGIN_SUCCESS', () => {
it('should add a user set loggedIn to true in auth state', () => {
const user = { name: 'test' } as User;
const createAction = new AuthApiActions.LoginSuccess({ user });
const createAction = AuthApiActions.loginSuccess(user);

const expectedResult = {
user: { name: 'test' },
Expand All @@ -42,7 +42,7 @@ describe('AuthReducer', () => {
const initialState = {
user: { name: 'test' },
} as fromAuth.State;
const createAction = new AuthActions.Logout();
const createAction = AuthActions.logout();

const expectedResult = fromAuth.initialState;

Expand Down
15 changes: 10 additions & 5 deletions projects/example-app/src/app/auth/reducers/auth.reducer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { AuthApiActions, AuthActions } from '@example-app/auth/actions';
import {
AuthActions,
AuthActionTypes,
AuthApiActions,
AuthApiActionTypes,
} from '@example-app/auth/actions';
import { User } from '@example-app/auth/models/user';

export interface State {
Expand All @@ -11,17 +16,17 @@ export const initialState: State = {

export function reducer(
state = initialState,
action: AuthApiActions.AuthApiActionsUnion | AuthActions.AuthActionsUnion
action: AuthApiActions | AuthActions
): State {
switch (action.type) {
case AuthApiActions.AuthApiActionTypes.LoginSuccess: {
case AuthApiActionTypes.LoginSuccess: {
return {
...state,
user: action.payload.user,
user: action.user,
};
}

case AuthActions.AuthActionTypes.Logout: {
case AuthActionTypes.Logout: {
return initialState;
}

Expand Down
5 changes: 1 addition & 4 deletions projects/example-app/src/app/auth/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ export interface State extends fromRoot.State {
auth: AuthState;
}

export const reducers: ActionReducerMap<
AuthState,
AuthApiActions.AuthApiActionsUnion
> = {
export const reducers: ActionReducerMap<AuthState, AuthApiActions> = {
status: fromAuth.reducer,
loginPage: fromLoginPage.reducer,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('LoginPageReducer', () => {
describe('LOGIN', () => {
it('should make pending to true', () => {
const user = { username: 'test' } as Credentials;
const createAction = new LoginPageActions.Login({ credentials: user });
const createAction = LoginPageActions.login(user);

const expectedResult = {
error: null,
Expand All @@ -35,7 +35,7 @@ describe('LoginPageReducer', () => {
describe('LOGIN_SUCCESS', () => {
it('should have no error and no pending state', () => {
const user = { name: 'test' } as User;
const createAction = new AuthApiActions.LoginSuccess({ user });
const createAction = AuthApiActions.loginSuccess(user);

const expectedResult = {
error: null,
Expand All @@ -51,7 +51,7 @@ describe('LoginPageReducer', () => {
describe('LOGIN_FAILURE', () => {
it('should have an error and no pending state', () => {
const error = 'login failed';
const createAction = new AuthApiActions.LoginFailure({ error });
const createAction = AuthApiActions.loginFailure(error);

const expectedResult = {
error: error,
Expand Down
Loading

0 comments on commit 52a8470

Please sign in to comment.