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: Add E2E Coverage for Property Information #4025

Merged
merged 9 commits into from
Dec 3, 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
1 change: 1 addition & 0 deletions e2e/tests/ui-driven/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"packageManager": "pnpm@8.6.6",
"devDependencies": {
"@playwright/test": "^1.49.0",
"@types/geojson": "^7946.0.14",
"@types/node": "18.16.1",
"eslint-plugin-playwright": "^0.20.0"
}
Expand Down
7 changes: 7 additions & 0 deletions e2e/tests/ui-driven/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 49 additions & 1 deletion e2e/tests/ui-driven/src/create-flow-with-geospatial.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import {
} from "./helpers/context";
import { getTeamPage } from "./helpers/getPage";
import { createAuthenticatedSession } from "./helpers/globalHelpers";
import { answerFindProperty, clickContinue } from "./helpers/userActions";
import {
answerFindProperty,
answerQuestion,
clickContinue,
} from "./helpers/userActions";
import { PlaywrightEditor } from "./pages/Editor";
import {
navigateToService,
Expand All @@ -15,6 +19,11 @@ import {
} from "./helpers/navigateAndPublish";
import { TestContext } from "./helpers/types";
import { serviceProps } from "./helpers/serviceData";
import { checkGeoJsonContent } from "./helpers/geospatialChecks";
import {
mockMapGeoJson,
mockPropertyTypeOptions,
} from "./mocks/geospatialMocks";

test.describe("Flow creation, publish and preview", () => {
let context: TestContext = {
Expand Down Expand Up @@ -48,6 +57,16 @@ test.describe("Flow creation, publish and preview", () => {

await editor.createFindProperty();
await expect(editor.nodeList).toContainText(["Find property"]);
// Find property will automate past this question at first
await editor.createQuestionWithDataFieldOptions(
"Assign property type",
RODO94 marked this conversation as resolved.
Show resolved Hide resolved
mockPropertyTypeOptions,
"property.type",
);
await expect(editor.nodeList).toContainText(["Assign property type"]);
// but property info "change" button will navigate back to it
await editor.createPropertyInformation();
await expect(editor.nodeList).toContainText(["About the property"]);
await editor.createInternalPortal();
await editor.populateInternalPortal();
await page.getByRole("link", { name: "start" }).click(); // return to main flow
Expand Down Expand Up @@ -99,12 +118,41 @@ test.describe("Flow creation, publish and preview", () => {
await page.goto(
`/${context.team.slug}/${serviceProps.slug}/published?analytics=false`,
);

await expect(
page.locator("h1", { hasText: "Find the property" }),
).toBeVisible();
await answerFindProperty(page);
await clickContinue({ page });

await expect(
page.getByRole("heading", { name: "About the property" }),
).toBeVisible();

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

// Check property info is being shown
await expect(page.getByText("Test Street, Testville")).toBeVisible();
await expect(page.getByText("Residential - Semi Detached")).toBeVisible();
const changeButton = page.getByRole("button", {
name: "Change your Property type",
});

await changeButton.click();

// change button navigates the user back thro the service so we need to continue twice
RODO94 marked this conversation as resolved.
Show resolved Hide resolved
RODO94 marked this conversation as resolved.
Show resolved Hide resolved
await answerQuestion({
page: page,
title: "Assign property type",
answer: "Commercial",
});

await clickContinue({ page });
await expect(page.getByText("Commercial")).toBeVisible();
RODO94 marked this conversation as resolved.
Show resolved Hide resolved

await clickContinue({ page });

await expect(
page.locator("h1", { hasText: "A notice inside a portal!" }),
).toBeVisible();
Expand Down
43 changes: 43 additions & 0 deletions e2e/tests/ui-driven/src/helpers/addComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ComponentType } from "@opensystemslab/planx-core/types";
import { expect, Locator, Page } from "@playwright/test";
import { contextDefaults } from "./context";
import { externalPortalServiceProps } from "./serviceData";
import { OptionWithDataValues } from "./types";

const createBaseComponent = async (
page: Page,
Expand Down Expand Up @@ -81,6 +82,9 @@ const createBaseComponent = async (
break;
case ComponentType.FindProperty:
break;
case ComponentType.PropertyInformation:
await page.getByLabel("Show users a 'change' link to").click();
break;
case ComponentType.PlanningConstraints:
break;
case ComponentType.DrawBoundary:
Expand Down Expand Up @@ -153,6 +157,21 @@ export const createQuestionWithOptions = async (
);
};

export const createQuestionWithDataFieldOptions = async (
RODO94 marked this conversation as resolved.
Show resolved Hide resolved
page: Page,
locatingNode: Locator,
questionText: string,
options: OptionWithDataValues[],
dataField: string,
) => {
await locatingNode.click();
await page.getByRole("dialog").waitFor();
await page.getByPlaceholder("Text").fill(questionText);
await page.getByPlaceholder("Data Field").fill(dataField);
await createComponentOptionsWithDataValues(page, options);
await page.locator('button[form="modal"][type="submit"]').click();
};

export const createNotice = async (
page: Page,
locatingNode: Locator,
Expand Down Expand Up @@ -275,6 +294,17 @@ export const createFindProperty = async (page: Page, locatingNode: Locator) => {
await createBaseComponent(page, locatingNode, ComponentType.FindProperty);
};

export const createPropertyInformation = async (
page: Page,
locatingNode: Locator,
) => {
await createBaseComponent(
page,
locatingNode,
ComponentType.PropertyInformation,
);
};

export const createPlanningConstraints = async (
page: Page,
locatingNode: Locator,
Expand Down Expand Up @@ -331,6 +361,19 @@ async function createComponentOptions(
}
}

async function createComponentOptionsWithDataValues(
page: Page,
options: OptionWithDataValues[],
) {
let index = 0;
for (const option of options) {
await page.locator("button").filter({ hasText: "add new" }).click();
await page.getByPlaceholder("Option").nth(index).fill(option.optionText);
await page.getByPlaceholder("Data Value").nth(index).fill(option.dataValue);
index++;
}
}

export const createList = async (
page: Page,
locatingNode: Locator,
Expand Down
12 changes: 12 additions & 0 deletions e2e/tests/ui-driven/src/helpers/geospatialChecks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { expect, Page } from "@playwright/test";
import { Feature } from "geojson";

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

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

expect(JSON.parse(geojsonData!)).toEqual(geoJson);
};
2 changes: 2 additions & 0 deletions e2e/tests/ui-driven/src/helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ export interface TestContext {
externalPortalFlow?: Flow;
sessionIds?: string[];
}

export type OptionWithDataValues = { optionText: string; dataValue: string };
39 changes: 39 additions & 0 deletions e2e/tests/ui-driven/src/mocks/geospatialMocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { OptionWithDataValues } from "../helpers/types";

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

import { Feature } from "geojson";

export const mockMapGeoJson: Feature = {
geometry: {
type: "MultiPolygon",
coordinates: [
[
[
[-0.633498, 51.605485],
[-0.633455, 51.605606],
[-0.633788, 51.605643],
[-0.634429, 51.605799],
[-0.634429, 51.605767],
[-0.633498, 51.605485],
],
],
],
},
type: "Feature",
properties: {
"entry-date": "2024-05-06",
"start-date": "2010-05-12",
"end-date": "",
entity: 12000041468,
name: "",
dataset: "title-boundary",
typology: "geography",
reference: "45211072",
prefix: "title-boundary",
"organisation-entity": "13",
},
};
24 changes: 24 additions & 0 deletions e2e/tests/ui-driven/src/pages/Editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ import {
createNotice,
createNumberInput,
createPlanningConstraints,
createPropertyInformation,
createQuestionWithDataFieldOptions,
createQuestionWithOptions,
createResult,
createReview,
createTaskList,
createTextInput,
createUploadAndLabel,
} from "../helpers/addComponent";
import { OptionWithDataValues } from "../helpers/types";

export class PlaywrightEditor {
readonly page: Page;
Expand Down Expand Up @@ -81,6 +84,23 @@ export class PlaywrightEditor {
).toBeVisible();
}

async createQuestionWithDataFieldOptions(
title: string,
answers: OptionWithDataValues[],
dataField: string,
) {
await createQuestionWithDataFieldOptions(
this.page,
this.getNextNode(),
title,
answers,
dataField,
);
await expect(
this.page.locator("a").filter({ hasText: title }),
).toBeVisible();
}

async createNoticeOnEachBranch() {
// Add a notice to the "Yes" path
await createNotice(
Expand Down Expand Up @@ -168,6 +188,10 @@ export class PlaywrightEditor {
await createFindProperty(this.page, this.getNextNode());
}

async createPropertyInformation() {
await createPropertyInformation(this.page, this.getNextNode());
}

async createDrawBoundary() {
await createDrawBoundary(this.page, this.getNextNode());
}
Expand Down
Loading