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

Improve test diagnostics #504

Merged
merged 8 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
66 changes: 34 additions & 32 deletions client/src/App.test.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {
render,
screen,
fireEvent,
waitForElementToBeRemoved,
} from "@testing-library/react";
import { server } from "./tests/setupTests.js";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { http, HttpResponse } from "msw";

import { server } from "./tests/setupTests.js";

import App from "./App.jsx";

describe("Main Page", () => {
/** @type {import("@testing-library/user-event").UserEvent} */
let user;

beforeEach(async () => {
// Here we create a fake backend that will always return two videos when calling the /api/videos endpoint
server.use(
Expand All @@ -34,6 +34,7 @@ describe("Main Page", () => {

// Let's wait for one of the videos to appear
await screen.findByText("Never Gonna Give You Up");
user = userEvent.setup();
});

it("Renders the videos", async () => {
Expand All @@ -43,72 +44,73 @@ describe("Main Page", () => {
);

// We have two videos, so the amount should be two
expect(videoContainers.length).toBe(2);
expect(videoContainers).toHaveLength(2);
});

it("Removes the video when asked to do", async () => {
// we create another fake backend that listens on the delete call, and returns success
server.use(
http.delete("/api/videos/1", () => HttpResponse.json({ success: true }))
http.delete(
"/api/videos/1",
() => new HttpResponse(null, { status: 204 })
)
);

// we find the delete button on the website
const deleteButton = screen.getAllByText("Remove video")[0];
const deleteButton = screen.getAllByRole("button", {
name: "Remove video",
})[0];

// then we click it
fireEvent.click(deleteButton);
await user.click(deleteButton);

// wait for the video to get deleted from the page
await waitForElementToBeRemoved(deleteButton);
await waitFor(() =>
expect(
screen.getAllByRole("button", { name: "Remove video" })
).toHaveLength(1)
);

// we calculate the number of videos after the call
const videoContainers = screen.getAllByText(
(_, e) => e.tagName.toLowerCase() === "iframe"
);

// this should now be only 1
expect(videoContainers.length).toBe(1);
expect(videoContainers).toHaveLength(1);
});

it("Adds a new video when asked to do", async () => {
const title = "New Title";
const url = "https://www.youtube.com/watch?v=CDEYRFUTURE";

// we set up a fake backend that allows us to send a new video. It only allows one specific title and url however
server.use(
http.post("/api/videos", async ({ request }) => {
const data = await request.json();
if (
data.title != "New Title" ||
data.url != "https://www.youtube.com/watch?v=CDEYRFUTURE"
) {
return HttpResponse.json({ success: false });
if (data.title !== title || data.url !== url) {
return HttpResponse.json({ success: false }, { status: 400 });
}
return HttpResponse.json({
id: 3,
title: "New Title",
url: "https://www.youtube.com/watch?v=CDEYRFUTURE",
});
return HttpResponse.json({ id: 3, title, url });
})
);

// we fill in the form
fireEvent.change(screen.getByRole("textbox", { name: "Title:" }), {
target: { value: "New Title" },
});
fireEvent.change(screen.getByRole("textbox", { name: "Url:" }), {
target: { value: "https://www.youtube.com/watch?v=CDEYRFUTURE" },
});
await user.type(screen.getByRole("textbox", { name: "Title:" }), title);
await user.type(screen.getByRole("textbox", { name: "Url:" }), url);

// then click submit
fireEvent.click(screen.getByRole("button", { name: "Submit" }));
await user.click(screen.getByRole("button", { name: "Submit" }));

// wait for the new video to appear
await screen.findByText("New Title");
await screen.findByText(title);

// afterwards we calculate the number of videos on the page
const videoContainers = screen.getAllByText(
(_, e) => e.tagName.toLowerCase() === "iframe"
);

// this should now be three
expect(videoContainers.length).toBe(3);
expect(videoContainers).toHaveLength(3);
});
});
2 changes: 0 additions & 2 deletions db/initdb.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
\c videorec;

DROP TABLE IF EXISTS videos CASCADE;

CREATE TABLE videos (
Expand Down
14 changes: 8 additions & 6 deletions server/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ describe("/api", () => {
const response = await request(app).get("/api/videos");

expect(response.statusCode).toBe(200);
expect(response.body[0].title).toBe("Never Gonna Give You Up");
expect(response.body[0].url).toBe(
"https://www.youtube.com/watch?v=dQw4w9WgXcQ"
);
expect(response.body).toEqual([
{
title: "Never Gonna Give You Up",
url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
},
]);
});
});

Expand All @@ -21,7 +23,7 @@ describe("/api", () => {
it("Returns a successful response if the id exists", async () => {
const response = await request(app).delete("/api/videos/1");

expect(response.statusCode).toBe(200);
expect(response.statusCode).toBe(204);
});

it("Deletes the video from the database if the id exists", async () => {
Expand All @@ -31,7 +33,7 @@ describe("/api", () => {
"SELECT * FROM videos WHERE id = $1",
[1]
);
expect(dbResponse.rows.length).toBe(0);
expect(dbResponse.rows).toHaveLength(0);
});
});
});
Expand Down
Loading