From 25ea52a83f34c3b524e7b56df14a498bf35b17b7 Mon Sep 17 00:00:00 2001 From: skoch Date: Wed, 27 Jul 2022 10:30:23 +0200 Subject: [PATCH] feat: fix linting violations --- src/app/core/configuration.module.ts | 4 +- src/app/core/facades/account.facade.ts | 24 ++--- .../data-request/data-request.interface.ts | 18 ---- .../data-request/data-request.mapper.spec.ts | 20 ----- .../data-request/data-request.mapper.ts | 16 ---- .../models/data-request/data-request.model.ts | 6 -- .../gdpr-data-request.interface.ts | 19 ++++ .../gdpr-data-request.mapper.spec.ts | 19 ++++ .../gdpr-data-request.mapper.ts | 15 ++++ .../gdpr-data-request.model.ts | 5 ++ .../core/services/user/user.service.spec.ts | 21 +++-- src/app/core/services/user/user.service.ts | 14 +-- .../data-request/data-request.actions.ts | 13 --- .../data-request/data-request.effects.spec.ts | 72 --------------- .../data-request/data-request.reducer.ts | 47 ---------- .../data-request.selectors.spec.ts | 82 ----------------- .../data-request/data-request.selectors.ts | 11 --- .../gdpr-data-request.actions.ts | 19 ++++ .../gdpr-data-request.effects.spec.ts | 72 +++++++++++++++ .../gdpr-data-request.effects.ts} | 16 ++-- .../gdpr-data-request.reducer.ts | 43 +++++++++ .../gdpr-data-request.selectors.spec.ts | 90 +++++++++++++++++++ .../gdpr-data-request.selectors.ts | 11 +++ .../store/general/general-store.module.ts | 8 +- src/app/core/store/general/general-store.ts | 4 +- ....ts => gdpr-data-request.error-handler.ts} | 2 +- src/app/pages/app-routing.module.ts | 2 +- .../data-request/data-request.component.html | 23 ----- .../data-request.component.spec.ts | 40 --------- .../gdpr-data-request.component.html | 25 ++++++ .../gdpr-data-request.component.spec.ts | 66 ++++++++++++++ .../gdpr-data-request.component.ts} | 25 +++--- src/app/pages/gdpr/gdpr-page.module.ts | 6 +- 33 files changed, 449 insertions(+), 409 deletions(-) delete mode 100644 src/app/core/models/data-request/data-request.interface.ts delete mode 100644 src/app/core/models/data-request/data-request.mapper.spec.ts delete mode 100644 src/app/core/models/data-request/data-request.mapper.ts delete mode 100644 src/app/core/models/data-request/data-request.model.ts create mode 100644 src/app/core/models/gdpr-data-request/gdpr-data-request.interface.ts create mode 100644 src/app/core/models/gdpr-data-request/gdpr-data-request.mapper.spec.ts create mode 100644 src/app/core/models/gdpr-data-request/gdpr-data-request.mapper.ts create mode 100644 src/app/core/models/gdpr-data-request/gdpr-data-request.model.ts delete mode 100644 src/app/core/store/general/data-request/data-request.actions.ts delete mode 100644 src/app/core/store/general/data-request/data-request.effects.spec.ts delete mode 100644 src/app/core/store/general/data-request/data-request.reducer.ts delete mode 100644 src/app/core/store/general/data-request/data-request.selectors.spec.ts delete mode 100644 src/app/core/store/general/data-request/data-request.selectors.ts create mode 100644 src/app/core/store/general/gdpr-data-request/gdpr-data-request.actions.ts create mode 100644 src/app/core/store/general/gdpr-data-request/gdpr-data-request.effects.spec.ts rename src/app/core/store/general/{data-request/data-request.effects.ts => gdpr-data-request/gdpr-data-request.effects.ts} (55%) create mode 100644 src/app/core/store/general/gdpr-data-request/gdpr-data-request.reducer.ts create mode 100644 src/app/core/store/general/gdpr-data-request/gdpr-data-request.selectors.spec.ts create mode 100644 src/app/core/store/general/gdpr-data-request/gdpr-data-request.selectors.ts rename src/app/core/utils/http-error/{data-request.error-handler.ts => gdpr-data-request.error-handler.ts} (87%) delete mode 100644 src/app/pages/gdpr/data-request/data-request.component.html delete mode 100644 src/app/pages/gdpr/data-request/data-request.component.spec.ts create mode 100644 src/app/pages/gdpr/gdpr-data-request/gdpr-data-request.component.html create mode 100644 src/app/pages/gdpr/gdpr-data-request/gdpr-data-request.component.spec.ts rename src/app/pages/gdpr/{data-request/data-request.component.ts => gdpr-data-request/gdpr-data-request.component.ts} (64%) diff --git a/src/app/core/configuration.module.ts b/src/app/core/configuration.module.ts index 4ab85a0049..3d3befe476 100644 --- a/src/app/core/configuration.module.ts +++ b/src/app/core/configuration.module.ts @@ -2,8 +2,8 @@ import { NgModule } from '@angular/core'; import { SPECIAL_HTTP_ERROR_HANDLER } from './interceptors/icm-error-mapper.interceptor'; import { createPaymentErrorHandler } from './utils/http-error/create-payment.error-handler'; -import { dataRequestErrorHandler } from './utils/http-error/data-request.error-handler'; import { editPasswordErrorHandler } from './utils/http-error/edit-password.error-handler'; +import { gdprDataRequestErrorHandler } from './utils/http-error/gdpr-data-request.error-handler'; import { LoginUserErrorHandler } from './utils/http-error/login-user.error-handler'; import { requestReminderErrorHandler } from './utils/http-error/request-reminder.error-handler'; import { updatePasswordErrorHandler } from './utils/http-error/update-password.error-handler'; @@ -13,7 +13,7 @@ import { updatePasswordErrorHandler } from './utils/http-error/update-password.e { provide: SPECIAL_HTTP_ERROR_HANDLER, useValue: updatePasswordErrorHandler, multi: true }, { provide: SPECIAL_HTTP_ERROR_HANDLER, useClass: LoginUserErrorHandler, multi: true }, { provide: SPECIAL_HTTP_ERROR_HANDLER, useValue: requestReminderErrorHandler, multi: true }, - { provide: SPECIAL_HTTP_ERROR_HANDLER, useValue: dataRequestErrorHandler, multi: true }, + { provide: SPECIAL_HTTP_ERROR_HANDLER, useValue: gdprDataRequestErrorHandler, multi: true }, { provide: SPECIAL_HTTP_ERROR_HANDLER, useValue: editPasswordErrorHandler, multi: true }, { provide: SPECIAL_HTTP_ERROR_HANDLER, useValue: createPaymentErrorHandler, multi: true }, ], diff --git a/src/app/core/facades/account.facade.ts b/src/app/core/facades/account.facade.ts index 53457b2f69..d6eeea52d6 100644 --- a/src/app/core/facades/account.facade.ts +++ b/src/app/core/facades/account.facade.ts @@ -6,7 +6,7 @@ import { map, switchMap, take, tap } from 'rxjs/operators'; import { Address } from 'ish-core/models/address/address.model'; import { Credentials } from 'ish-core/models/credentials/credentials.model'; import { Customer, CustomerRegistrationType, SsoRegistrationType } from 'ish-core/models/customer/customer.model'; -import { DataRequest } from 'ish-core/models/data-request/data-request.model'; +import { GDPRDataRequest } from 'ish-core/models/gdpr-data-request/gdpr-data-request.model'; import { HttpError } from 'ish-core/models/http-error/http-error.model'; import { PasswordReminderUpdate } from 'ish-core/models/password-reminder-update/password-reminder-update.model'; import { PasswordReminder } from 'ish-core/models/password-reminder/password-reminder.model'; @@ -53,12 +53,12 @@ import { updateUserPassword, updateUserPasswordByPasswordReminder, } from 'ish-core/store/customer/user'; -import { confirmDataRequest } from 'ish-core/store/general/data-request/data-request.actions'; +import { gdprConfirmDataRequest } from 'ish-core/store/general/gdpr-data-request/gdpr-data-request.actions'; import { - getDataRequestError, - getDataRequestLoading, - getDataRequest, -} from 'ish-core/store/general/data-request/data-request.selectors'; + getGDPRDataRequestError, + getGDPRDataRequestLoading, + isFirstTime, +} from 'ish-core/store/general/gdpr-data-request/gdpr-data-request.selectors'; import { whenTruthy } from 'ish-core/utils/operators'; /* eslint-disable @typescript-eslint/member-ordering */ @@ -73,14 +73,14 @@ export class AccountFacade { store.pipe(select(getUserError)).subscribe(this.internalUserError$); } - // confirmation data request + // confirmation gdpr data request - confirmationLoading$ = this.store.pipe(select(getDataRequestLoading)); - confirmationError$ = this.store.pipe(select(getDataRequestError)); + gdprConfirmationLoading$ = this.store.pipe(select(getGDPRDataRequestLoading)); + gdprConfirmationError$ = this.store.pipe(select(getGDPRDataRequestError)); + isFirstTime$ = this.store.pipe(select(isFirstTime)); - confirmDataRequest(data: DataRequest) { - this.store.dispatch(confirmDataRequest({ data })); - return this.store.pipe(select(getDataRequest)); + confirmGDPRDataRequest(data: GDPRDataRequest) { + this.store.dispatch(gdprConfirmDataRequest({ data })); } // USER diff --git a/src/app/core/models/data-request/data-request.interface.ts b/src/app/core/models/data-request/data-request.interface.ts deleted file mode 100644 index 1c313a579f..0000000000 --- a/src/app/core/models/data-request/data-request.interface.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * response data type for confirm data request - */ -export interface DataRequestData { - data?: { - hash: string; - }; - infos?: DataRequestInfo[]; -} - -export interface DataRequestInfo { - causes?: { - code: string; - message: string; - }; - code: string; - status: number; -} diff --git a/src/app/core/models/data-request/data-request.mapper.spec.ts b/src/app/core/models/data-request/data-request.mapper.spec.ts deleted file mode 100644 index 86b74e42a0..0000000000 --- a/src/app/core/models/data-request/data-request.mapper.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { DataRequestData, DataRequestInfo } from './data-request.interface'; -import { DataRequestMapper } from './data-request.mapper'; -import { DataRequest } from './data-request.model'; - -describe('Data Request Mapper', () => { - describe('fromData', () => { - it(`should return DataRequest when getting DataRequestData with request id`, () => { - const payloadData = { - infos: [{ status: 200, code: 'already confirmed' } as DataRequestInfo], - } as DataRequestData; - const requestData = { hash: 'test_hash', requestID: 'test_ID' } as DataRequest; - const dataRequest = DataRequestMapper.fromData(payloadData, requestData); - - expect(dataRequest.requestID).toEqual(requestData.requestID); - expect(dataRequest.hash).toEqual(requestData.hash); - expect(dataRequest.status).toEqual(200); - expect(dataRequest.code).toEqual('already confirmed'); - }); - }); -}); diff --git a/src/app/core/models/data-request/data-request.mapper.ts b/src/app/core/models/data-request/data-request.mapper.ts deleted file mode 100644 index 4e5d497bf1..0000000000 --- a/src/app/core/models/data-request/data-request.mapper.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataRequestData } from './data-request.interface'; -import { DataRequest } from './data-request.model'; - -export class DataRequestMapper { - /** - * Map data request payload to data request model - */ - static fromData(payload: DataRequestData, requestData: DataRequest): DataRequest { - return { - requestID: requestData.requestID, - hash: requestData.hash, - status: payload?.infos ? payload.infos[0].status : 200, - code: payload?.infos ? payload.infos[0].code : '', - } as DataRequest; - } -} diff --git a/src/app/core/models/data-request/data-request.model.ts b/src/app/core/models/data-request/data-request.model.ts deleted file mode 100644 index 0d9bd85d05..0000000000 --- a/src/app/core/models/data-request/data-request.model.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface DataRequest { - requestID: string; - hash: string; - status?: number; - code?: string; -} diff --git a/src/app/core/models/gdpr-data-request/gdpr-data-request.interface.ts b/src/app/core/models/gdpr-data-request/gdpr-data-request.interface.ts new file mode 100644 index 0000000000..44b92c1a1e --- /dev/null +++ b/src/app/core/models/gdpr-data-request/gdpr-data-request.interface.ts @@ -0,0 +1,19 @@ +/** + * response data type for confirm data request + */ +export interface GDPRDataRequestData { + data?: [ + { + hash: string; + } + ]; + infos?: GDPRDataRequestInfo[]; +} + +export interface GDPRDataRequestInfo { + causes?: GDPRDataRequestCauses[]; +} + +interface GDPRDataRequestCauses { + code: string; +} diff --git a/src/app/core/models/gdpr-data-request/gdpr-data-request.mapper.spec.ts b/src/app/core/models/gdpr-data-request/gdpr-data-request.mapper.spec.ts new file mode 100644 index 0000000000..28c9c1ef9b --- /dev/null +++ b/src/app/core/models/gdpr-data-request/gdpr-data-request.mapper.spec.ts @@ -0,0 +1,19 @@ +import { GDPRDataRequestData, GDPRDataRequestInfo } from './gdpr-data-request.interface'; +import { GDPRDataRequestMapper } from './gdpr-data-request.mapper'; +import { GDPRDataRequest } from './gdpr-data-request.model'; + +describe('Gdpr Data Request Mapper', () => { + describe('fromData', () => { + it(`should return DataRequest when getting DataRequestData with request id`, () => { + const payloadData = { + infos: [{ causes: [{ code: 'already confirmed' }] } as GDPRDataRequestInfo], + } as GDPRDataRequestData; + const requestData = { hash: 'test_hash', requestID: 'test_ID' } as GDPRDataRequest; + const dataRequest = GDPRDataRequestMapper.fromData(payloadData, requestData); + + expect(dataRequest.requestID).toEqual(requestData.requestID); + expect(dataRequest.hash).toEqual(requestData.hash); + expect(dataRequest.status).toEqual('already confirmed'); + }); + }); +}); diff --git a/src/app/core/models/gdpr-data-request/gdpr-data-request.mapper.ts b/src/app/core/models/gdpr-data-request/gdpr-data-request.mapper.ts new file mode 100644 index 0000000000..65222274c4 --- /dev/null +++ b/src/app/core/models/gdpr-data-request/gdpr-data-request.mapper.ts @@ -0,0 +1,15 @@ +import { GDPRDataRequestData } from './gdpr-data-request.interface'; +import { GDPRDataRequest } from './gdpr-data-request.model'; + +export class GDPRDataRequestMapper { + /** + * Map data request payload to data request model + */ + static fromData(payload: GDPRDataRequestData, requestData: GDPRDataRequest): GDPRDataRequest { + return { + requestID: requestData.requestID, + hash: requestData.hash, + status: payload.infos[0].causes[0].code, + }; + } +} diff --git a/src/app/core/models/gdpr-data-request/gdpr-data-request.model.ts b/src/app/core/models/gdpr-data-request/gdpr-data-request.model.ts new file mode 100644 index 0000000000..6313504d02 --- /dev/null +++ b/src/app/core/models/gdpr-data-request/gdpr-data-request.model.ts @@ -0,0 +1,5 @@ +export interface GDPRDataRequest { + requestID: string; + hash: string; + status?: string; +} diff --git a/src/app/core/services/user/user.service.spec.ts b/src/app/core/services/user/user.service.spec.ts index b75d9a4776..a8243e4306 100644 --- a/src/app/core/services/user/user.service.spec.ts +++ b/src/app/core/services/user/user.service.spec.ts @@ -9,8 +9,11 @@ import { Address } from 'ish-core/models/address/address.model'; import { Credentials } from 'ish-core/models/credentials/credentials.model'; import { CustomerData } from 'ish-core/models/customer/customer.interface'; import { Customer, CustomerRegistrationType, CustomerUserType } from 'ish-core/models/customer/customer.model'; -import { DataRequestData, DataRequestInfo } from 'ish-core/models/data-request/data-request.interface'; -import { DataRequest } from 'ish-core/models/data-request/data-request.model'; +import { + GDPRDataRequestData, + GDPRDataRequestInfo, +} from 'ish-core/models/gdpr-data-request/gdpr-data-request.interface'; +import { GDPRDataRequest } from 'ish-core/models/gdpr-data-request/gdpr-data-request.model'; import { User } from 'ish-core/models/user/user.model'; import { ApiService, AvailableOptions } from 'ish-core/services/api/api.service'; import { getUserPermissions } from 'ish-core/store/customer/authorization'; @@ -374,10 +377,10 @@ describe('User Service', () => { it('should return an error when called with undefined', done => { when(apiServiceMock.put(anything(), anything())).thenReturn(of({})); - userService.confirmDataRequest(undefined).subscribe({ + userService.confirmGDPRDataRequest(undefined).subscribe({ next: fail, error: err => { - expect(err).toMatchInlineSnapshot(`[Error: confirmDataRequest() called without data body]`); + expect(err).toMatchInlineSnapshot(`[Error: confirmGDPRDataRequest() called without data body]`); done(); }, }); @@ -389,17 +392,17 @@ describe('User Service', () => { const requestData = { requestID: 'test_ID', hash: 'test_hash', - } as DataRequest; + } as GDPRDataRequest; const payloadData = { - infos: [{ status: 200, code: 'already confirmed' } as DataRequestInfo], - } as DataRequestData; + infos: [{ causes: [{ code: 'already confirmed' }] } as GDPRDataRequestInfo], + } as GDPRDataRequestData; when(apiServiceMock.put(anything(), anything(), anything())).thenReturn(of(payloadData)); - userService.confirmDataRequest(requestData).subscribe(payload => { + userService.confirmGDPRDataRequest(requestData).subscribe(payload => { verify(apiServiceMock.put('gdpr-requests/test_ID/confirmations', anything(), anything())).once(); expect(capture(apiServiceMock.put).last()[0]).toMatchInlineSnapshot(`"gdpr-requests/test_ID/confirmations"`); - expect(payload).toHaveProperty('status', payloadData.infos[0].status); + expect(payload).toHaveProperty('status', 'already confirmed'); done(); }); }); diff --git a/src/app/core/services/user/user.service.ts b/src/app/core/services/user/user.service.ts index 54a8053747..e84c84e706 100644 --- a/src/app/core/services/user/user.service.ts +++ b/src/app/core/services/user/user.service.ts @@ -17,9 +17,9 @@ import { CustomerRegistrationType, CustomerUserType, } from 'ish-core/models/customer/customer.model'; -import { DataRequestData } from 'ish-core/models/data-request/data-request.interface'; -import { DataRequestMapper } from 'ish-core/models/data-request/data-request.mapper'; -import { DataRequest } from 'ish-core/models/data-request/data-request.model'; +import { GDPRDataRequestData } from 'ish-core/models/gdpr-data-request/gdpr-data-request.interface'; +import { GDPRDataRequestMapper } from 'ish-core/models/gdpr-data-request/gdpr-data-request.mapper'; +import { GDPRDataRequest } from 'ish-core/models/gdpr-data-request/gdpr-data-request.model'; import { PasswordReminderUpdate } from 'ish-core/models/password-reminder-update/password-reminder-update.model'; import { PasswordReminder } from 'ish-core/models/password-reminder/password-reminder.model'; import { UserCostCenter } from 'ish-core/models/user-cost-center/user-cost-center.model'; @@ -330,9 +330,9 @@ export class UserService { * @param data The DataRequest model includes request id and hash. * @returns The enriched DataRequest model includes additional response status and code of the request. */ - confirmDataRequest(data: DataRequest): Observable { + confirmGDPRDataRequest(data: GDPRDataRequest): Observable { if (!data) { - return throwError(() => new Error('confirmDataRequest() called without data body')); + return throwError(() => new Error('confirmGDPRDataRequest() called without data body')); } const dataRequestHeaderV1 = new HttpHeaders() @@ -340,12 +340,12 @@ export class UserService { .set('Accept', 'application/vnd.intershop.gdpr.v1+json'); return this.apiService - .put( + .put( `gdpr-requests/${data.requestID}/confirmations`, { hash: data.hash }, { headers: dataRequestHeaderV1 } ) - .pipe(map(payload => DataRequestMapper.fromData(payload, data))); + .pipe(map(payload => GDPRDataRequestMapper.fromData(payload, data))); } /** diff --git a/src/app/core/store/general/data-request/data-request.actions.ts b/src/app/core/store/general/data-request/data-request.actions.ts deleted file mode 100644 index 7b454d528e..0000000000 --- a/src/app/core/store/general/data-request/data-request.actions.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { createAction } from '@ngrx/store'; - -import { DataRequest } from 'ish-core/models/data-request/data-request.model'; -import { httpError, payload } from 'ish-core/utils/ngrx-creators'; - -export const confirmDataRequest = createAction('[DataRequest] Confirm Data Request', payload<{ data: DataRequest }>()); - -export const confirmDataRequestSuccess = createAction( - '[DataRequest] Confirm Data Request Success', - payload() -); - -export const confirmDataRequestFail = createAction('[DataRequest] Confirm Data Request Failed', httpError()); diff --git a/src/app/core/store/general/data-request/data-request.effects.spec.ts b/src/app/core/store/general/data-request/data-request.effects.spec.ts deleted file mode 100644 index c0255fcf8a..0000000000 --- a/src/app/core/store/general/data-request/data-request.effects.spec.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { TestBed } from '@angular/core/testing'; -import { provideMockActions } from '@ngrx/effects/testing'; -import { Action } from '@ngrx/store'; -import { cold, hot } from 'jest-marbles'; -import { Observable, of, throwError } from 'rxjs'; -import { anything, instance, mock, verify, when } from 'ts-mockito'; - -import { DataRequest } from 'ish-core/models/data-request/data-request.model'; -import { UserService } from 'ish-core/services/user/user.service'; -import { CoreStoreModule } from 'ish-core/store/core/core-store.module'; -import { GeneralStoreModule } from 'ish-core/store/general/general-store.module'; -import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; - -import { confirmDataRequest, confirmDataRequestFail, confirmDataRequestSuccess } from './data-request.actions'; -import { DataRequestEffects } from './data-request.effects'; - -describe('Data Request Effects', () => { - let actions$: Observable; - let effects: DataRequestEffects; - let userServiceMock: UserService; - - const dataRequest = { requestID: '0123456789', hash: 'test_hash' } as DataRequest; - const payloadSuccess = { hash: 'test_hash', requestID: 'request-id' } as DataRequest; - - beforeEach(() => { - userServiceMock = mock(UserService); - when(userServiceMock.confirmDataRequest(anything())).thenReturn(of(payloadSuccess)); - - TestBed.configureTestingModule({ - imports: [CoreStoreModule.forTesting(), GeneralStoreModule.forTesting('confirmations')], - providers: [ - { provide: UserService, useFactory: () => instance(userServiceMock) }, - DataRequestEffects, - provideMockActions(() => actions$), - ], - }); - - effects = TestBed.inject(DataRequestEffects); - }); - - describe('confirmDataRequest$', () => { - it('should call the userService for ConfirmDataRequest', done => { - const action = confirmDataRequest({ data: dataRequest }); - actions$ = of(action); - - effects.confirmDataRequest$.subscribe(() => { - verify(userServiceMock.confirmDataRequest(anything())).once(); - done(); - }); - }); - it('should map to action of type ConfirmDataRequestSuccess', () => { - const action = confirmDataRequest({ data: dataRequest }); - const completion = confirmDataRequestSuccess(payloadSuccess); - actions$ = hot('-a-a-a', { a: action }); - const expected$ = cold('-c-c-c', { c: completion }); - - expect(effects.confirmDataRequest$).toBeObservable(expected$); - }); - it('should map invalid request to action of type ConfirmDataRequestFail', () => { - when(userServiceMock.confirmDataRequest(anything())).thenReturn( - throwError(() => makeHttpError({ message: 'invalid' })) - ); - const action = confirmDataRequest({ data: dataRequest }); - const error = makeHttpError({ message: 'invalid' }); - const completion = confirmDataRequestFail({ error }); - actions$ = hot('-a-a-a', { a: action }); - const expected$ = cold('-c-c-c', { c: completion }); - - expect(effects.confirmDataRequest$).toBeObservable(expected$); - }); - }); -}); diff --git a/src/app/core/store/general/data-request/data-request.reducer.ts b/src/app/core/store/general/data-request/data-request.reducer.ts deleted file mode 100644 index 14620b2603..0000000000 --- a/src/app/core/store/general/data-request/data-request.reducer.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { createReducer, on } from '@ngrx/store'; - -import { HttpError } from 'ish-core/models/http-error/http-error.model'; -import { setErrorOn, setLoadingOn, unsetLoadingOn } from 'ish-core/utils/ngrx-creators'; - -import { confirmDataRequest, confirmDataRequestFail, confirmDataRequestSuccess } from './data-request.actions'; - -export interface DataRequestState { - status: number; - code: string; - loading: boolean; - error: HttpError; -} - -const initialState: DataRequestState = { - status: undefined, - code: undefined, - loading: false, - error: undefined, -}; - -export const dataRequestReducer = createReducer( - initialState, - setLoadingOn(confirmDataRequest), - unsetLoadingOn(confirmDataRequestSuccess, confirmDataRequestFail), - setErrorOn(confirmDataRequestFail), - on(confirmDataRequestFail, (_, action) => { - const error = action.payload.error; - - return { - ...initialState, - loading: false, - status: error.status, - error, - }; - }), - on(confirmDataRequestSuccess, (state, action) => { - const status = action.payload.status; - const code = action.payload.code; - - return { - ...state, - status: status ? status : 200, - code: code ? code : '', - }; - }) -); diff --git a/src/app/core/store/general/data-request/data-request.selectors.spec.ts b/src/app/core/store/general/data-request/data-request.selectors.spec.ts deleted file mode 100644 index 320c6928b5..0000000000 --- a/src/app/core/store/general/data-request/data-request.selectors.spec.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { DataRequest } from 'ish-core/models/data-request/data-request.model'; -import { CoreStoreModule } from 'ish-core/store/core/core-store.module'; -import { GeneralStoreModule } from 'ish-core/store/general/general-store.module'; -import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; -import { StoreWithSnapshots, provideStoreSnapshots } from 'ish-core/utils/dev/ngrx-testing'; - -import { confirmDataRequest, confirmDataRequestFail, confirmDataRequestSuccess } from './data-request.actions'; -import { getDataRequest, getDataRequestLoading } from './data-request.selectors'; - -describe('Data Request Selectors', () => { - let store$: StoreWithSnapshots; - - const dataRequest = { requestID: '0123456789', hash: 'test_hash' } as DataRequest; - - const payloadSuccess = dataRequest; - const payloadAlreadyConfirmed = { - requestID: '0123456789', - hash: 'test_hash', - code: 'already.confirmed', - status: 200, - } as DataRequest; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [CoreStoreModule.forTesting(), GeneralStoreModule.forTesting('confirmations')], - providers: [provideStoreSnapshots()], - }); - - store$ = TestBed.inject(StoreWithSnapshots); - }); - - describe('with empty state', () => { - it('should not set status when used', () => { - expect(getDataRequest(store$.state).status).toBeUndefined(); - expect(getDataRequestLoading(store$.state)).toBeFalsy(); - }); - }); - - describe('loading confirmation', () => { - beforeEach(() => { - store$.dispatch(confirmDataRequest({ data: dataRequest })); - }); - it('should set the state to loading', () => { - expect(getDataRequestLoading(store$.state)).toBeTrue(); - }); - - describe('and reporting success', () => { - beforeEach(() => { - store$.dispatch(confirmDataRequestSuccess(payloadSuccess)); - }); - - it('should set loading to false', () => { - expect(getDataRequestLoading(store$.state)).toBeFalse(); - expect(getDataRequest(store$.state).status).toEqual(200); - }); - }); - - describe('and reporting already confirmed', () => { - beforeEach(() => { - store$.dispatch(confirmDataRequestSuccess(payloadAlreadyConfirmed)); - }); - - it('should set loading to false', () => { - expect(getDataRequestLoading(store$.state)).toBeFalse(); - expect(getDataRequest(store$.state).status).toEqual(200); - }); - }); - - describe('and reporting failure', () => { - beforeEach(() => { - store$.dispatch(confirmDataRequestFail({ error: makeHttpError({ status: 422, message: 'error' }) })); - }); - - it('should not have loaded category on error', () => { - expect(getDataRequestLoading(store$.state)).toBeFalse(); - expect(getDataRequest(store$.state).status).toEqual(422); - }); - }); - }); -}); diff --git a/src/app/core/store/general/data-request/data-request.selectors.ts b/src/app/core/store/general/data-request/data-request.selectors.ts deleted file mode 100644 index ab5f7c54aa..0000000000 --- a/src/app/core/store/general/data-request/data-request.selectors.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createSelector } from '@ngrx/store'; - -import { getGeneralState } from 'ish-core/store/general/general-store'; - -const getDataRequestState = createSelector(getGeneralState, state => state.confirmations); - -export const getDataRequestLoading = createSelector(getDataRequestState, state => state.loading); - -export const getDataRequestError = createSelector(getDataRequestState, state => state.error); - -export const getDataRequest = createSelector(getDataRequestState, state => state); diff --git a/src/app/core/store/general/gdpr-data-request/gdpr-data-request.actions.ts b/src/app/core/store/general/gdpr-data-request/gdpr-data-request.actions.ts new file mode 100644 index 0000000000..31266126b8 --- /dev/null +++ b/src/app/core/store/general/gdpr-data-request/gdpr-data-request.actions.ts @@ -0,0 +1,19 @@ +import { createAction } from '@ngrx/store'; + +import { GDPRDataRequest } from 'ish-core/models/gdpr-data-request/gdpr-data-request.model'; +import { httpError, payload } from 'ish-core/utils/ngrx-creators'; + +export const gdprConfirmDataRequest = createAction( + '[GDPRDataRequest] Confirm GDPR Data Request', + payload<{ data: GDPRDataRequest }>() +); + +export const gdprConfirmDataRequestSuccess = createAction( + '[GDPRDataRequest] Confirm GDPR Data Request Success', + payload() +); + +export const gdprConfirmDataRequestFail = createAction( + '[GDPRDataRequest] Confirm GDPR Data Request Failed', + httpError() +); diff --git a/src/app/core/store/general/gdpr-data-request/gdpr-data-request.effects.spec.ts b/src/app/core/store/general/gdpr-data-request/gdpr-data-request.effects.spec.ts new file mode 100644 index 0000000000..539173a9e4 --- /dev/null +++ b/src/app/core/store/general/gdpr-data-request/gdpr-data-request.effects.spec.ts @@ -0,0 +1,72 @@ +import { TestBed } from '@angular/core/testing'; +import { provideMockActions } from '@ngrx/effects/testing'; +import { Action } from '@ngrx/store'; +import { cold, hot } from 'jasmine-marbles'; +import { Observable, of, throwError } from 'rxjs'; +import { anything, instance, mock, verify, when } from 'ts-mockito'; + +import { GDPRDataRequest } from 'ish-core/models/gdpr-data-request/gdpr-data-request.model'; +import { UserService } from 'ish-core/services/user/user.service'; +import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; + +import { + gdprConfirmDataRequest, + gdprConfirmDataRequestFail, + gdprConfirmDataRequestSuccess, +} from './gdpr-data-request.actions'; +import { GDPRDataRequestEffects } from './gdpr-data-request.effects'; + +describe('Gdpr Data Request Effects', () => { + let actions$: Observable; + let effects: GDPRDataRequestEffects; + let userServiceMock: UserService; + + const dataRequest = { requestID: '0123456789', hash: 'test_hash' } as GDPRDataRequest; + + beforeEach(() => { + userServiceMock = mock(UserService); + when(userServiceMock.confirmGDPRDataRequest(anything())).thenReturn(of(dataRequest)); + + TestBed.configureTestingModule({ + providers: [ + { provide: UserService, useFactory: () => instance(userServiceMock) }, + GDPRDataRequestEffects, + provideMockActions(() => actions$), + ], + }); + + effects = TestBed.inject(GDPRDataRequestEffects); + }); + + describe('confirmGDPRDataRequest$', () => { + it('should call the userService for GDPRConfirmDataRequest', done => { + const action = gdprConfirmDataRequest({ data: dataRequest }); + actions$ = of(action); + + effects.confirmGDPRDataRequest$.subscribe(() => { + verify(userServiceMock.confirmGDPRDataRequest(anything())).once(); + done(); + }); + }); + it('should map to action of type GDPRConfirmDataRequestSuccess', () => { + const action = gdprConfirmDataRequest({ data: dataRequest }); + const completion = gdprConfirmDataRequestSuccess(dataRequest); + actions$ = hot('-a-a-a', { a: action }); + const expected$ = cold('-c-c-c', { c: completion }); + + expect(effects.confirmGDPRDataRequest$).toBeObservable(expected$); + }); + it('should map invalid request to action of type GDPRConfirmDataRequestFail', () => { + when(userServiceMock.confirmGDPRDataRequest(anything())).thenReturn( + throwError(() => makeHttpError({ message: 'invalid' })) + ); + const action = gdprConfirmDataRequest({ data: dataRequest }); + const error = makeHttpError({ message: 'invalid' }); + const completion = gdprConfirmDataRequestFail({ error }); + actions$ = hot('-a-a-a', { a: action }); + const expected$ = cold('-c-c-c', { c: completion }); + + expect(effects.confirmGDPRDataRequest$).toBeObservable(expected$); + }); + }); +}); diff --git a/src/app/core/store/general/data-request/data-request.effects.ts b/src/app/core/store/general/gdpr-data-request/gdpr-data-request.effects.ts similarity index 55% rename from src/app/core/store/general/data-request/data-request.effects.ts rename to src/app/core/store/general/gdpr-data-request/gdpr-data-request.effects.ts index 021e1dbdf9..2fdf596459 100644 --- a/src/app/core/store/general/data-request/data-request.effects.ts +++ b/src/app/core/store/general/gdpr-data-request/gdpr-data-request.effects.ts @@ -5,20 +5,24 @@ import { concatMap, map } from 'rxjs/operators'; import { UserService } from 'ish-core/services/user/user.service'; import { mapErrorToAction, mapToPayload } from 'ish-core/utils/operators'; -import { confirmDataRequest, confirmDataRequestFail, confirmDataRequestSuccess } from './data-request.actions'; +import { + gdprConfirmDataRequest, + gdprConfirmDataRequestFail, + gdprConfirmDataRequestSuccess, +} from './gdpr-data-request.actions'; @Injectable() -export class DataRequestEffects { +export class GDPRDataRequestEffects { constructor(private actions$: Actions, private userService: UserService) {} - confirmDataRequest$ = createEffect(() => + confirmGDPRDataRequest$ = createEffect(() => this.actions$.pipe( - ofType(confirmDataRequest), + ofType(gdprConfirmDataRequest), mapToPayload(), concatMap(payload => this.userService - .confirmDataRequest(payload.data) - .pipe(map(confirmDataRequestSuccess), mapErrorToAction(confirmDataRequestFail)) + .confirmGDPRDataRequest(payload.data) + .pipe(map(gdprConfirmDataRequestSuccess), mapErrorToAction(gdprConfirmDataRequestFail)) ) ) ); diff --git a/src/app/core/store/general/gdpr-data-request/gdpr-data-request.reducer.ts b/src/app/core/store/general/gdpr-data-request/gdpr-data-request.reducer.ts new file mode 100644 index 0000000000..649ecc0c53 --- /dev/null +++ b/src/app/core/store/general/gdpr-data-request/gdpr-data-request.reducer.ts @@ -0,0 +1,43 @@ +import { EntityState, createEntityAdapter } from '@ngrx/entity'; +import { createReducer, on } from '@ngrx/store'; + +import { GDPRDataRequest } from 'ish-core/models/gdpr-data-request/gdpr-data-request.model'; +import { HttpError } from 'ish-core/models/http-error/http-error.model'; +import { setErrorOn, setLoadingOn, unsetLoadingOn } from 'ish-core/utils/ngrx-creators'; + +import { + gdprConfirmDataRequest, + gdprConfirmDataRequestFail, + gdprConfirmDataRequestSuccess, +} from './gdpr-data-request.actions'; + +const gdprDataRequestAdapter = createEntityAdapter({ + selectId: dataRequest => dataRequest.requestID, +}); + +export interface GDPRDataRequestState extends EntityState { + loading: boolean; + error: HttpError; + firstTime: boolean; +} + +const initialState: GDPRDataRequestState = gdprDataRequestAdapter.getInitialState({ + loading: false, + error: undefined, + firstTime: true, +}); + +export const gdprDataRequestReducer = createReducer( + initialState, + setLoadingOn(gdprConfirmDataRequest), + unsetLoadingOn(gdprConfirmDataRequestSuccess, gdprConfirmDataRequestFail), + setErrorOn(gdprConfirmDataRequestFail), + on(gdprConfirmDataRequestSuccess, (state, action) => { + const dataRequest = action.payload; + + return { + ...gdprDataRequestAdapter.upsertOne(dataRequest, state), + firstTime: dataRequest.status === 'gdpr_request.confirmed.info', + }; + }) +); diff --git a/src/app/core/store/general/gdpr-data-request/gdpr-data-request.selectors.spec.ts b/src/app/core/store/general/gdpr-data-request/gdpr-data-request.selectors.spec.ts new file mode 100644 index 0000000000..896fc6a37e --- /dev/null +++ b/src/app/core/store/general/gdpr-data-request/gdpr-data-request.selectors.spec.ts @@ -0,0 +1,90 @@ +import { TestBed } from '@angular/core/testing'; + +import { GDPRDataRequest } from 'ish-core/models/gdpr-data-request/gdpr-data-request.model'; +import { CoreStoreModule } from 'ish-core/store/core/core-store.module'; +import { GeneralStoreModule } from 'ish-core/store/general/general-store.module'; +import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; +import { StoreWithSnapshots, provideStoreSnapshots } from 'ish-core/utils/dev/ngrx-testing'; + +import { + gdprConfirmDataRequest, + gdprConfirmDataRequestFail, + gdprConfirmDataRequestSuccess, +} from './gdpr-data-request.actions'; +import { getGDPRDataRequestError, getGDPRDataRequestLoading, isFirstTime } from './gdpr-data-request.selectors'; + +describe('Gdpr Data Request Selectors', () => { + let store$: StoreWithSnapshots; + + const dataRequest = { + requestID: '0123456789', + hash: 'test_hash', + status: 'gdpr_request.confirmed.info', + } as GDPRDataRequest; + + const payloadSuccess = dataRequest; + const payloadAlreadyConfirmed = { + requestID: '0123456789', + hash: 'test_hash', + status: 'already.confirmed', + } as GDPRDataRequest; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [CoreStoreModule.forTesting(), GeneralStoreModule.forTesting('confirmations')], + providers: [provideStoreSnapshots()], + }); + + store$ = TestBed.inject(StoreWithSnapshots); + }); + + describe('with empty state', () => { + it('should not set status when used', () => { + expect(isFirstTime(store$.state)).toBeTruthy(); + expect(getGDPRDataRequestLoading(store$.state)).toBeFalsy(); + expect(getGDPRDataRequestError(store$.state)).toBeUndefined(); + }); + }); + + describe('loading confirmation', () => { + beforeEach(() => { + store$.dispatch(gdprConfirmDataRequest({ data: dataRequest })); + }); + it('should set the state to loading', () => { + expect(getGDPRDataRequestLoading(store$.state)).toBeTruthy(); + }); + + describe('and reporting success', () => { + beforeEach(() => { + store$.dispatch(gdprConfirmDataRequestSuccess(payloadSuccess)); + }); + + it('should set loading to false', () => { + expect(getGDPRDataRequestLoading(store$.state)).toBeFalsy(); + expect(isFirstTime(store$.state)).toBeTruthy(); + }); + }); + + describe('and reporting already confirmed', () => { + beforeEach(() => { + store$.dispatch(gdprConfirmDataRequestSuccess(payloadAlreadyConfirmed)); + }); + + it('should set loading to false', () => { + expect(getGDPRDataRequestLoading(store$.state)).toBeFalsy(); + expect(isFirstTime(store$.state)).toBeFalsy(); + }); + }); + + describe('and reporting failure', () => { + beforeEach(() => { + store$.dispatch(gdprConfirmDataRequestFail({ error: makeHttpError({ status: 422, message: 'error' }) })); + }); + + it('should not have loaded category on error', () => { + expect(getGDPRDataRequestLoading(store$.state)).toBeFalsy(); + expect(getGDPRDataRequestError(store$.state)).toBeTruthy(); + }); + }); + }); +}); diff --git a/src/app/core/store/general/gdpr-data-request/gdpr-data-request.selectors.ts b/src/app/core/store/general/gdpr-data-request/gdpr-data-request.selectors.ts new file mode 100644 index 0000000000..809c94404b --- /dev/null +++ b/src/app/core/store/general/gdpr-data-request/gdpr-data-request.selectors.ts @@ -0,0 +1,11 @@ +import { createSelector } from '@ngrx/store'; + +import { getGeneralState } from 'ish-core/store/general/general-store'; + +const getGDPRDataRequestState = createSelector(getGeneralState, state => state.confirmations); + +export const getGDPRDataRequestLoading = createSelector(getGDPRDataRequestState, state => state.loading); + +export const getGDPRDataRequestError = createSelector(getGDPRDataRequestState, state => state.error); + +export const isFirstTime = createSelector(getGDPRDataRequestState, state => state.firstTime); diff --git a/src/app/core/store/general/general-store.module.ts b/src/app/core/store/general/general-store.module.ts index 9a25a49b56..413497a9fa 100644 --- a/src/app/core/store/general/general-store.module.ts +++ b/src/app/core/store/general/general-store.module.ts @@ -5,8 +5,8 @@ import { pick } from 'lodash-es'; import { CountriesEffects } from './countries/countries.effects'; import { countriesReducer } from './countries/countries.reducer'; -import { DataRequestEffects } from './data-request/data-request.effects'; -import { dataRequestReducer } from './data-request/data-request.reducer'; +import { GDPRDataRequestEffects } from './gdpr-data-request/gdpr-data-request.effects'; +import { gdprDataRequestReducer } from './gdpr-data-request/gdpr-data-request.reducer'; import { GeneralState } from './general-store'; import { RegionsEffects } from './regions/regions.effects'; import { regionsReducer } from './regions/regions.reducer'; @@ -14,10 +14,10 @@ import { regionsReducer } from './regions/regions.reducer'; const generalReducers: ActionReducerMap = { countries: countriesReducer, regions: regionsReducer, - confirmations: dataRequestReducer, + confirmations: gdprDataRequestReducer, }; -const generalEffects = [CountriesEffects, RegionsEffects, DataRequestEffects]; +const generalEffects = [CountriesEffects, RegionsEffects, GDPRDataRequestEffects]; @NgModule({ imports: [EffectsModule.forFeature(generalEffects), StoreModule.forFeature('general', generalReducers)], diff --git a/src/app/core/store/general/general-store.ts b/src/app/core/store/general/general-store.ts index 6704fb8a74..ec677c5319 100644 --- a/src/app/core/store/general/general-store.ts +++ b/src/app/core/store/general/general-store.ts @@ -1,13 +1,13 @@ import { createFeatureSelector } from '@ngrx/store'; import { CountriesState } from './countries/countries.reducer'; -import { DataRequestState } from './data-request/data-request.reducer'; +import { GDPRDataRequestState } from './gdpr-data-request/gdpr-data-request.reducer'; import { RegionsState } from './regions/regions.reducer'; export interface GeneralState { countries: CountriesState; regions: RegionsState; - confirmations: DataRequestState; + confirmations: GDPRDataRequestState; } export const getGeneralState = createFeatureSelector('general'); diff --git a/src/app/core/utils/http-error/data-request.error-handler.ts b/src/app/core/utils/http-error/gdpr-data-request.error-handler.ts similarity index 87% rename from src/app/core/utils/http-error/data-request.error-handler.ts rename to src/app/core/utils/http-error/gdpr-data-request.error-handler.ts index b27f9fd9b8..af1ab0188c 100644 --- a/src/app/core/utils/http-error/data-request.error-handler.ts +++ b/src/app/core/utils/http-error/gdpr-data-request.error-handler.ts @@ -1,6 +1,6 @@ import { SpecialHttpErrorHandler } from 'ish-core/interceptors/icm-error-mapper.interceptor'; -export const dataRequestErrorHandler: SpecialHttpErrorHandler = { +export const gdprDataRequestErrorHandler: SpecialHttpErrorHandler = { test: (error, request) => error.url.endsWith('/confirmations') && request.method === 'PUT', map: error => { switch (error.status) { diff --git a/src/app/pages/app-routing.module.ts b/src/app/pages/app-routing.module.ts index 15ac39b8f7..accdcfd693 100644 --- a/src/app/pages/app-routing.module.ts +++ b/src/app/pages/app-routing.module.ts @@ -103,7 +103,7 @@ const routes: Routes = [ }, }, { - // confirmation of user data and account deletion request + // gdpr confirmation of user data and account deletion request path: 'gdpr-requests', loadChildren: () => import('./gdpr/gdpr-page.module').then(m => m.GDPRPageModule), data: { diff --git a/src/app/pages/gdpr/data-request/data-request.component.html b/src/app/pages/gdpr/data-request/data-request.component.html deleted file mode 100644 index 53a216cfd3..0000000000 --- a/src/app/pages/gdpr/data-request/data-request.component.html +++ /dev/null @@ -1,23 +0,0 @@ - - - -

{{ 'gdpr.request.personal.data.confirmation.title' | translate }}

- -

{{ 'gdpr.request.personal.data.confirmation.message' | translate }}

- -

{{ 'gdpr.request.personal.data.confirmation.details' | translate }}

-
- - -

{{ 'gdpr.request.personal.data.confirmation.link.already.verified.title' | translate }}

- -

{{ 'gdpr.request.personal.data.confirmation.link.already.verified.message' | translate }}

-

-
-
- - diff --git a/src/app/pages/gdpr/data-request/data-request.component.spec.ts b/src/app/pages/gdpr/data-request/data-request.component.spec.ts deleted file mode 100644 index 0d0693f931..0000000000 --- a/src/app/pages/gdpr/data-request/data-request.component.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; -import { TranslateModule } from '@ngx-translate/core'; -import { MockComponent } from 'ng-mocks'; -import { EMPTY } from 'rxjs'; -import { instance, mock, when } from 'ts-mockito'; - -import { AccountFacade } from 'ish-core/facades/account.facade'; -import { ErrorMessageComponent } from 'ish-shared/components/common/error-message/error-message.component'; - -import { DataRequestComponent } from './data-request.component'; - -describe('Data Request Component', () => { - let component: DataRequestComponent; - let fixture: ComponentFixture; - let element: HTMLElement; - - beforeEach(async () => { - const accountFacade = mock(AccountFacade); - when(accountFacade.passwordReminderSuccess$).thenReturn(EMPTY); - - await TestBed.configureTestingModule({ - declarations: [DataRequestComponent, MockComponent(ErrorMessageComponent)], - imports: [RouterTestingModule, TranslateModule.forRoot()], - providers: [{ provide: AccountFacade, useFactory: () => instance(accountFacade) }], - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(DataRequestComponent); - component = fixture.componentInstance; - element = fixture.nativeElement; - }); - - it('should be created', () => { - expect(component).toBeTruthy(); - expect(element).toBeTruthy(); - expect(() => fixture.detectChanges()).not.toThrow(); - }); -}); diff --git a/src/app/pages/gdpr/gdpr-data-request/gdpr-data-request.component.html b/src/app/pages/gdpr/gdpr-data-request/gdpr-data-request.component.html new file mode 100644 index 0000000000..947e2dfd60 --- /dev/null +++ b/src/app/pages/gdpr/gdpr-data-request/gdpr-data-request.component.html @@ -0,0 +1,25 @@ + + + +

+ {{ 'gdpr.request.personal.data.confirmation.title' | translate }} +

+ +

{{ 'gdpr.request.personal.data.confirmation.message' | translate }}

+ +

{{ 'gdpr.request.personal.data.confirmation.details' | translate }}

+
+ +

+ {{ 'gdpr.request.personal.data.confirmation.link.already.verified.title' | translate }} +

+ +

{{ 'gdpr.request.personal.data.confirmation.link.already.verified.message' | translate }}

+

+
+
+ diff --git a/src/app/pages/gdpr/gdpr-data-request/gdpr-data-request.component.spec.ts b/src/app/pages/gdpr/gdpr-data-request/gdpr-data-request.component.spec.ts new file mode 100644 index 0000000000..3ece2653d3 --- /dev/null +++ b/src/app/pages/gdpr/gdpr-data-request/gdpr-data-request.component.spec.ts @@ -0,0 +1,66 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { MockComponent } from 'ng-mocks'; +import { of } from 'rxjs'; +import { instance, mock, when } from 'ts-mockito'; + +import { AccountFacade } from 'ish-core/facades/account.facade'; +import { makeHttpError } from 'ish-core/utils/dev/api-service-utils'; +import { ErrorMessageComponent } from 'ish-shared/components/common/error-message/error-message.component'; +import { LoadingComponent } from 'ish-shared/components/common/loading/loading.component'; + +import { GDPRDataRequestComponent } from './gdpr-data-request.component'; + +describe('Gdpr Data Request Component', () => { + let component: GDPRDataRequestComponent; + let fixture: ComponentFixture; + let element: HTMLElement; + let accountFacade: AccountFacade; + + beforeEach(async () => { + accountFacade = mock(AccountFacade); + when(accountFacade.gdprConfirmationError$).thenReturn(undefined); + when(accountFacade.gdprConfirmationLoading$).thenReturn(of(false)); + when(accountFacade.isFirstTime$).thenReturn(of(true)); + await TestBed.configureTestingModule({ + declarations: [GDPRDataRequestComponent, MockComponent(ErrorMessageComponent), MockComponent(LoadingComponent)], + imports: [RouterTestingModule.withRoutes([{ path: 'confirmRequest', children: [] }]), TranslateModule.forRoot()], + providers: [{ provide: AccountFacade, useFactory: () => instance(accountFacade) }], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GDPRDataRequestComponent); + component = fixture.componentInstance; + element = fixture.nativeElement; + }); + + it('should be created', () => { + expect(component).toBeTruthy(); + expect(element).toBeTruthy(); + expect(() => fixture.detectChanges()).not.toThrow(); + expect(element.querySelector('h1[data-testing-id=successful-confirmation-title]')).toBeTruthy(); + expect(element.querySelector('h1[data-testing-id=already-confirmed-title]')).toBeFalsy(); + }); + it('should be displayed alternative content if confirmation already confirmed', () => { + when(accountFacade.isFirstTime$).thenReturn(of(false)); + expect(component).toBeTruthy(); + expect(element).toBeTruthy(); + expect(() => fixture.detectChanges()).not.toThrow(); + expect(element.querySelector('h1[data-testing-id=successful-confirmation-title]')).toBeFalsy(); + expect(element.querySelector('h1[data-testing-id=already-confirmed-title]')).toBeTruthy(); + }); + + it('should render loading component if landing page is loading', () => { + when(accountFacade.gdprConfirmationLoading$).thenReturn(of(true)); + fixture.detectChanges(); + expect(element.querySelector('ish-loading')).toBeTruthy(); + }); + + it('should render error component if confirmation failed', () => { + when(accountFacade.gdprConfirmationError$).thenReturn(of(makeHttpError({ status: 404 }))); + fixture.detectChanges(); + expect(element.querySelector('ish-error-message')).toBeTruthy(); + }); +}); diff --git a/src/app/pages/gdpr/data-request/data-request.component.ts b/src/app/pages/gdpr/gdpr-data-request/gdpr-data-request.component.ts similarity index 64% rename from src/app/pages/gdpr/data-request/data-request.component.ts rename to src/app/pages/gdpr/gdpr-data-request/gdpr-data-request.component.ts index 81f5333ca9..eb7ad80f36 100644 --- a/src/app/pages/gdpr/data-request/data-request.component.ts +++ b/src/app/pages/gdpr/gdpr-data-request/gdpr-data-request.component.ts @@ -4,25 +4,26 @@ import { Observable, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { AccountFacade } from 'ish-core/facades/account.facade'; +import { GDPRDataRequest } from 'ish-core/models/gdpr-data-request/gdpr-data-request.model'; import { HttpError } from 'ish-core/models/http-error/http-error.model'; -import { DataRequestState } from 'ish-core/store/general/data-request/data-request.reducer'; /** * The Personal Data Request Confirmation Component handles the interaction for dispatching of a confirmation request triggered via confirmation email link. */ @Component({ selector: 'ish-data-request', - templateUrl: './data-request.component.html', + templateUrl: './gdpr-data-request.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }) -export class DataRequestComponent implements OnInit, OnDestroy { - dataRequest$: Observable; +export class GDPRDataRequestComponent implements OnInit, OnDestroy { + dataRequest$: Observable; loading$: Observable; error$: Observable; + firstTime$: Observable; requestID: string; secureCode: string; - test: string; + firstTime1: boolean; errorTranslationCode: string; @@ -31,8 +32,9 @@ export class DataRequestComponent implements OnInit, OnDestroy { constructor(private accountFacade: AccountFacade, private route: ActivatedRoute) {} ngOnInit(): void { - this.error$ = this.accountFacade.confirmationError$; - this.loading$ = this.accountFacade.confirmationLoading$; + this.error$ = this.accountFacade.gdprConfirmationError$; + this.loading$ = this.accountFacade.gdprConfirmationLoading$; + this.firstTime$ = this.accountFacade.isFirstTime$; this.route.queryParams .pipe(takeUntil(this.destroy$)) @@ -40,17 +42,12 @@ export class DataRequestComponent implements OnInit, OnDestroy { this.requestID = params.PersonalDataRequestID; this.secureCode = params.Hash; }); - this.dataRequest$ = this.accountFacade.confirmDataRequest({ hash: this.secureCode, requestID: this.requestID }); + // confirmation of the personal data request + this.accountFacade.confirmGDPRDataRequest({ hash: this.secureCode, requestID: this.requestID }); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } - - isSuccess(dataRequest: DataRequestState) { - return dataRequest - ? dataRequest.status === 200 && dataRequest.code !== 'gdpr_request.already_confirmed.info' - : false; - } } diff --git a/src/app/pages/gdpr/gdpr-page.module.ts b/src/app/pages/gdpr/gdpr-page.module.ts index b71bc0cc24..f489ed4f8d 100644 --- a/src/app/pages/gdpr/gdpr-page.module.ts +++ b/src/app/pages/gdpr/gdpr-page.module.ts @@ -3,17 +3,17 @@ import { RouterModule, Routes } from '@angular/router'; import { SharedModule } from 'ish-shared/shared.module'; -import { DataRequestComponent } from './data-request/data-request.component'; +import { GDPRDataRequestComponent } from './gdpr-data-request/gdpr-data-request.component'; const gdprPageRoutes: Routes = [ { path: 'confirmRequest', - component: DataRequestComponent, + component: GDPRDataRequestComponent, }, ]; @NgModule({ imports: [RouterModule.forChild(gdprPageRoutes), SharedModule], - declarations: [DataRequestComponent], + declarations: [GDPRDataRequestComponent], }) export class GDPRPageModule {}