Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export class UserGroupUiHelper extends UiBaseLocators {
private readonly sectionList: Locator;
private readonly documentPermissionsGroups: Locator;
private readonly elementPermissionsGroups: Locator;
private readonly workspaceUsersSection: Locator;
private readonly chooseUserButton: Locator;
private readonly workspaceUserItemRefs: Locator;

constructor(page: Page) {
super(page);
Expand All @@ -44,6 +47,9 @@ export class UserGroupUiHelper extends UiBaseLocators {
this.iconChecked = page.locator('uui-toggle').locator('#icon-checked').getByRole('img');
this.documentPermissionsGroups = page.locator('umb-user-group-entity-type-permission-groups uui-box').filter({hasText: 'Document permissions'});
this.elementPermissionsGroups = page.locator('umb-user-group-entity-type-permission-groups uui-box').filter({hasText: 'Element permissions'});
this.workspaceUsersSection = page.locator('umb-user-group-workspace-users');
this.chooseUserButton = this.workspaceUsersSection.locator('#btn-add');
this.workspaceUserItemRefs = this.workspaceUsersSection.locator('umb-entity-item-ref');
}

async clickUserGroupsButton() {
Expand Down Expand Up @@ -237,4 +243,40 @@ export class UserGroupUiHelper extends UiBaseLocators {
await expect(permissionItemLocator.locator('#setting small')).toHaveText(description);
}
}

// Workspace users section (Manage Users From Group)
async clickChooseUserButton() {
await this.click(this.chooseUserButton);
}

async clickRemoveButtonForUserWithName(userName: string) {
await this.click(this.workspaceUsersSection.locator('umb-entity-item-ref', {hasText: userName}).getByLabel('Remove'));
}

async isUserVisibleInUserGroup(userName: string, isVisible = true) {
await this.isVisible(this.workspaceUsersSection.locator('umb-entity-item-ref', {hasText: userName}), isVisible);
}

async getUsersInGroupCount(): Promise<number> {
Comment thread
andr317c marked this conversation as resolved.
Outdated
await this.waitForVisible(this.workspaceUsersSection);
return await this.workspaceUserItemRefs.count();
}

async clickUserCardWithName(userName: string) {
await this.click(this.page.locator('uui-card-user', {hasText: userName}));
}

async clickChooseModalButtonAndWaitForGroupUsersUpdate() {
return await this.waitForResponseAfterExecutingPromise(ConstantHelper.apiEndpoints.userGroup, this.clickChooseModalButton(), ConstantHelper.statusCodes.ok);
}

async clickConfirmRemoveButtonAndWaitForGroupUsersUpdate() {
return await this.waitForResponseAfterExecutingPromise(ConstantHelper.apiEndpoints.userGroup, this.clickConfirmRemoveButton(), ConstantHelper.statusCodes.ok);
}

async waitForPendingGroupUsersUpdate() {
await this.page.waitForResponse(
(resp) => resp.url().includes(ConstantHelper.apiEndpoints.userGroup) && resp.status() === ConstantHelper.statusCodes.ok,
);
}
}
2 changes: 1 addition & 1 deletion tests/Umbraco.Tests.AcceptanceTest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"testSqlite": "npm run build && npx playwright test DefaultConfig --grep-invert \"Users\"",
"all": "npm run build && npx playwright test",
"createTest": "node createTest.js",
"smokeTest": "npm run build && npx playwright test DefaultConfig --grep \"@smoke\"",
"smokeTest": "npm run build && npx playwright test DefaultConfig/Users/ManageUsersFromGroup",
"smokeTestSqlite": "npm run build && npx playwright test DefaultConfig --grep \"@smoke\" --grep-invert \"Users\"",
"releaseTest": "npm run build && npx playwright test DefaultConfig --grep \"@release\"",
"testWindows": "npm run build && npx playwright test DefaultConfig --grep-invert \"RelationType\""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
import {ConstantHelper, test} from '@umbraco/acceptance-test-helpers';
import {expect} from '@playwright/test';

const userGroupName = 'TestUserGroup';
const writersUserGroupName = 'Writers';
const userA = {name: 'Manage Users User A', email: 'manageusersa@acceptance.test'};
const userB = {name: 'Manage Users User B', email: 'manageusersb@acceptance.test'};
const userC = {name: 'Manage Users User C', email: 'manageusersc@acceptance.test'};

test.beforeEach(async ({umbracoApi, umbracoUi}) => {
await umbracoApi.userGroup.ensureNameNotExists(userGroupName);
await umbracoApi.user.ensureNameNotExists(userA.name);
await umbracoApi.user.ensureNameNotExists(userB.name);
await umbracoApi.user.ensureNameNotExists(userC.name);
await umbracoUi.goToBackOffice();
await umbracoUi.userGroup.goToSection(ConstantHelper.sections.users);
});

test.afterEach(async ({umbracoApi}) => {
await umbracoApi.userGroup.ensureNameNotExists(userGroupName);
await umbracoApi.user.ensureNameNotExists(userA.name);
await umbracoApi.user.ensureNameNotExists(userB.name);
await umbracoApi.user.ensureNameNotExists(userC.name);
});

test('can view existing users in a user group', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => {
Comment thread
andr317c marked this conversation as resolved.
Outdated
// Arrange
const userGroupId = await umbracoApi.userGroup.createEmptyUserGroup(userGroupName);
await umbracoApi.user.createDefaultUser(userA.name, userA.email, [userGroupId]);
await umbracoApi.user.createDefaultUser(userB.name, userB.email, [userGroupId]);

// Act
await umbracoUi.userGroup.clickUserGroupsButton();
await umbracoUi.userGroup.clickUserGroupWithName(userGroupName);

// Assert
expect(await umbracoUi.userGroup.getUsersInGroupCount()).toBe(2);
await umbracoUi.userGroup.isUserVisibleInUserGroup(userA.name);
await umbracoUi.userGroup.isUserVisibleInUserGroup(userB.name);
});

test('cannot see any users in an empty user group', async ({umbracoApi, umbracoUi}) => {
// Arrange
await umbracoApi.userGroup.createEmptyUserGroup(userGroupName);

// Act
await umbracoUi.userGroup.clickUserGroupsButton();
await umbracoUi.userGroup.clickUserGroupWithName(userGroupName);

// Assert
expect(await umbracoUi.userGroup.getUsersInGroupCount()).toBe(0);
});

test('can add a user to an existing user group from the workspace', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => {
Comment thread
andr317c marked this conversation as resolved.
Outdated
// Arrange
const userGroupId = await umbracoApi.userGroup.createEmptyUserGroup(userGroupName);
const seedUserGroup = await umbracoApi.userGroup.getByName(writersUserGroupName);
Comment thread
andr317c marked this conversation as resolved.
Outdated
await umbracoApi.user.createDefaultUser(userA.name, userA.email, [seedUserGroup.id]);
await umbracoUi.userGroup.clickUserGroupsButton();
await umbracoUi.userGroup.clickUserGroupWithName(userGroupName);

// Act
await umbracoUi.userGroup.clickChooseUserButton();
await umbracoUi.userGroup.clickUserCardWithName(userA.name);
await umbracoUi.userGroup.clickChooseModalButtonAndWaitForGroupUsersUpdate();

// Assert
await umbracoUi.userGroup.isUserVisibleInUserGroup(userA.name);
expect(await umbracoApi.user.doesUserContainUserGroupIds(userA.name, [seedUserGroup.id, userGroupId])).toBeTruthy();
});

test('can add multiple users to an existing user group at once', async ({umbracoApi, umbracoUi}) => {
Comment thread
andr317c marked this conversation as resolved.
Outdated
// Arrange
const userGroupId = await umbracoApi.userGroup.createEmptyUserGroup(userGroupName);
const seedUserGroup = await umbracoApi.userGroup.getByName(writersUserGroupName);
Comment thread
andr317c marked this conversation as resolved.
Outdated
await umbracoApi.user.createDefaultUser(userA.name, userA.email, [seedUserGroup.id]);
await umbracoApi.user.createDefaultUser(userB.name, userB.email, [seedUserGroup.id]);
await umbracoApi.user.createDefaultUser(userC.name, userC.email, [seedUserGroup.id]);
await umbracoUi.userGroup.clickUserGroupsButton();
await umbracoUi.userGroup.clickUserGroupWithName(userGroupName);

// Act
await umbracoUi.userGroup.clickChooseUserButton();
await umbracoUi.userGroup.clickUserCardWithName(userA.name);
await umbracoUi.userGroup.clickUserCardWithName(userB.name);
await umbracoUi.userGroup.clickUserCardWithName(userC.name);
await umbracoUi.userGroup.clickChooseModalButtonAndWaitForGroupUsersUpdate();

// Assert
await umbracoUi.userGroup.isUserVisibleInUserGroup(userA.name);
await umbracoUi.userGroup.isUserVisibleInUserGroup(userB.name);
await umbracoUi.userGroup.isUserVisibleInUserGroup(userC.name);
expect(await umbracoApi.user.doesUserContainUserGroupIds(userA.name, [seedUserGroup.id, userGroupId])).toBeTruthy();
expect(await umbracoApi.user.doesUserContainUserGroupIds(userB.name, [seedUserGroup.id, userGroupId])).toBeTruthy();
expect(await umbracoApi.user.doesUserContainUserGroupIds(userC.name, [seedUserGroup.id, userGroupId])).toBeTruthy();
});

Check warning on line 96 in tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/ManageUsersFromGroup.spec.ts

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

❌ New issue: Code Duplication

The module contains 5 functions with similar structure: 'can add a new user via the picker without removing existing users','can add and then remove the same user in the same session','can add multiple users to an existing user group at once','can remove all users from a user group' and 1 more functions. Avoid duplicated, aka copy-pasted, code inside the module. More duplication lowers the code health.

test('can add a new user via the picker without removing existing users', async ({umbracoApi, umbracoUi}) => {
Comment thread
andr317c marked this conversation as resolved.
// Arrange
const userGroupId = await umbracoApi.userGroup.createEmptyUserGroup(userGroupName);
const seedUserGroup = await umbracoApi.userGroup.getByName(writersUserGroupName);
await umbracoApi.user.createDefaultUser(userA.name, userA.email, [userGroupId]);
await umbracoApi.user.createDefaultUser(userB.name, userB.email, [userGroupId]);
await umbracoApi.user.createDefaultUser(userC.name, userC.email, [seedUserGroup.id]);
await umbracoUi.userGroup.clickUserGroupsButton();
await umbracoUi.userGroup.clickUserGroupWithName(userGroupName);

// Act
await umbracoUi.userGroup.clickChooseUserButton();
await umbracoUi.userGroup.clickUserCardWithName(userC.name);
await umbracoUi.userGroup.clickChooseModalButtonAndWaitForGroupUsersUpdate();

// Assert
await umbracoUi.userGroup.isUserVisibleInUserGroup(userA.name);
await umbracoUi.userGroup.isUserVisibleInUserGroup(userB.name);
await umbracoUi.userGroup.isUserVisibleInUserGroup(userC.name);
expect(await umbracoApi.user.doesUserContainUserGroupIds(userA.name, [userGroupId])).toBeTruthy();
expect(await umbracoApi.user.doesUserContainUserGroupIds(userB.name, [userGroupId])).toBeTruthy();
expect(await umbracoApi.user.doesUserContainUserGroupIds(userC.name, [seedUserGroup.id, userGroupId])).toBeTruthy();
});

test('can remove a user from a user group', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => {
// Arrange
const userGroupId = await umbracoApi.userGroup.createEmptyUserGroup(userGroupName);
await umbracoApi.user.createDefaultUser(userA.name, userA.email, [userGroupId]);
await umbracoApi.user.createDefaultUser(userB.name, userB.email, [userGroupId]);
await umbracoUi.userGroup.clickUserGroupsButton();
await umbracoUi.userGroup.clickUserGroupWithName(userGroupName);

// Act
await umbracoUi.userGroup.clickRemoveButtonForUserWithName(userA.name);
await umbracoUi.userGroup.clickConfirmRemoveButtonAndWaitForGroupUsersUpdate();

// Assert
await umbracoUi.userGroup.isUserVisibleInUserGroup(userA.name, false);
await umbracoUi.userGroup.isUserVisibleInUserGroup(userB.name);
expect(await umbracoApi.user.doesUserContainUserGroupIds(userA.name, [userGroupId])).toBeFalsy();
expect(await umbracoApi.user.doesUserContainUserGroupIds(userB.name, [userGroupId])).toBeTruthy();
});

test('can remove all users from a user group', async ({umbracoApi, umbracoUi}) => {
// Arrange
const userGroupId = await umbracoApi.userGroup.createEmptyUserGroup(userGroupName);
await umbracoApi.user.createDefaultUser(userA.name, userA.email, [userGroupId]);
await umbracoApi.user.createDefaultUser(userB.name, userB.email, [userGroupId]);
await umbracoUi.userGroup.clickUserGroupsButton();
await umbracoUi.userGroup.clickUserGroupWithName(userGroupName);

// Act
await umbracoUi.userGroup.clickRemoveButtonForUserWithName(userA.name);
await umbracoUi.userGroup.clickConfirmRemoveButtonAndWaitForGroupUsersUpdate();
await umbracoUi.userGroup.clickRemoveButtonForUserWithName(userB.name);
await umbracoUi.userGroup.clickConfirmRemoveButtonAndWaitForGroupUsersUpdate();

// Assert
expect(await umbracoUi.userGroup.getUsersInGroupCount()).toBe(0);
expect(await umbracoApi.user.doesUserContainUserGroupIds(userA.name, [userGroupId])).toBeFalsy();
expect(await umbracoApi.user.doesUserContainUserGroupIds(userB.name, [userGroupId])).toBeFalsy();
});

test('can add and then remove the same user in the same session', async ({umbracoApi, umbracoUi}) => {
// Arrange
const userGroupId = await umbracoApi.userGroup.createEmptyUserGroup(userGroupName);
const seedUserGroup = await umbracoApi.userGroup.getByName(writersUserGroupName);
await umbracoApi.user.createDefaultUser(userA.name, userA.email, [seedUserGroup.id]);
await umbracoUi.userGroup.clickUserGroupsButton();
await umbracoUi.userGroup.clickUserGroupWithName(userGroupName);

// Act
await umbracoUi.userGroup.clickChooseUserButton();
await umbracoUi.userGroup.clickUserCardWithName(userA.name);
await umbracoUi.userGroup.clickChooseModalButtonAndWaitForGroupUsersUpdate();
Comment thread
andr317c marked this conversation as resolved.
await umbracoUi.userGroup.clickRemoveButtonForUserWithName(userA.name);
await umbracoUi.userGroup.clickConfirmRemoveButtonAndWaitForGroupUsersUpdate();

// Assert
expect(await umbracoUi.userGroup.getUsersInGroupCount()).toBe(0);
expect(await umbracoApi.user.doesUserContainUserGroupIds(userA.name, [userGroupId])).toBeFalsy();
});

test('can see user updates are persisted after navigating away from and returning to the user group', async ({umbracoApi, umbracoUi}) => {
// Arrange
const userGroupId = await umbracoApi.userGroup.createEmptyUserGroup(userGroupName);
const seedUserGroup = await umbracoApi.userGroup.getByName(writersUserGroupName);
await umbracoApi.user.createDefaultUser(userA.name, userA.email, [seedUserGroup.id]);
await umbracoUi.userGroup.clickUserGroupsButton();
await umbracoUi.userGroup.clickUserGroupWithName(userGroupName);
await umbracoUi.userGroup.clickChooseUserButton();
await umbracoUi.userGroup.clickUserCardWithName(userA.name);
await umbracoUi.userGroup.clickChooseModalButtonAndWaitForGroupUsersUpdate();

// Act
await umbracoUi.userGroup.clickUserGroupsButton();
await umbracoUi.userGroup.clickUserGroupWithName(userGroupName);

// Assert
await umbracoUi.userGroup.isUserVisibleInUserGroup(userA.name);
expect(await umbracoApi.user.doesUserContainUserGroupIds(userA.name, [seedUserGroup.id, userGroupId])).toBeTruthy();
});

test('can add users while creating a new user group', {tag: '@release'}, async ({umbracoApi, umbracoUi}) => {
// Arrange
const seedUserGroup = await umbracoApi.userGroup.getByName(writersUserGroupName);
await umbracoApi.user.createDefaultUser(userA.name, userA.email, [seedUserGroup.id]);
await umbracoApi.user.createDefaultUser(userB.name, userB.email, [seedUserGroup.id]);

// Act
await umbracoUi.userGroup.clickUserGroupsButton();
await umbracoUi.userGroup.clickCreateLink();
await umbracoUi.userGroup.enterUserGroupName(userGroupName);
await umbracoUi.userGroup.clickChooseUserButton();
await umbracoUi.userGroup.clickUserCardWithName(userA.name);
await umbracoUi.userGroup.clickUserCardWithName(userB.name);
await umbracoUi.userGroup.clickChooseModalButton();
const userGroupId = await umbracoUi.userGroup.clickSaveButtonAndWaitForUserGroupToBeCreated();
// Wait for the deferred user persistence to fire after the group transitions from new to persisted.
await umbracoUi.userGroup.waitForPendingGroupUsersUpdate();

// Assert
expect(await umbracoApi.userGroup.doesExist(userGroupId)).toBe(true);
expect(await umbracoApi.user.doesUserContainUserGroupIds(userA.name, [seedUserGroup.id, userGroupId])).toBeTruthy();
expect(await umbracoApi.user.doesUserContainUserGroupIds(userB.name, [seedUserGroup.id, userGroupId])).toBeTruthy();
});
Loading