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: E2E coverage for Draw Boundary #4035

Merged
merged 10 commits into from
Dec 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
70 changes: 63 additions & 7 deletions e2e/tests/ui-driven/src/create-flow-with-geospatial.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,24 @@ import {
} from "./helpers/navigateAndPublish";
import { TestContext } from "./helpers/types";
import { serviceProps } from "./helpers/serviceData";
import { checkGeoJsonContent } from "./helpers/geospatialChecks";
import {
mockMapGeoJson,
alterDrawGeoJson,
checkGeoJsonContent,
checkUploadFileAltRoute,
getMapProperties,
resetMapBoundary,
waitForMapComponent,
} from "./helpers/geospatialChecks";
import {
GeoJsonChangeHandler,
mockChangedMapGeoJson,
mockPropertyTypeOptions,
mockTitleBoundaryGeoJson,
} from "./mocks/geospatialMocks";
import {
setupOSMapsStyles,
setupOSMapsVectorTiles,
} from "./mocks/osMapsResponse";

test.describe("Flow creation, publish and preview", () => {
let context: TestContext = {
Expand Down Expand Up @@ -72,16 +85,14 @@ test.describe("Flow creation, publish and preview", () => {
await editor.createInternalPortal();
await editor.populateInternalPortal();
await page.getByRole("link", { name: "start" }).click(); // return to main flow
await editor.createUploadAndLabel();
// TODO: editor.createPropertyInfo()
// await editor.createUploadAndLabel();
await editor.createDrawBoundary();
await editor.createPlanningConstraints();
// await editor.createFileUpload();

await expect(editor.nodeList).toContainText([
"Find property",
"an internal portalEdit Portal",
"Upload and label",
"Confirm your location plan",
"Planning constraints",
// "File upload",
Expand Down Expand Up @@ -119,6 +130,9 @@ test.describe("Flow creation, publish and preview", () => {
`/${context.team.slug}/${serviceProps.slug}/published?analytics=false`,
);

setupOSMapsStyles(page);
setupOSMapsVectorTiles(page);

await expect(
page.locator("h1", { hasText: "Find the property" }),
).toBeVisible();
Expand All @@ -130,7 +144,7 @@ test.describe("Flow creation, publish and preview", () => {
).toBeVisible();

// Check map component has geoJson content
await checkGeoJsonContent(page, mockMapGeoJson);
await checkGeoJsonContent(page, "geojsondata", mockTitleBoundaryGeoJson);

// Check property info is being shown
await expect(page.getByText("Test Street, Testville")).toBeVisible();
Expand Down Expand Up @@ -169,7 +183,49 @@ test.describe("Flow creation, publish and preview", () => {
).toBeVisible();
await clickContinue({ page });

const drawBoundaryTitle = page.getByRole("heading", {
name: "Confirm your location plan",
});
await expect(drawBoundaryTitle).toBeVisible();

await checkGeoJsonContent(
page,
"drawgeojsondata",
mockTitleBoundaryGeoJson,
);

const area = "The property boundary you have drawn is 490.37";

await expect(page.getByText(area)).toBeVisible();

// navigate to upload file page and back
await checkUploadFileAltRoute(page);

await expect(
drawBoundaryTitle,
"We have navigated back to the map component",
).toBeVisible();

// ensure map has loaded correctly
await waitForMapComponent(page);

await resetMapBoundary(page);

await alterDrawGeoJson(page);

// extract new GeoJSON data
const newGeoJson = await getMapProperties(page, "drawgeojsondata");
const parsedJson: GeoJsonChangeHandler = JSON.parse(newGeoJson!);

// check it matches our static mock
await checkGeoJsonContent(page, "drawgeojsondata", mockChangedMapGeoJson);

await expect(
page.getByText(`${parsedJson.properties!["area.squareMetres"]}`),
"The correct value for area comes from the map properties ",
).toBeVisible();

// TODO: answer uploadAndLabel
// TODO: answerPropertyInfo, answerDrawBoundary, answerPlanningConstraints
// TODO: answerPropertyInfo, answerPlanningConstraints
});
});
81 changes: 78 additions & 3 deletions e2e/tests/ui-driven/src/helpers/geospatialChecks.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,87 @@
import { expect, Page } from "@playwright/test";
import { Feature } from "geojson";

export const checkGeoJsonContent = async (page: Page, geoJson: Feature) => {
export const waitForMapComponent = async (page: Page) => {
await page.waitForFunction(() => {
const map = document.getElementById("draw-boundary-map");
return map;
});
};

export const getMapProperties = async (
page: Page,
attribute: "geojsondata" | "drawgeojsondata",
) => {
const mapComponent = await page.waitForSelector("my-map");
return await mapComponent.getAttribute(attribute);
};

export const alterDrawGeoJson = async (page: Page) => {
const map = page.getByTestId("map-test-id");

await map.click({ button: "left", position: { x: 100, y: 200 } });
await map.click({ button: "left", position: { x: 150, y: 250 } });
await map.click({ button: "left", position: { x: 200, y: 250 } });
await map.click({ button: "left", position: { x: 100, y: 200 } });
};

export const resetMapBoundary = async (page: Page) => {
const resetButton = page.getByLabel("Reset map view");
await resetButton.click();

const resetGeoJson = await getMapProperties(page, "drawgeojsondata");

expect(resetGeoJson, "drawGeoJsonData should be reset").toEqual(null);
};

export const checkGeoJsonContent = async (
page: Page,
attribute: "geojsondata" | "drawgeojsondata",
geoJson: Feature,
) => {
// Wait for the map component to be present
const mapComponent = await page.waitForSelector("my-map");

await page.waitForFunction(() => customElements.get("my-map"));
await expect(
page.getByTestId("map-test-id"),
"Check we can see the map",
).toBeVisible();

// Get the geojsonData attribute
const geojsonData = await mapComponent.getAttribute("geojsondata");
const geojsonData = await mapComponent.getAttribute(attribute);

expect(
JSON.parse(geojsonData!),
"map attribute matches expected mock attribute",
).toEqual(geoJson);
};

export const checkUploadFileAltRoute = async (page: Page) => {
const uploadButton = page.getByTestId("upload-file-button");

await expect(
uploadButton,
"We can see a button to upload a file instead",
).toBeVisible();

await uploadButton.click();

await expect(
page.getByRole("heading", { name: "Upload a location plan" }),
"Should be in a page for uploading a file",
).toBeVisible();

await expect(
page.getByRole("button", { name: "Drop file here or choose" }),
"A button for uploading files is visible",
).toBeVisible();

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

await page.getByTestId("error-message-upload-location-plan").isVisible();

const useMapButton = page.getByTestId("use-map-button");
RODO94 marked this conversation as resolved.
Show resolved Hide resolved

expect(JSON.parse(geojsonData!)).toEqual(geoJson);
await useMapButton.click();
};
35 changes: 31 additions & 4 deletions e2e/tests/ui-driven/src/mocks/geospatialMocks.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { OptionWithDataValues } from "../helpers/types";
import { Feature, Polygon } from "geojson";

type ChangeHandlerProperties = {
label: string;
"area.squareMetres": number;
"area.hectares": number;
};

export type GeoJsonChangeHandler = Feature<Polygon, ChangeHandlerProperties>;

export const mockPropertyTypeOptions: OptionWithDataValues[] = [
{ optionText: "Residential", dataValue: "residential" },
{ optionText: "Commercial", dataValue: "commercial" },
];

import { Feature } from "geojson";

export const mockMapGeoJson: Feature = {
export const mockTitleBoundaryGeoJson: Feature = {
type: "Feature",
geometry: {
type: "MultiPolygon",
coordinates: [
Expand All @@ -23,7 +31,6 @@ export const mockMapGeoJson: Feature = {
],
],
},
type: "Feature",
properties: {
"entry-date": "2024-05-06",
"start-date": "2010-05-12",
Expand All @@ -37,3 +44,23 @@ export const mockMapGeoJson: Feature = {
"organisation-entity": "13",
},
};

export const mockChangedMapGeoJson: GeoJsonChangeHandler = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pulled this from the tests so I had a static mock to check against when running the tests

type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[-0.6341888375038146, 51.60562241658701],
[-0.6341217822784424, 51.605580770520504],
[-0.63405472705307, 51.605580770520504],
[-0.6341888375038146, 51.60562241658701],
],
],
},
properties: {
label: "1",
"area.squareMetres": 10.72,
"area.hectares": 0.001072,
},
};
22 changes: 22 additions & 0 deletions e2e/tests/ui-driven/src/mocks/osMapsMockData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export const osMapsStylesResponse = {
version: 8,
sprite:
"https://api.os.uk/maps/vector/v1/vts/resources/sprites/sprite?key=YOUR_KEY&srs=3857",
glyphs:
"https://api.os.uk/maps/vector/v1/vts/resources/fonts/{fontstack}/{range}.pbf?key=YOUR_KEY&srs=3857",
sources: {
esri: {
type: "vector",
url: "https://api.os.uk/maps/vector/v1/vts?key=YOUR_KEY&srs=3857",
},
},
layers: [
{
id: "background",
type: "background",
paint: {
"background-color": "#0437F2",
},
},
],
};
27 changes: 27 additions & 0 deletions e2e/tests/ui-driven/src/mocks/osMapsResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Page } from "@playwright/test";
import { osMapsStylesResponse } from "./osMapsMockData";

export async function setupOSMapsStyles(page: Page) {
const ordnanceSurveyMapsStyles = new RegExp(
/\/proxy\/ordnance-survey\/maps\/vector\/v1\/vts\/resources\/styles.*/,
);
await page.route(ordnanceSurveyMapsStyles, async (route) => {
await route.fulfill({
status: 200,
body: JSON.stringify(osMapsStylesResponse),
});
});
}

export async function setupOSMapsVectorTiles(page: Page) {
const ordnanceSurveyVectorTiles = new RegExp(
/\/proxy\/ordnance-survey\/maps\/vector\/v1\/vts\/tile/,
);

await page.route(ordnanceSurveyVectorTiles, async (route) => {
await route.fulfill({
status: 200,
body: Buffer.from([]),
});
});
}
Loading