diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 7b774780..7a1e9a69 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -71,9 +71,6 @@ jobs: - name: Migrate database working-directory: ./packages/backend run: yarn db:migrate - - name: Seed user - working-directory: ./packages/backend - run: yarn db:seed:user & - name: Install certutils run: sudo apt install -y libnss3-tools - name: Install mkcert diff --git a/packages/e2e-tests/fixtures/admin-setup-page.js b/packages/e2e-tests/fixtures/admin-setup-page.js new file mode 100644 index 00000000..704a9caf --- /dev/null +++ b/packages/e2e-tests/fixtures/admin-setup-page.js @@ -0,0 +1,75 @@ +import { BasePage } from "./base-page"; +const { faker } = require('@faker-js/faker'); +const { expect } = require('@playwright/test'); + +export class AdminSetupPage extends BasePage { + path = '/installation'; + + /** + * @param {import('@playwright/test').Page} page + */ + constructor(page) { + super(page); + + this.fullNameTextField = this.page.getByTestId('fullName-text-field'); + this.emailTextField = this.page.getByTestId('email-text-field'); + this.passwordTextField = this.page.getByTestId('password-text-field'); + this.repeatPasswordTextField = this.page.getByTestId('repeat-password-text-field'); + this.createAdminButton = this.page.getByTestId('signUp-button'); + this.invalidFields = this.page.locator('p.Mui-error'); + this.successAlert = this.page.getByTestId('success-alert'); + } + + async open() { + return await this.page.goto(this.path); + } + + async fillValidUserData() { + await this.fullNameTextField.fill(process.env.LOGIN_EMAIL); + await this.emailTextField.fill(process.env.LOGIN_EMAIL); + await this.passwordTextField.fill(process.env.LOGIN_PASSWORD); + await this.repeatPasswordTextField.fill(process.env.LOGIN_PASSWORD); + } + + async fillInvalidUserData() { + await this.fullNameTextField.fill(''); + await this.emailTextField.fill('abcde'); + await this.passwordTextField.fill(''); + await this.repeatPasswordTextField.fill('a'); + } + + async fillNotMatchingPasswordUserData() { + const testUser = this.generateUser(); + await this.fullNameTextField.fill(testUser.fullName); + await this.emailTextField.fill(testUser.email); + await this.passwordTextField.fill(testUser.password); + await this.repeatPasswordTextField.fill(testUser.wronglyRepeatedPassword); + } + + async submitAdminForm() { + await this.createAdminButton.click(); + } + + async expectInvalidFields(errorCount) { + await expect(await this.invalidFields.all()).toHaveLength(errorCount); + } + + async expectSuccessAlertToBeVisible() { + await expect(await this.successAlert).toBeVisible(); + } + + async expectSuccessMessageToContainLoginLink() { + await expect(await this.successAlert.locator('a')).toHaveAttribute('href', '/login'); + } + + generateUser() { + faker.seed(Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER)); + + return { + fullName: faker.person.fullName(), + email: faker.internet.email(), + password: faker.internet.password(), + wronglyRepeatedPassword: faker.internet.password() + }; + } +}; diff --git a/packages/e2e-tests/fixtures/index.js b/packages/e2e-tests/fixtures/index.js index fc9dabcf..d9fab044 100644 --- a/packages/e2e-tests/fixtures/index.js +++ b/packages/e2e-tests/fixtures/index.js @@ -7,6 +7,7 @@ const { UserInterfacePage } = require('./user-interface-page'); const { LoginPage } = require('./login-page'); const { AcceptInvitation } = require('./accept-invitation-page'); const { adminFixtures } = require('./admin'); +const { AdminSetupPage } = require('./admin-setup-page'); exports.test = test.extend({ page: async ({ page }, use) => { @@ -51,7 +52,12 @@ exports.publicTest = test.extend({ acceptInvitationPage: async ({ page }, use) => { const acceptInvitationPage = new AcceptInvitation(page); await use(acceptInvitationPage); - } + }, + + adminSetupPage: async ({ page }, use) => { + const adminSetupPage = new AdminSetupPage(page); + await use(adminSetupPage); + }, }); expect.extend({ diff --git a/packages/e2e-tests/playwright.config.js b/packages/e2e-tests/playwright.config.js index 315ca57a..be595059 100644 --- a/packages/e2e-tests/playwright.config.js +++ b/packages/e2e-tests/playwright.config.js @@ -42,9 +42,14 @@ module.exports = defineConfig({ /* Configure projects for major browsers */ projects: [ + { + name: 'setup', + testMatch: /.*\.setup\.js/, + }, { name: 'chromium', use: { ...devices['Desktop Chrome'] }, + dependencies: ['setup'], }, // { diff --git a/packages/e2e-tests/tests/admin-setup/admin.setup.js b/packages/e2e-tests/tests/admin-setup/admin.setup.js new file mode 100644 index 00000000..ede8ed56 --- /dev/null +++ b/packages/e2e-tests/tests/admin-setup/admin.setup.js @@ -0,0 +1,31 @@ +const { publicTest: setup, expect } = require('../../fixtures/index'); + +setup.describe.serial('Admin setup page', () => { + setup.skip(!process.env.CI); + + // eslint-disable-next-line no-unused-vars + setup('should not be able to login if admin is not created', async ({ page, adminSetupPage, loginPage }) => { + await expect(async () => { + await expect(await page.url()).toContain(adminSetupPage.path); + }).toPass(); + }); + + setup('should validate the inputs', async ({ adminSetupPage }) => { + await adminSetupPage.open(); + await adminSetupPage.fillInvalidUserData(); + await adminSetupPage.submitAdminForm(); + await adminSetupPage.expectInvalidFields(4); + + await adminSetupPage.fillNotMatchingPasswordUserData(); + await adminSetupPage.submitAdminForm(); + await adminSetupPage.expectInvalidFields(1); + }); + + setup('should create admin', async ({ adminSetupPage }) => { + await adminSetupPage.open(); + await adminSetupPage.fillValidUserData(); + await adminSetupPage.submitAdminForm(); + await adminSetupPage.expectSuccessAlertToBeVisible(); + await adminSetupPage.expectSuccessMessageToContainLoginLink(); + }); +}); diff --git a/packages/web/src/components/InstallationForm/index.jsx b/packages/web/src/components/InstallationForm/index.jsx index 04e30f3e..a21eefda 100644 --- a/packages/web/src/components/InstallationForm/index.jsx +++ b/packages/web/src/components/InstallationForm/index.jsx @@ -134,6 +134,7 @@ function InstallationForm() { fullWidth margin="dense" type="password" + data-test="password-text-field" error={touchedFields.password && !!errors?.password} helperText={ touchedFields.password && errors?.password?.message @@ -155,6 +156,7 @@ function InstallationForm() { fullWidth margin="dense" type="password" + data-test="repeat-password-text-field" error={touchedFields.confirmPassword && !!errors?.confirmPassword} helperText={ touchedFields.confirmPassword && @@ -186,7 +188,7 @@ function InstallationForm() { )} /> {install.isSuccess && ( - + {formatMessage('installationForm.success', { link: (str) => (