Skip to content

Commit

Permalink
feat: demo team integrations to fail gracefully (#3938)
Browse files Browse the repository at this point in the history
  • Loading branch information
RODO94 authored Nov 19, 2024
1 parent 68407a3 commit 0b080a5
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 13 deletions.
6 changes: 1 addition & 5 deletions editor.planx.uk/src/@planx/components/Pay/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import DataObjectIcon from "@mui/icons-material/DataObject";
import Box from "@mui/material/Box";
import FormControlLabel from "@mui/material/FormControlLabel";
import Link from "@mui/material/Link";
import Typography from "@mui/material/Typography";
import {
Expand Down Expand Up @@ -352,10 +351,7 @@ const Component: React.FC<Props> = (props: Props) => {
<Switch
checked={values.allowInviteToPay}
onChange={() =>
setFieldValue(
"allowInviteToPay",
!values.allowInviteToPay,
)
setFieldValue("allowInviteToPay", !values.allowInviteToPay)
}
label="Allow applicants to invite someone else to pay"
/>
Expand Down
28 changes: 28 additions & 0 deletions editor.planx.uk/src/@planx/components/Pay/Public/Pay.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -450,3 +450,31 @@ describe("Confirm component in information-only mode", () => {
expect(results).toHaveNoViolations();
});
});

describe("the demo user view", () => {
beforeEach(() => {
act(() =>
setState({
teamSlug: "demo",
}),
);
});
it("should render an error when teamSlug is demo", async () => {
const handleSubmit = vi.fn();
const { queryByText } = setup(
<Pay
title="Pay for your application"
fn="application.fee.typo"
handleSubmit={handleSubmit}
govPayMetadata={[]}
/>,
);
const errorHeader = queryByText("GOV.UK Pay is not enabled for demo users");
const errorGuidance = queryByText(
"Click continue to skip payment and proceed with your application for testing.",
);

expect(errorGuidance).toBeInTheDocument();
expect(errorHeader).toBeInTheDocument();
});
});
15 changes: 8 additions & 7 deletions editor.planx.uk/src/@planx/components/Pay/Public/Pay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ enum Action {
Success,
}

export const PAY_API_ERROR_UNSUPPORTED_TEAM =
"GOV.UK Pay is not enabled for this local authority";
export const PAY_API_ERROR_UNSUPPORTED_TEAM = "GOV.UK Pay is not enabled for";

function Component(props: Props) {
const [
Expand Down Expand Up @@ -114,6 +113,10 @@ function Component(props: Props) {

const handleError = useErrorHandler();

const isTeamSupported =
state.status !== "unsupported_team" && teamSlug !== "demo";
const showPayOptions = props.allowInviteToPay && !props.hidePay;

useEffect(() => {
// Auto-skip component when fee=0
if (fee <= 0) {
Expand Down Expand Up @@ -294,17 +297,15 @@ function Component(props: Props) {
: "Retry payment"
}
error={
(teamSlug === "demo" &&
"GOV.UK Pay is not enabled for demo users") ||
(state.status === "unsupported_team" &&
"GOV.UK Pay is not enabled for this local authority") ||
(state.status === "undefined_fee" &&
"We are unable to calculate your fee right now") ||
undefined
}
showInviteToPay={
props.allowInviteToPay &&
!props.hidePay &&
state.status !== "unsupported_team"
}
showInviteToPay={showPayOptions && isTeamSupported}
paymentStatus={govUkPayment?.state?.status}
hidePay={props.hidePay}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ vi.mock("swr", () => ({
}));

describe("error state", () => {
it("renders an error if no addres is present in the passport", async () => {
it("renders an error if no address is present in the passport", async () => {
const { getByRole, getByTestId } = setup(
<ErrorBoundary FallbackComponent={ErrorFallback}>
<PlanningConstraints
Expand Down Expand Up @@ -257,3 +257,51 @@ describe("following a FindProperty component", () => {
).toBeVisible();
});
});

describe("demo state", () => {
beforeEach(() => {
act(() =>
setState({
breadcrumbs: simpleBreadcrumbs,
flow: simpleFlow,
teamIntegrations: {
hasPlanningData: false,
},
teamSlug: "demo",
}),
);
});
it("should render an error when teamSlug is demo", async () => {
const handleSubmit = vi.fn();
const { queryByText, queryByRole, user, getByTestId } = setup(
<ErrorBoundary FallbackComponent={ErrorFallback}>
<PlanningConstraints
title="Planning constraints"
description="Things that might affect your project"
fn="property.constraints.planning"
disclaimer="This page does not include information about historic planning conditions that may apply to this property."
handleSubmit={handleSubmit}
/>
</ErrorBoundary>,
);

const errorMessage = queryByText(
"Planning Constraints are not enabled for demo users",
);
expect(errorMessage).toBeVisible();

// Check planning constraints has not rendered
// reused positive constraints from basic layout test
expect(
queryByRole("heading", { name: /These are the planning constraints/ }),
).not.toBeInTheDocument();
expect(
queryByRole("button", { name: /Parks and gardens/ }),
).not.toBeInTheDocument();

// Ensure a demo user can continue on in the application
await user.click(getByTestId("continue-button"));

expect(handleSubmit).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Typography from "@mui/material/Typography";
import type {
EnhancedGISResponse,
GISResponse,
Expand All @@ -13,6 +14,7 @@ import useSWR, { Fetcher } from "swr";
import { stringify } from "wkt";

import { SiteAddress } from "../FindProperty/model";
import { ErrorSummaryContainer } from "../shared/Preview/ErrorSummaryContainer";
import {
type IntersectingConstraints,
type PlanningConstraints,
Expand Down Expand Up @@ -195,6 +197,26 @@ function Component(props: Props) {
});
};

if (teamSlug === "demo") {
return (
<Card handleSubmit={props.handleSubmit}>
<CardHeader title={props.title} />
<ErrorSummaryContainer role="status">
<Typography variant="h4" ml={2} mb={1}>
Planning Constraints are not enabled for demo users
</Typography>
<Typography variant="body2" ml={2}>
Since we cannot automatically check constraints, you might be asked
additional questions about your project.
</Typography>
<Typography variant="body2" ml={2} mt={0.5}>
Click continue to proceed with your application.
</Typography>
</ErrorSummaryContainer>
</Card>
);
}

const isLoading = isValidating || isValidatingRoads;
if (isLoading)
return (
Expand Down
42 changes: 42 additions & 0 deletions editor.planx.uk/src/@planx/components/Send/Public.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,45 @@ it("should not have any accessibility violations", async () => {
const results = await axe(container);
expect(results).toHaveNoViolations();
});

describe("demo state", () => {
beforeEach(() => {
act(() =>
setState({
teamSlug: "demo",
}),
);
});
it("should render an error when teamSlug is demo", async () => {
const { queryByText } = setup(
<SendComponent title="Send" destinations={["bops", "uniform"]} />,
);

const errorHeader = queryByText(
"Send is not enabled for services created in the Demo team",
);
const errorGuidance = queryByText(
"Click continue to skip send and proceed with your application for testing.",
);

expect(errorHeader).toBeInTheDocument();
expect(errorGuidance).toBeInTheDocument();
});
it("should allow the user to continue with their application", async () => {
const handleSubmit = vi.fn();

const { findByRole, user } = setup(
<SendComponent
title="Send"
destinations={["bops", "uniform"]}
handleSubmit={handleSubmit}
/>,
);

const continueButton = await findByRole("button", { name: "Continue" });
expect(continueButton).toBeInTheDocument();

await user.click(continueButton);
expect(handleSubmit).toHaveBeenCalled();
});
});
18 changes: 18 additions & 0 deletions editor.planx.uk/src/@planx/components/Send/Public.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useAsync } from "react-use";
import { AsyncState } from "react-use/lib/useAsyncFn";

import Card from "../shared/Preview/Card";
import { ErrorSummaryContainer } from "../shared/Preview/ErrorSummaryContainer";
import { WarningContainer } from "../shared/Preview/WarningContainer";
import { PublicProps } from "../shared/types";
import { DEFAULT_DESTINATION, getCombinedEventsPayload, Send } from "./model";
Expand All @@ -25,12 +26,15 @@ const SendComponent: React.FC<Props> = ({
destinations = [DEFAULT_DESTINATION],
...props
}) => {
const teamSlug = useStore().teamSlug;
const fullProps = { destinations: destinations, ...props };
if (
window.location.pathname.endsWith("/draft") ||
window.location.pathname.endsWith("/preview")
) {
return <SkipSendWarning {...fullProps} />;
} else if (teamSlug === "demo") {
return <DemoTeamWarning {...fullProps} />;
} else {
return <CreateSendEvents {...fullProps} />;
}
Expand All @@ -52,6 +56,20 @@ const SkipSendWarning: React.FC<Props> = (props) => (
</Card>
);

const DemoTeamWarning: React.FC<Props> = (props) => (
<Card handleSubmit={props.handleSubmit}>
<ErrorSummaryContainer role="status">
<Typography variant="h4" ml={2} mb={1}>
Send is not enabled for services created in the Demo team
</Typography>
<Typography variant="body2" ml={2}>
Click continue to skip send and proceed with your application for
testing.
</Typography>
</ErrorSummaryContainer>
</Card>
);

const CreateSendEvents: React.FC<Props> = ({
destinations = [DEFAULT_DESTINATION],
...props
Expand Down

0 comments on commit 0b080a5

Please sign in to comment.