diff --git a/editor.planx.uk/.eslintrc b/editor.planx.uk/.eslintrc index 6b6e104b8f..54d1d6fbfd 100644 --- a/editor.planx.uk/.eslintrc +++ b/editor.planx.uk/.eslintrc @@ -5,13 +5,15 @@ "react-hooks", "simple-import-sort", "jsx-a11y", - "testing-library" + "testing-library", + "@vitest" ], "extends": [ "eslint:recommended", "plugin:jsx-a11y/recommended", "plugin:@typescript-eslint/recommended", - "prettier" + "prettier", + "plugin:@vitest/legacy-recommended" ], "rules": { "react-hooks/rules-of-hooks": "error", diff --git a/editor.planx.uk/package.json b/editor.planx.uk/package.json index 1b4a16f2e4..a2af9c9100 100644 --- a/editor.planx.uk/package.json +++ b/editor.planx.uk/package.json @@ -135,6 +135,7 @@ "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.58.0", + "@vitest/eslint-plugin": "^1.1.4", "autoprefixer": "^10.4.16", "css-loader": "^6.10.0", "esbuild": "^0.21.3", @@ -176,6 +177,7 @@ "storybook": "storybook dev -p 6006", "build-storybook": "mkdir -p build && storybook build --quiet --output-dir ./build/storybook", "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}' && prettier -c ./src", + "lint:error": "eslint --quiet 'src/**/*.{js,jsx,ts,tsx}' && prettier -c ./src", "lint:fix": "eslint --fix 'src/**/*.{js,jsx,ts,tsx}' && prettier -w ./src", "check": "tsc --noEmit && pnpm lint", "prepare": "cd .. && husky install editor.planx.uk/.husky" diff --git a/editor.planx.uk/pnpm-lock.yaml b/editor.planx.uk/pnpm-lock.yaml index 772015ebdf..f166824005 100644 --- a/editor.planx.uk/pnpm-lock.yaml +++ b/editor.planx.uk/pnpm-lock.yaml @@ -402,6 +402,9 @@ devDependencies: '@typescript-eslint/parser': specifier: ^5.58.0 version: 5.58.0(eslint@8.44.0)(typescript@5.6.2) + '@vitest/eslint-plugin': + specifier: ^1.1.4 + version: 1.1.4(eslint@8.44.0)(typescript@5.6.2)(vitest@1.6.0) autoprefixer: specifier: ^10.4.16 version: 10.4.16(postcss@8.4.32) @@ -4334,7 +4337,7 @@ packages: '@storybook/csf': 0.1.11 '@storybook/global': 5.0.0 '@storybook/icons': 1.2.12(react-dom@18.2.0)(react@18.2.0) - '@types/lodash': 4.17.9 + '@types/lodash': 4.14.202 color-convert: 2.0.1 dequal: 2.0.3 lodash: 4.17.21 @@ -4394,14 +4397,14 @@ packages: /@storybook/client-logger@6.5.16: resolution: {integrity: sha512-pxcNaCj3ItDdicPTXTtmYJE3YC1SjxFrBmHcyrN+nffeNyiMuViJdOOZzzzucTUG0wcOOX8jaSyak+nnHg5H1Q==} dependencies: - core-js: 3.38.1 + core-js: 3.31.0 global: 4.4.0 dev: true - /@storybook/components@8.3.3(storybook@8.3.1): - resolution: {integrity: sha512-i2JYtesFGkdu+Hwuj+o9fLuO3yo+LPT1/8o5xBVYtEqsgDtEAyuRUWjSz8d8NPtzloGPOv5kvR6MokWDfbeMfw==} + /@storybook/components@8.3.4(storybook@8.3.1): + resolution: {integrity: sha512-iQzLJd87uGbFBbYNqlrN/ABrnx3dUrL0tjPCarzglzshZoPCNOsllJeJx5TJwB9kCxSZ8zB9TTOgr7NXl+oyVA==} peerDependencies: - storybook: ^8.3.3 + storybook: ^8.3.4 dependencies: storybook: 8.3.1 dev: true @@ -4499,10 +4502,10 @@ packages: storybook: 8.3.1 dev: true - /@storybook/preview-api@8.3.3(storybook@8.3.1): - resolution: {integrity: sha512-GP2QlaF3BBQGAyo248N7549YkTQjCentsc1hUvqPnFWU4xfjkejbnFk8yLaIw0VbYbL7jfd7npBtjZ+6AnphMQ==} + /@storybook/preview-api@8.3.4(storybook@8.3.1): + resolution: {integrity: sha512-/YKQ3QDVSHmtFXXCShf5w0XMlg8wkfTpdYxdGv1CKFV8DU24f3N7KWulAgeWWCWQwBzZClDa9kzxmroKlQqx3A==} peerDependencies: - storybook: ^8.3.3 + storybook: ^8.3.4 dependencies: storybook: 8.3.1 dev: true @@ -4566,10 +4569,10 @@ packages: typescript: optional: true dependencies: - '@storybook/components': 8.3.3(storybook@8.3.1) + '@storybook/components': 8.3.4(storybook@8.3.1) '@storybook/global': 5.0.0 '@storybook/manager-api': 8.3.1(storybook@8.3.1) - '@storybook/preview-api': 8.3.3(storybook@8.3.1) + '@storybook/preview-api': 8.3.4(storybook@8.3.1) '@storybook/react-dom-shim': 8.3.1(react-dom@18.2.0)(react@18.2.0)(storybook@8.3.1) '@storybook/test': 8.3.1(storybook@8.3.1) '@storybook/theming': 8.3.1(storybook@8.3.1) @@ -5535,6 +5538,7 @@ packages: /@types/lodash@4.17.9: resolution: {integrity: sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w==} + dev: false /@types/markdown-it@14.1.2: resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} @@ -5963,6 +5967,26 @@ packages: - '@swc/helpers' dev: false + /@vitest/eslint-plugin@1.1.4(eslint@8.44.0)(typescript@5.6.2)(vitest@1.6.0): + resolution: {integrity: sha512-kudjgefmJJ7xQ2WfbUU6pZbm7Ou4gLYRaao/8Ynide3G0QhVKHd978sDyWX4KOH0CCMH9cyrGAkFd55eGzJ48Q==} + peerDependencies: + '@typescript-eslint/utils': '>= 8.0' + eslint: '>= 8.57.0' + typescript: '>= 5.0.0' + vitest: '*' + peerDependenciesMeta: + '@typescript-eslint/utils': + optional: true + typescript: + optional: true + vitest: + optional: true + dependencies: + eslint: 8.44.0 + typescript: 5.6.2 + vitest: 1.6.0(@types/node@17.0.45)(sass@1.71.1) + dev: true + /@vitest/expect@1.6.0: resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} dependencies: @@ -6975,7 +6999,7 @@ packages: dependencies: '@babel/runtime': 7.25.6 '@types/raf': 3.4.3 - core-js: 3.38.1 + core-js: 3.31.0 raf: 3.4.1 regenerator-runtime: 0.13.11 rgbcolor: 1.0.1 @@ -7410,6 +7434,7 @@ packages: /core-js@3.38.1: resolution: {integrity: sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==} requiresBuild: true + dev: true /core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -10606,7 +10631,7 @@ packages: fflate: 0.8.2 optionalDependencies: canvg: 3.0.10 - core-js: 3.38.1 + core-js: 3.31.0 dompurify: 2.5.7 html2canvas: 1.4.1 dev: false diff --git a/editor.planx.uk/src/components/Header.test.tsx b/editor.planx.uk/src/components/Header.test.tsx index 781b57aa1e..8c5f303976 100644 --- a/editor.planx.uk/src/components/Header.test.tsx +++ b/editor.planx.uk/src/components/Header.test.tsx @@ -172,11 +172,11 @@ for (const route of ["/published", "/preview", "/draft", "/pay", "/invite"]) { expect(screen.getByText("test flow")).toBeInTheDocument(); }); - // it("should not have any accessibility violations", async () => { - // const { container } = setup(
); - // const results = await axe(container); - // expect(results).toHaveNoViolations(); - // }); + it("should not have any accessibility violations", async () => { + const { container } = setup(
); + const results = await axe(container); + expect(results).toHaveNoViolations(); + }); }); } @@ -224,13 +224,13 @@ describe("Section navigation bar", () => { expect(screen.getByText("First section")).toBeInTheDocument(); }); - // it("should not have any accessibility violations", async () => { - // act(() => setState({ flow: flowWithThreeSections })); - // act(() => getState().initNavigationStore()); - // const { container } = setup(
); + it("should not have any accessibility violations", async () => { + act(() => setState({ flow: flowWithThreeSections })); + act(() => getState().initNavigationStore()); + const { container } = setup(
); - // const results = await axe(container); - // expect(results).toHaveNoViolations(); - // }); + const results = await axe(container); + expect(results).toHaveNoViolations(); + }); }); }); diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/FlowStatus/PublicLink.test.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/FlowStatus/PublicLink.test.tsx index 54b1a11359..cef3157b4b 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/FlowStatus/PublicLink.test.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Settings/ServiceSettings/FlowStatus/PublicLink.test.tsx @@ -57,12 +57,14 @@ describe("A team with a subdomain has an offline, published service.", () => { setupServiceSettingsScreen(); }); + // eslint-disable-next-line @vitest/expect-expect it("has a public link with the subdomain url in a

tag", async () => { const { flowSlug, teamDomain } = getState(); await inactiveLinkCheck(`https://${teamDomain}/${flowSlug}`); }); + // eslint-disable-next-line @vitest/expect-expect it("has a disabled copy button", disabledCopyCheck); }); @@ -79,12 +81,14 @@ describe("A team with a subdomain has an online, unpublished service.", () => { setupServiceSettingsScreen(); }); + // eslint-disable-next-line @vitest/expect-expect it("has a public link with the subdomain url in a

tag", async () => { const { flowSlug, teamDomain } = getState(); await inactiveLinkCheck(`https://${teamDomain}/${flowSlug}`); }); + // eslint-disable-next-line @vitest/expect-expect it("has a disabled copy button", disabledCopyCheck); }); @@ -102,6 +106,7 @@ describe("A team with a subdomain has an online, published service.", () => { ); }); + // eslint-disable-next-line @vitest/expect-expect it("has a public link with the subdomain url in an tag", async () => { // render the comp const { flowSlug, teamDomain } = getState(); @@ -110,6 +115,7 @@ describe("A team with a subdomain has an online, published service.", () => { await activeLinkCheck(`https://${teamDomain}/${flowSlug}`); }); + // eslint-disable-next-line @vitest/expect-expect it("has an enabled copy button", async () => { // render the comp await setupServiceSettingsScreen(); @@ -145,12 +151,14 @@ describe("A team with a subdomain has an offline, unpublished service.", () => { setupServiceSettingsScreen(); }); + // eslint-disable-next-line @vitest/expect-expect it("has a public link with the subdomain url in a

tag", async () => { const { flowSlug, teamDomain } = getState(); await inactiveLinkCheck(`https://${teamDomain}/${flowSlug}`); }); + // eslint-disable-next-line @vitest/expect-expect it("has a disabled copy button", disabledCopyCheck); }); @@ -172,10 +180,12 @@ describe("A team without a subdomain has an offline, published service.", () => setupServiceSettingsScreen(); }); + // eslint-disable-next-line @vitest/expect-expect it("has a public link with the url in a

tag", async () => { await inactiveLinkCheck(publishedUrl); }); + // eslint-disable-next-line @vitest/expect-expect it("has a disabled copy button", disabledCopyCheck); }); @@ -197,10 +207,12 @@ describe("A team without a subdomain has an online, unpublished service.", () => setupServiceSettingsScreen(); }); + // eslint-disable-next-line @vitest/expect-expect it("has a public link with the url in a

tag", async () => { await inactiveLinkCheck(publishedUrl); }); + // eslint-disable-next-line @vitest/expect-expect it("has a disabled copy button", disabledCopyCheck); }); @@ -223,12 +235,14 @@ describe("A team without a subdomain has an online, published service.", () => { ); }); + // eslint-disable-next-line @vitest/expect-expect it("has a public link with the subdomain url in an tag", async () => { // render the comp setupServiceSettingsScreen(); await activeLinkCheck(publishedUrl); }); + // eslint-disable-next-line @vitest/expect-expect it("has an enabled copy button", () => { // render the comp setupServiceSettingsScreen(); @@ -265,9 +279,11 @@ describe("A team without a subdomain has an offline, unpublished service.", () = setupServiceSettingsScreen(); }); + // eslint-disable-next-line @vitest/expect-expect it("has a public link with the url in a

tag", async () => { await inactiveLinkCheck(publishedUrl); }); + // eslint-disable-next-line @vitest/expect-expect it("has a disabled copy button", disabledCopyCheck); });