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

test: Basic coverage for PlanningConstraints public interface #3700

Merged
merged 4 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
import ErrorFallback from "components/Error/ErrorFallback";
import { useStore } from "pages/FlowEditor/lib/store";
import React from "react";
import { act } from "react-dom/test-utils";
import { ErrorBoundary } from "react-error-boundary";
import swr from "swr";
import { setup } from "testUtils";
import { vi } from "vitest";
import { axe } from "vitest-axe";

import classifiedRoadsResponseMock from "./mocks/classifiedRoadsResponseMock";
import digitalLandResponseMock from "./mocks/digitalLandResponseMock";
import { breadcrumbsWithoutUSRN, simpleBreadcrumbs, simpleFlow } from "./mocks/simpleFlow";
import PlanningConstraints from "./Public";

const { setState } = useStore;

beforeEach(() => vi.clearAllMocks());

const swrMock = (swr as jest.Mock).mock;

vi.mock("swr", () => ({
default: vi.fn((url: () => string) => {
const isGISRequest = url()?.startsWith(
`${import.meta.env.VITE_APP_API_URL}/gis/`,
`${import.meta.env.VITE_APP_API_URL}/gis`,
);
const isRoadsRequest = url()?.startsWith(
`${import.meta.env.VITE_APP_API_URL}/roads/`,
`${import.meta.env.VITE_APP_API_URL}/roads`,
);

if (isGISRequest) return { data: digitalLandResponseMock };
Expand All @@ -27,18 +37,15 @@ vi.mock("swr", () => ({

describe("error state", () => {
it("renders an error if no addres is present in the passport", async () => {
const handleSubmit = vi.fn();

const { getByRole, 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}
handleSubmit={vi.fn()}
/>
,
</ErrorBoundary>,
);

Expand All @@ -55,18 +62,175 @@ describe("error state", () => {
fn="property.constraints.planning"
disclaimer="This page does not include information about historic planning conditions that may apply to this property."
/>
,
</ErrorBoundary>,
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
});

it.todo("renders correctly");
describe("following a FindProperty component", () => {
beforeEach(() => {
act(() =>
setState({
breadcrumbs: simpleBreadcrumbs,
flow: simpleFlow,
teamIntegrations: {
hasPlanningData: true,
},
}),
);
});

it("renders correctly", async () => {
const handleSubmit = vi.fn();

const { user, getByRole, getByTestId } = setup(
<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}
/>,
);

expect(
getByRole("heading", { name: "Planning constraints" }),
).toBeInTheDocument();

await user.click(getByTestId("continue-button"));

it.todo("should not have any accessibility violations");
expect(handleSubmit).toHaveBeenCalled();
});

it.todo("fetches classified roads only when we have a siteBoundary"); // using expect(spy).toHaveBeenCalled() ??
it("should not have any accessibility violations", async () => {
const { container } = setup(
<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."
/>,
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});

it("fetches planning constraints when we have lng, lat or siteBoundary", async () => {
setup(
<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={vi.fn()}
/>,
);

expect(swr).toHaveBeenCalled();

// Planning data is called first
const swrURL = swrMock.calls[0][0]();
const swrResponse = swrMock.results[0].value;

expect(swrURL).toContain("/gis");
expect(swrResponse).toEqual({ data: digitalLandResponseMock });
});

it.todo("fetches planning constraints when we have lng,lat or siteBoundary");
it("fetches classified roads when a USRN is provided", () => {
setup(
<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={vi.fn()}
/>,
);

expect(swr).toHaveBeenCalled();

// Classified roads are called second
const swrURL = swrMock.calls[1][0]();
const swrResponse = swrMock.results[1].value;

expect(swrURL).toContain("/roads");
expect(swrResponse).toEqual({ data: classifiedRoadsResponseMock });
});

it("does not fetch classified roads when a USRN is not provided", async () => {
act(() =>
setState({
breadcrumbs: breadcrumbsWithoutUSRN,
flow: simpleFlow,
teamIntegrations: {
hasPlanningData: true,
},
})
);

setup(
<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={vi.fn()}
/>,
);

expect(swr).toHaveBeenCalled();

// Planning constraints API still called
const planingConstraintsURL = swrMock.calls[0][0]();
const planingConstraintsResponse = swrMock.results[0].value;

expect(planingConstraintsURL).toContain("/gis");
expect(planingConstraintsResponse).toEqual({ data: digitalLandResponseMock });

// Classified roads API not called due to missing USRN
const swrURL = swrMock.calls[1][0]();
const swrResponse = swrMock.results[1].value;

expect(swrURL).toBeNull();
expect(swrResponse).toEqual({ data: null });
});

test("basic layout and interactions", async () => {
const { user, getByRole, queryByRole, getByTestId } = setup(
<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={vi.fn()}
/>,
);

// Positive constraints visible by default
expect(
getByRole("heading", { name: /These are the planning constraints/ }),
).toBeVisible();
expect(getByRole("button", { name: /Parks and gardens/ })).toBeVisible();

// Negative constraints hidden by default
const showNegativeConstraintsButton = getByRole("button", {
name: /Constraints that don't apply/,
});
expect(showNegativeConstraintsButton).toBeVisible();

const negativeConstraintsContainer = getByTestId(
"negative-constraints-list",
);
expect(negativeConstraintsContainer).not.toBeVisible();

expect(queryByRole("heading", { name: /Ecology/ })).not.toBeInTheDocument();

// Negative constraints viewable on toggle
await user.click(showNegativeConstraintsButton);

expect(negativeConstraintsContainer).toBeVisible();
expect(getByRole("heading", { name: /Ecology/ })).toBeVisible();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ export function PlanningConstraintsContent(
{negativeConstraints.length > 0 && (
<SimpleExpand
id="negative-constraints-list"
data-testid="negative-constraints-list"
buttonText={{
open: "Constraints that don't apply to this property",
closed: "Hide constraints that don't apply",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { cloneDeep, merge } from "lodash";
import { Store } from "pages/FlowEditor/lib/store";

export const simpleFlow: Store.Flow = {
_root: {
edges: ["findProperty", "planningConstraints"],
},
findProperty: {
type: 9,
data: {
title: "Find the property",
allowNewAddresses: false,
newAddressTitle:
"Click or tap at where the property is on the map and name it below",
newAddressDescription:
"You will need to select a location and provide a name to continue",
newAddressDescriptionLabel: "Name the site",
},
},
planningConstraints: {
type: 11,
data: {
title: "Planning constraints",
description:
"Planning constraints might limit how you can develop or use the property",
fn: "property.constraints.planning",
disclaimer:
"<p><strong>This page does not include information about historic planning conditions that may apply to this property.</strong></p>",
},
},
};

export const simpleBreadcrumbs: Store.Breadcrumbs = {
findProperty: {
auto: false,
data: {
_address: {
uprn: "100071417680",
usrn: "2702440",
blpu_code: "2",
latitude: 52.4804358,
longitude: -1.9034539,
organisation: null,
sao: "",
saoEnd: "",
pao: "COUNCIL HOUSE",
paoEnd: "",
street: "VICTORIA SQUARE",
town: "BIRMINGHAM",
postcode: "B1 1BB",
ward: "E05011151",
x: 406653.64,
y: 286948.41,
planx_description: "Local Government Service",
planx_value: "commercial.office.workspace.gov.local",
single_line_address:
"COUNCIL HOUSE, VICTORIA SQUARE, BIRMINGHAM, B1 1BB",
title: "COUNCIL HOUSE, VICTORIA SQUARE",
source: "os",
},
"property.type": ["commercial.office.workspace.gov.local"],
"property.localAuthorityDistrict": ["Birmingham"],
"property.region": ["West Midlands"],
"property.boundary.title": {
geometry: {
type: "MultiPolygon",
coordinates: [
[
[
[-1.903955, 52.480237],
[-1.903881, 52.480179],
[-1.903955, 52.480237],
],
],
],
},
type: "Feature",
properties: {
"entry-date": "2024-05-06",
"start-date": "2021-03-25",
"end-date": "",
entity: 12001049997,
name: "",
dataset: "title-boundary",
typology: "geography",
reference: "61385289",
prefix: "title-boundary",
"organisation-entity": "13",
},
},
"property.boundary.title.area": 8242.37,
"property.boundary.title.area.hectares": 0.8242370000000001,
"findProperty.action": "Selected an existing address",
},
},
};

export const breadcrumbsWithoutUSRN = merge(cloneDeep(simpleBreadcrumbs), { findProperty: { data: { _address: { usrn: null }}}});
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const SimpleExpand: React.FC<PropsWithChildren<Props>> = ({
/>
</StyledButton>
</Box>
<Collapse in={show} id={id}>
<Collapse in={show} id={id} data-testid={id}>
{children}
</Collapse>
</>
Expand Down
Loading