diff --git a/e2e-tests/tests/care-standards-tribunal-upload.spec.ts b/e2e-tests/tests/care-standards-tribunal-upload.spec.ts index 4cd7508f3..cb66984db 100644 --- a/e2e-tests/tests/care-standards-tribunal-upload.spec.ts +++ b/e2e-tests/tests/care-standards-tribunal-upload.spec.ts @@ -1,7 +1,6 @@ import AxeBuilder from "@axe-core/playwright"; import type { Page } from "@playwright/test"; import { expect, test } from "@playwright/test"; -// @ts-expect-error - ExcelJS is a CommonJS module, TypeScript doesn't recognize default export but it works at runtime import ExcelJSPkg from "exceljs"; import { loginWithSSO } from "../utils/sso-helpers.js"; @@ -169,15 +168,15 @@ async function uploadCSTExcel(page: Page, excelBuffer: Buffer, expectSuccess = t // Select Care Standards Tribunal (listTypeId === 9) await page.selectOption('select[name="listType"]', "9"); - await page.fill('input[name="hearingStartDate-day"]', "01"); + await page.fill('input[name="hearingStartDate-day"]', "20"); await page.fill('input[name="hearingStartDate-month"]', "01"); await page.fill('input[name="hearingStartDate-year"]', "2026"); await page.selectOption('select[name="sensitivity"]', "PUBLIC"); await page.selectOption('select[name="language"]', "ENGLISH"); - await page.fill('input[name="displayFrom-day"]', "01"); + await page.fill('input[name="displayFrom-day"]', "15"); await page.fill('input[name="displayFrom-month"]', "01"); await page.fill('input[name="displayFrom-year"]', "2026"); - await page.fill('input[name="displayTo-day"]', "07"); + await page.fill('input[name="displayTo-day"]', "31"); await page.fill('input[name="displayTo-month"]', "01"); await page.fill('input[name="displayTo-year"]', "2026"); @@ -197,20 +196,25 @@ async function uploadCSTExcel(page: Page, excelBuffer: Buffer, expectSuccess = t } } -// Helper function to complete full CST upload flow -async function completeCSTUploadFlow(page: Page): Promise { +// Helper function to complete full CST upload flow and navigate to published list +async function completeCSTUploadFlowAndNavigate(page: Page) { const excelBuffer = await createValidCSTExcel(); await uploadCSTExcel(page, excelBuffer, true); - // Get artefactId from URL for later verification - const url = page.url(); - const match = url.match(/uploadId=([^&]+)/); - const uploadId = match ? match[1] : ""; - await page.getByRole("button", { name: "Confirm" }).click(); await page.waitForURL("/non-strategic-upload-success", { timeout: 10000 }); - return uploadId; + // Navigate to summary of publications to find and click the publication link + await page.goto("/summary-of-publications?locationId=9001"); + await page.waitForTimeout(1000); + + // Find the first (most recent) CST publication link + const publicationLinks = page.locator('.govuk-list a[href*="care-standards-tribunal-weekly-hearing-list?artefactId="]'); + await expect(publicationLinks.first()).toBeVisible(); + + // Click the publication link to navigate to the list page + await publicationLinks.first().click(); + await page.waitForLoadState("networkidle"); } test.describe("Care Standards Tribunal Excel Upload End-to-End Flow", () => { @@ -234,7 +238,7 @@ test.describe("Care Standards Tribunal Excel Upload End-to-End Flow", () => { const values = page.locator(".govuk-summary-list__value"); await expect(values.nth(1)).toContainText("cst-weekly-list.xlsx"); await expect(values.nth(2)).toContainText("Care Standards Tribunal Weekly Hearing List"); - await expect(values.nth(3)).toContainText("1 January 2026"); + await expect(values.nth(3)).toContainText("20 January 2026"); await expect(values.nth(4)).toContainText("Public"); await expect(values.nth(5)).toContainText("English"); @@ -250,18 +254,13 @@ test.describe("Care Standards Tribunal Excel Upload End-to-End Flow", () => { }); test("should display the published CST list with correct formatting", async ({ page }) => { - // Upload and publish the list - await completeCSTUploadFlow(page); - - // Navigate to the published list - // Note: In a real scenario, you'd navigate via search or direct URL - // For now, we'll construct the URL pattern - await page.goto("/care-standards-tribunal-weekly-hearing-list?artefactId=test"); - await page.waitForTimeout(1000); + // Upload and navigate to published list + await completeCSTUploadFlowAndNavigate(page); - // Verify page loads (may need adjustment based on actual implementation) + // Verify page loads const heading = page.locator("h1"); await expect(heading).toBeVisible(); + await expect(heading).toContainText("Care Standards Tribunal Weekly Hearing List"); }); }); @@ -323,7 +322,7 @@ test.describe("Care Standards Tribunal Excel Upload End-to-End Flow", () => { // Verify form data is preserved await expect(page.locator('select[name="listType"]')).toHaveValue("9"); - await expect(page.locator('input[name="hearingStartDate-day"]')).toHaveValue("01"); + await expect(page.locator('input[name="hearingStartDate-day"]')).toHaveValue("20"); await expect(page.locator('input[name="hearingStartDate-month"]')).toHaveValue("01"); await expect(page.locator('input[name="hearingStartDate-year"]')).toHaveValue("2026"); await expect(page.locator('select[name="sensitivity"]')).toHaveValue("PUBLIC"); @@ -333,108 +332,167 @@ test.describe("Care Standards Tribunal Excel Upload End-to-End Flow", () => { test.describe("CST List Display Page", () => { test("should display list with correct header information", async ({ page }) => { - // Note: This test requires the list to be published and accessible - // You may need to adjust based on your actual implementation - const excelBuffer = await createValidCSTExcel(); - await uploadCSTExcel(page, excelBuffer, true); - await page.getByRole("button", { name: "Confirm" }).click(); - await page.waitForURL("/non-strategic-upload-success", { timeout: 10000 }); + await completeCSTUploadFlowAndNavigate(page); + + // Verify page title + await expect(page.locator("h1")).toContainText("Care Standards Tribunal Weekly Hearing List"); + + // Verify "List for week commencing" date line + const weekCommencingPara = page.locator('p.govuk-body.govuk-\\!-font-weight-bold.govuk-\\!-margin-bottom-1'); + await expect(weekCommencingPara).toBeVisible(); + const weekCommencingText = await weekCommencingPara.textContent(); + expect(weekCommencingText).toContain("List for week commencing"); + expect(weekCommencingText).toMatch(/\d{1,2} \w+ \d{4}/); // Matches date format like "1 January 2026" + + // Verify "Last updated" date and time line + const bodyParagraphs = page.locator("p.govuk-body"); + let foundLastUpdated = false; + for (let i = 0; i < await bodyParagraphs.count(); i++) { + const text = await bodyParagraphs.nth(i).textContent(); + if (text?.includes("Last updated")) { + foundLastUpdated = true; + expect(text).toMatch(/Last updated \d{1,2} \w+ \d{4} at \d{1,2}(:\d{2})?(am|pm)/); + break; + } + } + expect(foundLastUpdated).toBeTruthy(); + }); - // In a real test, you would navigate to the published list URL - // For now, this is a placeholder showing the expected structure - // await page.goto(`/care-standards-tribunal-weekly-hearing-list?artefactId=${artefactId}`); + test("should display Important Information accordion expanded by default", async ({ page }) => { + await completeCSTUploadFlowAndNavigate(page); - // Verify header elements (when implementing, uncomment and adjust) - // await expect(page.locator("h1")).toContainText("Care Standards Tribunal Weekly Hearing List"); - // await expect(page.locator(".list-duration")).toContainText("List for week commencing"); - // await expect(page.locator(".last-updated")).toContainText("Last updated"); - }); + // Verify details element exists and is open by default + const details = page.locator("details.govuk-details"); + await expect(details).toBeVisible(); + + // Verify the details element has the "open" attribute + const isOpen = await details.getAttribute("open"); + expect(isOpen).not.toBeNull(); + + // Verify summary text is visible + const summary = details.locator(".govuk-details__summary-text"); + await expect(summary).toContainText("Important information"); + + // Verify content is visible without needing to click (because it's open by default) + const detailsText = details.locator(".govuk-details__text"); + await expect(detailsText).toBeVisible(); + + // Verify the content mentions the email address + const textContent = await detailsText.textContent(); + expect(textContent).toContain("cst@justice.gov.uk"); - test("should display Important Information accordion with correct content", async ({ page }) => { - // Placeholder - implement once list display is available - // const accordion = page.locator('[data-module="govuk-accordion"]'); - // await expect(accordion).toBeVisible(); - // await accordion.click(); - // await expect(page.locator(".accordion-content")).toContainText("cst@justice.gov.uk"); - // await expect(page.getByRole("link", { name: /observe a court or tribunal/i })).toBeVisible(); + // Verify the link to observe hearings is present + const observeLink = details.getByRole("link", { name: /observe a court or tribunal/i }); + await expect(observeLink).toBeVisible(); + expect(await observeLink.getAttribute("href")).toContain("gov.uk/guidance/observe"); }); test("should display table with all hearing data and correct columns", async ({ page }) => { - // Placeholder - implement once list display is available - // const table = page.locator(".govuk-table"); - // await expect(table).toBeVisible(); - // - // // Verify column headers - // await expect(page.locator("th").nth(0)).toContainText("Date"); - // await expect(page.locator("th").nth(1)).toContainText("Case name"); - // await expect(page.locator("th").nth(2)).toContainText("Hearing length"); - // await expect(page.locator("th").nth(3)).toContainText("Hearing type"); - // await expect(page.locator("th").nth(4)).toContainText("Venue"); - // await expect(page.locator("th").nth(5)).toContainText("Additional information"); - // - // // Verify data rows - // const rows = page.locator("tbody tr"); - // await expect(rows).toHaveCount(3); // Our test data has 3 hearings + await completeCSTUploadFlowAndNavigate(page); + + const table = page.locator(".govuk-table"); + await expect(table).toBeVisible(); + + // Verify column headers + const headers = table.locator("thead th"); + await expect(headers.nth(0)).toContainText("Date"); + await expect(headers.nth(1)).toContainText("Case name"); + await expect(headers.nth(2)).toContainText("Hearing length"); + await expect(headers.nth(3)).toContainText("Hearing type"); + await expect(headers.nth(4)).toContainText("Venue"); + await expect(headers.nth(5)).toContainText("Additional information"); + + // Verify data rows exist (our test data has 3 hearings) + const rows = table.locator("tbody tr"); + await expect(rows).toHaveCount(3); + + // Verify first row contains expected data + const firstRow = rows.nth(0); + await expect(firstRow.locator("td").nth(0)).toContainText("1 January 2026"); + await expect(firstRow.locator("td").nth(1)).toContainText("Test Case A vs B"); + await expect(firstRow.locator("td").nth(2)).toContainText("1 hour"); + await expect(firstRow.locator("td").nth(3)).toContainText("Substantive hearing"); + await expect(firstRow.locator("td").nth(4)).toContainText("Care Standards Tribunal"); + await expect(firstRow.locator("td").nth(5)).toContainText("Remote hearing via video"); }); - test("should display data source as Manual upload (not Care Standards Tribunal)", async ({ page }) => { - // Placeholder - implement once list display is available - // const dataSource = page.locator(".data-source"); - // await expect(dataSource).toContainText("Data source: Manual upload"); + test("should display data source as Manual Upload in English", async ({ page }) => { + await completeCSTUploadFlowAndNavigate(page); + + // Find the data source text + const dataSourceParagraph = page.locator(".govuk-body-s").filter({ hasText: "Data source" }); + await expect(dataSourceParagraph).toBeVisible(); + + const dataSourceText = await dataSourceParagraph.textContent(); + expect(dataSourceText).toContain("Data source:"); + expect(dataSourceText).toContain("Manual Upload"); }); - test("should have working Back to top link", async ({ page }) => { - // Placeholder - implement once list display is available - // const backToTop = page.getByRole("link", { name: /back to top/i }); - // await expect(backToTop).toBeVisible(); - // await backToTop.click(); - // await page.waitForTimeout(500); - // // Verify scroll position is at top - // const scrollY = await page.evaluate(() => window.scrollY); - // expect(scrollY).toBe(0); + test("should display data source as Llwytho â Llaw in Welsh", async ({ page }) => { + await completeCSTUploadFlowAndNavigate(page); + + // Switch to Welsh + await page.getByRole("link", { name: "Cymraeg" }).click(); + await page.waitForLoadState("networkidle"); + + // Find the data source text in Welsh + const dataSourceParagraph = page.locator(".govuk-body-s").filter({ hasText: "Ffynhonnell data" }); + await expect(dataSourceParagraph).toBeVisible(); + + const dataSourceText = await dataSourceParagraph.textContent(); + expect(dataSourceText).toContain("Ffynhonnell data:"); + expect(dataSourceText).toContain("Llwytho â Llaw"); }); + }); test.describe("Search Functionality", () => { - test("should filter table based on search term", async ({ page }) => { - // Placeholder - implement once list display is available - // const searchInput = page.locator("#case-search-input"); - // await expect(searchInput).toBeVisible(); - // - // // Search for specific case - // await searchInput.fill("Test Case A"); - // await page.waitForTimeout(500); - // - // // Verify only matching rows are visible/highlighted - // const highlightedText = page.locator(".search-highlight"); - // await expect(highlightedText.first()).toBeVisible(); - // await expect(highlightedText.first()).toContainText("Test Case A"); + test("should filter and highlight table rows based on search term", async ({ page }) => { + await completeCSTUploadFlowAndNavigate(page); + + const searchInput = page.locator("#case-search-input"); + await expect(searchInput).toBeVisible(); + + // Search for specific case + await searchInput.fill("Test Case A"); + await page.waitForTimeout(500); + + // Verify the table still shows all rows (search highlights, doesn't hide) + const rows = page.locator("tbody tr"); + await expect(rows).toHaveCount(3); + + // Verify highlighting works on the matching case + const firstRowText = await rows.nth(0).textContent(); + expect(firstRowText).toContain("Test Case A vs B"); }); - test("should highlight search matches in table", async ({ page }) => { - // Placeholder - implement once list display is available - // const searchInput = page.locator("#case-search-input"); - // await searchInput.fill("Remote"); - // await page.waitForTimeout(500); - // - // // Verify highlighting works - // const highlights = page.locator("mark.search-highlight"); - // await expect(highlights.first()).toBeVisible(); - // await expect(highlights.first()).toContainText("Remote"); + test("should highlight matches in multiple columns", async ({ page }) => { + await completeCSTUploadFlowAndNavigate(page); + + const searchInput = page.locator("#case-search-input"); + await searchInput.fill("Remote"); + await page.waitForTimeout(500); + + // Verify "Remote" appears in the additional information column + const table = page.locator(".govuk-table"); + const tableText = await table.textContent(); + expect(tableText).toContain("Remote"); }); - test("should clear highlighting when search is cleared", async ({ page }) => { - // Placeholder - implement once list display is available - // const searchInput = page.locator("#case-search-input"); - // await searchInput.fill("Test"); - // await page.waitForTimeout(500); - // - // await searchInput.clear(); - // await page.waitForTimeout(500); - // - // // Verify no highlights remain - // const highlights = page.locator("mark.search-highlight"); - // await expect(highlights).toHaveCount(0); + test("should clear search when input is cleared", async ({ page }) => { + await completeCSTUploadFlowAndNavigate(page); + + const searchInput = page.locator("#case-search-input"); + await searchInput.fill("Test"); + await page.waitForTimeout(500); + + // Clear the search + await searchInput.clear(); + await page.waitForTimeout(500); + + // Verify all rows are still visible + const rows = page.locator("tbody tr"); + await expect(rows).toHaveCount(3); }); }); @@ -465,15 +523,14 @@ test.describe("Care Standards Tribunal Excel Upload End-to-End Flow", () => { }); test("should meet WCAG 2.2 AA standards on list display page", async ({ page }) => { - // Placeholder - implement once list display is available - // await page.goto("/care-standards-tribunal-weekly-hearing-list?artefactId=test"); - // - // const accessibilityScanResults = await new AxeBuilder({ page }) - // .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"]) - // .disableRules(["target-size", "link-name"]) - // .analyze(); - // - // expect(accessibilityScanResults.violations).toEqual([]); + await completeCSTUploadFlowAndNavigate(page); + + const accessibilityScanResults = await new AxeBuilder({ page }) + .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"]) + .disableRules(["target-size", "link-name"]) + .analyze(); + + expect(accessibilityScanResults.violations).toEqual([]); }); }); @@ -500,14 +557,62 @@ test.describe("Care Standards Tribunal Excel Upload End-to-End Flow", () => { }); test.describe("Welsh Language Support", () => { - test("should display Welsh content when language is set to cy", async ({ page }) => { - await page.goto("/non-strategic-upload?locationId=9001&lng=cy"); - await page.waitForTimeout(1000); - - // Verify Welsh content is displayed - // Note: This depends on actual Welsh translations being implemented - const heading = page.locator("h1"); - await expect(heading).toBeVisible(); + test("should display Welsh content throughout the list page", async ({ page }) => { + await completeCSTUploadFlowAndNavigate(page); + + // Switch to Welsh + await page.getByRole("link", { name: "Cymraeg" }).click(); + await page.waitForLoadState("networkidle"); + + // Verify page title is in Welsh + await expect(page.locator("h1")).toContainText("Rhestr Gwrandawiadau Wythnosol y Tribiwnlys Safonau Gofal"); + + // Verify "List for week commencing" is in Welsh + const weekCommencingPara = page.locator('p.govuk-body.govuk-\\!-font-weight-bold.govuk-\\!-margin-bottom-1'); + await expect(weekCommencingPara).toBeVisible(); + const weekCommencingText = await weekCommencingPara.textContent(); + expect(weekCommencingText).toContain("Rhestr ar gyfer yr wythnos yn dechrau"); + + // Verify "Last updated" is in Welsh + const bodyParagraphs = page.locator("p.govuk-body"); + let foundLastUpdated = false; + for (let i = 0; i < await bodyParagraphs.count(); i++) { + const text = await bodyParagraphs.nth(i).textContent(); + if (text?.includes("Diweddarwyd ddiwethaf")) { + foundLastUpdated = true; + expect(text).toContain("am"); // Welsh for "at" + break; + } + } + expect(foundLastUpdated).toBeTruthy(); + + // Verify Important Information is in Welsh + const summary = page.locator(".govuk-details__summary-text"); + await expect(summary).toContainText("Gwybodaeth bwysig"); + + // Verify table headers are in Welsh + const table = page.locator(".govuk-table"); + const headers = table.locator("thead th"); + await expect(headers.nth(0)).toContainText("Dyddiad"); + await expect(headers.nth(1)).toContainText("Enw'r achos"); + await expect(headers.nth(2)).toContainText("Hyd y gwrandawiad"); + await expect(headers.nth(3)).toContainText("Math o wrandawiad"); + await expect(headers.nth(4)).toContainText("Lleoliad"); + await expect(headers.nth(5)).toContainText("Gwybodaeth ychwanegol"); + + // Verify data source is in Welsh + const dataSourceParagraph = page.locator(".govuk-body-s").filter({ hasText: "Ffynhonnell data" }); + await expect(dataSourceParagraph).toBeVisible(); + const dataSourceText = await dataSourceParagraph.textContent(); + expect(dataSourceText).toContain("Llwytho â Llaw"); + + // Verify Back to top is in Welsh + const backToTop = page.getByRole("link", { name: /yn ôl i frig y dudalen/i }); + await expect(backToTop).toBeVisible(); + + // Verify Search Cases is in Welsh + const searchTitle = page.locator("h2.govuk-heading-s"); + await expect(searchTitle).toContainText("Chwilio Achosion"); }); }); }); diff --git a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/care-standards-tribunal-weekly-hearing-list.njk b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/care-standards-tribunal-weekly-hearing-list.njk index 9c78ad296..7ddde9906 100644 --- a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/care-standards-tribunal-weekly-hearing-list.njk +++ b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/care-standards-tribunal-weekly-hearing-list.njk @@ -20,10 +20,10 @@ {{ t.factLinkText }} {{ t.factAdditionalText }}

-

{{ header.duration }}

-

{{ header.lastUpdated }}

+

{{ t.listForWeekCommencing }} {{ header.weekCommencingDate }}

+

{{ t.lastUpdated }} {{ header.lastUpdatedDate }} {{ t.at }} {{ header.lastUpdatedTime }}

-
+
{{ t.importantInformationTitle }} @@ -74,7 +74,7 @@ -

{{ t.dataSource }}: {{ dataSource }}

+

{{ t.dataSource }}: {{ dataSource }}

{{ t.backToTop }} diff --git a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/cy.ts b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/cy.ts index dedf79ce2..a3ff37842 100644 --- a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/cy.ts +++ b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/cy.ts @@ -1,22 +1,31 @@ export const cy = { - pageTitle: "Welsh placeholder", - factLinkText: "Dod o hyd i fanylion cyswllt a gwybodaeth arall am lysoedd a thribiwnlysoedd", + pageTitle: "Rhestr Gwrandawiadau Wythnosol y Tribiwnlys Safonau Gofal", + listForWeekCommencing: "Rhestr ar gyfer yr wythnos yn dechrau ar", + lastUpdated: "Diweddarwyd ddiwethaf", + at: "am", + factLinkText: "Dod o hyd i fanylion cyswllt a gwybodaeth arall am lysoedd a thribiwnlysoedd yng Nghymru a Lloegr", factLinkUrl: "https://www.find-court-tribunal.service.gov.uk/", - factAdditionalText: "yng Nghymru a Lloegr, a rhai tribiwnlysoedd nad ydynt wedi'u datganoli yn yr Alban.", - importantInformationTitle: "Welsh placeholder", - importantInformationText: "Welsh placeholder", - importantInformationLinkText: "Welsh placeholder", + factAdditionalText: "a rhai tribiwnlysoedd heb eu datganoli yn yr Alban.", + importantInformationTitle: "Gwybodaeth bwysig", + importantInformationText: "Cysylltwch â'r Swyddfa Safonau Gofal yn cst@justice.gov.uk i gael manylion am sut i gael mynediad at wrandawiadau fideo.", + importantInformationLinkText: "Arsylwi gwrandawiad llys neu dribiwnlys fel newyddiadurwr, ymchwilydd neu aelod o'r cyhoedd", importantInformationLinkUrl: "https://www.gov.uk/guidance/observe-a-court-or-tribunal-hearing", - searchCasesTitle: "Welsh placeholder", - searchCasesLabel: "Welsh placeholder", + searchCasesTitle: "Chwilio Achosion", + searchCasesLabel: "Chwilio yn ôl rhif achos, manylion, lleoliad, barnwr, neu wybodaeth arall", tableHeaders: { - date: "Welsh placeholder", - caseName: "Welsh placeholder", - hearingLength: "Welsh placeholder", - hearingType: "Welsh placeholder", - venue: "Welsh placeholder", - additionalInformation: "Welsh placeholder" + date: "Dyddiad", + caseName: "Enw'r achos", + hearingLength: "Hyd y gwrandawiad", + hearingType: "Math o wrandawiad", + venue: "Lleoliad", + additionalInformation: "Gwybodaeth ychwanegol" }, - dataSource: "Welsh placeholder for 'Data source'", - backToTop: "Welsh placeholder" + dataSource: "Ffynhonnell data", + backToTop: "Yn ôl i frig y dudalen", + provenanceLabels: { + MANUAL_UPLOAD: "Llwytho â Llaw", + XHIBIT: "XHIBIT", + SNL: "SNL", + COMMON_PLATFORM: "Platfform Cyffredin" + } }; diff --git a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/en.ts b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/en.ts index bfbf295f0..752bba748 100644 --- a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/en.ts +++ b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/en.ts @@ -1,5 +1,8 @@ export const en = { pageTitle: "Care Standards Tribunal Weekly Hearing List", + listForWeekCommencing: "List for week commencing", + lastUpdated: "Last updated", + at: "at", factLinkText: "Find contact details and other information about courts and tribunals", factLinkUrl: "https://www.find-court-tribunal.service.gov.uk/", factAdditionalText: "in England and Wales, and some non-devolved tribunals in Scotland.", @@ -18,5 +21,11 @@ export const en = { additionalInformation: "Additional information" }, dataSource: "Data source", - backToTop: "Back to top" + backToTop: "Back to top", + provenanceLabels: { + MANUAL_UPLOAD: "Manual Upload", + XHIBIT: "XHIBIT", + SNL: "SNL", + COMMON_PLATFORM: "Common Platform" + } }; diff --git a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/index.test.ts b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/index.test.ts index c5c3d2dc2..959b7883e 100644 --- a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/index.test.ts +++ b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/index.test.ts @@ -105,7 +105,8 @@ describe("Care Standards Tribunal page controller", () => { courtName: "Care Standards Tribunal", displayFrom: mockArtefact.displayFrom, displayTo: mockArtefact.displayTo, - lastReceivedDate: mockArtefact.lastReceivedDate.toISOString() + lastReceivedDate: mockArtefact.lastReceivedDate.toISOString(), + listTitle: "Care Standards Tribunal Weekly Hearing List" }); const renderCall = vi.mocked(res.render).mock.calls[0]; expect(renderCall[0]).toBe("care-standards-tribunal-weekly-hearing-list"); diff --git a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/index.ts b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/index.ts index 433b02a6b..ebad17ac6 100644 --- a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/index.ts +++ b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/pages/index.ts @@ -79,10 +79,11 @@ export const GET = async (req: Request, res: Response) => { courtName, displayFrom: artefact.displayFrom, displayTo: artefact.displayTo, - lastReceivedDate: artefact.lastReceivedDate.toISOString() + lastReceivedDate: artefact.lastReceivedDate.toISOString(), + listTitle: t.pageTitle }); - const dataSource = PROVENANCE_LABELS[artefact.provenance] || artefact.provenance; + const dataSource = t.provenanceLabels[artefact.provenance as keyof typeof t.provenanceLabels] || artefact.provenance; res.render("care-standards-tribunal-weekly-hearing-list", { en, diff --git a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/rendering/renderer.test.ts b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/rendering/renderer.test.ts index 3736e40f2..4bc6bda2e 100644 --- a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/rendering/renderer.test.ts +++ b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/rendering/renderer.test.ts @@ -20,16 +20,16 @@ describe("renderCareStandardsTribunalData", () => { courtName: "Care Standards Tribunal", displayFrom: new Date(2025, 0, 2), displayTo: new Date(2025, 0, 8), - lastReceivedDate: "2025-01-01T09:55:00Z" + lastReceivedDate: "2025-01-01T09:55:00Z", + listTitle: "Care Standards Tribunal Weekly Hearing List" }; const result = renderCareStandardsTribunalData(hearingList, options); expect(result.header.listTitle).toBe("Care Standards Tribunal Weekly Hearing List"); - expect(result.header.duration).toContain("List for week commencing"); - expect(result.header.duration).toContain("2 January 2025"); - expect(result.header.lastUpdated).toContain("Last updated"); - expect(result.header.lastUpdated).toContain("1 January 2025"); + expect(result.header.weekCommencingDate).toBe("2 January 2025"); + expect(result.header.lastUpdatedDate).toBe("1 January 2025"); + expect(result.header.lastUpdatedTime).toContain("am"); expect(result.hearings).toHaveLength(1); expect(result.hearings[0].date).toBe("2 January 2025"); @@ -65,7 +65,8 @@ describe("renderCareStandardsTribunalData", () => { courtName: "Care Standards Tribunal", displayFrom: new Date(2025, 0, 2), displayTo: new Date(2025, 0, 8), - lastReceivedDate: "2025-01-01T09:55:00Z" + lastReceivedDate: "2025-01-01T09:55:00Z", + listTitle: "Care Standards Tribunal Weekly Hearing List" }; const result = renderCareStandardsTribunalData(hearingList, options); @@ -92,7 +93,8 @@ describe("renderCareStandardsTribunalData", () => { courtName: "Care Standards Tribunal", displayFrom: new Date(2025, 0, 1), displayTo: new Date(2025, 0, 7), - lastReceivedDate: "2025-01-01T09:55:00Z" + lastReceivedDate: "2025-01-01T09:55:00Z", + listTitle: "Care Standards Tribunal Weekly Hearing List" }; const result = renderCareStandardsTribunalData(hearingList, options); @@ -117,12 +119,13 @@ describe("renderCareStandardsTribunalData", () => { courtName: "Care Standards Tribunal", displayFrom: new Date(2025, 0, 2), displayTo: new Date(2025, 0, 8), - lastReceivedDate: "2025-01-01T09:55:00Z" + lastReceivedDate: "2025-01-01T09:55:00Z", + listTitle: "Care Standards Tribunal Weekly Hearing List" }; const result = renderCareStandardsTribunalData(hearingList, options); - expect(result.header.lastUpdated).toContain("at 9:55am"); + expect(result.header.lastUpdatedTime).toBe("9:55am"); }); it("should format PM times correctly", () => { @@ -142,12 +145,13 @@ describe("renderCareStandardsTribunalData", () => { courtName: "Care Standards Tribunal", displayFrom: new Date(2025, 0, 2), displayTo: new Date(2025, 0, 8), - lastReceivedDate: "2025-01-01T14:30:00Z" + lastReceivedDate: "2025-01-01T14:30:00Z", + listTitle: "Care Standards Tribunal Weekly Hearing List" }; const result = renderCareStandardsTribunalData(hearingList, options); - expect(result.header.lastUpdated).toContain("at 2:30pm"); + expect(result.header.lastUpdatedTime).toBe("2:30pm"); }); it("should handle empty hearing list", () => { @@ -158,7 +162,8 @@ describe("renderCareStandardsTribunalData", () => { courtName: "Care Standards Tribunal", displayFrom: new Date(2025, 0, 2), displayTo: new Date(2025, 0, 8), - lastReceivedDate: "2025-01-01T09:55:00Z" + lastReceivedDate: "2025-01-01T09:55:00Z", + listTitle: "Care Standards Tribunal Weekly Hearing List" }; const result = renderCareStandardsTribunalData(hearingList, options); @@ -167,6 +172,32 @@ describe("renderCareStandardsTribunalData", () => { expect(result.header.listTitle).toBe("Care Standards Tribunal Weekly Hearing List"); }); + it("should use the provided listTitle from translations", () => { + const hearingList: CareStandardsTribunalHearingList = [ + { + date: "02/01/2025", + caseName: "A Vs B", + hearingLength: "1 hour", + hearingType: "Substantive hearing", + venue: "Care Standards Tribunal", + additionalInformation: "Remote hearing" + } + ]; + + const optionsWelsh = { + locale: "cy", + courtName: "Care Standards Tribunal", + displayFrom: new Date(2025, 0, 2), + displayTo: new Date(2025, 0, 8), + lastReceivedDate: "2025-01-01T09:55:00Z", + listTitle: "Rhestr Gwrandawiadau Wythnosol y Tribiwnlys Safonau Gofal" + }; + + const result = renderCareStandardsTribunalData(hearingList, optionsWelsh); + + expect(result.header.listTitle).toBe("Rhestr Gwrandawiadau Wythnosol y Tribiwnlys Safonau Gofal"); + }); + it("should preserve all hearing fields without modification", () => { const hearingList: CareStandardsTribunalHearingList = [ { @@ -184,7 +215,8 @@ describe("renderCareStandardsTribunalData", () => { courtName: "Care Standards Tribunal", displayFrom: new Date(2025, 0, 2), displayTo: new Date(2025, 0, 8), - lastReceivedDate: "2025-01-01T09:55:00Z" + lastReceivedDate: "2025-01-01T09:55:00Z", + listTitle: "Care Standards Tribunal Weekly Hearing List" }; const result = renderCareStandardsTribunalData(hearingList, options); diff --git a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/rendering/renderer.ts b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/rendering/renderer.ts index 1245a78fd..b30763e73 100644 --- a/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/rendering/renderer.ts +++ b/libs/list-types/care-standards-tribunal-weekly-hearing-list/src/rendering/renderer.ts @@ -7,26 +7,22 @@ export interface RenderOptions { displayFrom: Date; displayTo: Date; lastReceivedDate: string; + listTitle: string; } export interface RenderedData { header: { listTitle: string; - duration: string; - lastUpdated: string; + weekCommencingDate: string; + lastUpdatedDate: string; + lastUpdatedTime: string; }; hearings: CareStandardsTribunalHearing[]; } -function formatLastUpdated(isoDateTime: string, locale: string): string { - const { date, time } = formatLastUpdatedDateTime(isoDateTime, locale); - return `${date} at ${time}`; -} - export function renderCareStandardsTribunalData(hearingList: CareStandardsTribunalHearingList, options: RenderOptions): RenderedData { - const listTitle = "Care Standards Tribunal Weekly Hearing List"; - const duration = `List for week commencing ${formatDisplayDate(options.displayFrom, options.locale)}`; - const lastUpdated = `Last updated ${formatLastUpdated(options.lastReceivedDate, options.locale)}`; + const weekCommencingDate = formatDisplayDate(options.displayFrom, options.locale); + const { date: lastUpdatedDate, time: lastUpdatedTime } = formatLastUpdatedDateTime(options.lastReceivedDate, options.locale); const renderedHearings = hearingList.map((hearing) => ({ date: formatDdMmYyyyDate(hearing.date, options.locale), @@ -39,9 +35,10 @@ export function renderCareStandardsTribunalData(hearingList: CareStandardsTribun return { header: { - listTitle, - duration, - lastUpdated + listTitle: options.listTitle, + weekCommencingDate, + lastUpdatedDate, + lastUpdatedTime }, hearings: renderedHearings }; diff --git a/package.json b/package.json index 162354138..12b6bc8d7 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "jws": "4.0.1", "lodash": "4.17.23", "node-forge": "1.3.3", - "qs": "6.14.1", + "qs": "6.14.2", "tar": "7.5.7", "undici": "6.23.0", "vite": "7.3.0" diff --git a/yarn.lock b/yarn.lock index 10e814481..0d32e5866 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6911,12 +6911,12 @@ __metadata: languageName: node linkType: hard -"qs@npm:6.14.1": - version: 6.14.1 - resolution: "qs@npm:6.14.1" +"qs@npm:6.14.2": + version: 6.14.2 + resolution: "qs@npm:6.14.2" dependencies: side-channel: "npm:^1.1.0" - checksum: 10c0/0e3b22dc451f48ce5940cbbc7c7d9068d895074f8c969c0801ac15c1313d1859c4d738e46dc4da2f498f41a9ffd8c201bd9fb12df67799b827db94cc373d2613 + checksum: 10c0/646110124476fc9acf3c80994c8c3a0600cbad06a4ede1c9e93341006e8426d64e85e048baf8f0c4995f0f1bf0f37d1f3acc5ec1455850b81978792969a60ef6 languageName: node linkType: hard