who_need_help/e2e/tests/mutual-aid.spec.ts

181 lines
8.6 KiB
TypeScript

import { expect, test } from "@playwright/test";
import {
captureBrowserFailures,
clickUntilVisible,
gotoLiveView,
loginWithPassword,
markerKinds,
projectEmail,
projectText,
registerAndConfirm,
selectOptionContaining,
waitForMapReady,
} from "./helpers";
test("two users complete medicine tracking, handover, realtime chat, and blind reviews", async ({
browser,
request,
}, testInfo) => {
const runID = process.env.E2E_RUN_ID;
const fixturePassword = process.env.E2E_FIXTURE_PASSWORD;
const requestTitle = projectText(
runID ? `Staging E2E medicine pickup ${runID}` : "E2E medicine pickup",
testInfo.project.name,
);
const requesterEmail = projectEmail("requester", testInfo.project.name);
const helperEmail = projectEmail("helper", testInfo.project.name);
const requester =
runID && fixturePassword
? await loginWithPassword(browser, requesterEmail, fixturePassword)
: await registerAndConfirm(browser, request, requesterEmail, "E2E Requester");
const helper =
runID && fixturePassword
? await loginWithPassword(browser, helperEmail, fixturePassword)
: await registerAndConfirm(browser, request, helperEmail, "E2E Helper");
const assertRequesterClean = captureBrowserFailures(requester.page);
const assertHelperClean = captureBrowserFailures(helper.page);
await gotoLiveView(requester.page, "/requests/new");
await selectOptionContaining(requester.page, "Category", "Medicine pickup");
await requester.page.getByLabel("Medicine pickup status").selectOption("reserved");
await requester.page.getByLabel("Short title").fill(requestTitle);
await requester.page
.getByLabel("What help do you need?")
.fill("Please collect the legal medicine that is already reserved.");
await requester.page.getByLabel("Urgency").selectOption("now");
const expiresAt = new Date(Date.now() + 3 * 60 * 60 * 1000)
.toISOString()
.slice(0, 16);
await requester.page.getByLabel("Request expires (UTC)").fill(expiresAt);
await requester.page.getByLabel("Approximate area").fill("E2E central district");
await requester.page.getByLabel("Location visibility").selectOption("approximate_public");
await requester.page.getByLabel("Latitude").fill("50.4501");
await requester.page.getByLabel("Longitude").fill("30.5234");
await requester.page.locator("#request-form input[type=checkbox]").check();
await requester.page.getByRole("button", { name: "Publish request" }).click();
await expect(requester.page).toHaveURL(/\/requests\/[0-9a-f-]+$/);
const requestURL = requester.page.url();
await expect(requester.page.getByRole("heading", { name: requestTitle })).toBeVisible();
await gotoLiveView(helper.page, requestURL);
await helper.page.getByRole("button", { name: "I can help" }).click();
await expect(helper.page.getByRole("heading", { name: "Private match chat" })).toBeVisible();
await expect(requester.page.getByRole("heading", { name: "Private match chat" })).toBeVisible();
await helper.page
.getByPlaceholder("Write a safe coordination message…")
.fill("I am on my way to the pharmacy.");
await helper.page.getByRole("button", { name: "Send", exact: true }).click();
await expect(requester.page.getByText("I am on my way to the pharmacy.")).toBeVisible();
await requester.page
.getByPlaceholder("Write a safe coordination message…")
.fill("Thank you. The order is waiting at the counter.");
await requester.page.getByRole("button", { name: "Send", exact: true }).click();
await expect(helper.page.getByText("Thank you. The order is waiting at the counter.")).toBeVisible();
const origin = new URL(process.env.BASE_URL!).origin;
await helper.context.grantPermissions(["geolocation"], { origin });
await helper.context.setGeolocation({
latitude: 50.4504,
longitude: 30.5237,
accuracy: 5,
});
await helper.page.getByRole("button", { name: "Share location" }).click();
await expect(helper.page.getByRole("button", { name: "Stop and delete position" })).toBeVisible();
await expect.poll(() => markerKinds(requester.page)).toContain("Shared location");
await helper.page.getByRole("button", { name: "Stop and delete position" }).click();
await expect(helper.page.getByRole("button", { name: "Share location" })).toBeVisible();
await expect.poll(() => markerKinds(requester.page)).not.toContain("Shared location");
await helper.page.getByRole("button", { name: "Start helping" }).click();
const handoverCode = (
await requester.page.locator("text=HANDOVER CODE FOR THE HELPER").locator("..").locator(".font-mono").innerText()
).replace(/\s/g, "");
expect(handoverCode).toMatch(/^\d{6}$/);
await helper.page.getByLabel("Enter handover code").fill(handoverCode);
await helper.page.getByRole("button", { name: "Verify handover" }).click();
await expect(helper.page.getByText("Handover code verified.")).toBeVisible();
await helper.page.getByRole("button", { name: "Confirm my part is complete" }).click();
await requester.page.getByRole("button", { name: "Confirm my part is complete" }).click();
await expect(requester.page.getByRole("heading", { name: "Double-blind review" })).toBeVisible();
await expect(helper.page.getByRole("heading", { name: "Double-blind review" })).toBeVisible();
await helper.page.getByLabel("Rating").selectOption("5");
await helper.page.getByLabel("Comment (optional)").fill("Clear and safe coordination.");
await helper.page.getByRole("button", { name: "Submit review" }).click();
await expect(
helper.page.getByText("Review saved. It appears after both participants review."),
).toBeVisible();
await waitForMapReady(requester.page);
await gotoLiveView(requester.page, "/profile");
await expect(requester.page.getByText("None revealed yet.")).toBeVisible();
await expect(requester.page.getByText("Clear and safe coordination.")).toHaveCount(0);
await gotoLiveView(requester.page, requestURL);
await requester.page.getByLabel("Rating").selectOption("5");
await requester.page.getByLabel("Comment (optional)").fill("Reliable volunteer.");
await requester.page.getByRole("button", { name: "Submit review" }).click();
await expect(
requester.page.getByText("Review saved. It appears after both participants review."),
).toBeVisible();
await waitForMapReady(requester.page);
await gotoLiveView(requester.page, "/profile");
await expect(requester.page.getByText("Clear and safe coordination.")).toBeVisible();
await waitForMapReady(helper.page);
await gotoLiveView(helper.page, "/profile");
await expect(helper.page.getByText("Reliable volunteer.")).toBeVisible();
const roadsideTitle = projectText(
runID ? `Staging E2E motorcycle chain ${runID}` : "E2E motorcycle chain",
testInfo.project.name,
);
await gotoLiveView(requester.page, "/requests/new");
await selectOptionContaining(
requester.page,
"Category",
"Motorcycle roadside help",
);
await requester.page.getByLabel("Motorcycle problem").selectOption("broken_chain");
await requester.page
.getByLabel("Motorcycle is away from active traffic")
.selectOption("true");
await requester.page.getByLabel("Short title").fill(roadsideTitle);
await requester.page
.getByLabel("What help do you need?")
.fill("The motorcycle is secured and needs help with a broken chain.");
await requester.page.getByLabel("Urgency").selectOption("today");
await requester.page
.getByLabel("Request expires (UTC)")
.fill(new Date(Date.now() + 4 * 60 * 60 * 1000).toISOString().slice(0, 16));
await requester.page.getByLabel("Approximate area").fill("E2E secured roadside area");
await requester.page.getByLabel("Location visibility").selectOption("hidden");
await requester.page.getByLabel("Latitude").fill("50.4501");
await requester.page.getByLabel("Longitude").fill("30.5234");
await requester.page.locator("#request-form input[type=checkbox]").last().check();
await requester.page.getByRole("button", { name: "Publish request" }).click();
await expect(requester.page.getByRole("heading", { name: roadsideTitle })).toBeVisible();
const roadsideURL = requester.page.url();
await gotoLiveView(helper.page, roadsideURL);
await clickUntilVisible(
helper.page.getByRole("button", { name: "I can help" }),
helper.page.getByRole("button", { name: "Withdraw from this request" }),
);
await clickUntilVisible(
helper.page.getByRole("button", { name: "Withdraw from this request" }),
helper.page.getByText("You withdrew from this request."),
);
await expect(requester.page.getByText("Cancelled", { exact: true })).toBeVisible();
assertRequesterClean();
assertHelperClean();
await requester.context.close();
await helper.context.close();
});