Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(auth): refactor reset-password.effects.spec to decrease describe depth #3370

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
262 changes: 128 additions & 134 deletions libs/auth/state/src/effects/reset-password.effects.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TestBed } from '@angular/core/testing';
import { provideMockActions } from '@ngrx/effects/testing';
import { Action } from '@ngrx/store';
import {
hot,
cold,
Expand All @@ -8,6 +9,7 @@ import {
Observable,
of,
} from 'rxjs';
import { TestScheduler } from 'rxjs/testing';

import {
DaffAuthResetPasswordInfo,
Expand Down Expand Up @@ -40,6 +42,21 @@ import { daffTransformErrorToStateError } from '@daffodil/core/state';

import { DaffAuthResetPasswordEffects } from './reset-password.effects';

interface ResetPasswordTestState {
isAutoLoginTrue: boolean;
didPasswordResetSucceed: boolean;
didTokenStorageSucceed?: boolean;
whatErrorWasThrown?: DaffStorageServiceError;
whatActionWasReturned?: Action;
whatOtherActionWasReturned?: Action;
};

interface SendResetEmailTestState {
wasOperationSuccessful: boolean;
whatActionWasReturned: Action;
whatErrorWasThrown?: DaffStorageServiceError;
};

describe('@daffodil/auth/state | DaffAuthResetPasswordEffects', () => {
let actions$: Observable<any>;
let effects: DaffAuthResetPasswordEffects;
Expand Down Expand Up @@ -86,152 +103,129 @@ describe('@daffodil/auth/state | DaffAuthResetPasswordEffects', () => {
});

describe('resetPassword$', () => {
let expected;
let mockAuthResetPasswordAction: DaffResetPassword;

describe('when autoLogin is true', () => {
beforeEach(() => {
mockAuthResetPasswordAction = new DaffResetPassword(mockResetInfo, true);
actions$ = hot('--a', { a: mockAuthResetPasswordAction });
});

describe('and the resetPassword is successful', () => {
beforeEach(() => {
daffResetPasswordDriver.resetPassword.and.returnValue(of(token));
});

describe('and setToken is successful', () => {
beforeEach(() => {
const mockAuthResetPasswordSuccessAction = new DaffResetPasswordSuccess(token);

expected = cold('--a', { a: mockAuthResetPasswordSuccessAction });
});

it('should notify state that the resetPassword was successful', () => {
expect(effects.resetPassword$).toBeObservable(expected);
});

it('should store the auth token', () => {
expect(effects.resetPassword$).toBeObservable(expected);
expect(setAuthTokenSpy).toHaveBeenCalledWith(token);
});
});

describe('and the storage service throws a server side error', () => {
beforeEach(() => {
const error = new DaffServerSideStorageError('Server side');
const serverSideAction = new DaffAuthServerSide(daffTransformErrorToStateError(error));
const mockAuthResetPasswordFailureAction = new DaffResetPasswordFailure(daffTransformErrorToStateError(error));
setAuthTokenSpy.and.throwError(error);
expected = cold('--(ab)', { a: serverSideAction, b: mockAuthResetPasswordFailureAction });
});

it('should dispatch a server side action', () => {
expect(effects.resetPassword$).toBeObservable(expected);
});
});

describe('and the storage service throws a storage error', () => {
beforeEach(() => {
const error = new DaffStorageServiceError('Storage error');
const storageAction = new DaffAuthStorageFailure(daffTransformErrorToStateError(error));
const mockAuthResetPasswordFailureAction = new DaffResetPasswordFailure(daffTransformErrorToStateError(error));
setAuthTokenSpy.and.throwError(error);
expected = cold('--(ab)', { a: storageAction, b: mockAuthResetPasswordFailureAction });
});

it('should dispatch a server side action', () => {
expect(effects.resetPassword$).toBeObservable(expected);
});
});
});

describe('and the resetPassword fails', () => {
beforeEach(() => {
const error = new DaffAuthenticationFailedError('Failed to reset password');
const response = cold('#', {}, error);
daffResetPasswordDriver.resetPassword.and.returnValue(response);
const mockAuthResetPasswordFailureAction = new DaffResetPasswordFailure(daffTransformErrorToStateError(error));
it('should compute the next action correctly', () => {
const testStates: ResetPasswordTestState[] = [
{
isAutoLoginTrue: true,
didPasswordResetSucceed: true,
didTokenStorageSucceed: true,
whatActionWasReturned: new DaffResetPasswordSuccess(token),
},
{
isAutoLoginTrue: true,
didPasswordResetSucceed: true,
didTokenStorageSucceed: false,
whatErrorWasThrown: new DaffServerSideStorageError('Server side'),
whatActionWasReturned: new DaffResetPasswordFailure(daffTransformErrorToStateError(
new DaffServerSideStorageError('Server side'),
)),
whatOtherActionWasReturned: new DaffAuthServerSide(daffTransformErrorToStateError(
new DaffServerSideStorageError('Server side'),
)),
},
{
isAutoLoginTrue: true,
didPasswordResetSucceed: true,
didTokenStorageSucceed: false,
whatErrorWasThrown: new DaffStorageServiceError('Storage error'),
whatActionWasReturned: new DaffResetPasswordFailure(daffTransformErrorToStateError(
new DaffStorageServiceError('Storage error'),
)),
whatOtherActionWasReturned: new DaffAuthStorageFailure(daffTransformErrorToStateError(
new DaffStorageServiceError('Storage error'),
)),
},
{
isAutoLoginTrue: true,
didPasswordResetSucceed: false,
whatErrorWasThrown: new DaffAuthenticationFailedError('Failed to reset password'),
whatActionWasReturned: new DaffResetPasswordFailure(daffTransformErrorToStateError(
new DaffAuthenticationFailedError('Failed to reset password'),
)),
},
{
isAutoLoginTrue: false,
didPasswordResetSucceed: true,
whatActionWasReturned: new DaffResetPasswordSuccess(),
},
{
isAutoLoginTrue: false,
didPasswordResetSucceed: false,
whatErrorWasThrown: new DaffAuthenticationFailedError('Failed to reset password'),
whatActionWasReturned: new DaffResetPasswordFailure(daffTransformErrorToStateError(
new DaffAuthenticationFailedError('Failed to reset password'),
)),
},
];

actions$ = hot('--a', { a: mockAuthResetPasswordAction });
expected = cold('--b', { b: mockAuthResetPasswordFailureAction });
testStates.forEach((el) => {
const testScheduler = new TestScheduler((actual, expected) => {
expect(actual).toEqual(expected);
});

it('should notify state that the resetPassword failed', () => {
expect(effects.resetPassword$).toBeObservable(expected);
testScheduler.run(helpers => {
const mockAuthResetPasswordAction = new DaffResetPassword(mockResetInfo, el.isAutoLoginTrue);
actions$ = helpers.hot('--a', { a: mockAuthResetPasswordAction });
if (el.didPasswordResetSucceed) {
if (el.isAutoLoginTrue) {
daffResetPasswordDriver.resetPassword.and.returnValue(of(token));
} else {
daffResetPasswordDriver.resetPasswordOnly.and.returnValue(of(undefined));
}
if (el.whatErrorWasThrown) {
setAuthTokenSpy.and.throwError(el.whatErrorWasThrown);
} else {
setAuthTokenSpy.and.returnValue(undefined);
}
} else {
if (el.isAutoLoginTrue) {
daffResetPasswordDriver.resetPassword.and.returnValue(helpers.cold('#', {}, el.whatErrorWasThrown));
} else {
daffResetPasswordDriver.resetPasswordOnly.and.returnValue(helpers.cold('#', {}, el.whatErrorWasThrown));
}
}
if (el.didPasswordResetSucceed && el.whatErrorWasThrown){
helpers.expectObservable(effects.resetPassword$).toBe('--(ab)', { a: el.whatOtherActionWasReturned, b: el.whatActionWasReturned });
} else {
helpers.expectObservable(effects.resetPassword$).toBe('--b', { b: el.whatActionWasReturned });
}
});
});
});
});

describe('when autoLogin is false', () => {
beforeEach(() => {
mockAuthResetPasswordAction = new DaffResetPassword(mockResetInfo, false);
});

describe('and the resetPassword is successful', () => {
beforeEach(() => {
daffResetPasswordDriver.resetPasswordOnly.and.returnValue(of(undefined));
const mockAuthResetPasswordSuccessAction = new DaffResetPasswordSuccess();

actions$ = hot('--a', { a: mockAuthResetPasswordAction });
expected = cold('--b', { b: mockAuthResetPasswordSuccessAction });
});
describe('sendResetEmail$ | when the user registers an account', () => {
it('should compute the next action correctly', () => {
const testStates: SendResetEmailTestState[] = [
{
wasOperationSuccessful: true,
whatActionWasReturned: new DaffSendResetEmailSuccess(),
},
{
wasOperationSuccessful: false,
whatActionWasReturned: new DaffSendResetEmailFailure(daffTransformErrorToStateError(
new DaffAuthInvalidAPIResponseError('Failed to register a new user'),
)),
whatErrorWasThrown: new DaffAuthInvalidAPIResponseError('Failed to register a new user'),
},
];

it('should notify state that the resetPassword was successful', () => {
expect(effects.resetPassword$).toBeObservable(expected);
testStates.forEach((el) => {
const testScheduler = new TestScheduler((actual, expected) => {
expect(actual).toEqual(expected);
});
});
testScheduler.run(helpers => {
const mockAuthSendResetEmailAction = new DaffSendResetEmail(email);
actions$ = helpers.hot('--a', { a: mockAuthSendResetEmailAction });

describe('and the resetPassword fails', () => {
beforeEach(() => {
const error = new DaffAuthenticationFailedError('Failed to reset password');
const response = cold('#', {}, error);
daffResetPasswordDriver.resetPasswordOnly.and.returnValue(response);
const mockAuthResetPasswordFailureAction = new DaffResetPasswordFailure(daffTransformErrorToStateError(error));
if(el.whatErrorWasThrown) {
daffResetPasswordDriver.sendResetEmail.and.returnValue(helpers.cold('#', {}, el.whatErrorWasThrown));
} else {
daffResetPasswordDriver.sendResetEmail.and.returnValue(of(undefined));
}

actions$ = hot('--a', { a: mockAuthResetPasswordAction });
expected = cold('--b', { b: mockAuthResetPasswordFailureAction });
helpers.expectObservable(effects.sendResetEmail$).toBe('--b', { b: el.whatActionWasReturned });
});

it('should notify state that the resetPassword failed', () => {
expect(effects.resetPassword$).toBeObservable(expected);
});
});
});
});

describe('sendResetEmail$ | when the user registers an account', () => {
let expected;

const mockAuthSendResetEmailAction = new DaffSendResetEmail(email);

describe('and the operation is successful', () => {
beforeEach(() => {
daffResetPasswordDriver.sendResetEmail.and.returnValue(of(undefined));
const mockAuthSendResetEmailSuccessAction = new DaffSendResetEmailSuccess();

actions$ = hot('--a', { a: mockAuthSendResetEmailAction });
expected = cold('--b', { b: mockAuthSendResetEmailSuccessAction });
});

it('should notify state that the operation succeeded', () => {
expect(effects.sendResetEmail$).toBeObservable(expected);
});
});

describe('and the operation fails', () => {
beforeEach(() => {
const error = new DaffAuthInvalidAPIResponseError('Failed to register a new user');
const response = cold('#', {}, error);
daffResetPasswordDriver.sendResetEmail.and.returnValue(response);
const mockAuthResetPasswordFailureAction = new DaffSendResetEmailFailure(daffTransformErrorToStateError(error));

actions$ = hot('--a', { a: mockAuthSendResetEmailAction });
expected = cold('--b', { b: mockAuthResetPasswordFailureAction });
});

it('should notify state that the operation failed', () => {
expect(effects.sendResetEmail$).toBeObservable(expected);
});
});
});
Expand Down
Loading