-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
240 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
]); | ||
}); | ||
}); |