test: add page title test ids to await and await mounting loader components

This commit is contained in:
QAComet
2023-11-12 16:28:33 -07:00
parent 1e82e40802
commit 11e0cb9398
19 changed files with 157 additions and 113 deletions

View File

@@ -2,7 +2,7 @@ const { AuthenticatedPage } = require('../authenticated-page');
const { RoleConditionsModal } = require('./role-conditions-modal');
export class AdminCreateRolePage extends AuthenticatedPage {
screenshotPath = '/admin/create-role'
screenshotPath = '/admin/create-role';
/**
* @param {import('@playwright/test').Page} page
@@ -15,6 +15,7 @@ export class AdminCreateRolePage extends AuthenticatedPage {
this.connectionRow = page.getByTestId('Connection-permission-row');
this.executionRow = page.getByTestId('Execution-permission-row');
this.flowRow = page.getByTestId('Flow-permission-row');
this.pageTitle = page.getByTestId('create-role-title');
}
/**
@@ -30,12 +31,12 @@ export class AdminCreateRolePage extends AuthenticatedPage {
for (let subject of subjects) {
const row = this.getSubjectRow(subject);
const actionInputs = await this.getRowInputs(row);
Object.keys(actionInputs).forEach(action => {
Object.keys(actionInputs).forEach((action) => {
permissionConfigs.push({
action,
locator: actionInputs[action],
subject,
row
row,
});
});
}
@@ -49,11 +50,11 @@ export class AdminCreateRolePage extends AuthenticatedPage {
* )} subject
*/
getSubjectRow(subject) {
const k = `${subject.toLowerCase()}Row`
const k = `${subject.toLowerCase()}Row`;
if (this[k]) {
return this[k]
return this[k];
} else {
throw 'Unknown row'
throw 'Unknown row';
}
}
@@ -63,14 +64,14 @@ export class AdminCreateRolePage extends AuthenticatedPage {
async getRowInputs(row) {
const inputs = {
// settingsButton: row.getByTestId('permission-settings-button')
}
};
for (let input of ['create', 'read', 'update', 'delete', 'publish']) {
const testId = `${input}-checkbox`
if (await row.getByTestId(testId).count() > 0) {
const testId = `${input}-checkbox`;
if ((await row.getByTestId(testId).count()) > 0) {
inputs[input] = row.getByTestId(testId).locator('input');
}
}
return inputs
return inputs;
}
/**
@@ -100,7 +101,7 @@ export class AdminCreateRolePage extends AuthenticatedPage {
}
}
} else {
throw new Error(`${subject} does not have action ${action}`)
throw new Error(`${subject} does not have action ${action}`);
}
}
}

View File

@@ -14,6 +14,7 @@ export class AdminCreateUserPage extends AuthenticatedPage {
this.passwordInput = page.getByTestId('password-input');
this.roleInput = page.getByTestId('role.id-autocomplete');
this.createButton = page.getByTestId('create-button');
this.pageTitle = page.getByTestId('create-user-title');
}
seed(seed) {
@@ -24,7 +25,7 @@ export class AdminCreateUserPage extends AuthenticatedPage {
return {
fullName: faker.person.fullName(),
email: faker.internet.email().toLowerCase(),
password: faker.internet.password()
}
password: faker.internet.password(),
};
}
}

View File

@@ -5,5 +5,6 @@ export class AdminEditRolePage extends AdminCreateRolePage {
super(page);
delete this.createButton;
this.updateButton = page.getByTestId('update-button');
this.pageTitle = page.getByTestId('edit-role-title');
}
}

View File

@@ -15,6 +15,7 @@ export class AdminEditUserPage extends AuthenticatedPage {
this.emailInput = page.getByTestId('email-input');
this.roleInput = page.getByTestId('role.id-autocomplete');
this.updateButton = page.getByTestId('update-button');
this.pageTitle = page.getByTestId('edit-user-title');
}
generateUser () {

View File

@@ -14,6 +14,7 @@ export class AdminRolesPage extends AuthenticatedPage {
this.deleteRoleModal = new DeleteRoleModal(page);
this.roleRow = page.getByTestId('role-row');
this.rolesLoader = page.getByTestId('roles-list-loader');
this.pageTitle = page.getByTestId('roles-page-title');
}
/**
@@ -28,8 +29,9 @@ export class AdminRolesPage extends AuthenticatedPage {
await this.drawerMenuButton.click();
}
await this.roleDrawerLink.click();
await this.isMounted();
await this.rolesLoader.waitFor({
state: 'detached',
state: 'detached'
});
}

View File

@@ -20,14 +20,16 @@ export class AdminUsersPage extends AuthenticatedPage {
this.nextPageButton = page.getByTestId('next-page-button');
this.lastPageButton = page.getByTestId('last-page-button');
this.usersLoader = page.getByTestId('users-list-loader');
this.pageTitle = page.getByTestId('users-page-title');
}
async navigateTo() {
await this.profileMenuButton.click();
await this.adminMenuItem.click();
await this.isMounted();
if (await this.usersLoader.isVisible()) {
await this.usersLoader.waitFor({
state: 'detached'
state: 'detached',
});
}
}
@@ -38,8 +40,8 @@ export class AdminUsersPage extends AuthenticatedPage {
async getUserRowByEmail(email) {
return this.userRow.filter({
has: this.page.getByTestId('user-email').filter({
hasText: email
})
hasText: email,
}),
});
}
@@ -50,8 +52,8 @@ export class AdminUsersPage extends AuthenticatedPage {
return {
fullName: await row.getByTestId('user-full-name').textContent(),
email: await row.getByTestId('user-email').textContent(),
role: await row.getByTestId('user-role').textContent()
}
role: await row.getByTestId('user-role').textContent(),
};
}
/**
@@ -76,7 +78,7 @@ export class AdminUsersPage extends AuthenticatedPage {
async findUserPageWithEmail(email) {
if (await this.usersLoader.isVisible()) {
await this.usersLoader.waitFor({
state: 'detached'
state: 'detached',
});
}
// start at the first page
@@ -88,10 +90,11 @@ export class AdminUsersPage extends AuthenticatedPage {
while (true) {
if (await this.usersLoader.isVisible()) {
await this.usersLoader.waitFor({
state: 'detached'
state: 'detached',
});
}
const rowLocator = await this.getUserRowByEmail(email);
console.log('rowLocator.count', email, await rowLocator.count());
if ((await rowLocator.count()) === 1) {
return rowLocator;
}

View File

@@ -12,7 +12,9 @@ export class AuthenticatedPage extends BasePage {
this.profileMenuButton = this.page.getByTestId('profile-menu-button');
this.adminMenuItem = this.page.getByRole('menuitem', { name: 'Admin' });
this.userInterfaceDrawerItem = this.page.getByTestId('user-interface-drawer-link');
this.userInterfaceDrawerItem = this.page.getByTestId(
'user-interface-drawer-link'
);
this.appBar = this.page.getByTestId('app-bar');
this.drawerMenuButton = this.page.getByTestId('drawer-menu-button');
this.goToDashboardButton = this.page.getByTestId('go-back-drawer-link');

View File

@@ -15,6 +15,7 @@ export class BasePage {
constructor(page) {
this.page = page;
this.snackbar = page.locator('*[data-test^="snackbar"]');
this.pageTitle = this.page.getByTestId('page-title');
}
/**
@@ -35,18 +36,18 @@ export class BasePage {
const snack = this.page.getByTestId(testId);
return {
variant: await snack.getAttribute('data-snackbar-variant'),
text: await snack.evaluate(node => node.innerText),
dataset: await snack.evaluate(node => {
text: await snack.evaluate((node) => node.innerText),
dataset: await snack.evaluate((node) => {
function getChildren(n) {
return [n].concat(
...Array.from(n.children).map(c => getChildren(c))
...Array.from(n.children).map((c) => getChildren(c))
);
}
const datasets = getChildren(node).map(
n => Object.assign({}, n.dataset)
const datasets = getChildren(node).map((n) =>
Object.assign({}, n.dataset)
);
return Object.assign({}, ...datasets);
})
}),
};
}
@@ -78,4 +79,8 @@ export class BasePage {
return await this.page.screenshot({ path: computedPath, ...restOptions });
}
async isMounted() {
await this.pageTitle.waitFor({ state: 'attached' });
}
}

View File

@@ -25,6 +25,7 @@ export class LoginPage extends BasePage {
this.emailTextField = this.page.getByTestId('email-text-field');
this.passwordTextField = this.page.getByTestId('password-text-field');
this.loginButton = this.page.getByTestId('login-button');
this.pageTitle = this.page.getByTestId('login-form-title');
}
async open() {

View File

@@ -22,6 +22,7 @@ test.describe('Role management page', () => {
await test.step('Create a new role', async () => {
await adminRolesPage.navigateTo();
await adminRolesPage.createRoleButton.click();
await adminCreateRolePage.isMounted();
await adminCreateRolePage.nameInput.fill('Create Edit Test');
await adminCreateRolePage.descriptionInput.fill('Test description');
await adminCreateRolePage.createButton.click();
@@ -54,6 +55,7 @@ test.describe('Role management page', () => {
await test.step('Edit the role', async () => {
await adminRolesPage.clickEditRole(roleRow);
await adminEditRolePage.isMounted();
await adminEditRolePage.nameInput.fill('Create Update Test');
await adminEditRolePage.descriptionInput.fill('Update test description');
await adminEditRolePage.updateButton.click();
@@ -70,6 +72,7 @@ test.describe('Role management page', () => {
roleRow = await test.step(
'Make sure changes reflected on roles page',
async () => {
await adminRolesPage.isMounted();
const roleRow = await adminRolesPage.getRoleRowByName(
'Create Update Test'
);
@@ -110,6 +113,8 @@ test.describe('Role management page', () => {
// This test breaks right now
test.skip('Make sure create/edit role page is scrollable', async ({
adminRolesPage,
adminEditRolePage,
adminCreateRolePage,
page,
}) => {
const initViewportSize = page.viewportSize;
@@ -121,6 +126,7 @@ test.describe('Role management page', () => {
await test.step('Ensure create role page is scrollable', async () => {
await adminRolesPage.navigateTo(true);
await adminRolesPage.createRoleButton.click();
await adminCreateRolePage.isMounted();
const initScrollTop = await page.evaluate(() => {
return document.documentElement.scrollTop;
@@ -138,6 +144,7 @@ test.describe('Role management page', () => {
await adminRolesPage.navigateTo(true);
const adminRow = await adminRolesPage.getRoleRowByName('Admin');
await adminRolesPage.clickEditRole(adminRow);
await adminEditRolePage.isMounted();
const initScrollTop = await page.evaluate(() => {
return document.documentElement.scrollTop;
@@ -166,6 +173,7 @@ test.describe('Role management page', () => {
await adminRolesPage.navigateTo();
await test.step('Create a new role', async () => {
await adminRolesPage.createRoleButton.click();
await adminCreateRolePage.isMounted();
await adminCreateRolePage.nameInput.fill('Delete Role');
await adminCreateRolePage.createButton.click();
await adminCreateRolePage.snackbar.waitFor({
@@ -268,6 +276,7 @@ test.describe('Role management page', () => {
await adminRolesPage.navigateTo();
await test.step('Create a new role', async () => {
await adminRolesPage.createRoleButton.click();
await adminCreateRolePage.isMounted();
await adminCreateRolePage.nameInput.fill('Cannot Delete Role');
await adminCreateRolePage.createButton.click();
await adminCreateRolePage.snackbar.waitFor({
@@ -282,6 +291,7 @@ test.describe('Role management page', () => {
await test.step('Create a new user with this role', async () => {
await adminUsersPage.navigateTo();
await adminUsersPage.createUserButton.click();
await adminCreateUserPage.isMounted();
await adminCreateUserPage.fullNameInput.fill('User Delete Role Test');
await adminCreateUserPage.emailInput.fill(
'user-delete-role-test@automatisch.io'
@@ -306,6 +316,7 @@ test.describe('Role management page', () => {
const row = await adminUsersPage.findUserPageWithEmail(
'user-delete-role-test@automatisch.io'
);
// await test.waitForTimeout(10000);
const modal = await adminUsersPage.clickDeleteUser(row);
await modal.deleteButton.click();
await adminUsersPage.snackbar.waitFor({
@@ -348,6 +359,7 @@ test('Accessibility of role management page', async ({
await test.step('Create the basic test role', async () => {
await adminRolesPage.navigateTo();
await adminRolesPage.createRoleButton.click();
await adminCreateRolePage.isMounted();
await adminCreateRolePage.nameInput.fill('Basic Test');
await adminCreateRolePage.createButton.click();
await adminCreateRolePage.snackbar.waitFor({
@@ -363,6 +375,7 @@ test('Accessibility of role management page', async ({
await test.step('Create a new user with the basic role', async () => {
await adminUsersPage.navigateTo();
await adminUsersPage.createUserButton.click();
await adminCreateUserPage.isMounted();
await adminCreateUserPage.fullNameInput.fill('Role Test');
await adminCreateUserPage.emailInput.fill('basic-role-test@automatisch.io');
await adminCreateUserPage.passwordInput.fill('sample');
@@ -378,7 +391,7 @@ test('Accessibility of role management page', async ({
'snackbar-create-user-success'
);
await expect(snackbar.variant).toBe('success');
await adminCreateRolePage.closeSnackbar();
await adminCreateUserPage.closeSnackbar();
});
await test.step('Logout and login to the basic role user', async () => {
@@ -386,6 +399,7 @@ test('Accessibility of role management page', async ({
await page.getByTestId('logout-item').click();
// await page.reload({ waitUntil: 'networkidle' });
const loginPage = new LoginPage(page);
// await loginPage.isMounted();
await loginPage.login('basic-role-test@automatisch.io', 'sample');
await expect(loginPage.loginButton).not.toBeVisible();
await expect(page).toHaveURL('/flows');
@@ -414,6 +428,7 @@ test('Accessibility of role management page', async ({
await page.getByTestId('profile-menu-button').click();
await page.getByTestId('logout-item').click();
const loginPage = new LoginPage(page);
await loginPage.isMounted();
await loginPage.login();
});
@@ -423,6 +438,7 @@ test('Accessibility of role management page', async ({
'basic-role-test@automatisch.io'
);
await adminUsersPage.clickEditUser(row);
await adminEditUserPage.isMounted();
await adminEditUserPage.roleInput.click();
await adminEditUserPage.page.getByRole('option', { name: 'Admin' }).click();
await adminEditUserPage.updateButton.click();

View File

@@ -11,15 +11,21 @@ import DeleteIcon from '@mui/icons-material/Delete';
type ListLoaderProps = {
rowsNumber: number;
columnsNumber: number;
'data-test'?: string;
};
const ListLoader = ({ rowsNumber, columnsNumber }: ListLoaderProps) => {
const ListLoader = ({
rowsNumber,
columnsNumber,
'data-test': dataTest,
}: ListLoaderProps) => {
return (
<>
{[...Array(rowsNumber)].map((row, index) => (
<TableRow
key={index}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
data-test={dataTest && index === 0 ? dataTest : undefined}
>
{[...Array(columnsNumber)].map((cell, index) => (
<TableCell key={index} scope="row">

View File

@@ -44,6 +44,7 @@ function LoginForm() {
<Typography
variant="h3"
align="center"
data-test="login-form-title"
sx={{
borderBottom: '1px solid',
borderColor: (theme) => theme.palette.text.disabled,
@@ -78,13 +79,15 @@ function LoginForm() {
sx={{ mb: 1 }}
/>
{isCloud && <Link
{isCloud && (
<Link
component={RouterLink}
to={URLS.FORGOT_PASSWORD}
underline="none"
>
{formatMessage('loginForm.forgotPasswordText')}
</Link>}
</Link>
)}
<LoadingButton
type="submit"
@@ -98,13 +101,15 @@ function LoginForm() {
{formatMessage('loginForm.submit')}
</LoadingButton>
{isCloud && <Typography variant="body1" align="center" mt={3}>
{isCloud && (
<Typography variant="body1" align="center" mt={3}>
{formatMessage('loginForm.noAccount')}
&nbsp;
<Link component={RouterLink} to={URLS.SIGNUP} underline="none">
{formatMessage('loginForm.signUp')}
</Link>
</Typography>}
</Typography>
)}
</Form>
</Paper>
);

View File

@@ -4,5 +4,5 @@ import Typography, { TypographyProps } from '@mui/material/Typography';
type PageTitleProps = TypographyProps;
export default function PageTitle(props: PageTitleProps): React.ReactElement {
return <Typography variant="h3" {...props} />;
return <Typography variant="h3" data-test="page-title" {...props} />;
}

View File

@@ -44,8 +44,8 @@ export default function CreateRole(): React.ReactElement {
enqueueSnackbar(formatMessage('createRole.successfullyCreated'), {
variant: 'success',
SnackbarProps: {
'data-test': 'snackbar-create-role-success'
}
'data-test': 'snackbar-create-role-success',
},
});
navigate(URLS.ROLES);
@@ -58,7 +58,9 @@ export default function CreateRole(): React.ReactElement {
<Container sx={{ py: 3, display: 'flex', justifyContent: 'center' }}>
<Grid container item xs={12} sm={10} md={9}>
<Grid item xs={12} sx={{ mb: [2, 5] }}>
<PageTitle>{formatMessage('createRolePage.title')}</PageTitle>
<PageTitle data-test="create-role-title">
{formatMessage('createRolePage.title')}
</PageTitle>
</Grid>
<Grid item xs={12} justifyContent="flex-end" sx={{ pt: 5 }}>

View File

@@ -50,7 +50,7 @@ export default function CreateUser(): React.ReactElement {
persist: true,
SnackbarProps: {
'data-test': 'snackbar-create-user-success',
}
},
});
navigate(URLS.USERS);
@@ -63,7 +63,9 @@ export default function CreateUser(): React.ReactElement {
<Container sx={{ py: 3, display: 'flex', justifyContent: 'center' }}>
<Grid container item xs={12} sm={10} md={9}>
<Grid item xs={12} sx={{ mb: [2, 5] }}>
<PageTitle>{formatMessage('createUserPage.title')}</PageTitle>
<PageTitle data-test="create-user-title">
{formatMessage('createUserPage.title')}
</PageTitle>
</Grid>
<Grid item xs={12} justifyContent="flex-end" sx={{ pt: 5 }}>

View File

@@ -54,8 +54,8 @@ export default function EditRole(): React.ReactElement {
enqueueSnackbar(formatMessage('editRole.successfullyUpdated'), {
variant: 'success',
SnackbarProps: {
'data-test': 'snackbar-edit-role-success'
}
'data-test': 'snackbar-edit-role-success',
},
});
navigate(URLS.ROLES);
@@ -70,7 +70,9 @@ export default function EditRole(): React.ReactElement {
<Container sx={{ py: 3, display: 'flex', justifyContent: 'center' }}>
<Grid container item xs={12} sm={10} md={9}>
<Grid item xs={12} sx={{ mb: [2, 5] }}>
<PageTitle>{formatMessage('editRolePage.title')}</PageTitle>
<PageTitle data-test="edit-role-title">
{formatMessage('editRolePage.title')}
</PageTitle>
</Grid>
<Grid item xs={12} justifyContent="flex-end" sx={{ pt: 5 }}>

View File

@@ -57,8 +57,8 @@ export default function EditUser(): React.ReactElement {
variant: 'success',
SnackbarProps: {
'data-test': 'snackbar-edit-user-success',
persist: true
}
persist: true,
},
});
navigate(URLS.USERS);
@@ -71,7 +71,9 @@ export default function EditUser(): React.ReactElement {
<Container sx={{ py: 3, display: 'flex', justifyContent: 'center' }}>
<Grid container item xs={12} sm={10} md={9}>
<Grid item xs={12} sx={{ mb: [2, 5] }}>
<PageTitle>{formatMessage('editUserPage.title')}</PageTitle>
<PageTitle data-test="edit-user-title">
{formatMessage('editUserPage.title')}
</PageTitle>
</Grid>
<Grid item xs={12} justifyContent="flex-end" sx={{ pt: 5 }}>

View File

@@ -18,16 +18,12 @@ function RolesPage() {
<Grid container item xs={12} sm={10} md={9}>
<Grid container sx={{ mb: [0, 3] }} columnSpacing={1.5} rowSpacing={3}>
<Grid container item xs sm alignItems="center">
<PageTitle>{formatMessage('rolesPage.title')}</PageTitle>
<PageTitle data-test="roles-page-title">
{formatMessage('rolesPage.title')}
</PageTitle>
</Grid>
<Grid
container
item
xs="auto"
sm="auto"
alignItems="center"
>
<Grid container item xs="auto" sm="auto" alignItems="center">
<ConditionalIconButton
type="submit"
variant="contained"

View File

@@ -18,16 +18,12 @@ function UsersPage() {
<Grid container item xs={12} sm={10} md={9}>
<Grid container sx={{ mb: [0, 3] }} columnSpacing={1.5} rowSpacing={3}>
<Grid container item xs sm alignItems="center">
<PageTitle>{formatMessage('usersPage.title')}</PageTitle>
<PageTitle data-test="users-page-title">
{formatMessage('usersPage.title')}
</PageTitle>
</Grid>
<Grid
container
item
xs="auto"
sm="auto"
alignItems="center"
>
<Grid container item xs="auto" sm="auto" alignItems="center">
<ConditionalIconButton
type="submit"
variant="contained"