diff --git a/src/ui-spa/e2e-tests/offence-results-repealed-tag.spec.ts b/src/ui-spa/e2e-tests/offence-results-repealed-tag.spec.ts new file mode 100644 index 00000000..639579e9 --- /dev/null +++ b/src/ui-spa/e2e-tests/offence-results-repealed-tag.spec.ts @@ -0,0 +1,26 @@ +import { test } from "@playwright/test"; +import { ChargesOffenceSearchPage } from "./pages/chargesOffenceSearchPage"; +import { generateUniqueUrn } from "./utils/generateUrn"; +import { expectStep } from "./utils/expectStep"; +import { + startSingleSuspectUpToCharges, + chargeDates, +} from "./journeys/suspectChargeSteps"; + +const SEARCH_TERM = process.env.E2E_REPEALED_SEARCH_TERM ?? "burglary"; + +test("Scenario 22: repealed offences are tagged in the search results and active ones are not", async ({ + page, +}) => { + const urn = generateUniqueUrn(); + const { arrestDate } = chargeDates(); + + await startSingleSuspectUpToCharges(page, { urn, arrestDate }); + + const offenceSearchPage = new ChargesOffenceSearchPage(page); + await expectStep( + page, + "/case-registration/suspect-0/charge-0/charges-offence-search", + ); + await offenceSearchPage.searchAndVerifyRepealedTags(SEARCH_TERM); +}); diff --git a/src/ui-spa/e2e-tests/pages/chargesOffenceSearchPage.ts b/src/ui-spa/e2e-tests/pages/chargesOffenceSearchPage.ts index 25596d87..b02d23f3 100644 --- a/src/ui-spa/e2e-tests/pages/chargesOffenceSearchPage.ts +++ b/src/ui-spa/e2e-tests/pages/chargesOffenceSearchPage.ts @@ -1,6 +1,14 @@ import { type Page, type Locator, expect } from "@playwright/test"; import { ChargesOffenceSearchPagePage as IntegrationChargesOffenceSearchPage } from "../../integration-tests/pages/chargesOffenceSearchPage"; +const REPEALED_TAG_PREFIX = "offence-repealed-warning-"; + +interface Offence { + code: string; + description: string; + effectiveToDate: string | null; +} + // Reuses the integration offence-search page object (identical selectors) and // adds e2e-only assertions against the real /api/v1/offences response: an // offence code with no matches (covering both "zero results" and an invalid @@ -17,7 +25,7 @@ export class ChargesOffenceSearchPage extends IntegrationChargesOffenceSearchPag return this.currentPage.getByTestId("offence-search-results-wrapper"); } - private async submitSearch(searchText: string): Promise { + private async submitSearch(searchText: string): Promise { await this.addOffenceSearchText(searchText); // Match regardless of status so a non-2xx fails on the assertion, not a hang. const offencesResponse = this.currentPage.waitForResponse( @@ -30,6 +38,8 @@ export class ChargesOffenceSearchPage extends IntegrationChargesOffenceSearchPag response.ok(), `offence search for "${searchText}" returned ${response.status()}`, ).toBe(true); + const body = (await response.json()) as { offences: Offence[] }; + return body.offences; } async searchAndExpectNoResults(searchText: string): Promise { @@ -48,4 +58,50 @@ export class ChargesOffenceSearchPage extends IntegrationChargesOffenceSearchPag ).toBeVisible({ timeout: 30_000 }); await this.addOffence(0); } + + async searchAndVerifyRepealedTags(searchText: string): Promise { + const offences = await this.submitSearch(searchText); + const repealed = offences.filter((offence) => offence.effectiveToDate); + const active = offences.filter((offence) => !offence.effectiveToDate); + + expect( + repealed.length, + `"${searchText}" returned no repealed offence, so the tag assertions prove nothing`, + ).toBeGreaterThan(0); + expect( + active.length, + `"${searchText}" returned no active offence, so the absent-tag assertion proves nothing`, + ).toBeGreaterThan(0); + + const resultsTable = this.resultsWrapper().getByRole("table"); + await expect(resultsTable).toBeVisible(); + + await expect( + resultsTable.locator(`[data-testid^="${REPEALED_TAG_PREFIX}"]`), + ).toHaveCount(repealed.length); + + for (const offence of repealed) { + const tagId = `${REPEALED_TAG_PREFIX}${offence.code}`; + const row = resultsTable + .locator("tbody tr") + .filter({ has: this.currentPage.getByTestId(tagId) }); + await expect(row).toHaveCount(1); + await expect(row.locator("td").nth(1)).toHaveText(offence.code); + + const descriptionCell = row.locator("td").nth(2); + const tag = descriptionCell.getByTestId(tagId); + await expect(tag).toBeVisible(); + await expect(tag).toHaveClass(/govuk-warning-text/); + await expect(tag).toHaveText("!Repealed"); + await expect(descriptionCell).toHaveText( + `${offence.description}!Repealed`, + ); + } + + for (const offence of active) { + await expect( + this.currentPage.getByTestId(`${REPEALED_TAG_PREFIX}${offence.code}`), + ).toHaveCount(0); + } + } }