Merge pull request #1974 from kuba618/AUT-1115
test: add admin account setup tests
This commit is contained in:
3
.github/workflows/playwright.yml
vendored
3
.github/workflows/playwright.yml
vendored
@@ -71,9 +71,6 @@ jobs:
|
|||||||
- name: Migrate database
|
- name: Migrate database
|
||||||
working-directory: ./packages/backend
|
working-directory: ./packages/backend
|
||||||
run: yarn db:migrate
|
run: yarn db:migrate
|
||||||
- name: Seed user
|
|
||||||
working-directory: ./packages/backend
|
|
||||||
run: yarn db:seed:user &
|
|
||||||
- name: Install certutils
|
- name: Install certutils
|
||||||
run: sudo apt install -y libnss3-tools
|
run: sudo apt install -y libnss3-tools
|
||||||
- name: Install mkcert
|
- name: Install mkcert
|
||||||
|
@@ -44,6 +44,14 @@ and it should install the associated browsers for the test running. For more inf
|
|||||||
|
|
||||||
We recommend using [Playwright Test for VSCode](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright) maintained by Microsoft. This lets you run playwright tests from within the code editor, giving you access to additional tools, such as easily running subsets of tests.
|
We recommend using [Playwright Test for VSCode](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright) maintained by Microsoft. This lets you run playwright tests from within the code editor, giving you access to additional tools, such as easily running subsets of tests.
|
||||||
|
|
||||||
|
[Global setup and teardown](https://playwright.dev/docs/test-global-setup-teardown) are part of the tests.
|
||||||
|
|
||||||
|
By running `yarn test` setup and teardown actions will take place.
|
||||||
|
|
||||||
|
If you need to setup Admin account (if you didn't seed the DB with the admin account or have clean DB) you should run `auth.setup.js` file.
|
||||||
|
|
||||||
|
If you want to clean the database (drop tables) and perform required migrations run `global.teardown.js`.
|
||||||
|
|
||||||
# Test failures
|
# Test failures
|
||||||
|
|
||||||
If there are failing tests in the test suite, this can be caused by a myriad of reasons, but one of the best places to start is either running the test in a headed browser, looking at the associated trace file for the failed test, or checking out the output of a failed GitHub Action.
|
If there are failing tests in the test suite, this can be caused by a myriad of reasons, but one of the best places to start is either running the test in a headed browser, looking at the associated trace file for the failed test, or checking out the output of a failed GitHub Action.
|
||||||
|
75
packages/e2e-tests/fixtures/admin-setup-page.js
Normal file
75
packages/e2e-tests/fixtures/admin-setup-page.js
Normal file
@@ -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()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
@@ -7,6 +7,7 @@ const { UserInterfacePage } = require('./user-interface-page');
|
|||||||
const { LoginPage } = require('./login-page');
|
const { LoginPage } = require('./login-page');
|
||||||
const { AcceptInvitation } = require('./accept-invitation-page');
|
const { AcceptInvitation } = require('./accept-invitation-page');
|
||||||
const { adminFixtures } = require('./admin');
|
const { adminFixtures } = require('./admin');
|
||||||
|
const { AdminSetupPage } = require('./admin-setup-page');
|
||||||
const { AdminCreateUserPage } = require('./admin/create-user-page');
|
const { AdminCreateUserPage } = require('./admin/create-user-page');
|
||||||
|
|
||||||
exports.test = test.extend({
|
exports.test = test.extend({
|
||||||
@@ -54,6 +55,11 @@ exports.publicTest = test.extend({
|
|||||||
await use(acceptInvitationPage);
|
await use(acceptInvitationPage);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
adminSetupPage: async ({ page }, use) => {
|
||||||
|
const adminSetupPage = new AdminSetupPage(page);
|
||||||
|
await use(adminSetupPage);
|
||||||
|
},
|
||||||
|
|
||||||
adminCreateUserPage: async ({page}, use) => {
|
adminCreateUserPage: async ({page}, use) => {
|
||||||
const adminCreateUserPage = new AdminCreateUserPage(page);
|
const adminCreateUserPage = new AdminCreateUserPage(page);
|
||||||
await use(adminCreateUserPage);
|
await use(adminCreateUserPage);
|
||||||
|
25
packages/e2e-tests/knexfile.js
Normal file
25
packages/e2e-tests/knexfile.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
const fileExtension = 'js';
|
||||||
|
|
||||||
|
const knexConfig = {
|
||||||
|
client: 'pg',
|
||||||
|
connection: {
|
||||||
|
host: process.env.POSTGRES_HOST,
|
||||||
|
user: process.env.POSTGRES_USERNAME,
|
||||||
|
port: process.env.POSTGRES_PORT,
|
||||||
|
password: process.env.POSTGRES_PASSWORD,
|
||||||
|
database: process.env.POSTGRES_DATABASE
|
||||||
|
},
|
||||||
|
searchPath: ['public'],
|
||||||
|
pool: { min: 0, max: 20 },
|
||||||
|
migrations: {
|
||||||
|
directory: '../../packages/backend/src/db/migrations/',
|
||||||
|
extension: fileExtension,
|
||||||
|
loadExtensions: [`.${fileExtension}`],
|
||||||
|
},
|
||||||
|
seeds: {
|
||||||
|
directory: '../../packages/backend/src/db/seeds',
|
||||||
|
},
|
||||||
|
...(process.env.APP_ENV === 'test' ? knexSnakeCaseMappers() : {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default knexConfig;
|
@@ -42,9 +42,19 @@ module.exports = defineConfig({
|
|||||||
|
|
||||||
/* Configure projects for major browsers */
|
/* Configure projects for major browsers */
|
||||||
projects: [
|
projects: [
|
||||||
|
{
|
||||||
|
name: 'setup',
|
||||||
|
testMatch: /.*\.setup\.js/,
|
||||||
|
teardown: 'teardown',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'teardown',
|
||||||
|
testMatch: /.*\.teardown\.js/,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'chromium',
|
name: 'chromium',
|
||||||
use: { ...devices['Desktop Chrome'] },
|
use: { ...devices['Desktop Chrome'] },
|
||||||
|
dependencies: ['setup'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// {
|
// {
|
||||||
|
29
packages/e2e-tests/tests/admin-setup/admin.setup.js
Normal file
29
packages/e2e-tests/tests/admin-setup/admin.setup.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
const { publicTest: setup, expect } = require('../../fixtures/index');
|
||||||
|
|
||||||
|
setup.describe.serial('Admin setup page', () => {
|
||||||
|
// 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();
|
||||||
|
});
|
||||||
|
});
|
12
packages/e2e-tests/tests/global.teardown.js
Normal file
12
packages/e2e-tests/tests/global.teardown.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
const { publicTest } = require('../fixtures');
|
||||||
|
import knex from 'knex';
|
||||||
|
import knexConfig from '../knexfile.js';
|
||||||
|
|
||||||
|
publicTest.describe('restore db', () => {
|
||||||
|
publicTest('clean db and perform migrations', async () => {
|
||||||
|
const knexClient = knex(knexConfig)
|
||||||
|
const migrator = knexClient.migrate;
|
||||||
|
await migrator.rollback({}, true);
|
||||||
|
await migrator.latest();
|
||||||
|
})
|
||||||
|
});
|
@@ -134,6 +134,7 @@ function InstallationForm() {
|
|||||||
fullWidth
|
fullWidth
|
||||||
margin="dense"
|
margin="dense"
|
||||||
type="password"
|
type="password"
|
||||||
|
data-test="password-text-field"
|
||||||
error={touchedFields.password && !!errors?.password}
|
error={touchedFields.password && !!errors?.password}
|
||||||
helperText={
|
helperText={
|
||||||
touchedFields.password && errors?.password?.message
|
touchedFields.password && errors?.password?.message
|
||||||
@@ -155,6 +156,7 @@ function InstallationForm() {
|
|||||||
fullWidth
|
fullWidth
|
||||||
margin="dense"
|
margin="dense"
|
||||||
type="password"
|
type="password"
|
||||||
|
data-test="repeat-password-text-field"
|
||||||
error={touchedFields.confirmPassword && !!errors?.confirmPassword}
|
error={touchedFields.confirmPassword && !!errors?.confirmPassword}
|
||||||
helperText={
|
helperText={
|
||||||
touchedFields.confirmPassword &&
|
touchedFields.confirmPassword &&
|
||||||
@@ -186,7 +188,7 @@ function InstallationForm() {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{install.isSuccess && (
|
{install.isSuccess && (
|
||||||
<Alert severity="success" sx={{ mt: 3, fontWeight: 500 }}>
|
<Alert data-test="success-alert" severity="success" sx={{ mt: 3, fontWeight: 500 }}>
|
||||||
{formatMessage('installationForm.success', {
|
{formatMessage('installationForm.success', {
|
||||||
link: (str) => (
|
link: (str) => (
|
||||||
<Link
|
<Link
|
||||||
|
Reference in New Issue
Block a user