UNPKG

anonymous-student

Version:

Anonymous student is used to retrieve and save information from our website users.

335 lines (264 loc) 10.5 kB
import { IEventAggregationService } from '@studyportals/event-aggregation-service-interface'; import { StudentField } from '@studyportals/studentdomain'; import { suite, test } from '@testdeck/mocha'; import { assert } from 'chai'; import * as Moq from 'typemoq'; import { IMock } from 'typemoq/Api/IMock'; import { StudentRepositoryStateType } from '../../interfaces/enumerations'; import { AnonymousStudentEventBroadcaster } from '../../src/infrastructure/anonymous-student-event-broadcaster'; import { CachedStudentClient } from '../../src/infrastructure/clients/cached-student-client'; import { LocalStudentClient } from '../../src/infrastructure/clients/local-student-client'; import { StudentAPIClient } from '../../src/infrastructure/clients/student-api-client'; import { StudentClient } from '../../src/infrastructure/interfaces/student-client'; @suite class CachedStudentClientTest { protected testInstanceMock: IMock<CachedStudentClient>; protected get testInstance(): CachedStudentClient { return this.testInstanceMock.object; } protected studentAPIClientMock: IMock<StudentClient>; protected get studentAPIClient(): StudentClient { return this.studentAPIClientMock.object; } protected localStudentClientMock: IMock<StudentClient>; protected get localStudentClient(): StudentClient { return this.localStudentClientMock.object; } protected eventAggregationServiceMock: IMock<IEventAggregationService>; protected get eventAggregationService(): IEventAggregationService { return this.eventAggregationServiceMock.object; } protected anonymousStudentEventBroadcasterMock: IMock<AnonymousStudentEventBroadcaster>; protected get anonymousStudentEventBroadcaster(): AnonymousStudentEventBroadcaster { return this.anonymousStudentEventBroadcasterMock.object; } public before(): void { this.studentAPIClientMock = Moq.Mock.ofType(StudentAPIClient); this.localStudentClientMock = Moq.Mock.ofType(LocalStudentClient); this.eventAggregationServiceMock = Moq.Mock.ofType<IEventAggregationService>(); this.anonymousStudentEventBroadcasterMock = Moq.Mock.ofType(AnonymousStudentEventBroadcaster); const instance = new CachedStudentClient( this.studentAPIClient as StudentAPIClient, this.localStudentClient as LocalStudentClient, this.eventAggregationService, this.anonymousStudentEventBroadcaster, ); this.testInstanceMock = Moq.Mock.ofInstance(instance); this.testInstanceMock.callBase = true; } @test public async notify_Should_Not_Broadcast_When_Event_Is_Not_StudentProfileChanged(): Promise<void> { // given const providedEventType = 'SomeRandomEvent'; // when await this.testInstance.notify({eventType: providedEventType} as any); // then this.anonymousStudentEventBroadcasterMock.verify((x) => x.broadcastProfileUpdatedEvent(Moq.It.isAny()), Moq.Times.never()); } @test public async notify_Should_Broadcast_Correct_Changes_When_Called_With_Updates(): Promise<void> { // given const providedEvent = { eventType: 'StudentProfileChanged', updated: { first_name: 'ABC', last_name: 'XYZ', }, }; const expectedEvent = { state: StudentRepositoryStateType.ONLINE, changes: providedEvent.updated, } as any; // when await this.testInstance.notify(providedEvent as any); // then this.anonymousStudentEventBroadcasterMock.verify((x) => x.broadcastProfileUpdatedEvent(Moq.It.isObjectWith(expectedEvent)), Moq.Times.once()); } @test public async notify_Should_Broadcast_Correct_Deletion_When_Called_With_Deletes(): Promise<void> { // given const providedEvent = { eventType: 'StudentProfileChanged', deleted: { first_name: null, last_name: null, }, }; const expectedEvent = { state: StudentRepositoryStateType.ONLINE, isLocal: false, changes: { first_name: undefined, last_name: undefined, }, } as any; // when await this.testInstance.notify(providedEvent as any); // then this.anonymousStudentEventBroadcasterMock.verify((x) => x.broadcastProfileUpdatedEvent(Moq.It.isObjectWith(expectedEvent)), Moq.Times.once()); } @test public async notify_Should_BroadcastIsLocalTrue_When_EventHashIsLocalHash(): Promise<void> { // given const providedEvent = { eventType: 'StudentProfileChanged', updated: { [StudentField.FIRST_NAME]: 'ABC', [StudentField.LAST_STATE_CHANGE_HASH]: 'someHash', }, }; const expectedEvent = { state: StudentRepositoryStateType.ONLINE, isLocal: true, changes: { [StudentField.FIRST_NAME]: 'ABC', [StudentField.LAST_STATE_CHANGE_HASH]: 'someHash', }, } as any; this.testInstance['localStateHashes'] = ['someHash']; // when await this.testInstance.notify(providedEvent as any); // then this.anonymousStudentEventBroadcasterMock.verify((x) => x.broadcastProfileUpdatedEvent(Moq.It.isObjectWith(expectedEvent)), Moq.Times.once()); } @test public async notify_Should_Save_Changes_In_LocalStorage_When_Correct_Event(): Promise<void> { // given const providedEvent = { eventType: 'StudentProfileChanged', updated: { last_login: 434, }, deleted: { first_name: null, last_name: null, }, }; const expectedData = { last_login: 434, first_name: undefined, last_name: undefined, }; // when await this.testInstance.notify(providedEvent as any); // then this.localStudentClientMock.verify((x) => x.setData(Moq.It.isObjectWith(expectedData)), Moq.Times.once()); } @test public async addToCollection_Should_AddToCollection_Remote_AND_Local_When_Called_With_Disciplines(): Promise<void> { // given const expectedIds = [1, 2, 3]; // when await this.testInstance.addToCollection(StudentField.DISCIPLINES, expectedIds); // then this.studentAPIClientMock.verify((x) => x.addToCollection(StudentField.DISCIPLINES, expectedIds), Moq.Times.once()); this.localStudentClientMock.verify((x) => x.addToCollection(StudentField.DISCIPLINES, expectedIds), Moq.Times.once()); } @test public async addToCollection_Should_AddLocalHash_When_Called_With_Disciplines(): Promise<void> { // given const expectedLastStateChangeHash = 'someSecretHash'; const expectedIds = [1, 2, 3]; this.studentAPIClientMock .setup((x) => x.addToCollection(StudentField.DISCIPLINES, expectedIds)) .returns(async () => expectedLastStateChangeHash); // when await this.testInstance.addToCollection(StudentField.DISCIPLINES, expectedIds); // then assert.equal(this.testInstance['localStateHashes'][0], expectedLastStateChangeHash); } @test public async removeFromCollection_Should_RemoveFromCollection_Remote_AND_Local_When_Called_With_Disciplines(): Promise<void> { // given const expectedIds = [1, 2, 3]; // when await this.testInstance.removeFromCollection(StudentField.DISCIPLINES, expectedIds); // then this.studentAPIClientMock.verify((x) => x.removeFromCollection(StudentField.DISCIPLINES, expectedIds), Moq.Times.once()); this.localStudentClientMock.verify((x) => x.removeFromCollection(StudentField.DISCIPLINES, expectedIds), Moq.Times.once()); } @test public async removeFromCollection_Should_AddLocalHash_When_Called_With_Disciplines(): Promise<void> { // given const expectedLastStateChangeHash = 'someSecretHash'; const expectedIds = [1, 2, 3]; this.studentAPIClientMock .setup((x) => x.removeFromCollection(StudentField.DISCIPLINES, expectedIds)) .returns(async () => expectedLastStateChangeHash); // when await this.testInstance.removeFromCollection(StudentField.DISCIPLINES, expectedIds); // then assert.equal(this.testInstance['localStateHashes'][0], expectedLastStateChangeHash); } @test public async setData_Should_SetData_Remote_AND_Local_WHen_Called_With_Data(): Promise<void> { // given const expectedData = { first_name: 'SomeName', }; // when await this.testInstance.setData(expectedData); // then this.studentAPIClientMock.verify((x) => x.setData(expectedData), Moq.Times.once()); this.localStudentClientMock.verify((x) => x.setData(expectedData), Moq.Times.once()); } @test public async setData_Should_AddLocalHash_When_Called_With_Data(): Promise<void> { // given const expectedData = { first_name: 'SomeName', }; const expectedHash = 'someHash'; this.studentAPIClientMock .setup((x) => x.setData(expectedData)) .returns(async () => expectedHash); // when await this.testInstance.setData(expectedData); // then assert.equal(this.testInstance['localStateHashes'][0], expectedHash); } @test public async getData_Should_Return_Data_From_LocalClient_When_All_Fields_Are_Cached(): Promise<void> { // given const providedStudentFields = [StudentField.FIRST_NAME, StudentField.LAST_NAME]; const providedLocalData = {[StudentField.FIRST_NAME]: 'myName', [StudentField.LAST_NAME]: undefined}; this.localStudentClientMock .setup((x) => x.getData(Moq.It.isAny())) .returns(async () => providedLocalData); // when const result = await this.testInstance.getData(providedStudentFields); // then assert.equal(result, providedLocalData); } @test public async getData_Should_Only_Request_Fields_When_Fields_Are_Not_Cached(): Promise<void> { // given const providedStudentFields = [StudentField.FIRST_NAME, StudentField.LAST_NAME]; const providedLocalData = {[StudentField.LAST_NAME]: undefined}; this.localStudentClientMock .setup((x) => x.getData(Moq.It.isAny())) .returns(async () => providedLocalData); // when const result = await this.testInstance.getData(providedStudentFields); // then this.studentAPIClientMock.verify((x) => x.getData([StudentField.FIRST_NAME]), Moq.Times.once()); } @test public async getData_Should_Merge_Data_From_Local_And_Remote_When_Fields_Are_Both_Cached_And_Not_Cached(): Promise<void> { // given const providedStudentFields = [StudentField.FIRST_NAME, StudentField.LAST_NAME]; const providedLocalData = {[StudentField.LAST_NAME]: undefined}; const providedRemoteData = {[StudentField.FIRST_NAME]: 'MyFirstName'}; this.localStudentClientMock .setup((x) => x.getData(Moq.It.isAny())) .returns(async () => providedLocalData); this.studentAPIClientMock .setup((x) => x.getData(Moq.It.isAny())) .returns(async () => providedRemoteData); const expectedData = {...providedLocalData, ...providedRemoteData}; // when const result = await this.testInstance.getData(providedStudentFields); // then assert.deepEqual(result, expectedData); } }