From d3b5e0f31ea6115abc55ea1938b7e827471b676b Mon Sep 17 00:00:00 2001 From: Jo Humphrey <31373245+jamdelion@users.noreply.github.com> Date: Thu, 28 Nov 2024 17:07:25 +0000 Subject: [PATCH 1/9] Add tests for accessibility and no error on render [skip pizza] --- .../VerifyEmail/tests/VerifyEmail.test.tsx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/editor.planx.uk/src/pages/VerifyEmail/tests/VerifyEmail.test.tsx b/editor.planx.uk/src/pages/VerifyEmail/tests/VerifyEmail.test.tsx index d2f322a8ba..c380304199 100644 --- a/editor.planx.uk/src/pages/VerifyEmail/tests/VerifyEmail.test.tsx +++ b/editor.planx.uk/src/pages/VerifyEmail/tests/VerifyEmail.test.tsx @@ -1,17 +1,29 @@ import { screen } from "@testing-library/react"; import React from "react"; import { setup } from "testUtils"; +import { axe } from "vitest-axe"; import { VerifyEmail } from "../VerifyEmail"; describe("when the VerifyEmail component renders", () => { - it("displays the email address input", () => { + beforeEach(() => { setup(); - + }); + it("displays the email address input", () => { expect(screen.queryByText("Verify your email address")).toBeInTheDocument(); expect(screen.queryByLabelText("Email address")).toBeInTheDocument(); }); - it.todo("should not display an error message"); + it("should not display an error message", () => { + expect( + screen.queryByText("Sorry, something went wrong. Please try again."), + ).not.toBeInTheDocument(); + }); + it("should not have any accessibility violations", async () => { + const { container } = setup(); + + const results = await axe(container); + expect(results).toHaveNoViolations(); + }); }); describe("when the user submits a correct email address to the verifyEmail component", () => { From 9729bb6730c90bd300e2db85dacef486e0a5586b Mon Sep 17 00:00:00 2001 From: Jo Humphrey <31373245+jamdelion@users.noreply.github.com> Date: Mon, 2 Dec 2024 14:37:25 +0000 Subject: [PATCH 2/9] Readd after merge conflict --- .../tests/VerifySubmissionEmail.test.tsx | 21 +++++++++- .../VerifyEmail/tests/VerifyEmail.test.tsx | 40 ------------------- 2 files changed, 19 insertions(+), 42 deletions(-) delete mode 100644 editor.planx.uk/src/pages/VerifyEmail/tests/VerifyEmail.test.tsx diff --git a/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx b/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx index 793713f518..b087559f4b 100644 --- a/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx +++ b/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx @@ -1,19 +1,36 @@ import { screen } from "@testing-library/react"; import React from "react"; import { setup } from "testUtils"; +import { axe } from "vitest-axe"; import { VerifySubmissionEmail } from "../VerifySubmissionEmail"; describe("when the VerifySubmissionEmail component renders", () => { - it("displays the email address input", () => { + beforeEach(() => { setup(); + }); + it("displays the email address input", () => { expect( screen.queryByText("Verify your submission email address"), ).toBeInTheDocument(); expect(screen.queryByLabelText("Email address")).toBeInTheDocument(); }); - it.todo("should not display an error message"); + + it("should not display an error message", () => { + expect( + screen.queryByText("Sorry, something went wrong. Please try again."), + ).not.toBeInTheDocument(); + + it("should not have any accessibility violations", async () => { + const { container } = setup( + , + ); + + const results = await axe(container); + expect(results).toHaveNoViolations(); + }); + }); }); describe("when the user submits a correct email address", () => { diff --git a/editor.planx.uk/src/pages/VerifyEmail/tests/VerifyEmail.test.tsx b/editor.planx.uk/src/pages/VerifyEmail/tests/VerifyEmail.test.tsx deleted file mode 100644 index c380304199..0000000000 --- a/editor.planx.uk/src/pages/VerifyEmail/tests/VerifyEmail.test.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { screen } from "@testing-library/react"; -import React from "react"; -import { setup } from "testUtils"; -import { axe } from "vitest-axe"; - -import { VerifyEmail } from "../VerifyEmail"; - -describe("when the VerifyEmail component renders", () => { - beforeEach(() => { - setup(); - }); - it("displays the email address input", () => { - expect(screen.queryByText("Verify your email address")).toBeInTheDocument(); - expect(screen.queryByLabelText("Email address")).toBeInTheDocument(); - }); - it("should not display an error message", () => { - expect( - screen.queryByText("Sorry, something went wrong. Please try again."), - ).not.toBeInTheDocument(); - }); - it("should not have any accessibility violations", async () => { - const { container } = setup(); - - const results = await axe(container); - expect(results).toHaveNoViolations(); - }); -}); - -describe("when the user submits a correct email address to the verifyEmail component", () => { - it.todo("displays visual feedback to the user"); - it.todo("downloads the application file"); -}); - -describe("when the user submits an incorrect email address to the verifyEmail component", () => { - it.todo("displays a suitable error message"); -}); - -describe("when user submits an email address to the verifyEmail component and there is a server-side issue", () => { - it.todo("displays a suitable error message"); -}); From f41b484f4c3ef852059a114b405df67192fc84e5 Mon Sep 17 00:00:00 2001 From: Jo Humphrey <31373245+jamdelion@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:35:02 +0000 Subject: [PATCH 3/9] Fix merge --- editor.planx.uk/src/routes/index.tsx | 8 -------- editor.planx.uk/src/ui/shared/ErrorWrapper.tsx | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/editor.planx.uk/src/routes/index.tsx b/editor.planx.uk/src/routes/index.tsx index 793425748a..425e30f4b3 100644 --- a/editor.planx.uk/src/routes/index.tsx +++ b/editor.planx.uk/src/routes/index.tsx @@ -1,6 +1,5 @@ import { compose, lazy, map, mount, redirect, route, withView } from "navi"; import { loadingView } from "pages/layout/LoadingLayout"; -import { VerifySubmissionEmail } from "pages/SubmissionDownload/VerifySubmissionEmail"; import * as React from "react"; import { client } from "../lib/graphql"; @@ -31,13 +30,6 @@ const editorRoutes = mount({ }), ), - "/:team/:flow/:sessionId/download-application": map((req) => { - return route({ - title: makeTitle("Download application"), - view: , - }); - }), - "/logout": map((): any => { try { client.resetStore(); diff --git a/editor.planx.uk/src/ui/shared/ErrorWrapper.tsx b/editor.planx.uk/src/ui/shared/ErrorWrapper.tsx index b168c96c8a..6e4e7cb1c7 100644 --- a/editor.planx.uk/src/ui/shared/ErrorWrapper.tsx +++ b/editor.planx.uk/src/ui/shared/ErrorWrapper.tsx @@ -7,7 +7,7 @@ import React, { ReactElement, useEffect } from "react"; import { FONT_WEIGHT_SEMI_BOLD } from "theme"; export interface Props { - error?: string | null; + error?: string; children?: ReactElement; id?: string; // "alert" - important and time-sensitive information (e.g. invalid input feedback) From 72643ad0287c915a1b3032f0ff4507b3f2f1f9e9 Mon Sep 17 00:00:00 2001 From: Jo Humphrey <31373245+jamdelion@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:55:37 +0000 Subject: [PATCH 4/9] Fill out some more tests --- .../tests/VerifySubmissionEmail.test.tsx | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx b/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx index af03ff6733..d3d0116bdb 100644 --- a/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx +++ b/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx @@ -6,18 +6,20 @@ import { axe } from "vitest-axe"; import { VerifySubmissionEmail } from "../VerifySubmissionEmail"; describe("when the VerifySubmissionEmail component renders", () => { - beforeEach(() => { + it("displays the email address input", () => { setup(); - }); - it("displays the email address input", () => { expect( - screen.queryByText("Verify your submission email address"), + screen.getByText("Verify your submission email address"), + ).toBeInTheDocument(); + expect( + screen.getByLabelText("Submission email address"), ).toBeInTheDocument(); - expect(screen.queryByLabelText("Submission email address")).toBeInTheDocument(); }); it("should not display an error message", () => { + setup(); + expect( screen.queryByText("Sorry, something went wrong. Please try again."), ).not.toBeInTheDocument(); @@ -32,9 +34,19 @@ describe("when the VerifySubmissionEmail component renders", () => { expect(results).toHaveNoViolations(); }); - it.todo( - "shows sessionId and local authority in the application details table", - ); + it("shows sessionId and local authority in the application details table", async () => { + setup( + , + ); + expect(screen.getByText("Session ID")).toBeInTheDocument(); + expect(screen.getByText("a-session-id")).toBeInTheDocument(); + + expect(screen.getByText("Local Authority")).toBeInTheDocument(); + + expect(screen.getByText("Barking And Dagenham")).toBeInTheDocument(); // with correct casing + }); }); describe("when the user submits a correct email address", () => { From de7130b0638c159fc01c6031724caf2ab32a726f Mon Sep 17 00:00:00 2001 From: Jo Humphrey <31373245+jamdelion@users.noreply.github.com> Date: Mon, 6 Jan 2025 17:39:52 +0000 Subject: [PATCH 5/9] Test that download zip file is called when correct information supplied --- editor.planx.uk/package.json | 1 + editor.planx.uk/pnpm-lock.yaml | 175 +++++++++++++++++- .../tests/VerifySubmissionEmail.test.tsx | 42 ++++- 3 files changed, 214 insertions(+), 4 deletions(-) diff --git a/editor.planx.uk/package.json b/editor.planx.uk/package.json index 0cf555b1a8..c3a2f4d19c 100644 --- a/editor.planx.uk/package.json +++ b/editor.planx.uk/package.json @@ -152,6 +152,7 @@ "jest-environment-jsdom": "^29.7.0", "jest-localstorage-mock": "^2.4.26", "lint-staged": "^13.2.3", + "msw": "^2.7.0", "postcss": "^8.4.32", "prettier": "^3.0.0", "react-refresh": "^0.14.0", diff --git a/editor.planx.uk/pnpm-lock.yaml b/editor.planx.uk/pnpm-lock.yaml index d2a5f51ba1..1fc8740a7c 100644 --- a/editor.planx.uk/pnpm-lock.yaml +++ b/editor.planx.uk/pnpm-lock.yaml @@ -454,6 +454,9 @@ devDependencies: lint-staged: specifier: ^13.2.3 version: 13.2.3 + msw: + specifier: ^2.7.0 + version: 2.7.0(@types/node@22.10.5)(typescript@5.6.2) postcss: specifier: ^8.4.32 version: 8.4.32 @@ -1912,6 +1915,25 @@ packages: /@bcoe/v8-coverage@0.2.3: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + /@bundled-es-modules/cookie@2.0.1: + resolution: {integrity: sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==} + dependencies: + cookie: 0.7.2 + dev: true + + /@bundled-es-modules/statuses@1.0.1: + resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} + dependencies: + statuses: 2.0.1 + dev: true + + /@bundled-es-modules/tough-cookie@0.1.6: + resolution: {integrity: sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==} + dependencies: + '@types/tough-cookie': 4.0.5 + tough-cookie: 4.1.4 + dev: true + /@codemirror/autocomplete@0.19.15: resolution: {integrity: sha512-GQWzvvuXxNUyaEk+5gawbAD8s51/v2Chb++nx0e2eGWrphWk42isBtzOMdc3DxrxrZtPZ55q2ldNp+6G8KJLIQ==} dependencies: @@ -2787,6 +2809,48 @@ packages: dependencies: react: 18.2.0 + /@inquirer/confirm@5.1.1(@types/node@22.10.5): + resolution: {integrity: sha512-vVLSbGci+IKQvDOtzpPTCOiEJCNidHcAq9JYVoWTW0svb5FiwSLotkM+JXNXejfjnzVYV9n0DTBythl9+XgTxg==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + dependencies: + '@inquirer/core': 10.1.2(@types/node@22.10.5) + '@inquirer/type': 3.0.2(@types/node@22.10.5) + '@types/node': 22.10.5 + dev: true + + /@inquirer/core@10.1.2(@types/node@22.10.5): + resolution: {integrity: sha512-bHd96F3ezHg1mf/J0Rb4CV8ndCN0v28kUlrHqP7+ECm1C/A+paB7Xh2lbMk6x+kweQC+rZOxM/YeKikzxco8bQ==} + engines: {node: '>=18'} + dependencies: + '@inquirer/figures': 1.0.9 + '@inquirer/type': 3.0.2(@types/node@22.10.5) + ansi-escapes: 4.3.2 + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.2 + transitivePeerDependencies: + - '@types/node' + dev: true + + /@inquirer/figures@1.0.9: + resolution: {integrity: sha512-BXvGj0ehzrngHTPTDqUoDT3NXL8U0RxUk2zJm2A66RhCEIWdtU1v6GuUqNAgArW4PQ9CinqIWyHdQgdwOj06zQ==} + engines: {node: '>=18'} + dev: true + + /@inquirer/type@3.0.2(@types/node@22.10.5): + resolution: {integrity: sha512-ZhQ4TvhwHZF+lGhQ2O/rsjo80XoZR5/5qhOY3t6FJuX5XBg5Be8YzYTvaUGJnc12AUGI2nr4QSUE4PhKSigx7g==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + dependencies: + '@types/node': 22.10.5 + dev: true + /@isaacs/cliui@8.0.2: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -3254,6 +3318,18 @@ packages: - encoding dev: false + /@mswjs/interceptors@0.37.5: + resolution: {integrity: sha512-AAwRb5vXFcY4L+FvZ7LZusDuZ0vEe0Zm8ohn1FM6/X7A3bj4mqmkAcGRWuvC2JwSygNwHAAmMnAI73vPHeqsHA==} + engines: {node: '>=18'} + dependencies: + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/logger': 0.3.0 + '@open-draft/until': 2.1.0 + is-node-process: 1.2.0 + outvariant: 1.4.3 + strict-event-emitter: 0.5.1 + dev: true + /@mui/base@5.0.0-beta.36(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-6A8fYiXgjqTO6pgj31Hc8wm1M3rFYCxDRh09dBVk0L0W4cb2lnurRJa3cAyic6hHY+we1S58OdGYRbKmOsDpGQ==} engines: {node: '>=12.0.0'} @@ -3744,6 +3820,21 @@ packages: resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} dev: true + /@open-draft/deferred-promise@2.2.0: + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + dev: true + + /@open-draft/logger@0.3.0: + resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} + dependencies: + is-node-process: 1.2.0 + outvariant: 1.4.3 + dev: true + + /@open-draft/until@2.1.0: + resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} + dev: true + /@opensystemslab/map@1.0.0-alpha.4: resolution: {integrity: sha512-HNvJkw43hmVqCeXIhZhkuT2YWQEWE/yXKmohATv9TNMRf1e9rOi4JtNg094vrtiZ9L5Od+OfM+8tahlCkV9RNw==} dependencies: @@ -5326,6 +5417,10 @@ packages: '@types/node': 22.10.5 dev: true + /@types/cookie@0.6.0: + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + dev: true + /@types/debug@4.1.12: resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} dependencies: @@ -5648,6 +5743,10 @@ packages: /@types/stack-utils@2.0.3: resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + /@types/statuses@2.0.5: + resolution: {integrity: sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==} + dev: true + /@types/testing-library__jest-dom@5.14.9: resolution: {integrity: sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==} dependencies: @@ -6985,6 +7084,11 @@ packages: string-width: 5.1.2 dev: true + /cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + dev: true + /client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} dev: false @@ -7175,6 +7279,11 @@ packages: engines: {node: '>= 0.6'} dev: true + /cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + dev: true + /copy-to-clipboard@3.3.3: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} dependencies: @@ -8798,7 +8907,6 @@ packages: /graphql@16.10.0: resolution: {integrity: sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - dev: false /graphql@16.8.1: resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} @@ -8882,6 +8990,10 @@ packages: resolution: {integrity: sha512-zpImx2GoKXy42fVDSEad2BPKuSQdLcqsCYa48K3zHSzM/ugWuYjLDr8IXxpVuL7uCLHw56eaiLxCRthhOzf5ug==} dev: false + /headers-polyfill@4.0.3: + resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==} + dev: true + /hex-color-regex@1.1.0: resolution: {integrity: sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==} dev: true @@ -9288,6 +9400,10 @@ packages: engines: {node: '>= 0.4'} dev: true + /is-node-process@1.2.0: + resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} + dev: true + /is-number-object@1.1.0: resolution: {integrity: sha512-KVSZV0Dunv9DTPkhXwcZ3Q+tUc9TsaE1ZwX5J2WMvsSGS6Md8TFPun5uwh0yRdrNerI6vf/tbJxqSx4c1ZI1Lw==} engines: {node: '>= 0.4'} @@ -10864,6 +10980,45 @@ packages: /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + /msw@2.7.0(@types/node@22.10.5)(typescript@5.6.2): + resolution: {integrity: sha512-BIodwZ19RWfCbYTxWTUfTXc+sg4OwjCAgxU1ZsgmggX/7S3LdUifsbUPJs61j0rWb19CZRGY5if77duhc0uXzw==} + engines: {node: '>=18'} + hasBin: true + requiresBuild: true + peerDependencies: + typescript: '>= 4.8.x' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@bundled-es-modules/cookie': 2.0.1 + '@bundled-es-modules/statuses': 1.0.1 + '@bundled-es-modules/tough-cookie': 0.1.6 + '@inquirer/confirm': 5.1.1(@types/node@22.10.5) + '@mswjs/interceptors': 0.37.5 + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/until': 2.1.0 + '@types/cookie': 0.6.0 + '@types/statuses': 2.0.5 + graphql: 16.10.0 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + picocolors: 1.1.1 + strict-event-emitter: 0.5.1 + type-fest: 4.31.0 + typescript: 5.6.2 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + dev: true + + /mute-stream@2.0.0: + resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} + engines: {node: ^18.17.0 || >=20.5.0} + dev: true + /nano-css@5.6.2(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==} peerDependencies: @@ -11156,6 +11311,10 @@ packages: resolution: {integrity: sha512-wf5fci7GGpMYRDnbbdIFQymvhsbFACMHtxjivQo5KgvAHlxekyfJ9aPsRr6YfFQthQkk4bmsl5yESrZwC/oMYQ==} dev: false + /outvariant@1.4.3: + resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} + dev: true + /p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -11284,6 +11443,10 @@ packages: resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} dev: true + /path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + dev: true + /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -13003,6 +13166,10 @@ packages: readable-stream: 3.6.2 dev: true + /strict-event-emitter@0.5.1: + resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} + dev: true + /string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -13561,7 +13728,6 @@ packages: /type-fest@4.31.0: resolution: {integrity: sha512-yCxltHW07Nkhv/1F6wWBr8kz+5BGMfP+RbRSYFnegVb0qV/UMT0G0ElBloPVerqn4M2ZV80Ir1FtCcYv1cT6vQ==} engines: {node: '>=16'} - dev: false /type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} @@ -14460,6 +14626,11 @@ packages: engines: {node: '>=12.20'} dev: true + /yoctocolors-cjs@2.1.2: + resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} + engines: {node: '>=18'} + dev: true + /yup@0.32.11: resolution: {integrity: sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==} engines: {node: '>=10'} diff --git a/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx b/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx index d3d0116bdb..ba3933cb07 100644 --- a/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx +++ b/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx @@ -1,10 +1,16 @@ -import { screen } from "@testing-library/react"; +import { screen, waitFor } from "@testing-library/react"; +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; import React from "react"; import { setup } from "testUtils"; +import { vi } from "vitest"; import { axe } from "vitest-axe"; +import { downloadZipFile } from "../helpers/downloadZip"; import { VerifySubmissionEmail } from "../VerifySubmissionEmail"; +vi.mock("./../helpers/downloadZip.tsx"); + describe("when the VerifySubmissionEmail component renders", () => { it("displays the email address input", () => { setup(); @@ -50,8 +56,40 @@ describe("when the VerifySubmissionEmail component renders", () => { }); describe("when the user submits a correct email address", () => { + const mockData = new ArrayBuffer(); + const server = setupServer( + http.get( + "http://localhost:7002/download-application-files/a-session-id/?email=submission%40council.com&localAuthority=barking-and-dagenham", + () => { + return new HttpResponse(mockData, { status: 200 }); + }, + ), + ); + + beforeAll(() => server.listen()); + afterEach(() => server.resetHandlers()); + afterAll(() => server.close()); + it.todo("displays visual feedback to the user"); - it.todo("downloads the application file"); + + it("downloads the application file", async () => { + const { user } = setup( + , + ); + + const emailInput = screen.getByLabelText("Submission email address"); + await user.type(emailInput, "submission@council.com"); + await user.click(screen.getByRole("button", { name: "Continue" })); + + await waitFor(() => + expect(downloadZipFile).toHaveBeenCalledWith(mockData, { + // the filename should be in the form `${flow}-${sessionId}.zip` + filename: "undefined-a-session-id.zip", // undefined as we have not mocked a flow + }), + ); + }); }); describe("when the user submits an incorrect email address", () => { From ee13ecdc4be8da5f0e2235bb20cefc8f68002a0b Mon Sep 17 00:00:00 2001 From: Jo Humphrey <31373245+jamdelion@users.noreply.github.com> Date: Mon, 6 Jan 2025 17:54:54 +0000 Subject: [PATCH 6/9] Fill in error handling tests --- .../tests/VerifySubmissionEmail.test.tsx | 64 +++++++++++++++++-- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx b/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx index ba3933cb07..8117011bfa 100644 --- a/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx +++ b/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx @@ -70,8 +70,6 @@ describe("when the user submits a correct email address", () => { afterEach(() => server.resetHandlers()); afterAll(() => server.close()); - it.todo("displays visual feedback to the user"); - it("downloads the application file", async () => { const { user } = setup( { }); describe("when the user submits an incorrect email address", () => { - it.todo("displays a suitable error message"); + const server = setupServer( + http.get( + "http://localhost:7002/download-application-files/a-session-id/?email=wrong_email%40council.com&localAuthority=barking-and-dagenham", + () => { + return new HttpResponse(null, { status: 403 }); + }, + ), + ); + + beforeAll(() => server.listen()); + afterEach(() => server.resetHandlers()); + afterAll(() => server.close()); + + it("displays a suitable error message", async () => { + const { user } = setup( + , + ); + const emailInput = screen.getByLabelText("Submission email address"); + await user.type(emailInput, "wrong_email@council.com"); + await user.click(screen.getByRole("button", { name: "Continue" })); + + await waitFor(() => + expect( + screen.getByText("Sorry, something went wrong. Please try again."), + ).toBeInTheDocument(), + ); + }); }); -describe("when user submits an email address and there is a server-side issue", () => { - it.todo("displays a suitable error message"); +describe("when user submits a correct email address but there is a server-side issue", () => { + const server = setupServer( + http.get( + "http://localhost:7002/download-application-files/a-session-id/?email=submission%40council.com&localAuthority=barking-and-dagenham", + () => { + return new HttpResponse(null, { status: 500 }); + }, + ), + ); + + beforeAll(() => server.listen()); + afterEach(() => server.resetHandlers()); + afterAll(() => server.close()); + + it("displays a suitable error message", async () => { + const { user } = setup( + , + ); + const emailInput = screen.getByLabelText("Submission email address"); + await user.type(emailInput, "submission@council.com"); + await user.click(screen.getByRole("button", { name: "Continue" })); + + await waitFor(() => + expect( + screen.getByText("Sorry, something went wrong. Please try again."), + ).toBeInTheDocument(), + ); + }); }); From 3325882b12aa79f715701e268221cdf5d1d30774 Mon Sep 17 00:00:00 2001 From: Jo Humphrey <31373245+jamdelion@users.noreply.github.com> Date: Mon, 6 Jan 2025 18:34:40 +0000 Subject: [PATCH 7/9] Refactor to separate mockServer and handlers folder --- .../handlers/mockDownloadApplicationFile.ts | 25 +++++++++ editor.planx.uk/src/mockServer/server.ts | 5 ++ .../tests/VerifySubmissionEmail.test.tsx | 52 ++++--------------- editor.planx.uk/src/setupTests.tsx | 9 +++- 4 files changed, 48 insertions(+), 43 deletions(-) create mode 100644 editor.planx.uk/src/mockServer/handlers/mockDownloadApplicationFile.ts create mode 100644 editor.planx.uk/src/mockServer/server.ts diff --git a/editor.planx.uk/src/mockServer/handlers/mockDownloadApplicationFile.ts b/editor.planx.uk/src/mockServer/handlers/mockDownloadApplicationFile.ts new file mode 100644 index 0000000000..8d7767f3fa --- /dev/null +++ b/editor.planx.uk/src/mockServer/handlers/mockDownloadApplicationFile.ts @@ -0,0 +1,25 @@ +import { http, HttpResponse } from "msw"; +import { DOWNLOAD_APPLICATION_FILE_URL } from "pages/SubmissionDownload/VerifySubmissionEmail"; + +export const mockData = new ArrayBuffer(); + +export const getWithData = http.get( + `${DOWNLOAD_APPLICATION_FILE_URL}/a-session-id/?email=submission%40council.com&localAuthority=barking-and-dagenham`, + () => { + return new HttpResponse(mockData, { status: 200 }); + }, +); + +export const getWithServerSideError = http.get( + `${DOWNLOAD_APPLICATION_FILE_URL}/a-session-id/?email=submission%40council.com&localAuthority=barking-and-dagenham`, + () => { + return new HttpResponse(null, { status: 500 }); + }, +); + +export const getWith403 = http.get( + `${DOWNLOAD_APPLICATION_FILE_URL}/a-session-id/?email=wrong_email%40council.com&localAuthority=barking-and-dagenham`, + () => { + return new HttpResponse(null, { status: 403 }); + }, +); diff --git a/editor.planx.uk/src/mockServer/server.ts b/editor.planx.uk/src/mockServer/server.ts new file mode 100644 index 0000000000..7826431e60 --- /dev/null +++ b/editor.planx.uk/src/mockServer/server.ts @@ -0,0 +1,5 @@ +import { setupServer } from "msw/node"; + +const server = setupServer(); + +export default server; diff --git a/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx b/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx index 8117011bfa..3708d55ac9 100644 --- a/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx +++ b/editor.planx.uk/src/pages/SubmissionDownload/tests/VerifySubmissionEmail.test.tsx @@ -1,6 +1,11 @@ import { screen, waitFor } from "@testing-library/react"; -import { http, HttpResponse } from "msw"; -import { setupServer } from "msw/node"; +import { + getWith403, + getWithData, + getWithServerSideError, + mockData, +} from "mockServer/handlers/mockDownloadApplicationFile"; +import server from "mockServer/server"; import React from "react"; import { setup } from "testUtils"; import { vi } from "vitest"; @@ -56,21 +61,8 @@ describe("when the VerifySubmissionEmail component renders", () => { }); describe("when the user submits a correct email address", () => { - const mockData = new ArrayBuffer(); - const server = setupServer( - http.get( - "http://localhost:7002/download-application-files/a-session-id/?email=submission%40council.com&localAuthority=barking-and-dagenham", - () => { - return new HttpResponse(mockData, { status: 200 }); - }, - ), - ); - - beforeAll(() => server.listen()); - afterEach(() => server.resetHandlers()); - afterAll(() => server.close()); - it("downloads the application file", async () => { + server.use(getWithData); const { user } = setup( { }); describe("when the user submits an incorrect email address", () => { - const server = setupServer( - http.get( - "http://localhost:7002/download-application-files/a-session-id/?email=wrong_email%40council.com&localAuthority=barking-and-dagenham", - () => { - return new HttpResponse(null, { status: 403 }); - }, - ), - ); - - beforeAll(() => server.listen()); - afterEach(() => server.resetHandlers()); - afterAll(() => server.close()); - it("displays a suitable error message", async () => { + server.use(getWith403); const { user } = setup( { }); describe("when user submits a correct email address but there is a server-side issue", () => { - const server = setupServer( - http.get( - "http://localhost:7002/download-application-files/a-session-id/?email=submission%40council.com&localAuthority=barking-and-dagenham", - () => { - return new HttpResponse(null, { status: 500 }); - }, - ), - ); - - beforeAll(() => server.listen()); - afterEach(() => server.resetHandlers()); - afterAll(() => server.close()); - it("displays a suitable error message", async () => { + server.use(getWithServerSideError); const { user } = setup(
{children}
); -vi.mock("@mui/material/Fade", () => ({ +vi.doMock("@mui/material/Fade", () => ({ default: mockFade, })); beforeEach(() => { mockFade.mockClear(); }); + +beforeAll(() => server.listen()); + +afterEach(() => server.resetHandlers()); + +afterAll(() => server.close()); From 5b1b5162423f899cdb1857a72729d73b82c6f311 Mon Sep 17 00:00:00 2001 From: Jo Humphrey <31373245+jamdelion@users.noreply.github.com> Date: Mon, 6 Jan 2025 18:40:53 +0000 Subject: [PATCH 8/9] Add byte number to array buffer --- .../src/mockServer/handlers/mockDownloadApplicationFile.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor.planx.uk/src/mockServer/handlers/mockDownloadApplicationFile.ts b/editor.planx.uk/src/mockServer/handlers/mockDownloadApplicationFile.ts index 8d7767f3fa..895e2b64e8 100644 --- a/editor.planx.uk/src/mockServer/handlers/mockDownloadApplicationFile.ts +++ b/editor.planx.uk/src/mockServer/handlers/mockDownloadApplicationFile.ts @@ -1,7 +1,7 @@ import { http, HttpResponse } from "msw"; import { DOWNLOAD_APPLICATION_FILE_URL } from "pages/SubmissionDownload/VerifySubmissionEmail"; -export const mockData = new ArrayBuffer(); +export const mockData = new ArrayBuffer(100); // a byte number is needed export const getWithData = http.get( `${DOWNLOAD_APPLICATION_FILE_URL}/a-session-id/?email=submission%40council.com&localAuthority=barking-and-dagenham`, From 7c86786d8c54e46061e4effc59b9de0c5a418127 Mon Sep 17 00:00:00 2001 From: Jo Humphrey <31373245+jamdelion@users.noreply.github.com> Date: Wed, 8 Jan 2025 15:40:10 +0000 Subject: [PATCH 9/9] imports --- editor.planx.uk/pnpm-lock.yaml | 42 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/editor.planx.uk/pnpm-lock.yaml b/editor.planx.uk/pnpm-lock.yaml index 1fc8740a7c..638c09d315 100644 --- a/editor.planx.uk/pnpm-lock.yaml +++ b/editor.planx.uk/pnpm-lock.yaml @@ -48,8 +48,8 @@ dependencies: specifier: 1.0.0-alpha.4 version: 1.0.0-alpha.4 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#d004278 - version: github.com/theopensystemslab/planx-core/d004278(@types/react@18.2.45) + specifier: git+https://github.com/theopensystemslab/planx-core#dc2386b + version: github.com/theopensystemslab/planx-core/dc2386b(@types/react@18.2.45) '@tiptap/core': specifier: ^2.4.0 version: 2.4.0(@tiptap/pm@2.0.3) @@ -2738,31 +2738,31 @@ packages: react: 18.2.0 dev: true - /@formatjs/ecma402-abstract@2.3.1: - resolution: {integrity: sha512-Ip9uV+/MpLXWRk03U/GzeJMuPeOXpJBSB5V1tjA6kJhvqssye5J5LoYLc7Z5IAHb7nR62sRoguzrFiVCP/hnzw==} + /@formatjs/ecma402-abstract@2.3.2: + resolution: {integrity: sha512-6sE5nyvDloULiyOMbOTJEEgWL32w+VHkZQs8S02Lnn8Y/O5aQhjOEXwWzvR7SsBE/exxlSpY2EsWZgqHbtLatg==} dependencies: - '@formatjs/fast-memoize': 2.2.5 - '@formatjs/intl-localematcher': 0.5.9 + '@formatjs/fast-memoize': 2.2.6 + '@formatjs/intl-localematcher': 0.5.10 decimal.js: 10.4.3 tslib: 2.8.1 dev: false - /@formatjs/fast-memoize@2.2.5: - resolution: {integrity: sha512-6PoewUMrrcqxSoBXAOJDiW1m+AmkrAj0RiXnOMD59GRaswjXhm3MDhgepXPBgonc09oSirAJTsAggzAGQf6A6g==} + /@formatjs/fast-memoize@2.2.6: + resolution: {integrity: sha512-luIXeE2LJbQnnzotY1f2U2m7xuQNj2DA8Vq4ce1BY9ebRZaoPB1+8eZ6nXpLzsxuW5spQxr7LdCg+CApZwkqkw==} dependencies: tslib: 2.8.1 dev: false - /@formatjs/intl-listformat@7.7.8: - resolution: {integrity: sha512-ezlfqfyegMbepGVcf3rTApVGIbZQvJwx1PZsXjMe2xAqEU1jSBZ/2efLE8u3sUBHGrrsdWER98W85zCg4N7rmQ==} + /@formatjs/intl-listformat@7.7.9: + resolution: {integrity: sha512-VGbGrngcjwrlPvstc6ysCwGlbxaq3PKXSkC9P5DYyfLI+C6I+PIog9UW8rPwH1xLXMfmyZblrkvkRboGn3E8qA==} dependencies: - '@formatjs/ecma402-abstract': 2.3.1 - '@formatjs/intl-localematcher': 0.5.9 + '@formatjs/ecma402-abstract': 2.3.2 + '@formatjs/intl-localematcher': 0.5.10 tslib: 2.8.1 dev: false - /@formatjs/intl-localematcher@0.5.9: - resolution: {integrity: sha512-8zkGu/sv5euxbjfZ/xmklqLyDGQSxsLqg8XOq88JW3cmJtzhCP8EtSJXlaKZnVO4beEaoiT9wj4eIoCQ9smwxA==} + /@formatjs/intl-localematcher@0.5.10: + resolution: {integrity: sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q==} dependencies: tslib: 2.8.1 dev: false @@ -14048,8 +14048,8 @@ packages: dev: false optional: true - /uuid@11.0.3: - resolution: {integrity: sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==} + /uuid@11.0.4: + resolution: {integrity: sha512-IzL6VtTTYcAhA/oghbFJ1Dkmqev+FpQWnCBaKq/gUluLxliWvO8DPFWfIviRmYbtaavtSQe4WBL++rFjdcGWEg==} hasBin: true dev: false @@ -14694,9 +14694,9 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false - github.com/theopensystemslab/planx-core/d004278(@types/react@18.2.45): - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/d004278} - id: github.com/theopensystemslab/planx-core/d004278 + github.com/theopensystemslab/planx-core/dc2386b(@types/react@18.2.45): + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/dc2386b} + id: github.com/theopensystemslab/planx-core/dc2386b name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true @@ -14704,7 +14704,7 @@ packages: dependencies: '@emotion/react': 11.14.0(@types/react@18.2.45)(react@18.3.1) '@emotion/styled': 11.14.0(@emotion/react@11.14.0)(@types/react@18.2.45)(react@18.3.1) - '@formatjs/intl-listformat': 7.7.8 + '@formatjs/intl-listformat': 7.7.9 '@mui/base': 5.0.0-beta.60(@types/react@18.2.45)(react-dom@18.3.1)(react@18.3.1) '@mui/material': 5.15.10(@emotion/react@11.14.0)(@emotion/styled@11.14.0)(@types/react@18.2.45)(react-dom@18.3.1)(react@18.3.1) ajv: 8.17.1 @@ -14723,7 +14723,7 @@ packages: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) type-fest: 4.31.0 - uuid: 11.0.3 + uuid: 11.0.4 zod: 3.24.1 transitivePeerDependencies: - '@types/react'