diff --git a/.changeset/accessible-room-counts.md b/.changeset/accessible-room-counts.md new file mode 100644 index 0000000000000..a7d534e1414e3 --- /dev/null +++ b/.changeset/accessible-room-counts.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Added accessible labels to the Users and Msgs count cells in the admin Rooms table. diff --git a/apps/meteor/client/views/admin/rooms/RoomRow.tsx b/apps/meteor/client/views/admin/rooms/RoomRow.tsx index 722085881417d..30ec506de4e1c 100644 --- a/apps/meteor/client/views/admin/rooms/RoomRow.tsx +++ b/apps/meteor/client/views/admin/rooms/RoomRow.tsx @@ -84,8 +84,14 @@ const RoomRow = ({ room }: RoomRowProps) => { {t(getRoomType(room))} - {usersCount} - {mediaQuery && {msgs}} + + {usersCount} + + {mediaQuery && ( + + {msgs} + + )} {mediaQuery && {isDefault ? t('True') : t('False')}} {mediaQuery && {featured ? t('True') : t('False')}} {mediaQuery && {ts ? formatDate(ts) : ''}} diff --git a/apps/meteor/tests/e2e/imports.spec.ts b/apps/meteor/tests/e2e/imports.spec.ts index 0c9a4e3dd63e6..4a91c23003d0a 100644 --- a/apps/meteor/tests/e2e/imports.spec.ts +++ b/apps/meteor/tests/e2e/imports.spec.ts @@ -4,10 +4,10 @@ import * as path from 'path'; import { parse } from 'csv-parse'; import { Users } from './fixtures/userStates'; -import { AdminImports, AdminRooms } from './page-objects'; +import { AdminImports, AdminRooms, AdminUsers } from './page-objects'; import { test, expect } from './utils/test'; -test.use({ storageState: Users.admin.state }); +test.use({ storageState: Users.admin.state, viewport: { width: 1280, height: 720 } }); type csvRoomSpec = { name: string; @@ -46,7 +46,9 @@ const usersCsvsToJson = async (): Promise => { .pipe(parse({ delimiter: ',' })) .on('data', (rows) => { rowUserName.push(rows[0]); - csvImportedUsernames.push(rows[0]); + if (rows[0] !== 'billy.billy') { + csvImportedUsernames.push(rows[0]); + } }) .on('end', resolve), ); @@ -125,13 +127,21 @@ test.describe.serial('imports', () => { }); test('expect all imported users to be actually listed as users', async ({ page }) => { + const poAdmin = new AdminUsers(page); await page.goto('/admin/users'); for await (const user of rowUserName) { + const searchResponse = page.waitForResponse((response) => { + const url = new URL(response.url()); + return url.pathname.endsWith('/api/v1/users.listByStatus') && url.searchParams.get('searchTerm') === user && response.ok(); + }); + await poAdmin.fillUserSearch(user); + await searchResponse; if (user === 'billy.billy') { - await expect(page.locator(`tbody tr td:first-child >> text="${user}"`)).not.toBeVisible(); + await expect(page.getByRole('heading', { name: 'No users' })).toBeVisible(); + await expect(poAdmin.getUserRowByUsername(user)).not.toBeVisible(); } else { - expect(page.locator(`tbody tr td:first-child >> text="${user}"`)); + await expect(poAdmin.getUserRowByUsername(user)).toBeVisible(); } } }); @@ -143,8 +153,8 @@ test.describe.serial('imports', () => { for await (const room of importedRooms) { await poAdmin.inputSearchRooms.fill(room.name); - const expectedMembersCount = room.members.split(';').filter((username) => username !== room.ownerUsername).length + 1; - expect(page.locator(`tbody tr td:nth-child(2) >> text="${expectedMembersCount}"`)); + const expectedMembersCount = room.members.split(';').filter((username) => username && username !== room.ownerUsername).length + 1; + await expect(poAdmin.getRoomUsersCountCell(room.name, expectedMembersCount)).toHaveText(String(expectedMembersCount)); } }); @@ -156,9 +166,11 @@ test.describe.serial('imports', () => { await poAdmin.inputSearchRooms.fill(room.name); await poAdmin.getRoomRow(room.name).click(); - room.visibility === 'private' - ? await expect(poAdmin.editRoom.privateInput).toBeChecked() - : await expect(poAdmin.editRoom.privateInput).not.toBeChecked(); + if (room.visibility === 'private') { + await expect(poAdmin.editRoom.privateInput).toBeChecked(); + } else { + await expect(poAdmin.editRoom.privateInput).not.toBeChecked(); + } await expect(poAdmin.editRoom.roomOwnerInput).toHaveValue(room.ownerUsername); } }); @@ -169,13 +181,14 @@ test.describe.serial('imports', () => { for await (const user of csvImportedUsernames) { await poAdmin.inputSearchRooms.fill(user); - expect(page.locator(`tbody tr td:first-child >> text="${user}"`)); + const roomRow = poAdmin.getRoomRow(user); + await expect(roomRow).toBeVisible(); const expectedMembersCount = 2; - expect(page.locator(`tbody tr td:nth-child(2) >> text="${expectedMembersCount}"`)); + await expect(poAdmin.getRoomUsersCountCell(user, expectedMembersCount)).toHaveText(String(expectedMembersCount)); const expectedMessagesCount = dmMessages.length; - expect(page.locator(`tbody tr td:nth-child(3) >> text="${expectedMessagesCount}"`)); + await expect(poAdmin.getRoomMessagesCountCell(user, expectedMessagesCount)).toHaveText(String(expectedMessagesCount)); } }); }); diff --git a/apps/meteor/tests/e2e/page-objects/admin-rooms.ts b/apps/meteor/tests/e2e/page-objects/admin-rooms.ts index 40104eeeddb7b..8402bff986bc2 100644 --- a/apps/meteor/tests/e2e/page-objects/admin-rooms.ts +++ b/apps/meteor/tests/e2e/page-objects/admin-rooms.ts @@ -23,6 +23,14 @@ export class AdminRooms extends Admin { return this.adminPageContent.getByRole('link', { name }); } + getRoomUsersCountCell(name: string, count: number): Locator { + return this.getRoomRow(name).getByRole('cell', { name: `Users: ${count}`, exact: true }); + } + + getRoomMessagesCountCell(name: string, count: number): Locator { + return this.getRoomRow(name).getByRole('cell', { name: `Msgs: ${count}`, exact: true }); + } + get btnEdit(): Locator { return this.adminPageContent.getByRole('button', { name: 'Edit' }); } diff --git a/apps/meteor/tests/e2e/page-objects/admin-users.ts b/apps/meteor/tests/e2e/page-objects/admin-users.ts index 74e0ca44b1640..d16bee5591e36 100644 --- a/apps/meteor/tests/e2e/page-objects/admin-users.ts +++ b/apps/meteor/tests/e2e/page-objects/admin-users.ts @@ -64,8 +64,12 @@ export class AdminUsers extends Admin { await this.userInfo.menuItemDeleteUser.click(); } - async searchUser(username: string): Promise { + async fillUserSearch(username: string): Promise { await this.inputSearchUsers.fill(username); + } + + async searchUser(username: string): Promise { + await this.fillUserSearch(username); await expect(this.getUserRowByUsername(username)).toHaveCount(1); } }