diff --git a/src/main/controllers/style-guide/CrownFirmPddaListController.ts b/src/main/controllers/style-guide/CrownFirmPddaListController.ts new file mode 100644 index 000000000..055f0bd90 --- /dev/null +++ b/src/main/controllers/style-guide/CrownFirmPddaListController.ts @@ -0,0 +1,69 @@ +import { PipRequest } from '../../models/request/PipRequest'; +import { Response } from 'express'; +import { formatMetaDataListType, isUnexpectedListType, isValidList, isValidListType } from '../../helpers/listHelper'; +import { HttpStatusCode } from 'axios'; +import { cloneDeep } from 'lodash'; +import { ListParseHelperService } from '../../service/ListParseHelperService'; +import { LocationService } from '../../service/LocationService'; +import { PublicationService } from '../../service/PublicationService'; +import { formatDate } from '../../helpers/dateTimeHelper'; +import { CrownFirmPddaListService } from '../../service/listManipulation/CrownFirmPddaListService'; + +const publicationService = new PublicationService(); +const locationService = new LocationService(); +const helperService = new ListParseHelperService(); +const crownFirmPddaListService = new CrownFirmPddaListService(); + +const listType = 'crown-firm-pdda-list'; + +export default class CrownFirmPddaListController { + public async get(req: PipRequest, res: Response): Promise { + const artefactId = req.query.artefactId as string; + const payload = await publicationService.getIndividualPublicationJson(artefactId, req.user?.['userId']); + const metadata = await publicationService.getIndividualPublicationMetadata(artefactId, req.user?.['userId']); + const metadataListType = formatMetaDataListType(metadata); + + if (isValidList(payload, metadata) && isValidListType(metadataListType, listType)) { + const listData = crownFirmPddaListService.processPayload(payload as JSON, req.lng); + const returnedLocation = await locationService.getLocationById(metadata['locationId']); + const locationName = locationService.findCourtName(returnedLocation, req.lng, listType); + + const firmListData = payload['FirmList']; + const listHeader = firmListData.ListHeader; + const publishedDate = helperService.publicationDateInUkTime(listHeader.PublishedTime, req.lng); + const publishedTime = helperService.publicationTimeInUkTime(listHeader.PublishedTime); + const startDate = formatDate( + crownFirmPddaListService.toIsoDate(listHeader.StartDate), + 'dd MMMM yyyy', + req.lng + ); + const endDate = listHeader.EndDate + ? formatDate(crownFirmPddaListService.toIsoDate(listHeader.EndDate), 'dd MMMM yyyy', req.lng) + : ''; + const version = listHeader.Version; + const venueAddress = crownFirmPddaListService.formatAddress(firmListData.CrownCourt.CourtHouseAddress); + + res.render(`style-guide/${listType}`, { + ...cloneDeep(req.i18n.getDataByLanguage(req.lng)[listType]), + ...cloneDeep(req.i18n.getDataByLanguage(req.lng)['list-template']), + listData: listData, + locationName: locationName, + provenance: metadata.provenance, + publishedDate, + publishedTime, + startDate, + endDate, + version, + venueAddress, + }); + } else if ( + payload === HttpStatusCode.NotFound || + metadata === HttpStatusCode.NotFound || + isUnexpectedListType(metadataListType, listType) + ) { + res.render('list-not-found', req.i18n.getDataByLanguage(req.lng)['list-not-found']); + } else { + res.render('error', req.i18n.getDataByLanguage(req.lng).error); + } + } +} diff --git a/src/main/resources/listLookup.json b/src/main/resources/listLookup.json index af297013e..efee2978e 100644 --- a/src/main/resources/listLookup.json +++ b/src/main/resources/listLookup.json @@ -673,7 +673,7 @@ "shortenedFriendlyName": "London Circuit Commercial Court (KB) Daily Cause List", "url": "london-circuit-commercial-court-kb-daily-cause-list", "jurisdictionTypes": ["High Court"], - "restrictedProvenances": [], + "restrictedProvenances": [], "defaultSensitivity": "", "isNonStrategic": true }, @@ -822,9 +822,7 @@ "welshFriendlyName": "Rhestr Achosion Dyddiol y Llys Apêl (Adran Sifil)", "shortenedFriendlyName": "Court of Appeal (Civil Division) Daily Cause List", "url": "court-of-appeal-civil-daily-cause-list", - "jurisdictionTypes": [ - "Court of Appeal (Civil Division)" - ], + "jurisdictionTypes": ["Court of Appeal (Civil Division)"], "restrictedProvenances": [], "defaultSensitivity": "", "isNonStrategic": true @@ -929,5 +927,15 @@ "restrictedProvenances": [], "defaultSensitivity": "CLASSIFIED", "isNonStrategic": false + }, + "CROWN_FIRM_PDDA_LIST": { + "friendlyName": "Crown Firm PDDA List", + "welshFriendlyName": "Rhestr PDDA Cwmni Llys y Goron", + "shortenedFriendlyName": "Crown Firm PDDA List", + "url": "crown-firm-pdda-list", + "jurisdictionTypes": ["Crown Court"], + "restrictedProvenances": [], + "defaultSensitivity": "CLASSIFIED", + "isNonStrategic": false } } diff --git a/src/main/resources/locales/cy/crown-firm-pdda-list.json b/src/main/resources/locales/cy/crown-firm-pdda-list.json new file mode 100644 index 000000000..af34ad47a --- /dev/null +++ b/src/main/resources/locales/cy/crown-firm-pdda-list.json @@ -0,0 +1,28 @@ +{ + "title": "Rhestr Cwmni Llys y Goron", + "heading": "Rhestr Cwmni Llys y Goron ar gyfer", + "listDate": "Rhestr ar gyfer", + "to": "i", + "listUpdated": "Diweddarwyd diwethaf", + "at": "am", + "versionText": "Fersiwn", + "restrictionInformationHeading": "Cyfyngiadau ar gyhoeddi neu ysgrifennu am yr achosion hyn.", + "restrictionInformationP1": "Rhaid i chi wirio a oes unrhyw gyfyngiadau riportio yn berthnasol cyn cyhoeddi manylion am unrhyw un o'r achosion a restrir yma, naill ai'n ysgrifenedig, mewn darllediad neu ar y rhyngrwyd, gan gynnwys y cyfryngau cymdeithasol.", + "restrictionInformationBoldText": "Byddwch yn euog o ddirmyg llys os byddwch yn cyhoeddi unrhyw wybodaeth sydd wedi'i diogelu gan gyfyngiad riportio. Gallwch gael dirwy, eich dedfrydu i garchar, neu'r ddau.", + "restrictionInformationP2": "Bydd cyfyngiadau penodol a orchmynnir gan y llys yn cael eu crybwyll ar yr achosion a restrir yma.", + "restrictionInformationP3": "Fodd bynnag, nid yw'r cyfyngiadau bob amser yn cael eu rhestru. Mae rhai yn berthnasol yn awtomatig. Er enghraifft, anhysbysrwydd a roddir i ddioddefwyr rhai troseddau rhywiol.", + "restrictionInformationP4": "I ganfod pa gyfyngiadau riportio sy'n berthnasol ar achos penodol, cysylltwch â'r:", + "restrictionBulletPoint1": "llys yn uniongyrchol", + "restrictionBulletPoint2": "Gwasanaeth Llysoedd a Thribiwnlysoedd EM ar 0330 808 4407", + "courtRoom": "Ystafell llys", + "sittingAt": "Yn eistedd yn", + "tableHeaders": [ + "Cyfeirnod yr Achos", + "Enw'r Diffynnydd(Diffynyddion)", + "Math o Wrandawiad", + "Cynrychiolir gan", + "Yr Awdurdod sy'n Erlyn", + "Nodiadau Rhestru" + ], + "dataSource": "Ffynhonnell Data" +} diff --git a/src/main/resources/locales/en/crown-firm-pdda-list.json b/src/main/resources/locales/en/crown-firm-pdda-list.json new file mode 100644 index 000000000..e6acb6860 --- /dev/null +++ b/src/main/resources/locales/en/crown-firm-pdda-list.json @@ -0,0 +1,28 @@ +{ + "title": "Crown Firm List", + "heading": "Crown Firm List for", + "listDate": "List for", + "to": "to", + "listUpdated": "Last updated", + "at": "at", + "versionText": "Version", + "restrictionInformationHeading": "Restrictions on publishing or writing about these cases", + "restrictionInformationP1": "You must check if any reporting restrictions apply before publishing details on any of the cases listed here either in writing, in a broadcast or by internet, including social media.", + "restrictionInformationBoldText": "You'll be in contempt of court if you publish any information which is protected by a reporting restriction. You could get a fine, prison sentence or both.", + "restrictionInformationP2": "Specific restrictions ordered by the court will be mentioned on the cases listed here.", + "restrictionInformationP3": "However, restrictions are not always listed. Some apply automatically. For example, anonymity given to the victims of certain sexual offences.", + "restrictionInformationP4": "To find out which reporting restrictions apply on a specific case, contact:", + "restrictionBulletPoint1": "the court directly", + "restrictionBulletPoint2": "HM Courts and Tribunals Service on 0330 808 4407", + "courtRoom": "Courtroom", + "sittingAt": "Sitting at", + "tableHeaders": [ + "Case Number", + "Defendant Name(s)", + "Hearing Type", + "Representative", + "Prosecuting Authority", + "Listing Notes" + ], + "dataSource": "Data Source" +} diff --git a/src/main/routes/routes.ts b/src/main/routes/routes.ts index b88ff66ec..adc49a922 100644 --- a/src/main/routes/routes.ts +++ b/src/main/routes/routes.ts @@ -212,6 +212,7 @@ export default function (app: Application): void { 'magistrates-adult-court-list-future' ) ); + app.get('/crown-firm-pdda-list', app.locals.container.cradle.crownFirmPddaListController.get); //Non-Strategic Paths app.get('/cst-weekly-hearing-list', (req, res) => diff --git a/src/main/service/listManipulation/CrownFirmPddaListService.ts b/src/main/service/listManipulation/CrownFirmPddaListService.ts new file mode 100644 index 000000000..0b6d70f0a --- /dev/null +++ b/src/main/service/listManipulation/CrownFirmPddaListService.ts @@ -0,0 +1,134 @@ +import { ListParseHelperService } from '../ListParseHelperService'; +import { formatDate } from '../../helpers/dateTimeHelper'; + +const helperService = new ListParseHelperService(); + +export class CrownFirmPddaListService { + public processPayload(payload: JSON, language: string): any[] { + const results = []; + payload['FirmList'].CourtLists.forEach(courtList => { + const courtHouse = courtList.CourtHouse; + results.push({ + sittingDate: formatDate(this.toIsoDate(courtList.SittingDate), 'EEEE dd MMMM yyyy', language), + courtName: courtHouse.CourtHouseName, + courtAddress: courtHouse.CourtHouseAddress ? this.formatAddress(courtHouse.CourtHouseAddress) : [], + courtPhone: courtHouse.CourtHouseTelephone ? courtHouse.CourtHouseTelephone : '', + sittings: this.buildSittingInfo(courtList), + }); + }); + return results; + } + + private buildSittingInfo(courtList: any): any[] { + const sittings = []; + courtList.Sittings.forEach(sitting => { + sittings.push({ + courtRoomNumber: sitting.CourtRoomNumber, + sittingAt: sitting.SittingAt ? helperService.publicationTimeInUkTime(sitting.SittingAt) : '', + judgeName: this.formatJudgeName(sitting.Judiciary), + hearings: this.buildHearings(sitting), + }); + }); + return sittings; + } + + private buildHearings(sitting: any): any[] { + const hearings = []; + sitting.Hearings.forEach(hearing => { + hearings.push({ + caseNumber: hearing.CaseNumberCaTH, + defendantName: hearing.Defendants ? this.formatDefendantName(hearing.Defendants) : '', + hearingType: hearing.HearingDetails.HearingDescription, + representativeName: hearing.Defendants ? this.formatRepresentativeName(hearing.Defendants) : '', + prosecutingAuthority: hearing.Prosecution?.ProsecutingAuthority + ? hearing.Prosecution.ProsecutingAuthority + : '', + listNote: hearing.ListNote ? hearing.ListNote : '', + }); + }); + return hearings; + } + + private formatJudgeName(judiciary): string { + const names = []; + names.push(this.formatIndividualName(judiciary.Judge)); + + if (judiciary.Justice) { + judiciary.Justice.forEach(justice => { + names.push(this.formatIndividualName(justice)); + }); + } + return names.filter(name => name.trim().length > 0).join(', '); + } + + private formatDefendantName(defendants): string { + const names = []; + defendants.forEach(defendant => { + names.push(this.useMaskedNameIfRequested(defendant.PersonalDetails)); + }); + return names.filter(name => name.trim().length > 0).join(', '); + } + + private formatRepresentativeName(defendants): string { + const names = []; + defendants.forEach(defendant => { + defendant.Counsel?.forEach(counsel => + counsel.Solicitor?.forEach(solicitor => { + const party = solicitor.Party; + if (party?.Person) { + names.push(this.useMaskedNameIfRequested(party.Person.PersonalDetails)); + } else if (party?.Organisation) { + names.push(party.Organisation.OrganisationName); + } + }) + ); + }); + return names.filter(name => name.trim().length > 0).join(', '); + } + + private useMaskedNameIfRequested(nameDetails): string { + if (nameDetails.IsMasked && nameDetails.IsMasked == 'YES') { + return nameDetails.MaskedName ? nameDetails.MaskedName : ''; + } + return this.formatIndividualName(nameDetails.Name); + } + + private formatIndividualName(individual): string { + return individual.CitizenNameRequestedName + ? individual.CitizenNameRequestedName + : this.formatNameParts(individual); + } + + private formatNameParts(individual): string { + const nameParts = []; + if (individual.CitizenNameTitle) { + nameParts.push(individual.CitizenNameTitle); + } + if (individual.CitizenNameForename) { + nameParts.push(individual.CitizenNameForename); + } + if (individual.CitizenNameSurname) { + nameParts.push(individual.CitizenNameSurname); + } + if (individual.CitizenNameSuffix) { + nameParts.push(individual.CitizenNameSuffix); + } + return nameParts.filter(part => part.trim().length > 0).join(' '); + } + + public formatAddress(address): string[] { + const addressLines = []; + if (address) { + address.Line.forEach(line => addressLines.push(line)); + if (address.Postcode) { + addressLines.push(address.Postcode); + } + } + return addressLines.filter(line => line.trim().length > 0); + } + + public toIsoDate(date: string): string { + const dateParts = date.split('-'); + return new Date(Number(dateParts[0]), Number(dateParts[1]) - 1, Number(dateParts[2])).toISOString(); + } +} diff --git a/src/main/views/style-guide/crown-firm-pdda-list.njk b/src/main/views/style-guide/crown-firm-pdda-list.njk new file mode 100644 index 000000000..90c1eb9c0 --- /dev/null +++ b/src/main/views/style-guide/crown-firm-pdda-list.njk @@ -0,0 +1,120 @@ +{% from "govuk/components/table/macro.njk" import govukTable as 'govukTable' %} +{% from "../macros/common-components.njk" import goBack, searchInput %} +{% from "govuk/components/warning-text/macro.njk" import govukWarningText %} + +{% extends "../list-template.njk" %} +{% block pageTitle %} + {{ title }} +{% endblock %} + +{% block beforeContent %} + {{ super() }} + {{ goBack(text = backButton, cspNonce = cspNonce) }} +{% endblock %} + +{% block content %} +
+

{{ heading }} {{ locationName }}

+ {% if endDate | length %} +

{{ listDate }} {{ startDate }} {{ to }} {{ endDate }}

+ {% else %} +

{{ listDate }} {{ startDate }}

+ {% endif %} +

{{ listUpdated }} {{ publishedDate }} {{ at }} {{ publishedTime }}

+

{{ versionText }} {{ version }}

+ +

+ {% for line in venueAddress %} + {{ line }}
+ {% endfor %} +

+ +
+
+

{{ restrictionInformationHeading }}

+

{{ restrictionInformationP1 }}

+
+ + + Warning + {{ restrictionInformationBoldText }} + +
+

{{ restrictionInformationP2 }}

+

{{ restrictionInformationP3 }}

+

{{ restrictionInformationP4 }}

+
    +
  • {{ restrictionBulletPoint1 }}
  • +
  • {{ restrictionBulletPoint2 }}
  • +
+
+
+ + {{ searchInput(text = searchCases) }} +
+ {% set countHouseCount = 0 %} + {% set sittingCount = 0 %} + {% for courtHouse in listData %} + {% set countHouseCount = countHouseCount + 1 %} + +
+ {% for sitting in courtHouse.sittings %} +
+
+ {% set sittingCount = sittingCount + 1 %} +

+ + {{ courtRoom }} {{ sitting.courtRoomNumber }}: {{ sitting.judgeName }} + +

+

{{ sittingAt }} {{ sitting.sittingAt }}

+
+
+
+ + + + {% for header in tableHeaders %} + + {% endfor %} + + + + {% for row in sitting.hearings %} + + + + + + + + + {% endfor %} + +
{{ header }}
{{ row.caseNumber }}{{ row.defendantName }}{{ row.hearingType }}{{ row.representativeName }}{{ row.prosecutingAuthority }}{{ row.listNote }}
+
+
+
+ {% endfor %} +
+ {% endfor %} +

{{ dataSource }}: {{ provenance | convertDataSourceName(lng) }}

+ {{ super() }} +
+
+{% endblock %} + + diff --git a/src/test/a11y/tests/style-guide/crown-firm-pdda-list.test.ts b/src/test/a11y/tests/style-guide/crown-firm-pdda-list.test.ts new file mode 100644 index 000000000..eefff430a --- /dev/null +++ b/src/test/a11y/tests/style-guide/crown-firm-pdda-list.test.ts @@ -0,0 +1,20 @@ +import sinon from 'sinon'; +import { PublicationService } from '../../../../main/service/PublicationService'; +import { LocationService } from '../../../../main/service/LocationService'; +import { testAccessibility } from '../../common/pa11yHelper'; +import { testArtefactJsonData, testArtefactMetadata, testLocationData } from '../../common/testData'; + +const url = '/crown-firm-pdda-list?artefactId=xyz'; + +const jsonData = testArtefactJsonData('crownFirmPddaList.json'); +const metadata = testArtefactMetadata()[0]; +metadata.listType = 'CROWN_FIRM_PDDA_LIST'; +const locationData = testLocationData(); + +sinon.stub(LocationService.prototype, 'getLocationById').resolves(locationData); +sinon.stub(PublicationService.prototype, 'getIndividualPublicationJson').resolves(jsonData); +sinon.stub(PublicationService.prototype, 'getIndividualPublicationMetadata').returns(metadata); + +describe('Accessibility - Crown Firm PDDA List Page', () => { + testAccessibility(url); +}); diff --git a/src/test/routes/style-guide/crown-firm-pdda-list.test.ts b/src/test/routes/style-guide/crown-firm-pdda-list.test.ts new file mode 100644 index 000000000..6f2fe561e --- /dev/null +++ b/src/test/routes/style-guide/crown-firm-pdda-list.test.ts @@ -0,0 +1,33 @@ +import { expect } from 'chai'; +import request from 'supertest'; +import sinon from 'sinon'; + +import { app } from '../../../main/app'; +import { PublicationService } from '../../../main/service/PublicationService'; +import { LocationService } from '../../../main/service/LocationService'; +import fs from 'fs'; +import path from 'path'; +import { describe } from '@jest/globals'; + +const rawListData = fs.readFileSync(path.resolve(__dirname, '../../unit/mocks/crownFirmPddaList.json'), 'utf-8'); +const listData = JSON.parse(rawListData); + +const rawMetadata = fs.readFileSync(path.resolve(__dirname, '../../unit/mocks/returnedArtefacts.json'), 'utf-8'); +const metadata = JSON.parse(rawMetadata)[0]; +metadata.listType = 'CROWN_FIRM_PDDA_LIST'; + +sinon.stub(LocationService.prototype, 'getLocationById').resolves({ name: 'courtName' }); +sinon.stub(PublicationService.prototype, 'getIndividualPublicationJson').resolves(listData); +sinon.stub(PublicationService.prototype, 'getIndividualPublicationMetadata').returns(metadata); + +describe('Crown Firm PDDA List Page', () => { + describe('on GET', () => { + test('should return Crown Firm PDDA List page', async () => { + app.request['user'] = { userId: '2' }; + await request(app) + .get('/crown-firm-pdda-list?artefactId=abc') + .expect(res => expect(res.status).to.equal(200)) + .expect(res => expect(res.text).to.contain('Crown Firm List')); + }); + }); +}); diff --git a/src/test/unit/controllers/style-guide/CrownFirmPddaListController.test.ts b/src/test/unit/controllers/style-guide/CrownFirmPddaListController.test.ts new file mode 100644 index 000000000..feae6c07d --- /dev/null +++ b/src/test/unit/controllers/style-guide/CrownFirmPddaListController.test.ts @@ -0,0 +1,139 @@ +import sinon from 'sinon'; +import { Response } from 'express'; +import fs from 'fs'; +import path from 'path'; +import { PublicationService } from '../../../../main/service/PublicationService'; +import { mockRequest } from '../../mocks/mockRequest'; +import { LocationService } from '../../../../main/service/LocationService'; +import { describe } from '@jest/globals'; +import { CrownFirmPddaListService } from '../../../../main/service/listManipulation/CrownFirmPddaListService'; +import CrownFirmPddaListController from '../../../../main/controllers/style-guide/CrownFirmPddaListController'; +import { HttpStatusCode } from 'axios'; + +const url = '/crown-firm-pdda-list'; +const artefactId = 'abc'; +const artefactIdListNotFound = 'def'; +const artefactIdListInvalidListType = 'ghi'; + +const rawListData = fs.readFileSync(path.resolve(__dirname, '../../mocks/crownFirmPddaList.json'), 'utf-8'); +const listData = JSON.parse(rawListData); + +const rawMetadata = fs.readFileSync(path.resolve(__dirname, '../../mocks/returnedArtefacts.json'), 'utf-8'); +const metadata = JSON.parse(rawMetadata)[0]; +metadata.listType = 'CROWN_FIRM_PDDA_LIST'; +const metadataListNotFound = JSON.parse(rawMetadata)[0]; + +const rawCourtData = fs.readFileSync(path.resolve(__dirname, '../../mocks/courtAndHearings.json'), 'utf-8'); +const courtData = JSON.parse(rawCourtData); + +sinon.stub(LocationService.prototype, 'getLocationById').resolves(courtData[0]); +sinon.stub(CrownFirmPddaListService.prototype, 'processPayload').returns(listData); + +const jsonStub = sinon.stub(PublicationService.prototype, 'getIndividualPublicationJson'); +const metadataStub = sinon.stub(PublicationService.prototype, 'getIndividualPublicationMetadata'); + +jsonStub.withArgs(artefactId).resolves(listData); +jsonStub.withArgs(artefactId, undefined).resolves(undefined); +jsonStub.withArgs(artefactIdListNotFound).resolves(HttpStatusCode.NotFound); + +metadataStub.withArgs(artefactId).resolves(metadata); +metadataStub.withArgs(artefactIdListInvalidListType).resolves(metadataListNotFound); + +const i18n = { + listType: { value: '123' }, + 'list-template': {}, + 'crown-firm-pdda-list': { + title: 'Crown Firm List', + }, +}; + +const crownFirmPddaListController = new CrownFirmPddaListController(); + +describe('Crown Firm PDDA List Controller', () => { + const response = { + render: () => { + return ''; + }, + } as unknown as Response; + + const request = mockRequest(i18n); + const listPath = 'style-guide/crown-firm-pdda-list'; + + request.path = url; + + it('should render the Crown Firm PDDA List page', async () => { + request.query = { artefactId: artefactId }; + request.user = { userId: '1' }; + + const responseMock = sinon.mock(response); + + const expectedData = { + ...i18n['crown-firm-pdda-list'], + ...i18n['list-template'], + listData: listData, + locationName: "Abergavenny Magistrates' Court", + provenance: 'prov1', + publishedDate: '09 September 2025', + publishedTime: '11am', + startDate: '10 September 2025', + endDate: '11 September 2025', + version: '1.0', + venueAddress: ['1 Main Road', 'London', 'A1 1AA'], + }; + + responseMock.expects('render').once().withArgs(listPath, expectedData); + + await crownFirmPddaListController.get(request, response); + return responseMock.verify(); + }); + + it('should render error page if query param is empty', async () => { + request.query = {}; + request.user = { userId: '1' }; + const responseMock = sinon.mock(response); + + responseMock.expects('render').once().withArgs('error', request.i18n.getDataByLanguage(request.lng).error); + + await crownFirmPddaListController.get(request, response); + return responseMock.verify(); + }); + + it('should render list not found page if response is 404', async () => { + request.user = { userId: '1' }; + request.query = { artefactId: artefactIdListNotFound }; + const responseMock = sinon.mock(response); + + responseMock + .expects('render') + .once() + .withArgs('list-not-found', request.i18n.getDataByLanguage(request.lng)['list-not-found']); + + await crownFirmPddaListController.get(request, response); + return responseMock.verify(); + }); + + it('should render error page if list is not allowed to view by the user', async () => { + request.query = { artefactId: artefactId }; + request.user = {}; + const responseMock = sinon.mock(response); + + responseMock.expects('render').once().withArgs('error', request.i18n.getDataByLanguage(request.lng).error); + + await crownFirmPddaListController.get(request, response); + return responseMock.verify(); + }); + + it('should render list not found page if list type not valid', async () => { + request.query = { artefactId: artefactIdListInvalidListType }; + request.user = { userId: '1' }; + const responseMock = sinon.mock(response); + + responseMock + .expects('render') + .once() + .withArgs('list-not-found', request.i18n.getDataByLanguage(request.lng)['list-not-found']); + + await crownFirmPddaListController.get(request, response); + return responseMock.verify(); + }); +}); diff --git a/src/test/unit/mocks/crownFirmPddaList.json b/src/test/unit/mocks/crownFirmPddaList.json new file mode 100644 index 000000000..a28e3841b --- /dev/null +++ b/src/test/unit/mocks/crownFirmPddaList.json @@ -0,0 +1,429 @@ +{ + "FirmList": { + "DocumentID": { + "DocumentName": "TestDocumentName", + "UniqueID": "TestUniqueID", + "DocumentType": "TestDocumentType", + "TimeStamp": "2025-09-09T10:00:00Z", + "Version": "1.0", + "SecurityClassification": "TestSecurity" + }, + "ListHeader": { + "StartDate": "2025-09-10", + "EndDate": "2025-09-11", + "Version": "1.0", + "PublishedTime": "2025-09-09T10:00:00Z" + }, + "CrownCourt": { + "CourtHouseType": "Crown Court", + "CourtHouseCode": "1234", + "CourtHouseName": "TestCourtHouseName", + "CourtHouseAddress": { + "Line": [ + "1 Main Road", + "London" + ], + "Postcode": "A1 1AA" + }, + "CourtHouseTelephone": "02071234567" + }, + "CourtLists": [ + { + "SittingDate": "2025-09-10", + "CourtHouse": { + "CourtHouseType": "Crown Court", + "CourtHouseCode": "1234", + "CourtHouseShortName": "TestShortName", + "CourtHouseName": "TestCourtHouseName", + "CourtHouseAddress": { + "Line": [ + "1 Main Road", + "London" + ], + "Postcode": "A1 1AA" + }, + "CourtHouseTelephone": "02071234568" + }, + "Sittings": [ + { + "CourtRoomNumber": 1, + "SittingSequenceNo": "TestSeqNo", + "SittingAt": "10:00:00", + "SittingPriority": "T", + "SittingNote": "TestSittingNote", + "Judiciary": { + "Judge": { + "CitizenNameTitle": "Mr", + "CitizenNameForename": "TestJudgeForename", + "CitizenNameSurname": "TestJudgeSurname", + "CitizenNameSuffix": "Jr", + "CitizenNameRequestedName": "TestJudgeRequested" + }, + "Justice": [ + { + "CitizenNameTitle": "Ms", + "CitizenNameForename": "TestJusticeForename", + "CitizenNameSurname": "TestJusticeSurname", + "CitizenNameSuffix": "Sr" + } + ] + }, + "Hearings": [ + { + "HearingSequenceNumber": 1, + "HearingDetails": { + "HearingDescription": "TestHearingDescription", + "HearingDate": "2025-09-10", + "HearingEndDate": "2025-09-10", + "HearingType": "ABC" + }, + "TimeMarkingNote": "TestTimeMarkingNote", + "CaseNumber": "T00112233", + "CaseNumberCaTH": "T00112233", + "Prosecution": { + "Advocate": { + "PersonalDetails": { + "Name": { + "CitizenNameTitle": "Mr", + "CitizenNameForename": "TestAdvocateForename", + "CitizenNameSurname": "TestAdvocateSurname", + "CitizenNameRequestedName": "TestAdvocateRequestedName" + }, + "MaskedName": "TestAdvocateMasked", + "IsMasked": "no" + } + }, + "ProsecutingReference": "TestProsecutingRef", + "ProsecutingOrganisation": { + "OrganisationName": "TestProsecutingOrg" + }, + "ProsecutingAuthority": "Crown Prosecution Service" + }, + "CommittingCourt": { + "CourtHouseType": "Crown Court", + "CourtHouseCode": "5678", + "CourtHouseShortName": "TestOriginShortName", + "CourtHouseName": "TestOriginName" + }, + "ListNote": "TestListNote", + "Defendants": [ + { + "PersonalDetails": { + "Name": { + "CitizenNameTitle": "Mr", + "CitizenNameForename": "TestDefendantForename", + "CitizenNameSurname": "TestDefendantSurname", + "CitizenNameSuffix": "TestDefendantSuffix", + "CitizenNameRequestedName": "TestDefendantRequestedName" + }, + "MaskedName": "TestMaskedName", + "IsMasked": "yes", + "DateOfBirth": { + "BirthDate": "2000-01-01", + "VerifiedBy": "not verified" + }, + "Age": 24, + "Sex": "male", + "Address": { + "Line": ["TestDefendantAddress"], + "Postcode": "TestDefendantPostcode" + }, + "Nationality": "TestNationality" + }, + "URN": "TestURN", + "Counsel": [ + { + "Solicitor": [ + { + "Party": { + "Person": { + "PersonalDetails": { + "Name": { + "CitizenNameTitle": "Mr", + "CitizenNameForename": "TestForename", + "CitizenNameSurname": "TestSurname", + "CitizenNameSuffix": "TestSuffix", + "CitizenNameRequestedName": "TestSolicitorRequestedName" + }, + "MaskedName": "TestSolicitorMasked", + "IsMasked": "no", + "DateOfBirth": { + "BirthDate": "1980-01-01", + "VerifiedBy": "not verified" + }, + "Sex": "female", + "Address": { + "Line": [ + "TestSolicitorAddress" + ], + "Postcode": "TestSolicitorPostcode" + } + } + } + } + } + ] + } + ], + "Charges": [ + { + "OffenceStatement": "TestOffenceStatement", + "IndictmentCountNumber": 1, + "CJSoffenceCode": "TestCJSCode" + } + ] + }, + { + "PersonalDetails": { + "Name": { + "CitizenNameTitle": "Mr", + "CitizenNameForename": "TestDefendantForename", + "CitizenNameSurname": "TestDefendantSurname", + "CitizenNameSuffix": "TestDefendantSuffix" + }, + "IsMasked": "no" + } + } + ], + "Respondent": ["TestRespondent"] + } + ] + } + ] + }, + { + "SittingDate": "2025-09-11", + "CourtHouse": { + "CourtHouseType": "Crown Court", + "CourtHouseCode": "1234", + "CourtHouseShortName": "TestShortName", + "CourtHouseName": "TestCourtHouseName", + "CourtHouseAddress": { + "Line": [ + "1 High Road", + "London" + ], + "Postcode": "B1 1BB" + }, + "CourtHouseTelephone": "02071234568" + }, + "Sittings": [ + { + "CourtRoomNumber": 5, + "SittingSequenceNo": "TestSeqNo", + "SittingAt": "14:00:00", + "SittingPriority": "T", + "SittingNote": "TestSittingNote", + "Judiciary": { + "Judge": { + "CitizenNameTitle": "Mr", + "CitizenNameForename": "TestJudgeForename", + "CitizenNameSurname": "TestJudgeSurname", + "CitizenNameSuffix": "Jr", + "CitizenNameRequestedName": "TestJudgeRequested" + } + }, + "Hearings": [ + { + "HearingSequenceNumber": 1, + "HearingDetails": { + "HearingDescription": "TestHearingDescription2", + "HearingDate": "2025-09-10", + "HearingEndDate": "2025-09-11", + "HearingType": "ABC" + }, + "TimeMarkingNote": "TestTimeMarkingNote", + "CaseNumber": "T00112234", + "CaseNumberCaTH": "T00112234", + "Prosecution": { + "Advocate": { + "PersonalDetails": { + "Name": { + "CitizenNameTitle": "Mr", + "CitizenNameForename": "TestAdvocateForename", + "CitizenNameSurname": "TestAdvocateSurname", + "CitizenNameRequestedName": "TestAdvocateRequestedName" + }, + "MaskedName": "TestAdvocateMasked", + "IsMasked": "no" + } + }, + "ProsecutingReference": "TestProsecutingRef", + "ProsecutingOrganisation": { + "OrganisationName": "TestProsecutingOrg" + }, + "ProsecutingAuthority": "Inland Revenue" + }, + "CommittingCourt": { + "CourtHouseType": "Crown Court", + "CourtHouseCode": "5678", + "CourtHouseShortName": "TestOriginShortName", + "CourtHouseName": "TestOriginName" + }, + "ListNote": "TestListNote2", + "Defendants": [ + { + "PersonalDetails": { + "Name": { + "CitizenNameTitle": "Mr", + "CitizenNameForename": "TestDefendantForename", + "CitizenNameSurname": "TestDefendantSurname", + "CitizenNameSuffix": "TestDefendantSuffix", + "CitizenNameRequestedName": "TestDefendantRequestedName" + }, + "MaskedName": "TestMaskedName", + "IsMasked": "no", + "DateOfBirth": { + "BirthDate": "2000-01-01", + "VerifiedBy": "not verified" + }, + "Age": 24, + "Sex": "male", + "Address": { + "Line": ["TestDefendantAddress"], + "Postcode": "TestDefendantPostcode" + }, + "Nationality": "TestNationality" + }, + "URN": "TestURN", + "Counsel": [ + { + "Solicitor": [ + { + "Party": { + "Organisation": { + "OrganisationName": "TestSolicitorOrg" + } + } + } + ] + } + ], + "Charges": [ + { + "OffenceStatement": "TestOffenceStatement", + "IndictmentCountNumber": 1, + "CJSoffenceCode": "TestCJSCode" + } + ] + } + ], + "Respondent": ["TestRespondent"] + } + ] + }, + { + "CourtRoomNumber": 6, + "SittingSequenceNo": "TestSeqNo", + "SittingAt": "15:00:00", + "SittingPriority": "T", + "SittingNote": "TestSittingNote", + "Judiciary": { + "Judge": { + "CitizenNameTitle": "Mr", + "CitizenNameForename": "TestJudgeForename", + "CitizenNameSurname": "TestJudgeSurname" + } + }, + "Hearings": [ + { + "HearingSequenceNumber": 1, + "HearingDetails": { + "HearingDescription": "TestHearingDescription3", + "HearingDate": "2025-09-10", + "HearingEndDate": "2025-09-11", + "HearingType": "ABC" + }, + "TimeMarkingNote": "TestTimeMarkingNote", + "CaseNumber": "T00112235", + "CaseNumberCaTH": "T00112235", + "Prosecution": { + "Advocate": { + "PersonalDetails": { + "Name": { + "CitizenNameTitle": "Mr", + "CitizenNameForename": "TestAdvocateForename", + "CitizenNameSurname": "TestAdvocateSurname", + "CitizenNameRequestedName": "TestAdvocateRequestedName" + }, + "MaskedName": "TestAdvocateMasked", + "IsMasked": "no" + } + }, + "ProsecutingReference": "TestProsecutingRef", + "ProsecutingOrganisation": { + "OrganisationName": "TestProsecutingOrg" + }, + "ProsecutingAuthority": "Other Prosecutor" + }, + "CommittingCourt": { + "CourtHouseType": "Crown Court", + "CourtHouseCode": "5678", + "CourtHouseShortName": "TestOriginShortName", + "CourtHouseName": "TestOriginName" + }, + "ListNote": "TestListNote3" + } + ] + } + ] + } + ], + "ReserveList": [ + { + "HearingDetails": { + "HearingDescription": "TestReserveHearing", + "HearingDate": "2025-09-11", + "HearingEndDate": "2025-09-11", + "HearingType": "DEF" + }, + "CaseNumber": "T00112244", + "CaseNumberCaTH": "T00112244", + "Prosecution": { + "Advocate": { + "PersonalDetails": { + "Name": { + "CitizenNameTitle": "Mr", + "CitizenNameForename": "TestReserveAdvocateForename", + "CitizenNameSurname": "TestReserveAdvocateSurname", + "CitizenNameSuffix": "TestReserveAdvocateSuffix", + "CitizenNameRequestedName": "TestReserveAdvocateRequestedName" + }, + "MaskedName": "TestReserveAdvocateMasked", + "IsMasked": "yes" + } + }, + "ProsecutingReference": "TestReserveProsecutingRef", + "ProsecutingOrganisation": { + "OrganisationName": "TestReserveProsecutingOrg" + }, + "ProsecutingAuthority": "Other Prosecutor" + }, + "CommittingCourt": { + "CourtHouseType": "Magistrates Court", + "CourtHouseCode": "4321", + "CourtHouseShortName": "TestReserveOriginShortName", + "CourtHouseName": "TestReserveOriginName" + }, + "ListNote": "TestReserveListNote", + "Defendants": [ + { + "PersonalDetails": { + "Name": { + "CitizenNameTitle": "Mr", + "CitizenNameForename": "TestReserveForename", + "CitizenNameSurname": "TestReserveSurname", + "CitizenNameSuffix": "TestReserveSuffix", + "CitizenNameRequestedName": "TestReserveRequestedName" + }, + "MaskedName": "TestReserveMasked", + "IsMasked": "yes" + }, + "URN": "TestReserveURN" + } + ], + "Respondent": ["TestReserveRespondent"] + } + ] + } +} diff --git a/src/test/unit/service/ManualUploadService.test.ts b/src/test/unit/service/ManualUploadService.test.ts index 2fa2bb6ca..4e6c33401 100644 --- a/src/test/unit/service/ManualUploadService.test.ts +++ b/src/test/unit/service/ManualUploadService.test.ts @@ -149,7 +149,7 @@ describe('Manual upload service', () => { it('should build form data list subtypes when not non-strategic', async () => { const data = await manualUploadService.buildFormData(englishLanguage, false, undefined); - expect(data['listSubtypes'].length).to.equal(26); + expect(data['listSubtypes'].length).to.equal(27); expect(data['listSubtypes'][0]).to.deep.equal({ text: '', value: 'EMPTY', diff --git a/src/test/unit/service/PublicationService.test.ts b/src/test/unit/service/PublicationService.test.ts index 8e0d1d964..05cf3a703 100644 --- a/src/test/unit/service/PublicationService.test.ts +++ b/src/test/unit/service/PublicationService.test.ts @@ -176,7 +176,7 @@ describe('Publication service', () => { it('should return list types', () => { const listTypes = publicationService.getListTypes(); - expect(listTypes.size).to.equal(89); + expect(listTypes.size).to.equal(90); const sjpResult = listTypes.get('SJP_PUBLIC_LIST'); expect(sjpResult['friendlyName']).to.equal('Single Justice Procedure Public List (Full List)'); diff --git a/src/test/unit/service/SubscriptionService.test.ts b/src/test/unit/service/SubscriptionService.test.ts index a5d249fa3..6c9fa7d8d 100644 --- a/src/test/unit/service/SubscriptionService.test.ts +++ b/src/test/unit/service/SubscriptionService.test.ts @@ -1007,6 +1007,7 @@ describe('generateListTypesForCourts', () => { 'COP_DAILY_CAUSE_LIST', 'CROWN_DAILY_LIST', 'CROWN_FIRM_LIST', + 'CROWN_FIRM_PDDA_LIST', 'CROWN_WARNED_LIST', ]); @@ -1052,6 +1053,7 @@ describe('generateListTypesForCourts', () => { 'COP_DAILY_CAUSE_LIST', 'CROWN_DAILY_LIST', 'CROWN_FIRM_LIST', + 'CROWN_FIRM_PDDA_LIST', 'CROWN_WARNED_LIST', ]); @@ -1199,6 +1201,7 @@ describe('generateListTypeForCourts', () => { 'COP_DAILY_CAUSE_LIST', 'CROWN_DAILY_LIST', 'CROWN_FIRM_LIST', + 'CROWN_FIRM_PDDA_LIST', 'CROWN_WARNED_LIST', ]); @@ -1234,6 +1237,7 @@ describe('generateListTypeForCourts', () => { 'COP_DAILY_CAUSE_LIST', 'CROWN_DAILY_LIST', 'CROWN_FIRM_LIST', + 'CROWN_FIRM_PDDA_LIST', 'CROWN_WARNED_LIST', ]); diff --git a/src/test/unit/service/listManipulation/CrownFirmPddaListService.test.ts b/src/test/unit/service/listManipulation/CrownFirmPddaListService.test.ts new file mode 100644 index 000000000..2bfe6c691 --- /dev/null +++ b/src/test/unit/service/listManipulation/CrownFirmPddaListService.test.ts @@ -0,0 +1,70 @@ +import { expect } from 'chai'; +import fs from 'fs'; +import path from 'path'; +import { CrownFirmPddaListService } from '../../../../main/service/listManipulation/CrownFirmPddaListService'; + +const crownFirmPddaListService = new CrownFirmPddaListService(); +const rawListData = fs.readFileSync(path.resolve(__dirname, '../../mocks/crownFirmPddaList.json'), 'utf-8'); + +const lng = 'en'; + +describe('Crown Firm PDDA List service', () => { + describe('Process payload', () => { + it('should have correct result count', async () => { + const results = await crownFirmPddaListService.processPayload(JSON.parse(rawListData), lng); + expect(results).to.have.length(2); + expect(results[0].sittings).to.have.length(1); + expect(results[1].sittings).to.have.length(2); + }); + + it('should format courthouse info', async () => { + const results = await crownFirmPddaListService.processPayload(JSON.parse(rawListData), lng); + expect(results[0].sittingDate).to.equal('Wednesday 10 September 2025'); + expect(results[0].courtName).to.equal('TestCourtHouseName'); + expect(results[0].courtAddress).to.have.length(3); + expect(results[0].courtAddress[0]).to.equal('1 Main Road'); + expect(results[0].courtAddress[1]).to.equal('London'); + expect(results[0].courtAddress[2]).to.equal('A1 1AA'); + expect(results[0].courtPhone).to.equal('02071234568'); + }); + + it('should format sitting info', async () => { + const results = await crownFirmPddaListService.processPayload(JSON.parse(rawListData), lng); + const sitting = results[0].sittings[0]; + expect(sitting.courtRoomNumber).to.equal(1); + expect(sitting.sittingAt).to.equal('10am'); + expect(sitting.judgeName).to.equal('TestJudgeRequested, Ms TestJusticeForename TestJusticeSurname Sr'); + expect(sitting.hearings).to.have.length(1); + }); + + it('should format hearing info', async () => { + const results = await crownFirmPddaListService.processPayload(JSON.parse(rawListData), lng); + const hearing = results[0].sittings[0].hearings[0]; + expect(hearing.caseNumber).to.equal('T00112233'); + expect(hearing.defendantName).to.equal( + '' + 'TestDefendantRequestedName, Mr TestDefendantForename TestDefendantSurname TestDefendantSuffix' + ); + expect(hearing.hearingType).to.equal('TestHearingDescription'); + expect(hearing.representativeName).to.equal('TestSolicitorRequestedName'); + expect(hearing.prosecutingAuthority).to.equal('Crown Prosecution Service'); + expect(hearing.listNote).to.equal('TestListNote'); + }); + }); + + it('should format address', async () => { + const input = { + Line: ['1 Main Road', 'London'], + Postcode: 'A1 1AA', + }; + + const result = crownFirmPddaListService.formatAddress(input); + expect(result).to.have.length(3); + expect(result[0]).to.equal('1 Main Road'); + expect(result[1]).to.equal('London'); + expect(result[2]).to.equal('A1 1AA'); + }); + + it('should convert to ISO date', async () => { + expect(crownFirmPddaListService.toIsoDate('2025-01-10')).to.equal('2025-01-10T00:00:00.000Z'); + }); +}); diff --git a/src/test/unit/views/style-guide/crown-firm-pdda-list.test.ts b/src/test/unit/views/style-guide/crown-firm-pdda-list.test.ts new file mode 100644 index 000000000..1d42a7ba3 --- /dev/null +++ b/src/test/unit/views/style-guide/crown-firm-pdda-list.test.ts @@ -0,0 +1,194 @@ +import fs from 'fs'; +import path from 'path'; +import sinon from 'sinon'; +import { PublicationService } from '../../../../main/service/PublicationService'; +import { LocationService } from '../../../../main/service/LocationService'; +import { describe } from '@jest/globals'; +import request from 'supertest'; +import { app } from '../../../../main/app'; +import { expect } from 'chai'; + +const urlFirmPddaList = '/crown-firm-pdda-list'; +const artefactIdFirmPddaList = 'xyz'; + +const bodyClass = 'govuk-body'; +const tableHeaderClass = 'govuk-table__header'; +const tableCellClass = 'govuk-table__cell'; + +const rawData = fs.readFileSync(path.resolve(__dirname, '../../mocks/crownFirmPddaList.json'), 'utf-8'); +const listData = JSON.parse(rawData); +const rawMetadata = fs.readFileSync(path.resolve(__dirname, '../../mocks/returnedArtefacts.json'), 'utf-8'); + +const metadataFirmPddaList = JSON.parse(rawMetadata)[0]; +metadataFirmPddaList.listType = 'CROWN_FIRM_PDDA_LIST'; + +const rawCourtData = fs.readFileSync(path.resolve(__dirname, '../../mocks/courtAndHearings.json'), 'utf-8'); +const courtData = JSON.parse(rawCourtData); + +const jsonStub = sinon.stub(PublicationService.prototype, 'getIndividualPublicationJson'); +const metadataStub = sinon.stub(PublicationService.prototype, 'getIndividualPublicationMetadata'); +sinon.stub(LocationService.prototype, 'getLocationById').resolves(courtData[0]); + +jsonStub.withArgs(artefactIdFirmPddaList).resolves(listData); +metadataStub.withArgs(artefactIdFirmPddaList).resolves(metadataFirmPddaList); + +let htmlRes: Document; + +describe('Crown Firm PDDA List page', () => { + const pageUrl = urlFirmPddaList + '?artefactId=' + artefactIdFirmPddaList; + + beforeAll(async () => { + await request(app) + .get(pageUrl) + .then(res => { + htmlRes = new DOMParser().parseFromString(res.text, 'text/html'); + htmlRes.getElementsByTagName('div')[0].remove(); + }); + }); + + it('should have correct page title', () => { + const pageTitle = htmlRes.title; + expect(pageTitle).equals('Crown Firm List', 'Page title does not match'); + }); + + it('should display page heading', () => { + const heading = htmlRes.getElementsByClassName('govuk-heading-l'); + expect(heading[0].innerHTML).contains( + "Crown Firm List for Abergavenny Magistrates' Court", + 'Page heading does not match' + ); + }); + + it('should display list date', () => { + const body = htmlRes.getElementsByClassName(bodyClass); + expect(body[0].innerHTML).equals('List for 10 September 2025 to 11 September 2025'); + }); + + it('should display publication date', () => { + const body = htmlRes.getElementsByClassName(bodyClass); + expect(body[1].innerHTML).contains('Last updated 09 September 2025 at 11am', 'Publication date does not match'); + }); + + it('should display version', () => { + const body = htmlRes.getElementsByClassName(bodyClass); + expect(body[2].innerHTML).contains('Version 1.0', 'Version does not match'); + }); + + it('should display venue address', () => { + const body = htmlRes.getElementsByClassName(bodyClass); + expect(body[3].innerHTML).contains('1 Main Road', 'Address line 1 does not match'); + expect(body[3].innerHTML).contains('London', 'Address line 2 does not match'); + expect(body[3].innerHTML).contains('A1 1AA', 'Address line 3 does not match'); + }); + + it('should display reporting restriction heading', () => { + const restriction = htmlRes.getElementsByClassName('govuk-grid restriction-list-section'); + expect(restriction[0].innerHTML).contains( + 'Restrictions on publishing or writing about these cases', + 'Reporting restriction heading does not match' + ); + }); + + it('should display the search input box', () => { + const searchInput = htmlRes.getElementsByClassName('govuk-form-group'); + expect(searchInput[0].innerHTML).contains('Search Cases', 'Search input box not found'); + }); + + it('should display sitting date heading', () => { + const heading = htmlRes.getElementsByClassName('govuk-heading-l'); + expect(heading[1].innerHTML).contains('Wednesday 10 September 2025', 'Sitting date heading does not match'); + }); + + it('should display court house name', () => { + const body = htmlRes.getElementsByClassName(bodyClass); + expect(body[9].innerHTML).contains('TestCourtHouseName', 'Court house name does not match'); + }); + + it('should display court house address', () => { + const body = htmlRes.getElementsByClassName(bodyClass); + expect(body[10].innerHTML).contains('1 Main Road', 'Court house address line 1 does not match'); + expect(body[11].innerHTML).contains('London', 'Court house address line 2 does not match'); + expect(body[12].innerHTML).contains('A1 1AA', 'Court house address line 3 does not match'); + }); + + it('should display court house telephone', () => { + const body = htmlRes.getElementsByClassName(bodyClass); + expect(body[13].innerHTML).contains('02071234568', 'Court house telephone does not match'); + }); + + it('should display court room and judge names section heading', () => { + const searchInput = htmlRes.getElementsByClassName('govuk-accordion__section-heading'); + expect(searchInput[0].innerHTML).contains( + 'Courtroom 1: TestJudgeRequested, Ms TestJusticeForename TestJusticeSurname Sr', + 'Court room and judge names section heading not found' + ); + }); + + it('should display sitting at time', () => { + const body = htmlRes.getElementsByClassName(bodyClass); + expect(body[14].innerHTML).contains('Sitting at 10am', 'Sitting at time does not match'); + }); + + it('should display Case Number table header', () => { + const cell = htmlRes.getElementsByClassName(tableHeaderClass); + expect(cell[0].innerHTML).contains('Case Number', 'Case number header does not match'); + }); + + it('should display Defendant Name(s) table header', () => { + const cell = htmlRes.getElementsByClassName(tableHeaderClass); + expect(cell[1].innerHTML).contains('Defendant Name(s)', 'Defendant name header does not match'); + }); + + it('should display Hearing Type table header', () => { + const cell = htmlRes.getElementsByClassName(tableHeaderClass); + expect(cell[2].innerHTML).contains('Hearing Type', 'Hearing type header does not match'); + }); + + it('should display Representative table header', () => { + const cell = htmlRes.getElementsByClassName(tableHeaderClass); + expect(cell[3].innerHTML).contains('Representative', 'Representative header does not match'); + }); + + it('should display Prosecuting Authority table header', () => { + const cell = htmlRes.getElementsByClassName(tableHeaderClass); + expect(cell[4].innerHTML).contains('Prosecuting Authority', 'Prosecuting authority header does not match'); + }); + + it('should display Listing Notes table header', () => { + const cell = htmlRes.getElementsByClassName(tableHeaderClass); + expect(cell[5].innerHTML).contains('Listing Notes', 'Listing notes header does not match'); + }); + + it('should display Case Number table v', () => { + const cell = htmlRes.getElementsByClassName(tableCellClass); + expect(cell[0].innerHTML).contains('T00112233', 'Case number cell does not match'); + }); + + it('should display Defendant Name(s) table cell', () => { + const cell = htmlRes.getElementsByClassName(tableCellClass); + expect(cell[1].innerHTML).contains( + 'TestDefendantRequestedName, Mr TestDefendantForename TestDefendantSurname TestDefendantSuffix', + 'Defendant name cell does not match' + ); + }); + + it('should display Hearing Type table cell', () => { + const cell = htmlRes.getElementsByClassName(tableCellClass); + expect(cell[2].innerHTML).contains('TestHearingDescription', 'Hearing type cell does not match'); + }); + + it('should display Representative table cell', () => { + const cell = htmlRes.getElementsByClassName(tableCellClass); + expect(cell[3].innerHTML).contains('TestSolicitorRequestedName', 'Representative cell does not match'); + }); + + it('should display Prosecuting Authority table cell', () => { + const cell = htmlRes.getElementsByClassName(tableCellClass); + expect(cell[4].innerHTML).contains('Crown Prosecution Service', 'Prosecuting authority cell does not match'); + }); + + it('should display Listing Notes table cell', () => { + const cell = htmlRes.getElementsByClassName(tableCellClass); + expect(cell[5].innerHTML).contains('TestListNote', 'Listing notes cell does not match'); + }); +});