Skip to content

Commit

Permalink
feat(cb2-14450): initial migration of weights section
Browse files Browse the repository at this point in the history
  • Loading branch information
BrandonT95 committed Jan 3, 2025
1 parent 37ad486 commit 665be13
Show file tree
Hide file tree
Showing 17 changed files with 319 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,20 @@
<div class="govuk-summary-list__row" *ngIf="techRecordEdited.techRecord_vehicleType !== 'psv'">
<dt class="govuk-summary-list__key">Make</dt>
<dd class="govuk-summary-list__value" id="test-techRecord_make">
{{
techRecordEdited.techRecord_vehicleType === 'trl' || techRecordEdited.techRecord_vehicleType === 'hgv'
? (techRecordEdited.techRecord_make | defaultNullOrEmpty)
: '-'
{{
techRecordEdited.techRecord_vehicleType === 'trl' || techRecordEdited.techRecord_vehicleType === 'hgv'
? (techRecordEdited.techRecord_make | defaultNullOrEmpty)
: '-'
}}
</dd>
</div>
<div class="govuk-summary-list__row" *ngIf="techRecordEdited.techRecord_vehicleType !== 'psv'">
<dt class="govuk-summary-list__key">Model</dt>
<dd class="govuk-summary-list__value" id="test-techRecord_model">
{{
techRecordEdited.techRecord_vehicleType === 'trl' || techRecordEdited.techRecord_vehicleType === 'hgv'
? (techRecordEdited.techRecord_model | defaultNullOrEmpty)
: '-'
{{
techRecordEdited.techRecord_vehicleType === 'trl' || techRecordEdited.techRecord_vehicleType === 'hgv'
? (techRecordEdited.techRecord_model | defaultNullOrEmpty)
: '-'
}}
</dd>
</div>
Expand Down Expand Up @@ -184,10 +184,27 @@
You removed an axle.
</strong>
</div>
<app-weights [vehicleTechRecord]="techRecordEdited"></app-weights>
<!-- New Weights section -->
<ng-container *ngIf="featureToggleService.isFeatureEnabled('FsTyres'); else oldWeightsSection">
<app-weights-section [techRecord]="techRecordEdited" [mode]="'summary'"/>
</ng-container>

<!-- Old Weights section -->
<ng-template #oldWeightsSection>
<app-weights [vehicleTechRecord]="techRecordEdited"></app-weights>
</ng-template>
</ng-container>

<ng-template #noDeleted>
<app-modified-weights *ngIf="changesForWeights" [vehicleType]="vehicleType" [changes]="changesForWeights"></app-modified-weights>
<!-- New Weights section -->
<ng-container *ngIf="featureToggleService.isFeatureEnabled('FsTyres') && changesForWeights; else oldModifiedWeightsSection">
<app-weights-section [techRecord]="techRecordEdited" [mode]="'summary'"/>
</ng-container>

<!-- Old Weights section -->
<ng-template #oldModifiedWeightsSection>
<app-modified-weights *ngIf="changesForWeights" [vehicleType]="vehicleType" [changes]="changesForWeights"></app-modified-weights>
</ng-template>
</ng-template>
</ng-container>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,16 +140,26 @@
</ng-container>

<ng-container *ngSwitchCase="'weightsSection'">
<app-weights
*ngIf="
<ng-container *ngIf="
techRecordCalculated.techRecord_vehicleType === 'trl' ||
techRecordCalculated.techRecord_vehicleType === 'hgv' ||
techRecordCalculated.techRecord_vehicleType === 'psv'
"
[vehicleTechRecord]="techRecordCalculated"
[isEditing]="(isEditing$ | async) ?? false"
(formChange)="handleFormState($event)"
></app-weights>
">
<!-- New Weights Section -->
<ng-container *ngIf="featureToggleService.isFeatureEnabled('FsWeights'); else oldWeightsSection">
<app-weights-section
[techRecord]="techRecordCalculated"
[mode]="(isEditing$ | async) ? 'edit' : 'view'"/>
</ng-container>
<!-- Old Weights Section -->
<ng-template #oldWeightsSection>
<app-weights
[vehicleTechRecord]="techRecordCalculated"
[isEditing]="(isEditing$ | async) ?? false"
(formChange)="handleFormState($event)"
></app-weights>
</ng-template>
</ng-container>
</ng-container>

<ng-container *ngSwitchCase="'lettersSection'">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { ComponentRef } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {
ControlContainer,
FormControl,
FormGroup,
FormGroupDirective,
FormsModule,
ReactiveFormsModule,
} from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { TechRecordType } from '@dvsa/cvs-type-definitions/types/v3/tech-record/tech-record-vehicle-type';
import { DynamicFormsModule } from '@forms/dynamic-forms.module';
import { mockVehicleTechnicalRecord } from '@mocks/mock-vehicle-technical-record.mock';
import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { TechnicalRecordService } from '@services/technical-record/technical-record.service';
import { initialAppState } from '@store/index';
import { of } from 'rxjs';
import { WeightsSectionEditComponent } from '../weights-section-edit/weights-section-edit.component';

describe('weightsSectionEditComponent', () => {
let controlContainer: ControlContainer;
let component: WeightsSectionEditComponent;
let componentRef: ComponentRef<WeightsSectionEditComponent>;
let fixture: ComponentFixture<WeightsSectionEditComponent>;
let formGroupDirective: FormGroupDirective;
let store: MockStore;

beforeEach(async () => {
formGroupDirective = new FormGroupDirective([], []);
formGroupDirective.form = new FormGroup<Partial<Record<keyof TechRecordType<'hgv' | 'psv' | 'trl'>, FormControl>>>(
{}
);
const mockTechRecord = mockVehicleTechnicalRecord('hgv');

await TestBed.configureTestingModule({
declarations: [WeightsSectionEditComponent],
imports: [DynamicFormsModule, FormsModule, ReactiveFormsModule],
providers: [
provideMockStore({ initialState: initialAppState }),
provideHttpClient(),
provideHttpClientTesting(),
{ provide: ControlContainer, useValue: formGroupDirective },
{ provide: ActivatedRoute, useValue: { params: of([{ id: 1 }]) } },
TechnicalRecordService,
],
}).compileComponents();

store = TestBed.inject(MockStore);
controlContainer = TestBed.inject(ControlContainer);

fixture = TestBed.createComponent(WeightsSectionEditComponent);
component = fixture.componentInstance;
componentRef = fixture.componentRef;
componentRef.setInput('techRecord', mockTechRecord);
component.form.reset();
fixture.detectChanges();
});

describe('ngOnInit', () => {
it('should call addControlsBasedOffVehicleType', () => {
const addControlsBasedOffVehicleTypeSpy = jest.spyOn(component, 'addControlsBasedOffVehicleType');
component.ngOnInit();
expect(addControlsBasedOffVehicleTypeSpy).toHaveBeenCalled();
});

it('should attach all form controls to parent', () => {
const parent = controlContainer.control as FormGroup;
component.ngOnInit();
expect(parent.controls).toEqual(component.form.controls);
});
});

describe('ngOnDestroy', () => {
it('should detach all form controls from parent', () => {
const parent = controlContainer.control as FormGroup;
component.ngOnDestroy();
expect(Object.keys(parent.controls)).toEqual([]);
});

it('should complete destroy$ subject', () => {
const completeSpy = jest.spyOn(component.destroy$, 'complete');
component.ngOnDestroy();
expect(completeSpy).toHaveBeenCalled();
});

it('should emit true to destroy$ subject', () => {
let emittedValue: boolean | undefined;
component.destroy$.subscribe((value) => (emittedValue = value));
component.ngOnDestroy();
expect(emittedValue).toBe(true);
});
});

describe('addControlsBasedOffVehicleType', () => {
it('should add vehicle specific controls to the form', () => {
const addControlSpy = jest.spyOn(component.form, 'addControl');
const vehicleControlsSpy = jest.spyOn(component, 'controlsBasedOffVehicleType', 'get');
component.addControlsBasedOffVehicleType();
expect(vehicleControlsSpy).toHaveBeenCalled();
expect(addControlSpy).toHaveBeenCalled();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div [formGroup]="form">

</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Component, OnDestroy, OnInit, inject, input } from '@angular/core';
import { ControlContainer, FormBuilder, FormGroup } from '@angular/forms';
import { CommonValidatorsService } from '@forms/validators/common-validators.service';
import { V3TechRecordModel } from '@models/vehicle-tech-record.model';
import { Store } from '@ngrx/store';
import { TechnicalRecordService } from '@services/technical-record/technical-record.service';
import { ReplaySubject } from 'rxjs';

@Component({
selector: 'app-weights-section-edit',
templateUrl: './weights-section-edit.component.html',
styleUrls: ['./weights-section-edit.component.scss'],
})
export class WeightsSectionEditComponent implements OnInit, OnDestroy {
fb = inject(FormBuilder);
store = inject(Store);
controlContainer = inject(ControlContainer);
commonValidators = inject(CommonValidatorsService);
technicalRecordService = inject(TechnicalRecordService);
techRecord = input.required<V3TechRecordModel>();

destroy$ = new ReplaySubject<boolean>(1);

form: FormGroup = this.fb.group({});

ngOnInit(): void {
this.addControlsBasedOffVehicleType();

// Attach all form controls to parent
const parent = this.controlContainer.control;
if (parent instanceof FormGroup) {
for (const [key, control] of Object.entries(this.form.controls)) {
parent.addControl(key, control, { emitEvent: false });
}
}
}

ngOnDestroy(): void {
// Detach all form controls from parent
const parent = this.controlContainer.control;
if (parent instanceof FormGroup) {
for (const key of Object.keys(this.form.controls)) {
parent.removeControl(key, { emitEvent: false });
}
}

// Clear subscriptions
this.destroy$.next(true);
this.destroy$.complete();
}

addControlsBasedOffVehicleType() {
const vehicleControls = this.controlsBasedOffVehicleType;
for (const [key, control] of Object.entries(vehicleControls)) {
this.form.addControl(key, control, { emitEvent: false });
}
}

get controlsBasedOffVehicleType() {
switch (this.techRecord().techRecord_vehicleType) {
default:
return {};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<ng-container *ngIf="amendedTechRecord() as vm">
<dl class="govuk-summary-list">
<div class="govuk-summary-list__row" *ngIf="hasChanged('')">
<dt class="govuk-summary-list__key"></dt>
<dd class="govuk-summary-list__value" id="test-">

</dd>
</div>
</dl>
</ng-container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { TechnicalRecordService } from '@/src/app/services/technical-record/technical-record.service';
import { Component, inject } from '@angular/core';
import { TechRecordType } from '@dvsa/cvs-type-definitions/types/v3/tech-record/tech-record-verb';
import { VehicleTypes } from '@models/vehicle-tech-record.model';
import { Store } from '@ngrx/store';
import { editingTechRecord, techRecord } from '@store/technical-records';
import { isEqual } from 'lodash';

@Component({
selector: 'app-weights-section-summary',
templateUrl: './weights-section-summary.component.html',
styleUrls: ['./weights-section-summary.component.scss'],
})
export class WeightsSectionSummaryComponent {
protected readonly VehicleTypes = VehicleTypes;

store = inject(Store);
technicalRecordService = inject(TechnicalRecordService);

currentTechRecord = this.store.selectSignal(techRecord);
amendedTechRecord = this.store.selectSignal(editingTechRecord);

hasChanged(property: string) {
const current = this.currentTechRecord();
const amended = this.amendedTechRecord();
if (!current || !amended) return true;

return !isEqual(current[property as keyof TechRecordType<'put'>], amended[property as keyof TechRecordType<'put'>]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<ng-container *ngIf="techRecord() as vm">
<dl class="govuk-summary-list">
<div class="govuk-summary-list__row">
<dt class="govuk-summary-list__key"></dt>
<dd class="govuk-summary-list__value" id="test-">

</dd>
</div>
</dl>
</ng-container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Component, inject } from '@angular/core';
import { VehicleTypes } from '@models/vehicle-tech-record.model';
import { Store } from '@ngrx/store';
import { TechnicalRecordService } from '@services/technical-record/technical-record.service';
import { techRecord } from '@store/technical-records';

@Component({
selector: 'app-weights-section-view',
templateUrl: './weights-section-view.component.html',
styleUrls: ['./weights-section-view.component.scss'],
})
export class WeightsSectionViewComponent {
protected readonly VehicleTypes = VehicleTypes;

store = inject(Store);
technicalRecordService = inject(TechnicalRecordService);
techRecord = this.store.selectSignal(techRecord);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<ng-container [ngSwitch]="mode()">
<app-weights-section-view *ngSwitchCase="'view'" />
<app-weights-section-edit *ngSwitchCase="'edit'" [techRecord]="techRecord()" />
<app-weights-section-summary *ngSwitchCase="'summary'" />
</ng-container>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { V3TechRecordModel } from '@/src/app/models/vehicle-tech-record.model';
import { Component, input } from '@angular/core';

@Component({
selector: 'app-weights-section',
templateUrl: './weights-section.component.html',
styleUrls: ['./weights-section.component.scss'],
})
export class WeightsSectionComponent {
mode = input<Mode>('edit');
techRecord = input.required<V3TechRecordModel>();
}

type Mode = 'view' | 'edit' | 'summary';
Loading

0 comments on commit 665be13

Please sign in to comment.