Skip to content

Commit

Permalink
mes-examinerRecordsLocationListBugFix (#1677)
Browse files Browse the repository at this point in the history
* Fixed a problem where the limited details functionality on the location list would not work properly

* removed unnecessary brackets

* Changed typing on variables

* Moved category and location logic to a new function and included unit tests

* Replaced instances of omitting a value from an interface with a new interface that extends from the previosu

* optimised loops

* Removed remaining omit

* removed unneeded comment
  • Loading branch information
RLCorp committed Aug 6, 2024
1 parent dbf6307 commit bcb751a
Show file tree
Hide file tree
Showing 6 changed files with 337 additions and 146 deletions.
209 changes: 182 additions & 27 deletions src/app/pages/examiner-records/__tests__/examiner-records.page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ import { DASHBOARD_PAGE } from '@pages/page-names.constants';
import { ScreenOrientation } from '@capawesome/capacitor-screen-orientation';
import { ScrollDetail } from '@ionic/core';
import moment from 'moment';
import { selectCachedExaminerRecords, selectLastCachedDate } from '@store/examiner-records/examiner-records.selectors';
import {
selectCachedExaminerRecords,
selectLastCachedDate,
} from '@store/examiner-records/examiner-records.selectors';
import { ExaminerRecordModel } from '@dvsa/mes-microservice-common/domain/examiner-records';
import { DateRange } from '@shared/helpers/date-time';

Expand All @@ -47,8 +50,8 @@ describe('ExaminerRecordsPage', () => {
circuits$: of([]),
locationList$: of([]),
categoryList$: of([]),
emergencyStops$: of([])
}
emergencyStops$: of([]),
};
const mockTests: ExaminerRecordModel[] = [
{
testCategory: TestCategory.B,
Expand Down Expand Up @@ -240,11 +243,51 @@ describe('ExaminerRecordsPage', () => {
});

describe('ngOnInit', () => {
it('should call setFilterLists', () => {
it('should initialize testResults and update testSubject$', async () => {
spyOn(component, 'removeDuplicatesAndSort').and.returnValue(mockTests);
spyOn(component.testSubject$, 'next');

await component.ngOnInit();

expect(component.removeDuplicatesAndSort).toHaveBeenCalledWith(component.getLocalResults());
expect(component.testSubject$.next).toHaveBeenCalledWith(mockTests);
});

it('should set default date filter', async () => {
spyOn(component, 'handleDateFilter');

await component.ngOnInit();

expect(component.handleDateFilter).toHaveBeenCalledWith(
{
detail: { value: component.defaultDate },
} as CustomEvent);
});

it('should set categorySelectPristine to false if categorySubject$ has value', async () => {
component.categorySubject$.next(TestCategory.B);

await component.ngOnInit();

expect(component.categorySelectPristine).toBeFalse();
});

it('should set locationSelectPristine to false if locationSubject$ has value', async () => {
component.locationSubject$.next(1);

await component.ngOnInit();

expect(component.locationSelectPristine).toBeFalse();
});

it('should set location filter and fetch online records', async () => {
spyOn(component, 'setLocationFilter');
spyOn(component, 'getOnlineRecords');

await component.ngOnInit();

component.ngOnInit();
expect(component.setLocationFilter).toHaveBeenCalled();
expect(component.getOnlineRecords).toHaveBeenCalled();
});
});

Expand All @@ -262,6 +305,116 @@ describe('ExaminerRecordsPage', () => {
});
});

describe('setupCategorySelectList', () => {
it('should add every completed category to categoryFilterOptions', () => {
const categories = [
{ item: TestCategory.B, count: 1 },
{ item: TestCategory.C, count: 2 },
];
component.setupCategorySelectList(categories);
expect(component.categoryFilterOptions).toEqual([TestCategory.B, TestCategory.C]);
});

it('should set the most common category as the default if current category is not included', () => {
const categories = [
{ item: TestCategory.B, count: 1 },
{ item: TestCategory.C, count: 2 },
];
spyOn(component, 'setDefault').and.returnValue(categories[1]);
spyOn(component, 'handleCategoryFilter');

component.categorySubject$.next(TestCategory.A);
component.setupCategorySelectList(categories);
expect(component.categoryPlaceholder).toEqual(TestCategory.C);
expect(component.handleCategoryFilter).toHaveBeenCalledWith(TestCategory.C);
});

it('should call changeEligibleTests if current category is included in categoryFilterOptions', () => {
const categories = [
{ item: TestCategory.B, count: 1 },
{ item: TestCategory.C, count: 2 },
];
component.categorySubject$.next(TestCategory.B);
spyOn(component, 'changeEligibleTests');
component.setupCategorySelectList(categories);
expect(component.changeEligibleTests).toHaveBeenCalled();
});

it('should set categorySelectPristine to true if most common category is set as default', () => {
const categories = [
{ item: TestCategory.B, count: 1 },
{ item: TestCategory.C, count: 2 },
];
spyOn(component, 'setDefault').and.returnValue(categories[1]);
component.categorySubject$.next(TestCategory.A);
component.setupCategorySelectList(categories);
expect(component.categorySelectPristine).toBeTrue();
});

it('should not set categorySelectPristine if current category is included in categoryFilterOptions', () => {
component.categorySelectPristine = false;
const categories = [
{ item: TestCategory.B, count: 1 },
{ item: TestCategory.C, count: 2 },
];
component.categorySubject$.next(TestCategory.B);
spyOn(component, 'changeEligibleTests');
component.setupCategorySelectList(categories);
expect(component.categorySelectPristine).toEqual(false);
});
});

describe('setupLocationSelectList', () => {
it('should add every visited location to locationFilterOptions', () => {
const locations = [
{ item: { centreName: 'Centre 1', centreId: 1, costCode: 'X1' }, count: 1 },
{ item: { centreName: 'Centre 2', centreId: 2, costCode: 'X2' }, count: 2 },
];
component.setupLocationSelectList(locations);
expect(component.locationFilterOptions).toEqual([
{ centreName: 'Centre 1', centreId: 1, costCode: 'X1' },
{ centreName: 'Centre 2', centreId: 2, costCode: 'X2' },
]);
});

it('should display cost code or centre id if centre name is not available', () => {
const locations = [
{ item: { centreName: null, centreId: 1, costCode: 'X1' }, count: 1 },
{ item: { centreName: null, centreId: 2, costCode: null }, count: 2 },
];
component.setupLocationSelectList(locations);
expect(component.locationFilterOptions).toEqual([
{ centreName: 'Limited details - X1', centreId: 1, costCode: 'X1' },
{ centreName: 'Limited details - 2', centreId: 2, costCode: null },
]);
});

it('should set the most common location as the default if current location is not included', () => {
const locations = [
{ item: { centreName: 'Centre 1', centreId: 1, costCode: 'X1' }, count: 1 },
{ item: { centreName: 'Centre 2', centreId: 2, costCode: 'X2' }, count: 2 },
];
spyOn(component, 'setDefault').and.returnValue(locations[1]);
spyOn(component, 'handleLocationFilter');

component.locationSubject$.next(3);
component.setupLocationSelectList(locations);
expect(component.locationPlaceholder).toEqual('Centre 2');
expect(component.handleLocationFilter).toHaveBeenCalledWith(locations[1].item);
});

it('should set locationPlaceholder to an empty string if locations array is empty', () => {
const locations = [];
spyOn(component, 'handleLocationFilter');

component.setupLocationSelectList(locations);
expect(component.locationPlaceholder).toEqual('');
expect(component.handleLocationFilter).toHaveBeenCalledWith(
{ centreId: null, centreName: '', costCode: '' }
);
});
});

describe('setLocationFilter', () => {
it('should set locationFilterOptions to the item property of each object in locationList$', () => {
spyOn(component, 'ngOnInit');
Expand All @@ -278,7 +431,7 @@ describe('ExaminerRecordsPage', () => {
]);
});
it('should set locationPlaceholder to the centreName property ' +
'of the object in the location array with the highest count', () => {
'of the object in the location array with the highest count', () => {
spyOn(component, 'ngOnInit');
component.locationFilterOptions = null;
component.pageState.locationList$ = of([
Expand All @@ -289,7 +442,7 @@ describe('ExaminerRecordsPage', () => {
expect(component.locationPlaceholder).toEqual('2');
});
it('should call handleLocationFilter with the item of ' +
'the object in the location array with the highest count', () => {
'the object in the location array with the highest count', () => {
spyOn(component, 'ngOnInit');

spyOn(component, 'handleLocationFilter');
Expand All @@ -300,7 +453,9 @@ describe('ExaminerRecordsPage', () => {
{ item: { centreName: '2', centreId: 2, costCode: 'X2' }, count: 2 },
]);
component.setLocationFilter();
expect(component.handleLocationFilter).toHaveBeenCalledWith({ centreName: '2', centreId: 2, costCode: 'X2' });
expect(component.handleLocationFilter).toHaveBeenCalledWith(
{ centreName: '2', centreId: 2, costCode: 'X2' }
);
});
});

Expand All @@ -320,9 +475,9 @@ describe('ExaminerRecordsPage', () => {
{
detail: {
value:
{
display: '1',
},
{
display: '1',
},
},
} as CustomEvent,
);
Expand All @@ -333,10 +488,10 @@ describe('ExaminerRecordsPage', () => {
{
detail: {
value:
{
display: '1',
val: 'today',
},
{
display: '1',
val: 'today',
},
},
} as CustomEvent,
);
Expand All @@ -350,9 +505,9 @@ describe('ExaminerRecordsPage', () => {
{
detail: {
value:
{
val: '1',
},
{
val: '1',
},
},
} as CustomEvent,
);
Expand Down Expand Up @@ -385,8 +540,8 @@ describe('ExaminerRecordsPage', () => {
});

describe('getOnlineRecords', () => {
// eslint-disable-next-line max-len
it('should dispatch LoadingExaminerRecords and GetExaminerRecords actions when cached records are not available or last cached date is different', () => {
it('should dispatch LoadingExaminerRecords and GetExaminerRecords actions when ' +
'cached records are not available or last cached date is different', () => {
store$.overrideSelector(selectCachedExaminerRecords, null);
store$.overrideSelector(selectLastCachedDate, 'some other date');

Expand Down Expand Up @@ -580,8 +735,8 @@ describe('ExaminerRecordsPage', () => {

describe('cardClicked', () => {
it('should dispatch the store', () => {
component.cardClicked({isExpanded: false, title: 'test'});
expect(component.store$.dispatch).toHaveBeenCalledWith(ClickDataCard({isExpanded: false, title: 'test'}));
component.cardClicked({ isExpanded: false, title: 'test' });
expect(component.store$.dispatch).toHaveBeenCalledWith(ClickDataCard({ isExpanded: false, title: 'test' }));
});
});

Expand All @@ -599,7 +754,7 @@ describe('ExaminerRecordsPage', () => {
emergencyStops: [],
circuits: [],
locationList: [],
categoryList: []
categoryList: [],
};
expect(component.displayNoDataCard(emptyData)).toBeTrue();
});
Expand All @@ -616,8 +771,8 @@ describe('ExaminerRecordsPage', () => {
testCount: 1,
emergencyStops: [],
circuits: [],
locationList: [{item: {centreName: 'Test Centre 1', centreId: 1, costCode: 'TC1'}, count: 1}],
categoryList: [{item: TestCategory.B, count: 1}]
locationList: [{ item: { centreName: 'Test Centre 1', centreId: 1, costCode: 'TC1' }, count: 1 }],
categoryList: [{ item: TestCategory.B, count: 1 }],
};

spyOn(component, 'getTotal').and.returnValue(1);
Expand All @@ -637,7 +792,7 @@ describe('ExaminerRecordsPage', () => {
emergencyStops: [],
circuits: [],
locationList: [],
categoryList: []
categoryList: [],
};
expect(component.displayNoDataCard(data)).toBeTrue();
});
Expand Down Expand Up @@ -670,7 +825,7 @@ describe('ExaminerRecordsPage', () => {

const expectedText = 'Displaying <strong>2</strong> Category <strong>C</strong>' +
' test<ion-text>s</ion-text>, from <strong>01/02/2021</strong> to <strong>28/02/2021</strong>' +
'<ion-text> <br /></ion-text> at <strong>Test Centre 2</strong>'
'<ion-text> <br /></ion-text> at <strong>Test Centre 2</strong>';
expect(component.getLabelText()).toEqual(expectedText);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { AccessibilityService } from '@providers/accessibility/accessibility.service';
import { ExaminerRecordData } from '@pages/examiner-records/examiner-records.selector';
import { ExaminerRecordDataWithPercentage } from '@pages/examiner-records/examiner-records.selector';
import { ChartType } from 'ng-apexcharts';

export interface ExaminerReportsCardClick {
Expand All @@ -20,7 +20,7 @@ export class ExaminerReportsCard {
onCardClick: EventEmitter<ExaminerReportsCardClick> = new EventEmitter<ExaminerReportsCardClick>();

@Input()
passedData: ExaminerRecordData<any>[] = null;
passedData: ExaminerRecordDataWithPercentage<any>[] = null;
@Input()
chartID: string = null;
@Input()
Expand Down Expand Up @@ -87,11 +87,11 @@ export class ExaminerReportsCard {
* The `count` property is converted to a number before summing.
*
* @template T - The type of the data contained in the `ExaminerRecordData` objects.
* @param {ExaminerRecordData<T>[]} value - The array of `ExaminerRecordData` objects to be totaled.
* @param {ExaminerRecordDataWithPercentage<T>[]} value - The array of `ExaminerRecordData` objects to be totaled.
* @returns {number} The total count of all `ExaminerRecordData` objects.
*/
getTotal = <T>(
value: ExaminerRecordData<T>[],
value: ExaminerRecordDataWithPercentage<T>[],
): number => value.reduce((total, val) => total + Number(val.count), 0);

/**
Expand All @@ -102,11 +102,12 @@ export class ExaminerReportsCard {
* containing an empty array.
*
* @template T - The type of the data contained in the `ExaminerRecordData` objects.
* @param {ExaminerRecordData<T>[]} examinerRecordData - The array of `ExaminerRecordData` objects to be formatted.
* @param {ExaminerRecordDataWithPercentage<T>[]} examinerRecordData - The array of `ExaminerRecordData` objects
* to be formatted.
* @returns {T[][]} A two-dimensional array where each inner array contains the values of an `ExaminerRecordData`
* object.
*/
filterDataForGrid<T>(examinerRecordData: ExaminerRecordData<T>[]): T[][] {
filterDataForGrid<T>(examinerRecordData: ExaminerRecordDataWithPercentage<T>[]): T[][] {
if (!!examinerRecordData && examinerRecordData.length > 0) {
return examinerRecordData.map((obj) => Object.values(obj) as T[]);
}
Expand Down
Loading

0 comments on commit bcb751a

Please sign in to comment.