311 lines
12 KiB
JavaScript
311 lines
12 KiB
JavaScript
const fs = require("fs");
|
|
const puppeteer = require("puppeteer");
|
|
const mongoose = require("mongoose");
|
|
const { toMatchImageSnapshot } = require("jest-image-snapshot");
|
|
expect.extend({ toMatchImageSnapshot });
|
|
|
|
require("dotenv").config();
|
|
const options = {
|
|
showPrefix: false,
|
|
showMatcherMessage: true,
|
|
showStack: true,
|
|
};
|
|
|
|
let browser;
|
|
let page;
|
|
|
|
const user = {
|
|
name: "John Doe",
|
|
username: "johndoe",
|
|
email: "johndoe@gmail.com",
|
|
password: "12345678",
|
|
};
|
|
|
|
beforeAll(async () => {
|
|
mongoose.set("strictQuery", true);
|
|
await mongoose.connect(process.env.MONGODB_URI, {
|
|
useNewUrlParser: true,
|
|
useUnifiedTopology: true,
|
|
});
|
|
await mongoose.connection
|
|
.collection("users")
|
|
.findOneAndDelete({ username: user.username });
|
|
|
|
browser = await puppeteer.launch({
|
|
headless: true,
|
|
slowMo: 0,
|
|
devtools: false,
|
|
defaultViewport: {
|
|
width: 1024,
|
|
height: 768,
|
|
},
|
|
});
|
|
page = await browser.newPage();
|
|
await page.setDefaultTimeout(10000);
|
|
await page.setDefaultNavigationTimeout(20000);
|
|
});
|
|
|
|
beforeEach(async () => {
|
|
await page.goto(`http://localhost:${process.env.PORT}/`);
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await mongoose.connection
|
|
.collection("users")
|
|
.findOneAndDelete({ username: user.username });
|
|
await mongoose.connection.close();
|
|
await browser.close();
|
|
});
|
|
|
|
describe("Testing the index page title and content", () => {
|
|
it("should have the right title", async () => {
|
|
const title = await page.title();
|
|
expect(
|
|
title,
|
|
`The title for the web page "${title}" is wrong it should be "Auth-Experiment | Home" Make sure that the function handling the GET "/" route is sending the right title`,
|
|
options
|
|
).toBe("Auth-Experiment | Home");
|
|
});
|
|
|
|
it("should have nav bar with 3 links", async () => {
|
|
const navBar = await page.$eval("nav", (el) => el.textContent);
|
|
expect(
|
|
navBar,
|
|
`The page should contain a link to the home page. Check the "main.ejs" file in the "web/views/layouts" folder to find the nav bar"`,
|
|
options
|
|
).toContain("Home");
|
|
expect(
|
|
navBar,
|
|
`The page should contain a link to the register page. Check the "main.ejs" file in the "web/views/layouts" folder to find the nav bar`,
|
|
options
|
|
).toContain("Register");
|
|
expect(
|
|
navBar,
|
|
`The page should contain a link to the login page. Check the "main.ejs" file in the "web/views/layouts" folder to find the nav bar`,
|
|
options
|
|
).toContain("Login");
|
|
});
|
|
});
|
|
|
|
describe("Testing the error `Not Found` page", () => {
|
|
it("should have the right title", async () => {
|
|
await page.goto(
|
|
`http://localhost:${process.env.PORT}/thisurldoesnotexist`
|
|
);
|
|
const title = await page.title();
|
|
expect(
|
|
title,
|
|
`The title for the web page "${title}" is wrong it should be "Auth-Experiment | Error" Make sure that the function handling the GET "/:url" route is sending the right title`,
|
|
options
|
|
).toBe("Auth-Experiment | Error");
|
|
});
|
|
|
|
it("should have a status code of 404", async () => {
|
|
await page.goto(
|
|
`http://localhost:${process.env.PORT}/thisurldoesnotexist`
|
|
);
|
|
const statusCode = await page.$eval(".title", (el) => el.textContent);
|
|
expect(
|
|
statusCode,
|
|
`The status code "${statusCode}" is wrong it should be "404" Make sure that the function handling the GET "/:url" route is sending the right status code`,
|
|
options
|
|
).toBe("404");
|
|
});
|
|
|
|
it("should have a message saying `NOT FOUND`", async () => {
|
|
await page.goto(
|
|
`http://localhost:${process.env.PORT}/thisurldoesnotexist`
|
|
);
|
|
const message = await page.$eval(".message", (el) => el.textContent);
|
|
expect(
|
|
message,
|
|
`The message "${message}" is wrong it should be "NOT FOUND" Make sure that the function handling the GET "/:url" route is sending the right message`,
|
|
options
|
|
).toBe("NOT FOUND");
|
|
});
|
|
});
|
|
|
|
describe("Testing the register page", () => {
|
|
it("should have the right title", async () => {
|
|
await page.goto(`http://localhost:${process.env.PORT}/register`);
|
|
const title = await page.title();
|
|
expect(
|
|
title,
|
|
`The title for the web page "${title}" is wrong it should be "Auth-Experiment | Register" Make sure that the function handling the GET "/register" route is sending the right title`,
|
|
options
|
|
).toBe("Auth-Experiment | Register");
|
|
});
|
|
|
|
it("should have a form with 5 inputs and 1 button", async () => {
|
|
await page.goto(`http://localhost:${process.env.PORT}/register`);
|
|
const name_input = await page.$eval("#name", (el) => ({
|
|
name: el.name,
|
|
type: el.type,
|
|
}));
|
|
expect(
|
|
name_input,
|
|
`The form should contain an input with the name "name" and the type "text" Check the "register.ejs" file in the "web/views/auth" folder to find the form`,
|
|
options
|
|
).toEqual({ name: "name", type: "text" });
|
|
const username_input = await page.$eval("#username", (el) => ({
|
|
name: el.name,
|
|
type: el.type,
|
|
}));
|
|
expect(
|
|
username_input,
|
|
`The form should contain an input with the name "username" and the type "text" Check the "register.ejs" file in the "web/views/auth" folder to find the form`,
|
|
options
|
|
).toEqual({ name: "username", type: "text" });
|
|
const email_input = await page.$eval("#email", (el) => ({
|
|
name: el.name,
|
|
type: el.type,
|
|
}));
|
|
expect(
|
|
email_input,
|
|
`The form should contain an input with the name "email" and the type "email" Check the "register.ejs" file in the "web/views/auth" folder to find the form`,
|
|
options
|
|
).toEqual({ name: "email", type: "email" });
|
|
const password_input = await page.$eval("#password", (el) => ({
|
|
name: el.name,
|
|
type: el.type,
|
|
}));
|
|
expect(
|
|
password_input,
|
|
`The form should contain an input with the name "password" and the type "password" Check the "register.ejs" file in the "web/views/auth" folder to find the form`,
|
|
options
|
|
).toEqual({ name: "password", type: "password" });
|
|
const confirmPassword_input = await page.$eval(
|
|
"#confirmPassword",
|
|
(el) => ({
|
|
name: el.name,
|
|
type: el.type,
|
|
})
|
|
);
|
|
expect(
|
|
confirmPassword_input,
|
|
`The form should contain an input with the name "confirmPassword" and the type "password" Check the "register.ejs" file in the "web/views/auth" folder to find the form`,
|
|
options
|
|
).toEqual({ name: "confirmPassword", type: "password" });
|
|
|
|
const button = await page.$eval("button", (el) => ({
|
|
type: el.type,
|
|
text: el.textContent,
|
|
}));
|
|
expect(
|
|
button,
|
|
`The form should contain a button with the text "Register" and the type "submit" Check the "register.ejs" file in the "web/views/auth" folder to find the form`,
|
|
options
|
|
).toEqual({ type: "submit", text: "Register" });
|
|
});
|
|
|
|
it("should register a new user", async () => {
|
|
await page.goto(`http://localhost:${process.env.PORT}/register`);
|
|
await page.type("#name", user.name);
|
|
await page.type("#username", user.username);
|
|
await page.type("#email", user.email);
|
|
await page.type("#password", user.password);
|
|
await page.type("#confirmPassword", user.password);
|
|
await page.click("button");
|
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
|
|
const url = await page.url();
|
|
expect(
|
|
url,
|
|
`The user should be redirected to the profile page after registering, the current url is "${url}"`,
|
|
options
|
|
).toBe(`http://localhost:${process.env.PORT}/profile`);
|
|
});
|
|
|
|
it("should have the name of the user in the index page", async () => {
|
|
const message = await page.$eval(".message", (el) => el.textContent);
|
|
expect(
|
|
message,
|
|
`The message "${message}" is wrong it should be "Hello ${user.name}" Make sure that the function handling the GET "/profile" route is sending the right message`,
|
|
options
|
|
).toBe(`Hello ${user.name}`);
|
|
});
|
|
});
|
|
|
|
describe("Testing the index page, register page, and error `Not Found` page image snapshots", () => {
|
|
it("matches the expected styling for the index page after register", async () => {
|
|
if (!fs.existsSync("tests/web/images/index-page-after-register.png")) {
|
|
throw new Error(
|
|
`The reference image for the index after register page does not exist, please import the image from the "tests/web/images/index-page-after-register.png"`
|
|
);
|
|
}
|
|
const screenshot = await page.screenshot({ fullPage: true });
|
|
expect(
|
|
screenshot,
|
|
`The web styling for the index page is not correct check the file "tests/web/images/__diff_output__/index-page-after-register-diff.png" to find the difference`,
|
|
options
|
|
).toMatchImageSnapshot({
|
|
customDiffConfig: { threshold: 0.9 },
|
|
customSnapshotsDir: "tests/web/images",
|
|
customSnapshotIdentifier: "index-page-after-register",
|
|
});
|
|
});
|
|
|
|
it("matches the expected styling for the index page before register", async () => {
|
|
// restart the browser and go to the index page
|
|
const client = await page.target().createCDPSession();
|
|
await client.send("Network.clearBrowserCookies");
|
|
await client.send("Network.clearBrowserCache");
|
|
if (!fs.existsSync("tests/web/images/index-page.png")) {
|
|
throw new Error(
|
|
`The reference image for the index page does not exist, please import the image from the "tests/web/images/index-page.png"`
|
|
);
|
|
}
|
|
await page.goto(`http://localhost:${process.env.PORT}/`);
|
|
const screenshot = await page.screenshot({ fullPage: true });
|
|
expect(
|
|
screenshot,
|
|
`The web styling for the index page is not correct check the file "tests/web/images/__diff_output__/index-page-diff.png" to find the difference`,
|
|
options
|
|
).toMatchImageSnapshot({
|
|
customDiffConfig: { threshold: 0.9 },
|
|
customSnapshotsDir: "tests/web/images",
|
|
customSnapshotIdentifier: "index-page",
|
|
});
|
|
});
|
|
|
|
it("matches the expected styling for the register page", async () => {
|
|
if (!fs.existsSync("tests/web/images/register-page.png")) {
|
|
throw new Error(
|
|
`The reference image for the register page does not exist, please import the image from the "tests/web/images/register-page.png"`
|
|
);
|
|
}
|
|
await page.goto(`http://localhost:${process.env.PORT}/register`);
|
|
const screenshot = await page.screenshot({ fullPage: true });
|
|
expect(
|
|
screenshot,
|
|
`The web styling for the register page is not correct check the file "tests/web/images/__diff_output__/register-page-diff.png" to find the difference`,
|
|
options
|
|
).toMatchImageSnapshot({
|
|
customDiffConfig: { threshold: 0.9 },
|
|
customSnapshotsDir: "tests/web/images",
|
|
customSnapshotIdentifier: "register-page",
|
|
});
|
|
});
|
|
|
|
it("matches the expected styling for the error page", async () => {
|
|
if (!fs.existsSync("tests/web/images/error-notFound-page.png")) {
|
|
throw new Error(
|
|
`The reference image for the error page does not exist, please import the image from the "tests/web/images/error-notFound-page.png"`
|
|
);
|
|
}
|
|
await page.goto(
|
|
`http://localhost:${process.env.PORT}/thisurldoesnotexist`
|
|
);
|
|
const screenshot = await page.screenshot({ fullPage: true });
|
|
expect(
|
|
screenshot,
|
|
`The web styling for the error "Not Found" page is not correct check the file "tests/web/images/__diff_output__/error-notFound-page-diff.png" to find the difference`,
|
|
options
|
|
).toMatchImageSnapshot({
|
|
customDiffConfig: { threshold: 0.9 },
|
|
customSnapshotsDir: "tests/web/images",
|
|
customSnapshotIdentifier: "error-notFound-page",
|
|
});
|
|
});
|
|
});
|