Merge pull request #1974 from kuba618/AUT-1115

test: add admin account setup tests
This commit is contained in:
Ali BARIN
2024-07-22 17:03:55 +02:00
committed by GitHub
9 changed files with 168 additions and 4 deletions

View File

@@ -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

View File

@@ -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.
[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
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.

View 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()
};
}
};

View File

@@ -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');
const { AdminCreateUserPage } = require('./admin/create-user-page');
exports.test = test.extend({
@@ -54,6 +55,11 @@ exports.publicTest = test.extend({
await use(acceptInvitationPage);
},
adminSetupPage: async ({ page }, use) => {
const adminSetupPage = new AdminSetupPage(page);
await use(adminSetupPage);
},
adminCreateUserPage: async ({page}, use) => {
const adminCreateUserPage = new AdminCreateUserPage(page);
await use(adminCreateUserPage);

View 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;

View File

@@ -42,9 +42,19 @@ module.exports = defineConfig({
/* Configure projects for major browsers */
projects: [
{
name: 'setup',
testMatch: /.*\.setup\.js/,
teardown: 'teardown',
},
{
name: 'teardown',
testMatch: /.*\.teardown\.js/,
},
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
dependencies: ['setup'],
},
// {

View 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();
});
});

View 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();
})
});

View File

@@ -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 && (
<Alert severity="success" sx={{ mt: 3, fontWeight: 500 }}>
<Alert data-test="success-alert" severity="success" sx={{ mt: 3, fontWeight: 500 }}>
{formatMessage('installationForm.success', {
link: (str) => (
<Link