test: playkit v0.3.1 adoption, Zod widening, PROD smoke, NextAuth write gates #68

Merged
ilia merged 8 commits from feat/admin-manage-users-e2e into dev 2026-07-14 22:24:07 -05:00
Showing only changes of commit f080a0cdb1 - Show all commits
+11 -4
View File
@@ -26,6 +26,15 @@ export class ManageUsersPanel extends BasePage {
return this.page.locator('tbody tr').filter({ hasText: email });
}
/** The row's action buttons (Edit is always first; Deactivate/Delete is
* second and only rendered for active users). Positional rather than
* aria-label-based — proved more reliable against the live table than
* exact accessible-name matching. */
private actionButton(email: string, position: 'first' | 'last'): Locator {
const buttons = this.row(email).getByRole('button');
return position === 'first' ? buttons.first() : buttons.last();
}
/** Scopes to the currently-open dialog matching a heading, to avoid
* ambiguous matches against hidden/portalled sibling dialogs. */
private dialog(headingText: string): Locator {
@@ -53,7 +62,7 @@ export class ManageUsersPanel extends BasePage {
}
async openEditDialog(email: string): Promise<void> {
await this.click(this.row(email).getByRole('button', { name: `Edit ${email}`, exact: true }));
await this.click(this.actionButton(email, 'first'));
await waitForVisible(this.dialog('Edit User'));
}
@@ -82,9 +91,7 @@ export class ManageUsersPanel extends BasePage {
* Hard-deletes if the account has no related records, otherwise the
* backend soft-deactivates it — either way `isActive` ends up false. */
async deleteUser(email: string): Promise<void> {
await this.click(
this.row(email).getByRole('button', { name: `Deactivate ${email}`, exact: true }),
);
await this.click(this.actionButton(email, 'last'));
const dialog = this.dialog('Delete User');
await waitForVisible(dialog);
await this.click(dialog.getByRole('button', { name: 'Delete', exact: true }));