Skip to content

Commit a5702a9

Browse files
committed
chore: 🤖 add sorting e2e test
1 parent 738fa1f commit a5702a9

File tree

3 files changed

+154
-3
lines changed

3 files changed

+154
-3
lines changed

‎e2e-tests/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ cd boundary-ui/e2e-tests
176176
Run the command for the corresponding enos scenario to run all supported tests:
177177
| | `@aws` | `@docker` |
178178
| ------------- | --------------------------------- | ------------------------------------ |
179-
| `@ce` | command: `pnpm run admin:ce:aws` | command: `admin:ce:docker` |
179+
| `@ce` | command: `pnpm run admin:ce:aws` | command: `pnpm admin:ce:docker` |
180180
| `@enterprise` | command: `pnpm run admin:ent:aws` | command: `pnpm run admin:ent:docker` |
181181

182182

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/**
2+
* Copyright (c) HashiCorp, Inc.
3+
* SPDX-License-Identifier: BUSL-1.1
4+
*/
5+
6+
import { test } from '../../global-setup.js';
7+
import * as boundaryHttp from '../../helpers/boundary-http.js';
8+
import * as boundaryCli from '../../helpers/boundary-cli.js';
9+
import { RolesPage } from '../pages/roles.js';
10+
import { expect } from '@playwright/test';
11+
12+
const roleNamesToCreate = ['Alpha', 'Beta', 'Delta', 'Gamma', 'Zeta'];
13+
14+
export const tableSortButton = (tableLocator, nth) =>
15+
tableLocator.locator(`thead tr th`).nth(nth).locator('button');
16+
export const tableSortButtonUpArrow = (tableLocator, nth) =>
17+
tableLocator
18+
.locator(`thead tr th`)
19+
.nth(nth)
20+
.locator('button .hds-icon-arrow-up');
21+
export const tableSortButtonDownArrow = (tableLocator, nth) =>
22+
tableLocator
23+
.locator(`thead tr th`)
24+
.nth(nth)
25+
.locator('button .hds-icon-arrow-down');
26+
27+
const columnHeadersOrder = {
28+
name: 0,
29+
id: 2,
30+
};
31+
32+
let org, rolesSortedByCreatedTime, rolesSortedByName, rolesSortedById;
33+
34+
test.beforeEach(
35+
async ({
36+
request,
37+
controllerAddr,
38+
adminAuthMethodId,
39+
adminLoginName,
40+
adminPassword,
41+
}) => {
42+
org = await boundaryHttp.createOrg(request);
43+
44+
await boundaryCli.authenticateBoundary(
45+
controllerAddr,
46+
adminAuthMethodId,
47+
adminLoginName,
48+
adminPassword,
49+
);
50+
51+
// when the org is created some roles are created automatically, but for the purposes
52+
// of this sorting test it's clearer if only the roles created by the test are present
53+
const existingRolesToDelete = await boundaryCli.listRoles(org.id);
54+
for (const role of existingRolesToDelete) {
55+
await boundaryCli.deleteRole(role.id);
56+
}
57+
58+
// create roles with specific names
59+
for (const roleName of roleNamesToCreate) {
60+
boundaryCli.createRole(org.id, { name: roleName });
61+
}
62+
63+
// collect all roles and data so that sorting can be tested based on the underlying data
64+
const roles = await boundaryCli.listRoles(org.id);
65+
rolesSortedByCreatedTime = roles.toSorted((a, b) => {
66+
return new Date(b.created_time) - new Date(a.created_time);
67+
});
68+
rolesSortedByName = roles.toSorted((a, b) => a.name.localeCompare(b.name));
69+
rolesSortedById = roles.toSorted((a, b) => a.id.localeCompare(b.id));
70+
},
71+
);
72+
73+
test.afterEach(async ({ request }) => {
74+
// deletes roles associated with the org
75+
await boundaryHttp.deleteOrg(request, org.id);
76+
});
77+
78+
test('Sorting works', { tag: ['@ce', '@aws', '@docker'] }, async ({ page }) => {
79+
const rolesPage = new RolesPage(page);
80+
rolesPage.goToRolesPage({ scope: org.id });
81+
82+
const table = page.locator('table');
83+
await expect(table.locator('tbody tr')).toHaveCount(roleNamesToCreate.length);
84+
85+
// by default, resources are sorted by created time, descending
86+
for (const [index, role] of Object.entries(
87+
rolesSortedByCreatedTime,
88+
).toReversed()) {
89+
await expect(table.locator('tbody tr').nth(index)).toContainText(role.name);
90+
}
91+
92+
// click the "Name" column header to sort by name, ascending
93+
await tableSortButton(table, columnHeadersOrder.name).click();
94+
await tableSortButtonUpArrow(table, columnHeadersOrder.name).isVisible();
95+
96+
for (const [index, role] of Object.entries(rolesSortedByName)) {
97+
await expect(table.locator('tbody tr').nth(index)).toContainText(role.name);
98+
}
99+
100+
// click the "Name" column header again, to sort by name, descending
101+
await tableSortButton(table, columnHeadersOrder.name).click();
102+
await tableSortButtonDownArrow(table, columnHeadersOrder.name).isVisible();
103+
for (const [index, role] of Object.entries(rolesSortedByName.toReversed())) {
104+
await expect(table.locator('tbody tr').nth(index)).toContainText(role.name);
105+
}
106+
107+
// click the "ID" column header to sort by ID, ascending
108+
await tableSortButton(table, columnHeadersOrder.id).click();
109+
await tableSortButtonUpArrow(table, columnHeadersOrder.id).isVisible();
110+
for (const [index, role] of Object.entries(rolesSortedById)) {
111+
await expect(table.locator('tbody tr').nth(index)).toContainText(role.name);
112+
}
113+
114+
// click the "ID" column header again, to sort by ID, descending
115+
await tableSortButton(table, columnHeadersOrder.id).click();
116+
await tableSortButtonDownArrow(table, columnHeadersOrder.id).isVisible();
117+
for (const [index, role] of Object.entries(rolesSortedById.toReversed())) {
118+
await expect(table.locator('tbody tr').nth(index)).toContainText(role.name);
119+
}
120+
});

‎e2e-tests/helpers/boundary-cli/roles.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import { nanoid } from 'nanoid';
1111
* @param {string} scopeId ID of the scope under which the role will be created.
1212
* @returns {Promise<string>} new role's ID
1313
*/
14-
export async function createRole(scopeId) {
15-
const roleName = 'role-' + nanoid();
14+
export async function createRole(scopeId, { name }) {
15+
const roleName = name ?? 'role-' + nanoid();
1616
let role;
1717
try {
1818
role = JSON.parse(
@@ -28,3 +28,34 @@ export async function createRole(scopeId) {
2828
}
2929
return role.id;
3030
}
31+
32+
export async function deleteRole(id) {
33+
try {
34+
execSync(
35+
`boundary roles delete \
36+
-id ${id} \
37+
-format json`,
38+
);
39+
} catch (e) {
40+
console.log(`${e.stderr}`);
41+
}
42+
43+
return id;
44+
}
45+
46+
export async function listRoles(scopeId) {
47+
let roles;
48+
try {
49+
roles = JSON.parse(
50+
execSync(
51+
`boundary roles list \
52+
-scope-id ${scopeId} \
53+
-format json`,
54+
),
55+
);
56+
} catch (e) {
57+
console.log(`${e.stderr}`);
58+
}
59+
60+
return roles.items;
61+
}

0 commit comments

Comments
 (0)