test: write tests for role management (#1396)
This commit is contained in:
106
packages/e2e-tests/fixtures/admin/create-role-page.js
Normal file
106
packages/e2e-tests/fixtures/admin/create-role-page.js
Normal file
@@ -0,0 +1,106 @@
|
||||
const { AuthenticatedPage } = require('../authenticated-page');
|
||||
const { RoleConditionsModal } = require('./role-conditions-modal');
|
||||
|
||||
export class AdminCreateRolePage extends AuthenticatedPage {
|
||||
screenshotPath = '/admin/create-role'
|
||||
|
||||
/**
|
||||
* @param {import('@playwright/test').Page} page
|
||||
*/
|
||||
constructor (page) {
|
||||
super(page);
|
||||
this.nameInput = page.getByTestId('name-input');
|
||||
this.descriptionInput = page.getByTestId('description-input');
|
||||
this.createButton = page.getByTestId('create-button');
|
||||
this.connectionRow = page.getByTestId('Connection-permission-row');
|
||||
this.executionRow = page.getByTestId('Execution-permission-row');
|
||||
this.flowRow = page.getByTestId('Flow-permission-row');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {('Connection'|'Execution'|'Flow')} subject
|
||||
*/
|
||||
getRoleConditionsModal (subject) {
|
||||
return new RoleConditionsModal(this.page, subject);
|
||||
}
|
||||
|
||||
async getPermissionConfigs () {
|
||||
const subjects = ['Connection', 'Flow', 'Execution'];
|
||||
const permissionConfigs = [];
|
||||
for (let subject of subjects) {
|
||||
const row = this.getSubjectRow(subject);
|
||||
const actionInputs = await this.getRowInputs(row);
|
||||
Object.keys(actionInputs).forEach(action => {
|
||||
permissionConfigs.push({
|
||||
action,
|
||||
locator: actionInputs[action],
|
||||
subject,
|
||||
row
|
||||
});
|
||||
});
|
||||
}
|
||||
return permissionConfigs;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {(
|
||||
* 'Connection' | 'Flow' | 'Execution'
|
||||
* )} subject
|
||||
*/
|
||||
getSubjectRow (subject) {
|
||||
const k = `${subject.toLowerCase()}Row`
|
||||
if (this[k]) {
|
||||
return this[k]
|
||||
} else {
|
||||
throw 'Unknown row'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@playwright/test').Locator} row
|
||||
*/
|
||||
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) {
|
||||
inputs[input] = row.getByTestId(testId).locator('input');
|
||||
}
|
||||
}
|
||||
return inputs
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@playwright/test').Locator} row
|
||||
*/
|
||||
async clickPermissionSettings (row) {
|
||||
await row.getByTestId('permission-settings-button').click();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} subject
|
||||
* @param {'create'|'read'|'update'|'delete'|'publish'} action
|
||||
* @param {boolean} val
|
||||
*/
|
||||
async updateAction (subject, action, val) {
|
||||
const row = await this.getSubjectRow(subject);
|
||||
const inputs = await this.getRowInputs(row);
|
||||
if (inputs[action]) {
|
||||
if (await inputs[action].isChecked()) {
|
||||
if (!val) {
|
||||
await inputs[action].click();
|
||||
}
|
||||
} else {
|
||||
if (val) {
|
||||
await inputs[action].click();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Error(`${subject} does not have action ${action}`)
|
||||
}
|
||||
}
|
||||
}
|
19
packages/e2e-tests/fixtures/admin/delete-role-modal.js
Normal file
19
packages/e2e-tests/fixtures/admin/delete-role-modal.js
Normal file
@@ -0,0 +1,19 @@
|
||||
export class DeleteRoleModal {
|
||||
screenshotPath = '/admin/delete-role-modal';
|
||||
|
||||
/**
|
||||
* @param {import('@playwright/test').Page} page
|
||||
*/
|
||||
constructor (page) {
|
||||
this.page = page;
|
||||
this.modal = page.getByTestId('delete-role-modal');
|
||||
this.cancelButton = this.modal.getByTestId('confirmation-cancel-button');
|
||||
this.deleteButton = this.modal.getByTestId('confirmation-confirm-button');
|
||||
}
|
||||
|
||||
async close () {
|
||||
await this.page.click('body', {
|
||||
position: { x: 10, y: 10 }
|
||||
});
|
||||
}
|
||||
}
|
9
packages/e2e-tests/fixtures/admin/edit-role-page.js
Normal file
9
packages/e2e-tests/fixtures/admin/edit-role-page.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const { AdminCreateRolePage } = require('./create-role-page')
|
||||
|
||||
export class AdminEditRolePage extends AdminCreateRolePage {
|
||||
constructor (page) {
|
||||
super(page);
|
||||
delete this.createButton;
|
||||
this.updateButton = page.getByTestId('update-button');
|
||||
}
|
||||
}
|
@@ -13,6 +13,7 @@ export class AdminEditUserPage extends AuthenticatedPage {
|
||||
super(page);
|
||||
this.fullNameInput = page.getByTestId('full-name-input');
|
||||
this.emailInput = page.getByTestId('email-input');
|
||||
this.roleInput = page.getByTestId('role.id-autocomplete');
|
||||
this.updateButton = page.getByTestId('update-button');
|
||||
}
|
||||
|
||||
|
@@ -2,6 +2,10 @@ const { AdminCreateUserPage } = require('./create-user-page');
|
||||
const { AdminEditUserPage } = require('./edit-user-page');
|
||||
const { AdminUsersPage } = require('./users-page');
|
||||
|
||||
const { AdminRolesPage } = require('./roles-page');
|
||||
const { AdminCreateRolePage } = require('./create-role-page');
|
||||
const { AdminEditRolePage } = require('./edit-role-page');
|
||||
|
||||
export const adminFixtures = {
|
||||
adminUsersPage: async ({ page }, use) => {
|
||||
await use(new AdminUsersPage(page));
|
||||
@@ -11,5 +15,15 @@ export const adminFixtures = {
|
||||
},
|
||||
adminEditUserPage: async ({page}, use) => {
|
||||
await use(new AdminEditUserPage(page));
|
||||
}
|
||||
}
|
||||
},
|
||||
adminRolesPage: async ({ page}, use) => {
|
||||
await use(new AdminRolesPage(page));
|
||||
},
|
||||
adminEditRolePage: async ({ page}, use) => {
|
||||
await use(new AdminEditRolePage(page));
|
||||
},
|
||||
adminCreateRolePage: async ({ page}, use) => {
|
||||
await use(new AdminCreateRolePage(page));
|
||||
},
|
||||
}
|
||||
|
||||
|
47
packages/e2e-tests/fixtures/admin/role-conditions-modal.js
Normal file
47
packages/e2e-tests/fixtures/admin/role-conditions-modal.js
Normal file
@@ -0,0 +1,47 @@
|
||||
export class RoleConditionsModal {
|
||||
|
||||
/**
|
||||
* @param {import('@playwright/test').Page} page
|
||||
* @param {('Connection'|'Execution'|'Flow')} subject
|
||||
*/
|
||||
constructor (page, subject) {
|
||||
this.page = page;
|
||||
this.modal = page.getByTestId(`${subject}-role-conditions-modal`);
|
||||
this.modalBody = this.modal.getByTestId('role-conditions-modal-body');
|
||||
this.createCheckbox = this.modal.getByTestId(
|
||||
'isCreator-create-checkbox'
|
||||
).locator('input');
|
||||
this.readCheckbox = this.modal.getByTestId(
|
||||
'isCreator-read-checkbox'
|
||||
).locator('input');
|
||||
this.updateCheckbox = this.modal.getByTestId(
|
||||
'isCreator-update-checkbox'
|
||||
).locator('input');
|
||||
this.deleteCheckbox = this.modal.getByTestId(
|
||||
'isCreator-delete-checkbox'
|
||||
).locator('input');
|
||||
this.publishCheckbox = this.modal.getByTestId(
|
||||
'isCreator-publish-checkbox'
|
||||
).locator('input');
|
||||
this.applyButton = this.modal.getByTestId('confirmation-confirm-button');
|
||||
this.cancelButton = this.modal.getByTestId('confirmation-cancel-button');
|
||||
}
|
||||
|
||||
async getAvailableConditions () {
|
||||
let conditions = {};
|
||||
const actions = ['create', 'read', 'update', 'delete', 'publish'];
|
||||
for (let action of actions) {
|
||||
const locator = this[`${action}Checkbox`];
|
||||
if (locator && await locator.count() > 0) {
|
||||
conditions[action] = locator;
|
||||
}
|
||||
}
|
||||
return conditions;
|
||||
}
|
||||
|
||||
async close () {
|
||||
await this.page.click('body', {
|
||||
position: { x: 10, y: 10 }
|
||||
});
|
||||
}
|
||||
}
|
79
packages/e2e-tests/fixtures/admin/roles-page.js
Normal file
79
packages/e2e-tests/fixtures/admin/roles-page.js
Normal file
@@ -0,0 +1,79 @@
|
||||
const { AuthenticatedPage } = require('../authenticated-page');
|
||||
const { DeleteRoleModal } = require('./delete-role-modal')
|
||||
|
||||
export class AdminRolesPage extends AuthenticatedPage {
|
||||
screenshotPath = '/admin-roles';
|
||||
|
||||
/**
|
||||
* @param {import('@playwright/test').Page} page
|
||||
*/
|
||||
constructor (page) {
|
||||
super(page);
|
||||
this.roleDrawerLink = page.getByTestId('roles-drawer-link');
|
||||
this.createRoleButton = page.getByTestId('create-role');
|
||||
this.deleteRoleModal = new DeleteRoleModal(page);
|
||||
this.roleRow = page.getByTestId('role-row');
|
||||
this.rolesLoader = page.getByTestId('roles-list-loader');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {boolean} isMobile - navigation on smaller devices requires the
|
||||
* user to open up the drawer menu
|
||||
*/
|
||||
async navigateTo (isMobile=false) {
|
||||
await this.profileMenuButton.click();
|
||||
await this.adminMenuItem.click();
|
||||
if (isMobile) {
|
||||
await this.drawerMenuButton.click();
|
||||
}
|
||||
await this.roleDrawerLink.click();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
async getRoleRowByName (name) {
|
||||
return this.roleRow.filter({
|
||||
has: this.page.getByTestId('role-name').filter({
|
||||
hasText: name
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@playwright/test').Locator} row
|
||||
*/
|
||||
async getRowData (row) {
|
||||
return {
|
||||
role: await row.getByTestId('role-name').textContent(),
|
||||
description: await row.getByTestId('role-description').textContent(),
|
||||
canEdit: await row.getByTestId(
|
||||
'role-edit'
|
||||
).isEnabled(),
|
||||
canDelete: await row.getByTestId(
|
||||
'role-delete'
|
||||
).isEnabled()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@playwright/test').Locator} row
|
||||
*/
|
||||
async clickEditRole (row) {
|
||||
await row.getByTestId('role-edit').click();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@playwright/test').Locator} row
|
||||
*/
|
||||
async clickDeleteRole (row) {
|
||||
await row.getByTestId('role-delete').click();
|
||||
return this.deleteRoleModal;
|
||||
}
|
||||
|
||||
async editRole (subject) {
|
||||
const row = await this.getRoleRowByName(subject);
|
||||
await this.clickEditRole(row);
|
||||
}
|
||||
}
|
@@ -25,6 +25,11 @@ export class AdminUsersPage extends AuthenticatedPage {
|
||||
async navigateTo () {
|
||||
await this.profileMenuButton.click();
|
||||
await this.adminMenuItem.click();
|
||||
if (await this.usersLoader.isVisible()) {
|
||||
await this.usersLoader.waitFor({
|
||||
state: 'detached'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,8 +71,14 @@ export class AdminUsersPage extends AuthenticatedPage {
|
||||
|
||||
/**
|
||||
* @param {string} email
|
||||
* @returns {import('@playwright/test').Locator | null}
|
||||
*/
|
||||
async findUserPageWithEmail (email) {
|
||||
if (await this.usersLoader.isVisible()) {
|
||||
await this.usersLoader.waitFor({
|
||||
state: 'detached'
|
||||
});
|
||||
}
|
||||
// start at the first page
|
||||
const firstPageDisabled = await this.firstPageButton.isDisabled();
|
||||
if (!firstPageDisabled) {
|
||||
@@ -75,6 +86,11 @@ export class AdminUsersPage extends AuthenticatedPage {
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (await this.usersLoader.isVisible()) {
|
||||
await this.usersLoader.waitFor({
|
||||
state: 'detached'
|
||||
});
|
||||
}
|
||||
const rowLocator = await this.getUserRowByEmail(email);
|
||||
if ((await rowLocator.count()) === 1) {
|
||||
return rowLocator;
|
||||
|
@@ -14,6 +14,7 @@ export class AuthenticatedPage extends BasePage {
|
||||
this.adminMenuItem = this.page.getByRole('menuitem', { name: 'Admin' });
|
||||
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');
|
||||
this.typographyLogo = this.page.getByTestId('typography-logo');
|
||||
this.customLogo = this.page.getByTestId('custom-logo');
|
||||
|
@@ -1,9 +1,19 @@
|
||||
const path = require('node:path');
|
||||
const { expect } = require('@playwright/test');
|
||||
const { BasePage } = require('./base-page');
|
||||
|
||||
export class LoginPage extends BasePage {
|
||||
path = '/login';
|
||||
static defaultEmail = process.env.LOGIN_EMAIL;
|
||||
static defaultPassword = process.env.LOGIN_PASSWORD;
|
||||
|
||||
static setDefaultLogin (email, password) {
|
||||
this.defaultEmail = email;
|
||||
this.defaultPassword = password;
|
||||
}
|
||||
|
||||
static resetDefaultLogin () {
|
||||
this.defaultEmail = process.env.LOGIN_EMAIL;
|
||||
this.defaultPassword = process.env.LOGIN_PASSWORD;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@playwright/test').Page} page
|
||||
@@ -22,8 +32,8 @@ export class LoginPage extends BasePage {
|
||||
}
|
||||
|
||||
async login(
|
||||
email = process.env.LOGIN_EMAIL,
|
||||
password = process.env.LOGIN_PASSWORD
|
||||
email = LoginPage.defaultEmail,
|
||||
password = LoginPage.defaultPassword
|
||||
) {
|
||||
await this.page.goto(this.path);
|
||||
await this.emailTextField.fill(email);
|
||||
|
483
packages/e2e-tests/tests/admin/manage-roles.spec.js
Normal file
483
packages/e2e-tests/tests/admin/manage-roles.spec.js
Normal file
@@ -0,0 +1,483 @@
|
||||
const { test, expect } = require('../../fixtures/index');
|
||||
const { LoginPage } = require('../../fixtures/login-page');
|
||||
|
||||
test.describe('Role management page', () => {
|
||||
|
||||
test('Admin role is not deletable', async ({ adminRolesPage }) => {
|
||||
await adminRolesPage.navigateTo();
|
||||
const adminRow = await adminRolesPage.getRoleRowByName('Admin');
|
||||
const rowCount = await adminRow.count();
|
||||
await expect(rowCount).toBe(1);
|
||||
const data = await adminRolesPage.getRowData(adminRow);
|
||||
await expect(data.role).toBe('Admin');
|
||||
await expect(data.canEdit).toBe(true);
|
||||
await expect(data.canDelete).toBe(false);
|
||||
});
|
||||
|
||||
test(
|
||||
'Can create, edit, and delete a role',
|
||||
async ({
|
||||
adminCreateRolePage, adminEditRolePage, adminRolesPage, page
|
||||
}) => {
|
||||
await test.step('Create a new role', async () => {
|
||||
await adminRolesPage.navigateTo();
|
||||
await adminRolesPage.createRoleButton.click();
|
||||
await adminCreateRolePage.nameInput.fill('Create Edit Test');
|
||||
await adminCreateRolePage.descriptionInput.fill('Test description');
|
||||
await adminCreateRolePage.createButton.click();
|
||||
await adminCreateRolePage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminCreateRolePage.getSnackbarData(
|
||||
'snackbar-create-role-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminCreateRolePage.closeSnackbar();
|
||||
});
|
||||
|
||||
let roleRow = await test.step(
|
||||
'Make sure role data is correct',
|
||||
async () => {
|
||||
const roleRow = await adminRolesPage.getRoleRowByName(
|
||||
'Create Edit Test'
|
||||
);
|
||||
const rowCount = await roleRow.count();
|
||||
await expect(rowCount).toBe(1);
|
||||
const roleData = await adminRolesPage.getRowData(roleRow);
|
||||
await expect(roleData.role).toBe('Create Edit Test');
|
||||
await expect(roleData.description).toBe('Test description');
|
||||
await expect(roleData.canEdit).toBe(true);
|
||||
await expect(roleData.canDelete).toBe(true);
|
||||
return roleRow
|
||||
}
|
||||
);
|
||||
|
||||
await test.step('Edit the role', async () => {
|
||||
await adminRolesPage.clickEditRole(roleRow);
|
||||
await adminEditRolePage.nameInput.fill('Create Update Test');
|
||||
await adminEditRolePage.descriptionInput.fill(
|
||||
'Update test description'
|
||||
);
|
||||
await adminEditRolePage.updateButton.click();
|
||||
await adminEditRolePage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminEditRolePage.getSnackbarData(
|
||||
'snackbar-edit-role-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminEditRolePage.closeSnackbar();
|
||||
});
|
||||
|
||||
roleRow = await test.step(
|
||||
'Make sure changes reflected on roles page',
|
||||
async () => {
|
||||
const roleRow = await adminRolesPage.getRoleRowByName(
|
||||
'Create Update Test'
|
||||
);
|
||||
const rowCount = await roleRow.count();
|
||||
await expect(rowCount).toBe(1);
|
||||
const roleData = await adminRolesPage.getRowData(roleRow);
|
||||
await expect(roleData.role).toBe('Create Update Test');
|
||||
await expect(roleData.description).toBe('Update test description');
|
||||
await expect(roleData.canEdit).toBe(true);
|
||||
await expect(roleData.canDelete).toBe(true);
|
||||
return roleRow;
|
||||
}
|
||||
);
|
||||
|
||||
await test.step('Delete the role', async () => {
|
||||
await adminRolesPage.clickDeleteRole(roleRow);
|
||||
const deleteModal = adminRolesPage.deleteRoleModal;
|
||||
await deleteModal.modal.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
await deleteModal.deleteButton.click();
|
||||
await adminRolesPage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminRolesPage.getSnackbarData(
|
||||
'snackbar-delete-role-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminRolesPage.closeSnackbar();
|
||||
await deleteModal.modal.waitFor({
|
||||
state: 'detached'
|
||||
});
|
||||
const rowCount = await roleRow.count();
|
||||
await expect(rowCount).toBe(0);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// This test breaks right now
|
||||
test.skip(
|
||||
'Make sure create/edit role page is scrollable',
|
||||
async ({ adminRolesPage, page }) => {
|
||||
const initViewportSize = page.viewportSize;
|
||||
await page.setViewportSize({
|
||||
width: 800,
|
||||
height: 400
|
||||
});
|
||||
|
||||
await test.step('Ensure create role page is scrollable', async () => {
|
||||
await adminRolesPage.navigateTo(true);
|
||||
await adminRolesPage.createRoleButton.click();
|
||||
|
||||
const initScrollTop = await page.evaluate(() => {
|
||||
return document.documentElement.scrollTop;
|
||||
});
|
||||
await page.mouse.move(400, 100);
|
||||
await page.mouse.click(400, 100);
|
||||
await page.mouse.wheel(200, 0);
|
||||
const updatedScrollTop = await page.evaluate(() => {
|
||||
return document.documentElement.scrollTop;
|
||||
});
|
||||
await expect(initScrollTop).not.toBe(updatedScrollTop);
|
||||
});
|
||||
|
||||
await test.step('Ensure edit role page is scrollable', async () => {
|
||||
await adminRolesPage.navigateTo(true);
|
||||
const adminRow = await adminRolesPage.getRoleRowByName('Admin');
|
||||
await adminRolesPage.clickEditRole(adminRow);
|
||||
|
||||
const initScrollTop = await page.evaluate(() => {
|
||||
return document.documentElement.scrollTop;
|
||||
});
|
||||
await page.mouse.move(400, 100);
|
||||
await page.mouse.wheel(200, 0);
|
||||
const updatedScrollTop = await page.evaluate(() => {
|
||||
return document.documentElement.scrollTop;
|
||||
});
|
||||
await expect(initScrollTop).not.toBe(updatedScrollTop);
|
||||
});
|
||||
|
||||
await test.step('Reset viewport', async () => {
|
||||
await page.setViewportSize(initViewportSize);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
test(
|
||||
'Cannot delete a role with a user attached to it',
|
||||
async ({
|
||||
adminCreateRolePage, adminRolesPage,
|
||||
adminUsersPage, adminCreateUserPage, adminEditUserPage,
|
||||
page
|
||||
}) => {
|
||||
await adminRolesPage.navigateTo();
|
||||
await test.step('Create a new role', async () => {
|
||||
await adminRolesPage.createRoleButton.click();
|
||||
await adminCreateRolePage.nameInput.fill('Delete Role');
|
||||
await adminCreateRolePage.createButton.click();
|
||||
await adminCreateRolePage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminCreateRolePage.getSnackbarData(
|
||||
'snackbar-create-role-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminCreateRolePage.closeSnackbar();
|
||||
});
|
||||
await test.step(
|
||||
'Create a new user with the "Delete Role" role',
|
||||
async () => {
|
||||
await adminUsersPage.navigateTo();
|
||||
await adminUsersPage.createUserButton.click();
|
||||
await adminCreateUserPage.fullNameInput.fill('User Role Test');
|
||||
await adminCreateUserPage.emailInput.fill('user-role-test@automatisch.io');
|
||||
await adminCreateUserPage.passwordInput.fill('sample');
|
||||
await adminCreateUserPage.roleInput.click();
|
||||
await adminCreateUserPage.page.getByRole(
|
||||
'option', { name: 'Delete Role' }
|
||||
).click();
|
||||
await adminCreateUserPage.createButton.click();
|
||||
await adminUsersPage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminUsersPage.getSnackbarData(
|
||||
'snackbar-create-user-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminUsersPage.closeSnackbar();
|
||||
}
|
||||
);
|
||||
await test.step(
|
||||
'Try to delete "Delete Role" role when new user has it',
|
||||
async () => {
|
||||
await adminRolesPage.navigateTo();
|
||||
const row = await adminRolesPage.getRoleRowByName('Delete Role');
|
||||
const modal = await adminRolesPage.clickDeleteRole(row);
|
||||
await modal.deleteButton.click();
|
||||
await adminRolesPage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminRolesPage.getSnackbarData(
|
||||
'snackbar-error'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('error');
|
||||
await adminRolesPage.closeSnackbar();
|
||||
await modal.close();
|
||||
}
|
||||
);
|
||||
await test.step(
|
||||
'Change the role the user has',
|
||||
async () => {
|
||||
await adminUsersPage.navigateTo();
|
||||
await adminUsersPage.usersLoader.waitFor({
|
||||
state: 'detached'
|
||||
});
|
||||
const row = await adminUsersPage.findUserPageWithEmail(
|
||||
'user-role-test@automatisch.io'
|
||||
);
|
||||
await adminUsersPage.clickEditUser(row);
|
||||
await adminEditUserPage.roleInput.click();
|
||||
await adminEditUserPage.page.getByRole(
|
||||
'option', { name: 'Admin' }
|
||||
).click();
|
||||
await adminEditUserPage.updateButton.click();
|
||||
await adminEditUserPage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminEditUserPage.getSnackbarData(
|
||||
'snackbar-edit-user-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminEditUserPage.closeSnackbar();
|
||||
}
|
||||
);
|
||||
await test.step(
|
||||
'Delete the original role',
|
||||
async () => {
|
||||
await adminRolesPage.navigateTo();
|
||||
const row = await adminRolesPage.getRoleRowByName('Delete Role');
|
||||
const modal = await adminRolesPage.clickDeleteRole(row);
|
||||
await expect(modal.modal).toBeVisible();
|
||||
await modal.deleteButton.click();
|
||||
await adminRolesPage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminRolesPage.getSnackbarData(
|
||||
'snackbar-delete-role-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminRolesPage.closeSnackbar();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
test(
|
||||
'Deleting a role after deleting a user with that role',
|
||||
async ({
|
||||
adminCreateRolePage, adminRolesPage,
|
||||
adminUsersPage, adminCreateUserPage,
|
||||
page
|
||||
}) => {
|
||||
await adminRolesPage.navigateTo();
|
||||
await test.step('Create a new role', async () => {
|
||||
await adminRolesPage.createRoleButton.click();
|
||||
await adminCreateRolePage.nameInput.fill('Cannot Delete Role');
|
||||
await adminCreateRolePage.createButton.click();
|
||||
await adminCreateRolePage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminCreateRolePage.getSnackbarData(
|
||||
'snackbar-create-role-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminCreateRolePage.closeSnackbar();
|
||||
});
|
||||
await test.step('Create a new user with this role', async () => {
|
||||
await adminUsersPage.navigateTo();
|
||||
await adminUsersPage.createUserButton.click();
|
||||
await adminCreateUserPage.fullNameInput.fill('User Delete Role Test');
|
||||
await adminCreateUserPage.emailInput.fill(
|
||||
'user-delete-role-test@automatisch.io'
|
||||
);
|
||||
await adminCreateUserPage.passwordInput.fill('sample');
|
||||
await adminCreateUserPage.roleInput.click();
|
||||
await adminCreateUserPage.page.getByRole(
|
||||
'option', { name: 'Cannot Delete Role' }
|
||||
).click();
|
||||
await adminCreateUserPage.createButton.click();
|
||||
await adminCreateUserPage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminCreateUserPage.getSnackbarData(
|
||||
'snackbar-create-user-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminCreateUserPage.closeSnackbar();
|
||||
});
|
||||
await test.step('Delete this user', async () => {
|
||||
await adminUsersPage.navigateTo();
|
||||
const row = await adminUsersPage.findUserPageWithEmail(
|
||||
'user-delete-role-test@automatisch.io'
|
||||
);
|
||||
const modal = await adminUsersPage.clickDeleteUser(row);
|
||||
await modal.deleteButton.click();
|
||||
await adminUsersPage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminUsersPage.getSnackbarData(
|
||||
'snackbar-delete-user-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminUsersPage.closeSnackbar();
|
||||
});
|
||||
await test.step('Try deleting this role', async () => {
|
||||
await adminRolesPage.navigateTo();
|
||||
const row = await adminRolesPage.getRoleRowByName(
|
||||
'Cannot Delete Role'
|
||||
);
|
||||
const modal = await adminRolesPage.clickDeleteRole(row);
|
||||
await modal.deleteButton.click();
|
||||
await adminRolesPage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
/*
|
||||
* TODO: await snackbar - make assertions based on product
|
||||
* decisions
|
||||
const snackbar = await adminRolesPage.getSnackbarData();
|
||||
await expect(snackbar.variant).toBe('...');
|
||||
*/
|
||||
await adminRolesPage.closeSnackbar();
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test(
|
||||
'Accessibility of role management page',
|
||||
async ({
|
||||
page,
|
||||
adminUsersPage, adminCreateUserPage, adminEditUserPage,
|
||||
adminRolesPage, adminCreateRolePage,
|
||||
}) => {
|
||||
test.slow();
|
||||
await test.step('Create the basic test role', async () => {
|
||||
await adminRolesPage.navigateTo();
|
||||
await adminRolesPage.createRoleButton.click();
|
||||
await adminCreateRolePage.nameInput.fill('Basic Test');
|
||||
await adminCreateRolePage.createButton.click();
|
||||
await adminCreateRolePage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminCreateRolePage.getSnackbarData(
|
||||
'snackbar-create-role-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminCreateRolePage.closeSnackbar();
|
||||
});
|
||||
|
||||
await test.step('Create a new user with the basic role', async () => {
|
||||
await adminUsersPage.navigateTo();
|
||||
await adminUsersPage.createUserButton.click();
|
||||
await adminCreateUserPage.fullNameInput.fill('Role Test');
|
||||
await adminCreateUserPage.emailInput.fill('basic-role-test@automatisch.io');
|
||||
await adminCreateUserPage.passwordInput.fill('sample');
|
||||
await adminCreateUserPage.roleInput.click();
|
||||
await adminCreateUserPage.page.getByRole(
|
||||
'option', { name: 'Basic Test' }
|
||||
).click();
|
||||
await adminCreateUserPage.createButton.click();
|
||||
await adminCreateUserPage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminCreateUserPage.getSnackbarData(
|
||||
'snackbar-create-user-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminCreateRolePage.closeSnackbar();
|
||||
});
|
||||
|
||||
await test.step('Logout and login to the basic role user', async () => {
|
||||
await page.getByTestId('profile-menu-button').click();
|
||||
await page.getByTestId('logout-item').click();
|
||||
// await page.reload({ waitUntil: 'networkidle' });
|
||||
const loginPage = new LoginPage(page);
|
||||
await loginPage.login('basic-role-test@automatisch.io', 'sample');
|
||||
await expect(loginPage.loginButton).not.toBeVisible();
|
||||
await expect(page).toHaveURL('/flows');
|
||||
});
|
||||
|
||||
await test.step(
|
||||
'Navigate to the admin settings page and make sure it is blank',
|
||||
async () => {
|
||||
const pageUrl = new URL(page.url());
|
||||
const url = `${pageUrl.origin}/admin-settings/users`;
|
||||
await page.goto(url);
|
||||
await page.waitForTimeout(750);
|
||||
const isUnmounted = await page.evaluate(() => {
|
||||
const root = document.querySelector('#root');
|
||||
if (root) {
|
||||
return root.children.length === 0;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
await expect(isUnmounted).toBe(true);
|
||||
}
|
||||
);
|
||||
|
||||
await test.step(
|
||||
'Log back into the admin account',
|
||||
async () => {
|
||||
await page.goto('/');
|
||||
await page.getByTestId('profile-menu-button').click();
|
||||
await page.getByTestId('logout-item').click();
|
||||
const loginPage = new LoginPage(page);
|
||||
await loginPage.login();
|
||||
}
|
||||
);
|
||||
|
||||
await test.step(
|
||||
'Move the user off the role',
|
||||
async () => {
|
||||
await adminUsersPage.navigateTo();
|
||||
const row = await adminUsersPage.findUserPageWithEmail(
|
||||
'basic-role-test@automatisch.io'
|
||||
);
|
||||
await adminUsersPage.clickEditUser(row);
|
||||
await adminEditUserPage.roleInput.click();
|
||||
await adminEditUserPage.page.getByRole(
|
||||
'option', { name: 'Admin' }
|
||||
).click();
|
||||
await adminEditUserPage.updateButton.click();
|
||||
await adminEditUserPage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
await adminEditUserPage.closeSnackbar();
|
||||
}
|
||||
);
|
||||
|
||||
await test.step(
|
||||
'Delete the role',
|
||||
async () => {
|
||||
await adminRolesPage.navigateTo();
|
||||
const roleRow = await adminRolesPage.getRoleRowByName(
|
||||
'Basic Test'
|
||||
);
|
||||
await adminRolesPage.clickDeleteRole(roleRow);
|
||||
const deleteModal = adminRolesPage.deleteRoleModal;
|
||||
await deleteModal.modal.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
await deleteModal.deleteButton.click();
|
||||
await adminRolesPage.snackbar.waitFor({
|
||||
state: 'attached'
|
||||
});
|
||||
const snackbar = await adminRolesPage.getSnackbarData(
|
||||
'snackbar-delete-role-success'
|
||||
);
|
||||
await expect(snackbar.variant).toBe('success');
|
||||
await adminRolesPage.closeSnackbar();
|
||||
await deleteModal.modal.waitFor({
|
||||
state: 'detached'
|
||||
});
|
||||
const rowCount = await roleRow.count();
|
||||
await expect(rowCount).toBe(0);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
69
packages/e2e-tests/tests/admin/role-conditions.spec.js
Normal file
69
packages/e2e-tests/tests/admin/role-conditions.spec.js
Normal file
@@ -0,0 +1,69 @@
|
||||
const { test, expect } = require('../../fixtures/index');
|
||||
|
||||
test(
|
||||
'Role permissions conform with role conditions ',
|
||||
async({ adminRolesPage, adminCreateRolePage }) => {
|
||||
await adminRolesPage.navigateTo();
|
||||
await adminRolesPage.createRoleButton.click();
|
||||
|
||||
/*
|
||||
example config: {
|
||||
action: 'read',
|
||||
subject: 'connection',
|
||||
row: page.getByTestId('connection-permission-row'),
|
||||
locator: row.getByTestId('read-checkbox')
|
||||
}
|
||||
*/
|
||||
const permissionConfigs =
|
||||
await adminCreateRolePage.getPermissionConfigs();
|
||||
|
||||
await test.step(
|
||||
'Iterate over each permission config and make sure role conditions conform',
|
||||
async () => {
|
||||
for (let config of permissionConfigs) {
|
||||
await config.locator.click();
|
||||
await adminCreateRolePage.clickPermissionSettings(config.row);
|
||||
const modal = adminCreateRolePage.getRoleConditionsModal(
|
||||
config.subject
|
||||
);
|
||||
await expect(modal.modal).toBeVisible();
|
||||
const conditions = await modal.getAvailableConditions();
|
||||
for (let conditionAction of Object.keys(conditions)) {
|
||||
if (conditionAction === config.action) {
|
||||
await expect(conditions[conditionAction]).not.toBeDisabled();
|
||||
} else {
|
||||
await expect(conditions[conditionAction]).toBeDisabled();
|
||||
}
|
||||
}
|
||||
await modal.close();
|
||||
await config.locator.click();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
test(
|
||||
'Default role permissions conforms with role conditions',
|
||||
async({ adminRolesPage, adminCreateRolePage }) => {
|
||||
await adminRolesPage.navigateTo();
|
||||
await adminRolesPage.createRoleButton.click();
|
||||
|
||||
const subjects = ['Connection', 'Execution', 'Flow'];
|
||||
for (let subject of subjects) {
|
||||
const row = adminCreateRolePage.getSubjectRow(subject)
|
||||
const modal = adminCreateRolePage.getRoleConditionsModal(subject);
|
||||
await adminCreateRolePage.clickPermissionSettings(row);
|
||||
await expect(modal.modal).toBeVisible();
|
||||
const availableConditions = await modal.getAvailableConditions();
|
||||
const conditions = ['create', 'read', 'update', 'delete', 'publish'];
|
||||
for (let condition of conditions) {
|
||||
if (availableConditions[condition]) {
|
||||
await expect(availableConditions[condition]).toBeDisabled();
|
||||
}
|
||||
}
|
||||
await modal.close();
|
||||
}
|
||||
|
||||
}
|
||||
);
|
Reference in New Issue
Block a user