Skip to content

Commit

Permalink
add functionlity to highlight if slot is autosaved remotely
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewsetterfield committed May 9, 2024
1 parent 0778de4 commit 0c3e68a
Show file tree
Hide file tree
Showing 28 changed files with 298 additions and 32 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"@dvsa/mes-config-schema": "1.7.0",
"@dvsa/mes-driver-schema": "^0.0.2",
"@dvsa/mes-journal-schema": "1.3.1",
"@dvsa/mes-search-schema": "1.2.0",
"@dvsa/mes-search-schema": "1.3.0",
"@dvsa/mes-test-schema": "3.42.5",
"@ionic-enterprise/auth": "3.9.5",
"@ionic/angular": "~7.5.6",
Expand Down Expand Up @@ -189,4 +189,4 @@
"npm run format"
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<h2 class="des-header-style-4" id="candidate-details-title">Candidate details</h2>
</ion-card-header>
<ion-card-content>
<test-recovered-banner *ngIf="isRecovered"></test-recovered-banner>
<inappropriate-use-banner></inappropriate-use-banner>
<ion-grid>
<data-row [idPrefix]="idPrefix" [label]="'Test category'" [value]="pageState.details.testCategory">
Expand Down
2 changes: 2 additions & 0 deletions src/app/pages/candidate-details/candidate-details.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class CandidateDetailsPage implements OnInit, OnDestroy, ViewDidEnter {
slots: TestSlot[];
slotChanged: boolean = false;
isTeamJournal: boolean = false;
isRecovered: boolean = false;
testCategory: TestCategory = null;
idPrefix: string = 'candidate-details';
prevSlot: TestSlot;
Expand All @@ -81,6 +82,7 @@ export class CandidateDetailsPage implements OnInit, OnDestroy, ViewDidEnter {
const navSlots = this.navParams.get('slots');
this.slotChanged = this.navParams.get('slotChanged');
this.isTeamJournal = this.navParams.get('isTeamJournal');
this.isRecovered = this.navParams.get('isRecovered');

// if `slot` is not defined, then use the slot value from `navParams`
// it will be undefined, when using the next/prev buttons as the value wouldn't be set via the Journal navigation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ describe('JournalSlotComponent', () => {
expect(component.derivedTestStatus({} as TestSlot, [])).toEqual(TestStatus.Submitted);
});
});
describe('derivedAutosaveStatus', () => {
it('should return null when slot not completed', () => {
spyOn(slotSelector, 'hasSlotBeenPartiallyCompleted').and.returnValue(null);
expect(component.derivedAutosaveStatus({} as TestSlot, [])).toEqual(null);
});
it('should return true when remote slot status is autosaved', () => {
spyOn(slotSelector, 'hasSlotBeenPartiallyCompleted').and.returnValue(1);
expect(component.derivedAutosaveStatus({} as TestSlot, [])).toEqual(true);
});
});
describe('hasSlotBeenTested', () => {
it('should return null when hasSlotBeenTested returns null', () => {
spyOn(slotSelector, 'hasSlotBeenTested').and.returnValue(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
[derivedActivityCode]="hasSlotBeenTested(slot.slotData, completedTests)"
[derivedPassCertificate]="didSlotPass(slot.slotData, completedTests)"
[derivedTestStatus]="derivedTestStatus(slot?.slotData, completedTests)"
[derivedAutosaveStatus]="derivedAutosaveStatus(slot?.slotData, completedTests)"
[hasSeenCandidateDetails]="slot?.hasSeenCandidateDetails"
[hasSlotChanged]="slot?.hasSlotChanged"
[isPortrait]="isPortrait"
Expand Down
6 changes: 6 additions & 0 deletions src/app/pages/journal/components/journal-slot/journal-slot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ export class JournalSlotComponent {
completedTests: SearchResultTestSchema[],
): TestStatus | null => this.slotSelector.hasSlotBeenTested(slotData, completedTests) ? TestStatus.Submitted : null;

derivedAutosaveStatus = (
slotData: TestSlot,
completedTests: SearchResultTestSchema[],
): boolean | null =>
this.slotSelector.hasSlotBeenPartiallyCompleted(slotData, completedTests) ? true : null;

hasSlotBeenTested = (
slotData: TestSlot,
completedTests: SearchResultTestSchema[],
Expand Down
2 changes: 2 additions & 0 deletions src/app/providers/search/__mocks__/search-results.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const searchResultsMock: SearchResultTestSchema [] = [
lastName: 'Blogs',
title: 'Mr',
},
autosave: 1,
},
{
activityCode: '2',
Expand All @@ -26,5 +27,6 @@ export const searchResultsMock: SearchResultTestSchema [] = [
lastName: 'Smith',
title: 'Mr',
},
autosave: 1,
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export class SlotSelectorProviderMock {
return '1';
}

hasSlotBeenPartiallyCompleted(): number | null {
return 1;
}

createSlots = (): void => { };

}
54 changes: 54 additions & 0 deletions src/app/providers/slot-selector/__tests__/slot-selector.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,63 @@ describe('SlotSelectorProvider', () => {
applicationReference: 111222333,
category: 'A',
activityCode: '4',
autosave: 1,
}]))
.toEqual('4');
});
});

describe('hasSlotBeenPartiallyCompleted', () => {
it('should return null if completedTest is empty', () => {
expect(slotSelector.hasSlotBeenPartiallyCompleted(null, null))
.toEqual(null);
});

it('should return autosave status if the searched test entry exists', () => {
expect(slotSelector.hasSlotBeenPartiallyCompleted({
booking: {
application: {
applicationId: 111,
bookingSequence: 222,
checkDigit: 333,
},
},
}, [{
costCode: '123456',
testDate: '11/1/11',
driverNumber: '1234',
candidateName: { firstName: 'name' },
applicationReference: 111222333,
category: 'A',
activityCode: '4',
autosave: 1,
}]))
.toEqual(1);
});

it('should return null if the searched test entry does not exist', () => {
expect(slotSelector.hasSlotBeenPartiallyCompleted({
booking: {
application: {
applicationId: 111,
bookingSequence: 222,
checkDigit: 333,
},
},
}, [{
costCode: '123456',
testDate: '11/1/11',
driverNumber: '1234',
candidateName: { firstName: 'name' },
applicationReference: 999999999,
category: 'A',
activityCode: '4',
autosave: 1,
}]))
.toEqual(null);
});
});

describe('didSlotPass', () => {
it('should return null if completedTest is empty', () => {
expect(slotSelector.didSlotPass(null, null))
Expand All @@ -63,6 +115,7 @@ describe('SlotSelectorProvider', () => {
applicationReference: 111222333,
category: 'A',
activityCode: '4',
autosave: 1,
}]))
.toEqual(undefined);
});
Expand All @@ -84,6 +137,7 @@ describe('SlotSelectorProvider', () => {
category: 'A',
activityCode: '4',
passCertificateNumber: '123456789',
autosave: 1,
}]))
.toEqual('123456789');
});
Expand Down
13 changes: 13 additions & 0 deletions src/app/providers/slot-selector/slot-selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@ export class SlotSelectorProvider {
return completedTest.activityCode;
}

/**
* Returns the autosave status of a test if held remotely
* @param slotData
* @param completedTests
*/
public hasSlotBeenPartiallyCompleted(slotData: TestSlot, completedTests: SearchResultTestSchema[]): number | null {
const completedTest = this.getCompletedTest(slotData, completedTests);
if (!completedTest) {
return null;
}
return completedTest.autosave;
}

private getCompletedTest = (slotData: TestSlot, completedTests: SearchResultTestSchema[]) => {
if (isEmpty(completedTests)) {
return null;
Expand Down
3 changes: 3 additions & 0 deletions src/components/common/common-components.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { DrivingFaultsBadgeComponent } from './driving-faults-badge/driving-faul
import { EndTestLinkComponent } from './end-test-link/end-test-link';
import { VRNCaptureModalModule } from './vrn-capture-modal/vrn-capture-modal.module';
import { DirectivesModule } from '@directives/directives.module';
import { TestRecoveredBannerComponent } from '@components/common/test-recovered-banner/test-recovered-banner';

@NgModule({
declarations: [
Expand All @@ -73,6 +74,7 @@ import { DirectivesModule } from '@directives/directives.module';
PracticeModeBanner,
LockScreenIndicator,
SeriousFaultBadgeComponent,
TestRecoveredBannerComponent,
TickIndicatorComponent,
TransmissionComponent,
SignatureComponent,
Expand Down Expand Up @@ -121,6 +123,7 @@ import { DirectivesModule } from '@directives/directives.module';
PracticeModeBanner,
LockScreenIndicator,
SeriousFaultBadgeComponent,
TestRecoveredBannerComponent,
TickIndicatorComponent,
TransmissionComponent,
SignatureComponent,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { TestRecoveredBannerComponent } from '@components/common/test-recovered-banner/test-recovered-banner';

describe('TestRecoveredBannerComponent', () => {
let component: TestRecoveredBannerComponent;
let fixture: ComponentFixture<TestRecoveredBannerComponent>;

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [TestRecoveredBannerComponent],
imports: [IonicModule],
});

fixture = TestBed.createComponent(TestRecoveredBannerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div>
<ion-grid>
<ion-row>
<ion-col size="8" class="recovered-centre">
<ion-icon class="alert-icon" name="alert-circle" aria-label="Information icon"></ion-icon>
</ion-col>
<ion-col class="recovered-centre" size="83">
<span id="test-recovered-text" class="recovered-text">
This test has been successfully recorded.
<br />No further action is required.
</span>
</ion-col>
</ion-row>
</ion-grid>
</div>
<br />
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
:host {
.alert-icon {
color: var(--mes-white);
font-size: 50px;
}

div {
background: var(--gds-dark-green);
border-left: 10px solid var(--gds-black);
}

.center-icon {
text-align: center;
}

.modal-alert-header {
margin: 0 0 24px;
}

.recovered-centre {
display: flex;
align-items: center;
}

.recovered-text {
color: var(--mes-white);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Component } from '@angular/core';

@Component({
selector: 'test-recovered-banner',
templateUrl: 'test-recovered-banner.html',
styleUrls: ['test-recovered-banner.scss'],
})
export class TestRecoveredBannerComponent {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { AutosaveStatusComponent } from '@components/test-slot/autosave-status/autosave-status';

describe('AutosaveStatusComponent', () => {
let component: AutosaveStatusComponent;
let fixture: ComponentFixture<AutosaveStatusComponent>;

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [AutosaveStatusComponent],
imports: [IonicModule],
});

fixture = TestBed.createComponent(AutosaveStatusComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));

it('should create', () => {
expect(component).toBeTruthy();
});
});
3 changes: 3 additions & 0 deletions src/components/test-slot/autosave-status/autosave-status.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
<ion-text class="des-header-style-6 recovered-text">RECOVERED</ion-text>
</div>
8 changes: 8 additions & 0 deletions src/components/test-slot/autosave-status/autosave-status.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.recovered-text {
font-size: 15px !important;
background: var(--gds-dark-green);
color: var(--mes-white) !important;
display: flex;
align-items: center;
justify-content: center;
}
9 changes: 9 additions & 0 deletions src/components/test-slot/autosave-status/autosave-status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Component } from '@angular/core';

@Component({
selector: 'autosave-status',
templateUrl: 'autosave-status.html',
styleUrls: ['autosave-status.scss'],
})
export class AutosaveStatusComponent {
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
'candidate-name-portrait': isPortrait,
'candidate-name-landscape': !isPortrait,
'team-journal': isTeamJournal,
'recovered': isRecovered,
'extra-large-mode': accessibilityService.getTextZoomClass() === 'text-zoom-x-large'
}"
>{{name.title}} {{name.firstName}} {{name.lastName}}</ion-text
Expand Down
Loading

0 comments on commit 0c3e68a

Please sign in to comment.