Skip to content

Commit

Permalink
Create e2e test for the web
Browse files Browse the repository at this point in the history
  • Loading branch information
sistracia committed Apr 7, 2024
1 parent f491f6e commit 2008ec7
Show file tree
Hide file tree
Showing 2 changed files with 240 additions and 4 deletions.
3 changes: 2 additions & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"start:client": "concurrently \"make style\" \"make client\"",
"start": "concurrently \"make server\" \"make style\" \"make client\"",
"test": "playwright test --reporter list",
"test:ui": "playwright test --ui"
"test:ui": "playwright test --ui",
"test:codegen": "playwright codegen"
},
"devDependencies": {
"@playwright/test": "^1.42.1",
Expand Down
241 changes: 238 additions & 3 deletions web/tests/rssbokmarkr.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,245 @@
import { test, expect } from "@playwright/test";

const pageURL = process.env.PAGE_URL || "http://localhost:8080"
const pageURL = process.env.PAGE_URL || "http://localhost:8080";

const username = "testingusername";
const password = "testingpassword";
const sessionKey = "session_id";
const subscribeEmail = "[email protected]";

const rssURLS = [
"https://overreacted.io/rss.xml",
"https://feed.infoq.com/",
"https://stackoverflow.blog/feed/",
];
const [overreactedURL, infoqURL, stackoverflowURL] = rssURLS;

test("has title", async ({ page }) => {
await page.goto(pageURL);
await expect(page).toHaveTitle("RSS Bookmarkr");
});

test.describe("single url", () => {
test("add new url", async ({ page }) => {
await page.goto(pageURL);

const urlInput = page.getByPlaceholder("https://overreacted.io/rss.xml");
await urlInput.fill(overreactedURL);

const rssListResponsePromise = page.waitForResponse(
"**/rpc/IRPCStore/getRSSList"
);
await page.getByRole("button", { name: "Add" }).click();

const rssListResponse = await rssListResponsePromise;
expect(rssListResponse.ok()).toStrictEqual(true);
expect(rssListResponse.request().postDataJSON()).toStrictEqual([
[overreactedURL],
]);

await expect(urlInput).toHaveValue("");
await expect(page.getByText(overreactedURL)).toBeVisible();
await expect(page).toHaveURL(`${pageURL}/?url=${overreactedURL}`);
});

test("init url with query param", async ({ page }) => {
const rssListResponsePromise = page.waitForResponse(
"**/rpc/IRPCStore/getRSSList"
);
await page.goto(`${pageURL}/?url=${overreactedURL}`);

const rssListResponse = await rssListResponsePromise;
expect(rssListResponse.ok()).toStrictEqual(true);
expect(rssListResponse.request().postDataJSON()).toStrictEqual([
[overreactedURL],
]);

const urlInput = page.getByPlaceholder("https://overreacted.io/rss.xml");

await expect(urlInput).toHaveValue("");
await expect(page.getByText(overreactedURL)).toBeVisible();
await expect(page).toHaveURL(`${pageURL}/?url=${overreactedURL}`);
});

test("delete url", async ({ page }) => {
await page.goto(`${pageURL}/?url=${overreactedURL}`);

await page.getByRole("button", { name: "X" }).click();
expect(await page.getByText(overreactedURL).count()).toStrictEqual(0);
await expect(page).toHaveURL(pageURL);
});
});

test.describe("multiple url", () => {
test("add new url", async ({ page }) => {
await page.goto(pageURL);

const urlInput = page.getByPlaceholder("https://overreacted.io/rss.xml");
const addButton = page.getByRole("button", { name: "Add" });

for (const rssURL of rssURLS) {
await urlInput.fill(rssURL);

const rssListResponsePromise = page.waitForResponse(
"**/rpc/IRPCStore/getRSSList"
);
await addButton.click();

const rssListResponse = await rssListResponsePromise;
expect(rssListResponse.ok()).toStrictEqual(true);
expect(rssListResponse.request().postDataJSON()).toStrictEqual([
[rssURL],
]);

await expect(page.getByText(rssURL)).toBeVisible();
}

await expect(page).toHaveURL(`${pageURL}/?url=${rssURLS.join(",")}`);
});

test("init url with query param", async ({ page }) => {
await page.goto(`${pageURL}/?url=${rssURLS.join(",")}`);

await page.locator(".skeleton").first().waitFor({ state: "visible" });
await page.locator(".skeleton").first().waitFor({ state: "detached" });
for (const rssURL of rssURLS) {
await expect(page.getByText(rssURL)).toBeVisible();
}

await expect(page).toHaveURL(`${pageURL}/?url=${rssURLS.join(",")}`);
});

test("delete url", async ({ page }) => {
await page.goto(`${pageURL}/?url=${rssURLS.join(",")}`);

await page.getByRole("button", { name: "X" }).first().click();

expect(await page.getByText(overreactedURL).count()).toStrictEqual(0);
await expect(page.getByText(infoqURL)).toBeVisible();
await expect(page.getByText(stackoverflowURL)).toBeVisible();
await expect(page).toHaveURL(
`${pageURL}/?url=${infoqURL},${stackoverflowURL}`
);
});
});

test.describe("user authentication", () => {
test("login", async ({ page }) => {
await page.goto(pageURL);

await page
.locator("div")
.filter({ hasText: /^Log In$/ })
.locator("label")
.click();
await expect(
page.getByRole("heading", { name: "Log In Form" })
).toBeVisible();

await page.getByPlaceholder("Username").fill(username);
await page.getByPlaceholder("******").fill(password);
await page.locator("form").getByText("Log In", { exact: true }).click();

await expect(page.getByText("Log Out")).toBeVisible();
await page.waitForFunction((sessionKey) => {
return localStorage[sessionKey] !== undefined;
}, sessionKey);
});

test("logout", async ({ page }) => {
await page.goto(pageURL);

await page
.locator("div")
.filter({ hasText: /^Log In$/ })
.locator("label")
.click();

await page.getByPlaceholder("Username").fill(username);
await page.getByPlaceholder("******").fill(password);
await page.locator("form").getByText("Log In", { exact: true }).click();
await page.waitForFunction((sessionKey) => {
return localStorage[sessionKey] === undefined;
}, sessionKey);
});
});

test.describe("authorized user", () => {
test.beforeEach(async ({ page }) => {
await page.goto(pageURL);

await page
.locator("div")
.filter({ hasText: /^Log In$/ })
.locator("label")
.click();

await page.getByPlaceholder("Username").fill(username);
await page.getByPlaceholder("******").fill(password);
await page.locator("form").getByText("Log In", { exact: true }).click();
await page.waitForFunction((sessionKey) => {
return localStorage[sessionKey] !== undefined;
}, sessionKey);
});

test("save urls and delete the url", async ({ page }) => {
await page
.getByPlaceholder("https://overreacted.io/rss.xml")
.fill(overreactedURL);
await page.getByRole("button", { name: "Add" }).click();
await page.locator(".skeleton").first().waitFor({ state: "visible" });
await page.locator(".skeleton").first().waitFor({ state: "detached" });

let rssSaveResponsePromise = page.waitForResponse(
"**/rpc/IRPCStore/saveRSSUrls"
);
await page.getByRole("button", { name: "Save Urls" }).click();

let rssSaveResponse = await rssSaveResponsePromise;
expect(rssSaveResponse.ok()).toStrictEqual(true);
expect(rssSaveResponse.request().postDataJSON()).toStrictEqual([
[expect.stringContaining("-"), [overreactedURL]],
]);

rssSaveResponsePromise = page.waitForResponse(
"**/rpc/IRPCStore/saveRSSUrls"
);

await page.getByRole("button", { name: "X" }).click();
expect(await page.getByText(overreactedURL).count()).toStrictEqual(0);
await page.getByRole("button", { name: "Save Urls" }).click();

rssSaveResponse = await rssSaveResponsePromise;
expect(rssSaveResponse.ok()).toStrictEqual(true);
expect(rssSaveResponse.request().postDataJSON()).toStrictEqual([
[expect.stringContaining("-"), []],
]);
});

test("subscribe and subscribe", async ({ page }) => {
await page.getByText("Subscribe").first().click();
await page.getByPlaceholder("[email protected]").fill(subscribeEmail);

const subscribeResponsePromise = page.waitForResponse(
"**/rpc/IRPCStore/subscribe"
);
await page.getByText("Subscribe").nth(2).click();

const subscribeResponse = await subscribeResponsePromise;
expect(subscribeResponse.ok()).toStrictEqual(true);
expect(subscribeResponse.request().postDataJSON()).toStrictEqual([
[expect.stringContaining("-"), subscribeEmail],
]);

const unsubscribeResponsePromise = page.waitForResponse(
"**/rpc/IRPCStore/unsubscribe"
);
await page.getByRole("button", { name: "Unsubscribe" }).click();

// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/RSS Bookmarkr/);
const unsubscribeResponse = await unsubscribeResponsePromise;
expect(unsubscribeResponse.ok()).toStrictEqual(true);
expect(unsubscribeResponse.request().postDataJSON()).toStrictEqual([
subscribeEmail,
]);
});
});

0 comments on commit 2008ec7

Please sign in to comment.