diff --git a/.github/workflows/sync-staging-db.yml b/.github/workflows/sync-staging-db.yml index 03f0dc775b..2c8930f161 100644 --- a/.github/workflows/sync-staging-db.yml +++ b/.github/workflows/sync-staging-db.yml @@ -2,8 +2,8 @@ name: Weekly staging database sync on: schedule: - # Runs Sunday at 00:00 (https://crontab.guru/#0_0_*_*_0) - - cron: '0 0 * * 0' + # Runs nightly at 00:00 (https://crontab.guru/#0_0_*_*_*) + - cron: '0 0 * * *' workflow_dispatch: jobs: diff --git a/editor.planx.uk/src/@planx/components/ContactInput/Public.test.tsx b/editor.planx.uk/src/@planx/components/ContactInput/Public.test.tsx index d208d7ed82..7b5debb6f4 100644 --- a/editor.planx.uk/src/@planx/components/ContactInput/Public.test.tsx +++ b/editor.planx.uk/src/@planx/components/ContactInput/Public.test.tsx @@ -216,3 +216,32 @@ it("should not have any accessibility violations while in the error state", asyn const results = await axe(container); expect(results).toHaveNoViolations(); }); + +test("does not allow the name 'Test Test' to be used", async () => { + const handleSubmit = jest.fn(); + const dataField = "applicant"; + + const { user } = setup( + + ); + + await fillInFieldsUsingLabel(user, { + "First name": "Test", + "Last name": "Test", + "Phone number": "0123456789", + "Email address": "test@gov.uk", + }); + + await user.click(screen.getByTestId("continue-button")); + + expect(handleSubmit).not.toHaveBeenCalled(); + + const errorMessage = await screen.findByText( + "'Test Test' is not a valid name - please submit test applications via the staging environment" + ); + expect(errorMessage).toBeVisible(); +}); diff --git a/editor.planx.uk/src/@planx/components/ContactInput/model.ts b/editor.planx.uk/src/@planx/components/ContactInput/model.ts index db3c6b9650..abdfaebfb6 100644 --- a/editor.planx.uk/src/@planx/components/ContactInput/model.ts +++ b/editor.planx.uk/src/@planx/components/ContactInput/model.ts @@ -23,6 +23,22 @@ export const userDataSchema: SchemaOf = object({ "Enter an email address in the correct format, like name@example.com" ) .required("Enter an email address"), +}).test({ + name: "Test Test is not used for applications", + test: ({ firstName, lastName }, context) => { + const isValid = + [firstName, lastName] + .map((x) => String(x).toLowerCase().trim()) + .join("|") !== "test|test"; + + if (isValid) return true; + + return context.createError({ + path: "firstName", + message: + "'Test Test' is not a valid name - please submit test applications via the staging environment", + }); + }, }); export interface ContactInput extends MoreInformation { diff --git a/editor.planx.uk/src/@planx/components/Pay/Public/Pay.tsx b/editor.planx.uk/src/@planx/components/Pay/Public/Pay.tsx index 3da23168b2..3fb054f702 100644 --- a/editor.planx.uk/src/@planx/components/Pay/Public/Pay.tsx +++ b/editor.planx.uk/src/@planx/components/Pay/Public/Pay.tsx @@ -9,7 +9,7 @@ import React, { useEffect, useReducer } from "react"; import type { GovUKPayment, Passport, Session } from "types"; import { PaymentStatus } from "types"; -import { makeData, useStagingUrlIfTestApplication } from "../../shared/utils"; +import { makeData } from "../../shared/utils"; import { createPayload, GOV_PAY_PASSPORT_KEY, @@ -157,7 +157,6 @@ function Component(props: Props) { sessionId, flowId, teamSlug, - passport, paymentId: govUkPayment?.payment_id, }) ); @@ -223,7 +222,7 @@ function Component(props: Props) { } await axios .post( - getGovUkPayUrlForTeam({ sessionId, flowId, teamSlug, passport }), + getGovUkPayUrlForTeam({ sessionId, flowId, teamSlug }), createPayload(fee, sessionId) ) .then(async (res) => { @@ -294,18 +293,14 @@ function getGovUkPayUrlForTeam({ sessionId, flowId, teamSlug, - passport, paymentId, }: { sessionId: string; flowId: string; teamSlug: string; - passport: Passport; paymentId?: string; }): string { - const baseURL = useStagingUrlIfTestApplication(passport)( - `${GOV_UK_PAY_URL}/${teamSlug}` - ); + const baseURL = `${GOV_UK_PAY_URL}/${teamSlug}`; const queryString = `?sessionId=${sessionId}&flowId=${flowId}`; if (paymentId) { return `${baseURL}/${paymentId}${queryString}`; diff --git a/editor.planx.uk/src/@planx/components/Send/Public.tsx b/editor.planx.uk/src/@planx/components/Send/Public.tsx index 21543ceb47..b607163355 100644 --- a/editor.planx.uk/src/@planx/components/Send/Public.tsx +++ b/editor.planx.uk/src/@planx/components/Send/Public.tsx @@ -5,7 +5,7 @@ import React, { useEffect } from "react"; import { useAsync } from "react-use"; import Card from "../shared/Preview/Card"; -import { makeData, useStagingUrlIfTestApplication } from "../shared/utils"; +import { makeData } from "../shared/utils"; import { PublicProps } from "../ui"; import { DEFAULT_DESTINATION, @@ -36,10 +36,7 @@ const SendComponent: React.FC = ({ sessionId, }); - return axios.post( - useStagingUrlIfTestApplication(passport)(url), - combinedEventsPayload - ); + return axios.post(url, combinedEventsPayload); }); useEffect(() => { diff --git a/editor.planx.uk/src/@planx/components/shared/utils.test.ts b/editor.planx.uk/src/@planx/components/shared/utils.test.ts deleted file mode 100644 index 7178a3f698..0000000000 --- a/editor.planx.uk/src/@planx/components/shared/utils.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { - getPreviouslySubmittedData, - useStagingUrlIfTestApplication, -} from "./utils"; - -describe("useStagingUrlIfTestApplication()", () => { - test("replaces URL if test user", () => { - const url = useStagingUrlIfTestApplication({ - data: { - "applicant.name.first": "Test ", - "applicant.name.last": "test", - }, - })("https://api.editor.planx.uk/bops/southwark"); - - expect(url).toStrictEqual("https://api.editor.planx.dev/bops/southwark"); - }); - - test("doesn't replace URL if not a test user", () => { - const url = useStagingUrlIfTestApplication({ - data: { - applicant: { - "name.first": "Regular", - "name.last": "User", - }, - }, - })("https://api.editor.planx.uk/pay"); - - expect(url).toStrictEqual("https://api.editor.planx.uk/pay"); - }); - - test("returns correct result providing an id", () => { - const data = { - id: "some-id", - previouslySubmittedData: { - data: { - "some-id": 1234, - randomAttribute: "abcd", - }, - }, - }; - - expect(getPreviouslySubmittedData(data)).toEqual(1234); - }); - - test("returns correct result providing an fn value", () => { - const data = { - id: "some-id", - fn: "data-field", - previouslySubmittedData: { - data: { - "data-field": 1234, - randomAttribute: "abcd", - }, - }, - }; - - expect(getPreviouslySubmittedData(data)).toEqual(1234); - }); -}); diff --git a/editor.planx.uk/src/@planx/components/shared/utils.ts b/editor.planx.uk/src/@planx/components/shared/utils.ts index 7bb157c86f..c03a2da64c 100644 --- a/editor.planx.uk/src/@planx/components/shared/utils.ts +++ b/editor.planx.uk/src/@planx/components/shared/utils.ts @@ -1,7 +1,4 @@ import isNil from "lodash/isNil"; -import { Store } from "pages/FlowEditor/lib/store"; - -import { bopsDictionary } from "../Send/bops"; export const validateEmail = (email: string) => { // eslint-disable-next-line @@ -49,36 +46,6 @@ export const makeData = ( }; }; -/** - * Replaces a URL containing planx.uk with planx.dev - * if the passport appears to contain test data. - * Explanation: https://bit.ly/3AypxGW - * - * @example - * useStagingUrlIfTestApplication(passport)("https://api.editor.planx.uk/test") - * // when applicant's full name is 'Test Test' - * // => "https://api.editor.planx.dev/test" - * // otherwise - * // => "https://api.editor.planx.uk/test" - */ -export const useStagingUrlIfTestApplication = - (passport: Store.passport) => (urlThatMightBeReplaced: string) => { - if ( - [ - passport.data?.[bopsDictionary.applicant_first_name], - passport.data?.[bopsDictionary.applicant_last_name], - ] - .map((x) => String(x).toLowerCase().trim()) - .join("|") === "test|test" - ) { - const url = new URL(urlThatMightBeReplaced); - url.hostname = url.hostname.replace("planx.uk", "planx.dev"); - return url.href; - } - - return urlThatMightBeReplaced; - }; - export const getPreviouslySubmittedData = ({ id, fn, diff --git a/editor.planx.uk/src/api/upload.ts b/editor.planx.uk/src/api/upload.ts index b68e1ce45e..8671312db3 100644 --- a/editor.planx.uk/src/api/upload.ts +++ b/editor.planx.uk/src/api/upload.ts @@ -1,4 +1,3 @@ -import { useStagingUrlIfTestApplication } from "@planx/components/shared/utils"; import axios from "axios"; import { useStore } from "pages/FlowEditor/lib/store"; @@ -41,9 +40,7 @@ function handleUpload( // Private uploads for test applications should be handled by the staging environment const paths = { public: `${process.env.REACT_APP_API_URL}/public-file-upload`, - private: useStagingUrlIfTestApplication(passport)( - `${process.env.REACT_APP_API_URL}/private-file-upload` - ), + private: `${process.env.REACT_APP_API_URL}/private-file-upload`, }; const endpoint = paths[path];