diff --git a/package-lock.json b/package-lock.json index a081b50..7d6b31b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -324,9 +324,9 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", diff --git a/playwright.config.js b/playwright.config.js index 87d4f31..d8d0432 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -1,14 +1,14 @@ // @ts-check -require('dotenv').config(); +require("dotenv").config(); -const { defineConfig, devices } = require('@playwright/test'); +const { defineConfig, devices } = require("@playwright/test"); const { BASE_URL } = process.env; /** * @see https://playwright.dev/docs/test-configuration */ module.exports = defineConfig({ - testDir: './src/tests', + testDir: "./src/tests", // testDir: './src/examples', /* Run tests in files in parallel */ fullyParallel: false, @@ -19,32 +19,32 @@ module.exports = 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: BASE_URL, /* 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: 'webkit', - // use: { ...devices['Desktop Safari'] }, - // }, + { + name: "firefox", + use: { ...devices["Desktop Firefox"] }, + }, + + { + name: "webkit", + use: { ...devices["Desktop Safari"] }, + }, /* Test against mobile viewports. */ // { @@ -74,4 +74,3 @@ module.exports = defineConfig({ // reuseExistingServer: !process.env.CI, // }, }); - diff --git a/src/fixtures/fixtures.js b/src/fixtures/fixtures.js index b940e58..f01d48c 100644 --- a/src/fixtures/fixtures.js +++ b/src/fixtures/fixtures.js @@ -4,20 +4,16 @@ const { ADMIN_USERNAME, ADMIN_PASSWORD } = process.env; export const username = ADMIN_USERNAME; export const password = ADMIN_PASSWORD; -export const userFullName = "Lišák Admin"; -export const applicationsPageSize = 10; -export const applicationsSearchText = "Eli"; -export const applicationsSearchResultText = /.*[Ee]l[ií].*/; +export const userFullName = "Konečná Hana"; +export const invalidPassword = "123456789"; export const ApplicationTexts = { - loginPage: { - title:"Přihlášení - Czechitas", - emailFieldLabel: "Email", - passwordFieldLabel: "Heslo", - loginButtonLabel: "Přihlásit", - }, - applicationsPage: { - title: "Přihlášky - Czechitas", - applicationsSectionName: "Přihlášky" - } -} + loginPage: { + title: "Přihlášení - Czechitas", + loginButtonLabel: "Přihlásit", + }, + registrationPage: { + title: "Registrace - Czechitas", + registrationButtonLabel: "Zaregistrovat", + }, +}; \ No newline at end of file diff --git a/src/tests/example.spec.js b/src/tests/example.spec.js deleted file mode 100644 index 4d2f244..0000000 --- a/src/tests/example.spec.js +++ /dev/null @@ -1,6 +0,0 @@ -import { test } from "@playwright/test"; - -test("should open login page", async ({ page }) => { - await page.goto("/prihlaseni"); - console.log(await page.title()); -}); diff --git a/src/tests/homework.spec.js b/src/tests/homework.spec.js new file mode 100644 index 0000000..b4393d9 --- /dev/null +++ b/src/tests/homework.spec.js @@ -0,0 +1,125 @@ +import { expect, test } from "@playwright/test"; + +import { + ApplicationTexts, + invalidPassword, + password, + userFullName, +} from "../fixtures/fixtures.js"; + +import { LoginPage } from "./pages/login.page.js"; +import { RegistrationPage } from "./pages/registration.page.js"; + +test.describe("Registration Page is Correctly Displayed", async () => { + test.beforeEach(async ({ page }) => { + const loginPage = new LoginPage(page); + await loginPage.open(); + await loginPage.registrationButton.click(); + await test + .expect(page) + .toHaveTitle(ApplicationTexts.registrationPage.title); + }); + + test("verify registration form is displayed correctly ", async ({ page }) => { + const registrationPage = new RegistrationPage(page); + + await expect( + registrationPage.fullNameInput, + "name input field should be visible" + ).toBeVisible(); + await expect( + registrationPage.fullNameInput, + "name input field should be enabled" + ).toBeEnabled(); + + await expect( + registrationPage.emailInput, + "email input field should be visible" + ).toBeVisible(); + await expect( + registrationPage.emailInput, + "email input field should be enabled" + ).toBeEnabled(); + + await expect( + registrationPage.passwordInput, + "password input field should be visible" + ).toBeVisible(); + await expect( + registrationPage.passwordInput, + "password input field should be enabled" + ).toBeEnabled(); + + await expect( + registrationPage.confirmPasswordInput, + "confirm password input field should be visible" + ).toBeVisible(); + await expect( + registrationPage.confirmPasswordInput, + "confirm password input field should be enabled" + ).toBeEnabled(); + + await expect( + registrationPage.registrationButton, + "registration button should be visible" + ).toBeVisible(); + await expect( + registrationPage.registrationButton, + "login button text should have text" + ).toHaveText(ApplicationTexts.registrationPage.registrationButtonLabel); + }); + + test("verify registration form using screenshot", async ({ page }) => { + await page.screenshot({ path: "registrationForm.png" }); + }); +}); + +//Temporarily force a single worker // +test.describe("User Registration - Valid and Invalid Credentials", () => { + let testEmail; + + test.beforeAll(async () => { + testEmail = `testuserCzechitas+${Date.now()}@gmail.com`; + console.log("Generated Email in beforeAll:", testEmail); + }); + + test.beforeEach(async ({ page }) => { + const registrationPage = new RegistrationPage(page); + await registrationPage.open(); + await test + .expect(page) + .toHaveTitle(ApplicationTexts.registrationPage.title); + }); + + test("should register with valid credentials", async ({ page }) => { + const registrationPage = new RegistrationPage(page); + await registrationPage.register(userFullName, testEmail, password); + + await expect(registrationPage.usernameDropdown).toHaveText(userFullName); + }); + + test("should not register with existing email", async ({ page }) => { + const registrationPage = new RegistrationPage(page); + await registrationPage.register(userFullName, testEmail, password); + await expect(registrationPage.toast).toHaveText( + "Některé pole obsahuje špatně zadanou hodnotu" + ); + await expect(registrationPage.fieldError).toHaveText( + "Účet s tímto emailem již existuje" + ); + }); + + test("should not register with invalid password - only digits", async ({ + page, + }) => { + const testEmail2 = `testuserCzechitas+${Date.now()}@gmail.com`; + const registrationPage = new RegistrationPage(page); + await registrationPage.register(userFullName, testEmail2, invalidPassword); + await expect(registrationPage.toast).toHaveText( + "Některé pole obsahuje špatně zadanou hodnotu" + ); + await expect(registrationPage.fieldError).toHaveText( + "Heslo musí obsahovat minimálně 6 znaků, velké i malé písmeno a číslici" + ); + }); +}); diff --git a/src/tests/pages/app.page.js b/src/tests/pages/app.page.js new file mode 100644 index 0000000..46225e5 --- /dev/null +++ b/src/tests/pages/app.page.js @@ -0,0 +1,30 @@ +export class AppPage { + constructor(page, url) { + this.url = url; + this.page = page; + this.toast = this.page.locator(".toast-message"); + this.navbarRight = this.page.locator(".navbar-right"); + this.usernameDropdown = this.navbarRight.locator( + "[data-toggle='dropdown']" + ); + this.logoutLink = this.page.locator("#logout-link"); + this.fieldError = this.page.locator(".invalid-feedback"); + } + + async open() { + await this.page.goto("/" + this.url); + } + + async getToastMessage() { + return await this.toast.textContent(); + } + + async logout() { + await this.usernameDropdown.click(); + await this.logoutLink.click(); + } + + async getCurrentUser() { + return await this.usernameDropdown.textContent(); + } +} diff --git a/src/tests/pages/login.page.js b/src/tests/pages/login.page.js new file mode 100644 index 0000000..f1c2794 --- /dev/null +++ b/src/tests/pages/login.page.js @@ -0,0 +1,21 @@ +//Page object describing the login page// + +const { AppPage } = require("./app.page"); + +export class LoginPage extends AppPage { + constructor(page) { + super(page, "prihlaseni"); + this.emailField = this.page.getByLabel("Email"); + this.passwordField = this.page.getByLabel("Heslo"); + this.loginButton = this.page.getByRole("button", { name: "Přihlásit" }); + this.registrationButton = this.page.getByRole("link", { + name: "Zaregistrujte se", + }); + } + + async login(username, password) { + await this.emailField.fill(username); + await this.passwordField.fill(password); + await this.loginButton.click(); + } +} diff --git a/src/tests/pages/registration.page.js b/src/tests/pages/registration.page.js new file mode 100644 index 0000000..38dc0b4 --- /dev/null +++ b/src/tests/pages/registration.page.js @@ -0,0 +1,24 @@ +//Page object describing the registration page// + +import { AppPage } from "./app.page"; + +export class RegistrationPage extends AppPage { + constructor(page) { + super(page, "registrace"); + this.fullNameInput = this.page.getByLabel("Jméno a příjmení"); + this.emailInput = this.page.getByLabel("Email"); + this.passwordInput = this.page.getByLabel("Heslo"); + this.confirmPasswordInput = this.page.getByLabel("Kontrola hesla"); + this.registrationButton = this.page.getByRole("button", { + name: "Zaregistrovat", + }); + } + + async register(userFullName, username, password) { + await this.fullNameInput.fill(userFullName); + await this.emailInput.fill(username); + await this.passwordInput.fill(password); + await this.confirmPasswordInput.fill(password); + await this.registrationButton.click(); + } +}