Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: demo team integrations to fail gracefully #3938

Merged
merged 8 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -240,3 +240,47 @@ describe("following a FindProperty component", () => {
expect(getByRole("heading", { name: /Ecology/ })).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
expect(
queryByRole("heading", { name: "Planning constraints" }),
).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 @@ -209,6 +211,22 @@ function Component(props: Props) {
});
};

if (teamSlug === "demo") {
return (
<Card handleSubmit={props.handleSubmit}>
<ErrorSummaryContainer role="status">
<Typography variant="h4" ml={2} mb={1}>
Planning Constraints are not enabled for demo users.
</Typography>
<Typography variant="body2" ml={2}>
Click continue to skip planning constraints and proceed with your
application for testing.
RODO94 marked this conversation as resolved.
Show resolved Hide resolved
</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
Loading