diff --git a/e2e/login/login.spec.ts b/e2e/login/login.spec.ts
index 2738a05..377ee85 100644
--- a/e2e/login/login.spec.ts
+++ b/e2e/login/login.spec.ts
@@ -44,6 +44,9 @@ test.describe("login flow", async () => {
await expect(
page.getByRole("heading", { name: "Test" }),
).not.toBeVisible()
+ await expect(
+ page.getByRole("alert").filter({ hasText: /login unsuccessful/i }),
+ ).toBeVisible()
})
})
test("unsuccessful login with wrong password", async ({ page }) => {
@@ -63,6 +66,9 @@ test.describe("login flow", async () => {
await expect(
page.getByText(/hmmm incorrect password. let's hope you made a typo./i),
).toBeVisible()
+ await expect(
+ page.getByRole("alert").filter({ hasText: /login unsuccessful/i }),
+ ).toBeVisible()
})
})
})
diff --git a/e2e/randomiser/randomiser.spec.ts b/e2e/randomiser/randomiser.spec.ts
new file mode 100644
index 0000000..d6a68da
--- /dev/null
+++ b/e2e/randomiser/randomiser.spec.ts
@@ -0,0 +1,71 @@
+import { Genre } from "@/types/Genre"
+import test, { expect } from "@playwright/test"
+
+test.describe("Happy path to create book selection", async () => {
+ const username = "Test"
+ const password = "testTEST.123"
+ let bookId
+ let token
+
+ test.afterAll("delete book", async ({ request }) => {
+ const unreadBooksReq = await request.get(
+ "http://localhost:8080/books/unread/all",
+ )
+ const unreadBooks = await unreadBooksReq.json()
+ bookId = unreadBooks?.find((book) => book.title === "e Test Title")?._id
+ if (bookId && token) {
+ await request.delete(`http://localhost:8080/books/${bookId}`, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ "Content-Type": "application/json",
+ },
+ })
+ }
+ })
+
+ test.beforeEach(async ({ request }) => {
+ const authResponse = await request.post(
+ "http://localhost:8080/users/login",
+ {
+ data: { username, password },
+ },
+ )
+
+ const authData = await authResponse.json()
+ token = authData.token
+ })
+
+ test("successfully create a book", async ({ page, context }) => {
+ await context.addCookies([
+ {
+ name: "token",
+ value: token,
+ domain: "localhost",
+ path: "/",
+ },
+ ])
+ await page.goto("http://localhost:3000/")
+ await test.step("Navigate to book randomiser page", async () => {
+ await page.goto("http://localhost:3000/books/randomiser")
+ })
+ await test.step("open book from", async () => {
+ await page.getByRole("button", { name: /add book/i }).click()
+ })
+ await test.step("fill out book form", async () => {
+ await page.getByTestId("unread-book-title-input").fill("e Test Title")
+ await page.getByTestId("unread-book-author-input").fill("e Test Author")
+ await page.getByTestId("unread-book-pages-input").fill("500")
+ await page.getByTestId("unread-book-yearPublished-input").fill("1992")
+ await page.getByTestId("unread-book-genre-input").click()
+ await page.getByText(Genre.ACTION).click()
+ await page.keyboard.press("Escape")
+ })
+ await test.step("successfully submit book", async () => {
+ await page.getByRole("button", { name: /submit/i }).click()
+
+ await expect(
+ page.getByRole("alert").filter({ hasText: /book successfully added/i }),
+ ).toBeVisible()
+ })
+ })
+})
diff --git a/e2e/rating/rating.spec.ts b/e2e/rating/rating.spec.ts
new file mode 100644
index 0000000..e02bbd6
--- /dev/null
+++ b/e2e/rating/rating.spec.ts
@@ -0,0 +1,80 @@
+import { Genre } from "@/types/Genre"
+import { test, expect } from "@playwright/test"
+
+test.describe("Happy path to rating a book", () => {
+ const username = "Test"
+ const password = "testTEST.123"
+ let bookId
+ let token
+
+ test.afterAll("Delete created book", async ({ request }) => {
+ if (bookId && token) {
+ await request.delete(`http://localhost:8080/books/${bookId}`, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ "Content-Type": "application/json",
+ },
+ })
+ }
+ })
+
+ test.beforeEach(async ({ request }) => {
+ const authResponse = await request.post(
+ "http://localhost:8080/users/login",
+ {
+ data: { username, password },
+ },
+ )
+
+ const authData = await authResponse.json()
+ token = authData.token
+
+ const bookResponse = await request.post("http://localhost:8080/books", {
+ data: {
+ title: `testTitle${Math.random() * 100}`,
+ author: "testAuthor",
+ pages: 500,
+ yearPublished: 1992,
+ genre: [Genre.ACTION],
+ read: true,
+ },
+ headers: {
+ Authorization: `Bearer ${token}`,
+ "Content-Type": "application/json",
+ },
+ })
+ const bookData = await bookResponse.json()
+ bookId = bookData._id
+ })
+
+ test("submit a 10 rating", async ({ page, context }) => {
+ await context.addCookies([
+ {
+ name: "token",
+ value: token,
+ domain: "localhost",
+ path: "/",
+ },
+ ])
+ await page.goto("http://localhost:3000/")
+ await test.step("navigate to book page", async () => {
+ await page.goto(`http://localhost:3000/books/library/${bookId}`)
+ })
+
+ await test.step("open rating modal", async () => {
+ await page
+ .getByRole("button", { name: "Submit rating", exact: true })
+ .click()
+ })
+
+ await test.step("enter and submit rating", async () => {
+ await page.getByTestId("book-rating-input").fill("10")
+ await page.getByRole("button", { name: "Submit", exact: true }).click()
+ await expect(
+ page
+ .getByRole("alert")
+ .filter({ hasText: /Rating successfully submitted/i }),
+ ).toBeVisible()
+ })
+ })
+})
diff --git a/playwright.config.ts b/playwright.config.ts
index dfe72ab..69cdc3f 100644
--- a/playwright.config.ts
+++ b/playwright.config.ts
@@ -1,4 +1,6 @@
-import { defineConfig, devices } from '@playwright/test';
+import { defineConfig, devices } from "@playwright/test"
+
+// ◄ FORCE NODE TO LOAD THE ENV VARIABLES FIRST
/**
* Read environment variables from file.
@@ -12,7 +14,7 @@ import { defineConfig, devices } from '@playwright/test';
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
- testDir: './e2e',
+ testDir: "./e2e",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
@@ -22,31 +24,31 @@ export default defineConfig({
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
- reporter: 'html',
+ reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('')`. */
// baseURL: 'http://localhost:3000',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
- trace: 'on-first-retry',
+ trace: "on-first-retry",
},
/* Configure projects for major browsers */
projects: [
{
- name: 'chromium',
- use: { ...devices['Desktop Chrome'] },
+ name: "chromium",
+ use: { ...devices["Desktop Chrome"] },
},
{
- name: 'firefox',
- use: { ...devices['Desktop Firefox'] },
+ name: "firefox",
+ use: { ...devices["Desktop Firefox"] },
},
{
- name: 'webkit',
- use: { ...devices['Desktop Safari'] },
+ name: "webkit",
+ use: { ...devices["Desktop Safari"] },
},
/* Test against mobile viewports. */
@@ -76,4 +78,4 @@ export default defineConfig({
// url: 'http://localhost:3000',
// reuseExistingServer: !process.env.CI,
// },
-});
+})
diff --git a/src/components/forms/bookform-randomise/CreateUnreadBookForm.tsx b/src/components/forms/bookform-randomise/CreateUnreadBookForm.tsx
index da32726..8a6893c 100644
--- a/src/components/forms/bookform-randomise/CreateUnreadBookForm.tsx
+++ b/src/components/forms/bookform-randomise/CreateUnreadBookForm.tsx
@@ -113,6 +113,7 @@ const CreateBook: React.FC = () => {
handleSubmitSuggestion()}
+ data-testid="unread-book-title-input"
onChange={(e) =>
dispatch(setFormData({ ...formData, title: e.target.value }))
}
@@ -147,6 +148,7 @@ const CreateBook: React.FC = () => {
>
dispatch(setFormData({ ...formData, author: e.target.value }))
}
@@ -175,6 +177,7 @@ const CreateBook: React.FC = () => {
>
dispatch(
setFormData({ ...formData, pages: Number(e.target.value) }),
@@ -206,6 +209,7 @@ const CreateBook: React.FC = () => {
>
dispatch(
setFormData({
@@ -227,6 +231,7 @@ const CreateBook: React.FC = () => {
>