Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@if (selectedOffenceConfirmation) {
@if (offenceCode.count === 1) {
@if (matchedOffenceTitle; as offenceTitle) {
<ng-container
*ngTemplateOutlet="offenceCodeHint; context: { found: true, offenceTitle: offenceCode.refData[0].offence_title }"
*ngTemplateOutlet="offenceCodeHint; context: { found: true, offenceTitle: offenceTitle }"
></ng-container>
} @else {
<ng-container *ngTemplateOutlet="offenceCodeHint; context: { found: false }"></ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { NgTemplateOutlet } from '@angular/common';
import { MojTicketPanelComponent } from '@hmcts/opal-frontend-common/components/moj/moj-ticket-panel';
import { FinesMacOffenceCodeHintComponent } from './fines-mac-offence-code-hint.component';
import { IOpalFinesOffencesRefData } from '@services/fines/opal-fines-service/interfaces/opal-fines-offences-ref-data.interface';
import {
OPAL_FINES_OFFENCES_REF_DATA_DUPLICATE_CODE_MOCK,
OPAL_FINES_OFFENCES_REF_DATA_EXACT_MATCH_MULTI_RESULT_MOCK,
} from '@services/fines/opal-fines-service/mocks/opal-fines-offences-ref-data-multi-result.mock';
import { OPAL_FINES_OFFENCES_REF_DATA_MOCK } from '@services/fines/opal-fines-service/mocks/opal-fines-offences-ref-data.mock';
import { beforeEach, describe, expect, it } from 'vitest';

Expand Down Expand Up @@ -53,6 +57,7 @@ describe('FinesMacOffenceCodeHintComponent', () => {

it('should render component with both inputs provided', () => {
fixture.componentRef.setInput('offenceCode', mockOffenceCode);
fixture.componentRef.setInput('searchedOffenceCode', 'AK123456');
fixture.componentRef.setInput('selectedOffenceConfirmation', true);
fixture.detectChanges();

Expand All @@ -70,6 +75,7 @@ describe('FinesMacOffenceCodeHintComponent', () => {
it('should maintain component state through input changes', () => {
// Initial state
fixture.componentRef.setInput('offenceCode', mockOffenceCode);
fixture.componentRef.setInput('searchedOffenceCode', 'AK123456');
fixture.componentRef.setInput('selectedOffenceConfirmation', false);
fixture.detectChanges();

Expand All @@ -82,4 +88,38 @@ describe('FinesMacOffenceCodeHintComponent', () => {
expect(component.selectedOffenceConfirmation).toBe(true);
expect(component.offenceCode).toEqual(mockOffenceCode);
});

it('should render Offence found when the searched code matches one result exactly', () => {
fixture.componentRef.setInput('offenceCode', OPAL_FINES_OFFENCES_REF_DATA_EXACT_MATCH_MULTI_RESULT_MOCK);
fixture.componentRef.setInput('searchedOffenceCode', 'CD71039');
fixture.componentRef.setInput('selectedOffenceConfirmation', true);
fixture.detectChanges();

const textContent = fixture.nativeElement.textContent;
expect(textContent).toContain('Offence found');
expect(textContent).toContain('Criminal damage to property valued under £5000');
});

it('should resolve a duplicate code match using the saved offence id', () => {
fixture.componentRef.setInput('offenceCode', OPAL_FINES_OFFENCES_REF_DATA_DUPLICATE_CODE_MOCK);
fixture.componentRef.setInput('offenceId', 41800);
fixture.componentRef.setInput('searchedOffenceCode', 'GMMET001');
fixture.componentRef.setInput('selectedOffenceConfirmation', true);
fixture.detectChanges();

const textContent = fixture.nativeElement.textContent;
expect(textContent).toContain('Offence found');
expect(textContent).toContain('Duplicate offence title B');
});

it('should render Offence not found when there is no exact code match', () => {
fixture.componentRef.setInput('offenceCode', mockOffenceCode);
fixture.componentRef.setInput('searchedOffenceCode', 'AK12345');
fixture.componentRef.setInput('selectedOffenceConfirmation', true);
fixture.detectChanges();

const textContent = fixture.nativeElement.textContent;
expect(textContent).toContain('Offence not found');
expect(textContent).toContain('Enter a valid offence code');
});
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { NgTemplateOutlet } from '@angular/common';
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { ChangeDetectionStrategy, Component, Input, inject } from '@angular/core';
import { MojTicketPanelComponent } from '@hmcts/opal-frontend-common/components/moj/moj-ticket-panel';
import { IOpalFinesOffencesRefData } from '@services/fines/opal-fines-service/interfaces/opal-fines-offences-ref-data.interface';
import { FinesMacOffenceDetailsService } from '../../fines-mac-offence-details/services/fines-mac-offence-details.service';

@Component({
selector: 'app-fines-mac-offence-code-hint',
Expand All @@ -10,6 +11,21 @@ import { IOpalFinesOffencesRefData } from '@services/fines/opal-fines-service/in
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FinesMacOffenceCodeHintComponent {
private readonly offenceDetailsService = inject(FinesMacOffenceDetailsService);

@Input() public offenceCode!: IOpalFinesOffencesRefData;
@Input() public offenceId: number | null = null;
@Input() public searchedOffenceCode: string | null = null;
@Input() public selectedOffenceConfirmation!: boolean;

/**
* Returns the title for a single exact offence-code match from the lookup response.
* @returns The matched offence title, or `null` when the code is missing, ambiguous, or not found.
*/
public get matchedOffenceTitle(): string | null {
return (
this.offenceDetailsService.findExactOffenceMatch(this.offenceCode, this.searchedOffenceCode, this.offenceId)
?.offence_title ?? null
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ <h2 class="govuk-heading-m govuk-!-margin-0">Offence Details</h2>
@if (offenceCode$ | async; as offenceCode) {
<app-fines-mac-offence-code-hint
[offenceCode]="offenceCode"
[offenceId]="form.controls['fm_fp_offence_details_offence_id'].value"
[searchedOffenceCode]="form.controls['fm_fp_offence_details_offence_cjs_code'].value"
[selectedOffenceConfirmation]="selectedOffenceConfirmation"
></app-fines-mac-offence-code-hint>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ <h2 class="govuk-label-wrapper">
@if (offenceCode$ | async; as offenceCode) {
<app-fines-mac-offence-code-hint
[offenceCode]="offenceCode"
[offenceId]="form.controls['fm_offence_details_offence_id'].value"
[searchedOffenceCode]="form.controls['fm_offence_details_offence_cjs_code'].value"
[selectedOffenceConfirmation]="selectedOffenceConfirmation"
></app-fines-mac-offence-code-hint>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { FinesMacOffenceDetailsReviewOffenceHeadingTitleComponent } from './fines-mac-offence-details-review-offence-heading-title.component';
import {
OPAL_FINES_OFFENCES_REF_DATA_DUPLICATE_CODE_MOCK,
OPAL_FINES_OFFENCES_REF_DATA_EXACT_MATCH_MULTI_RESULT_MOCK,
} from '@services/fines/opal-fines-service/mocks/opal-fines-offences-ref-data-multi-result.mock';
import { OPAL_FINES_OFFENCES_REF_DATA_SINGULAR_MOCK } from '@services/fines/opal-fines-service/mocks/opal-fines-offences-ref-data-singular.mock';
import { beforeEach, describe, expect, it, vi } from 'vitest';

Expand All @@ -16,6 +20,7 @@ describe('FinesMacOffenceDetailsReviewOffenceHeadingTitleComponent', () => {
fixture = TestBed.createComponent(FinesMacOffenceDetailsReviewOffenceHeadingTitleComponent);
component = fixture.componentInstance;

component.offenceCode = OPAL_FINES_OFFENCES_REF_DATA_SINGULAR_MOCK.refData[0].get_cjs_code;
component.offenceRefData = OPAL_FINES_OFFENCES_REF_DATA_SINGULAR_MOCK;

fixture.detectChanges();
Expand All @@ -40,4 +45,33 @@ describe('FinesMacOffenceDetailsReviewOffenceHeadingTitleComponent', () => {

expect(component.offenceTitle).toEqual(component.offenceRefData.refData[0].offence_title);
});

it('should use the exact code match when multiple offences are returned', () => {
component.offenceCode = 'CD71039';
component.offenceRefData = OPAL_FINES_OFFENCES_REF_DATA_EXACT_MATCH_MULTI_RESULT_MOCK;

component.getOffenceTitle();

expect(component.offenceTitle).toEqual('Criminal damage to property valued under £5000');
});

it('should use the saved offence id when duplicate code matches are returned', () => {
component.offenceCode = 'GMMET001';
component.offenceId = 41800;
component.offenceRefData = OPAL_FINES_OFFENCES_REF_DATA_DUPLICATE_CODE_MOCK;

component.getOffenceTitle();

expect(component.offenceTitle).toEqual('Duplicate offence title B');
});

it('should fall back to the first offence title when duplicate code matches are returned without a saved offence id', () => {
component.offenceCode = 'GMMET001';
component.offenceId = null;
component.offenceRefData = OPAL_FINES_OFFENCES_REF_DATA_DUPLICATE_CODE_MOCK;

component.getOffenceTitle();

expect(component.offenceTitle).toEqual('Duplicate offence title A');
});
});
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core';
import { GovukHeadingWithCaptionComponent } from '@hmcts/opal-frontend-common/components/govuk/govuk-heading-with-caption';
import {
GovukSummaryListRowActionItemComponent,
GovukSummaryListRowActionsComponent,
} from '@hmcts/opal-frontend-common/components/govuk/govuk-summary-list';
import { IOpalFinesOffencesRefData } from '@services/fines/opal-fines-service/interfaces/opal-fines-offences-ref-data.interface';
import { FinesMacOffenceDetailsService } from '../../../services/fines-mac-offence-details.service';

@Component({
selector: 'app-fines-mac-offence-details-review-offence-heading-title',
Expand All @@ -20,7 +21,10 @@ import { IOpalFinesOffencesRefData } from '@services/fines/opal-fines-service/in
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FinesMacOffenceDetailsReviewOffenceHeadingTitleComponent implements OnInit {
private readonly offenceDetailsService = inject(FinesMacOffenceDetailsService);

@Input({ required: true }) public offenceCode!: string;
@Input({ required: false }) public offenceId: number | null = null;
@Input({ required: true }) public offenceRefData!: IOpalFinesOffencesRefData;
@Input({ required: false }) public showActions!: boolean;
@Input({ required: false }) public showDetails: boolean = true;
Expand All @@ -41,7 +45,12 @@ export class FinesMacOffenceDetailsReviewOffenceHeadingTitleComponent implements
* Retrieves the offence title from the offence reference data and assigns it to the `offenceTitle` property.
*/
public getOffenceTitle(): void {
this.offenceTitle = this.offenceRefData.refData[0].offence_title;
const exactMatch = this.offenceDetailsService.findExactOffenceMatch(
this.offenceRefData,
this.offenceCode,
this.offenceId,
);
this.offenceTitle = exactMatch?.offence_title ?? this.offenceRefData.refData[0]?.offence_title ?? '';
}

public ngOnInit(): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@if (offenceRefData$ | async; as offenceRefData) {
<app-fines-mac-offence-details-review-offence-heading-title
[offenceCode]="offenceCode"
[offenceId]="offenceRefId"
[offenceRefData]="offenceRefData"
[showActions]="showActions"
[showDetails]="showDetails"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class FinesMacOffenceDetailsReviewOffenceHeadingComponent implements OnIn
private readonly opalFinesService = inject(OpalFines);

@Input({ required: true }) public offenceId!: number;
@Input({ required: false }) public offenceRefId: number | null = null;
@Input({ required: true }) public offenceCode!: string;
@Input({ required: false }) public showActions!: boolean;
@Input({ required: false }) public showDetails: boolean = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<app-fines-mac-offence-details-review-offence-heading
[offenceId]="offence.formData.fm_offence_details_id"
[offenceRefId]="offence.formData.fm_offence_details_offence_id"
[offenceCode]="offence.formData.fm_offence_details_offence_cjs_code!"
[showActions]="showActions"
[showDetails]="showDetails"
Expand Down
Loading
Loading