Files
myeasycms-v2/apps/e2e/tests/team-accounts/team-accounts.spec.ts
Giancarlo Buomprisco 131b1061e6 Enforce RLS when user opted in to MFA. (#188)
* Allow Super Admin to view tables using RLS
* Replace previous usages of the Admin client using the authed client using the new RLS
* Enforce MFA for Super Admin users
* Enforce RLS when user opted in to MFA.
* Add Super Admin Access Policies and Update Database Types
* Consolidate super admin logic into a single function that uses the RPC is_super_admin
* Added Super Admin E2E tests
* Fixes and improvements
* Bump version to 2.5.0
2025-03-02 11:21:01 +08:00

219 lines
6.6 KiB
TypeScript

import { Page, expect, test } from '@playwright/test';
import { InvitationsPageObject } from '../invitations/invitations.po';
import { TeamAccountsPageObject } from './team-accounts.po';
// Helper function to set up a team with a member
async function setupTeamWithMember(page: Page, memberRole = 'member') {
// Setup invitations page object
const invitations = new InvitationsPageObject(page);
const teamAccounts = invitations.teamAccounts;
// Setup team with owner
const { email: ownerEmail, slug } = await invitations.setup();
// Navigate to members page
await invitations.navigateToMembers();
// Create a new member email and invite them with the specified role
const memberEmail = invitations.auth.createRandomEmail();
const invites = [
{
email: memberEmail,
role: memberRole,
},
];
await invitations.openInviteForm();
await invitations.inviteMembers(invites);
// Verify the invitation was sent
await expect(invitations.getInvitations()).toHaveCount(1);
// Sign out the current user
await page.context().clearCookies();
// Sign up with the new member email and accept the invitation
await invitations.auth.visitConfirmEmailLink(memberEmail);
await invitations.auth.signUp({
email: memberEmail,
password: 'password',
repeatPassword: 'password',
});
await invitations.auth.visitConfirmEmailLink(memberEmail);
await invitations.acceptInvitation();
await invitations.teamAccounts.openAccountsSelector();
await expect(invitations.teamAccounts.getTeams()).toHaveCount(1);
// Sign out and sign back in as the original owner
await page.context().clearCookies();
await page.goto('/auth/sign-in');
await invitations.auth.signIn({
email: ownerEmail,
password: 'password',
});
await page.waitForURL('/home');
// Navigate to the team members page
await page.goto(`/home/${slug}/members`);
return { invitations, teamAccounts, ownerEmail, memberEmail, slug };
}
test.describe('Team Accounts', () => {
let page: Page;
let teamAccounts: TeamAccountsPageObject;
test.beforeAll(async ({ browser }) => {
page = await browser.newPage();
teamAccounts = new TeamAccountsPageObject(page);
});
test('user can update their team name (and slug)', async () => {
await teamAccounts.setup();
const { teamName, slug } = teamAccounts.createTeamName();
await teamAccounts.goToSettings();
const request = teamAccounts.updateName(teamName, slug);
// the slug should be updated to match the new team name
const newUrl = page.waitForURL(`**/home/${slug}/settings`);
await Promise.all([request, newUrl]);
await teamAccounts.openAccountsSelector();
await expect(teamAccounts.getTeamFromSelector(teamName)).toBeVisible();
});
});
test.describe('Team Account Deletion', () => {
test('user can delete their team account', async ({ page }) => {
const teamAccounts = new TeamAccountsPageObject(page);
const params = teamAccounts.createTeamName();
const { email } = await teamAccounts.setup(params);
await teamAccounts.goToSettings();
await teamAccounts.deleteAccount(email);
await teamAccounts.openAccountsSelector();
await expect(
teamAccounts.getTeamFromSelector(params.teamName),
).not.toBeVisible();
});
});
test.describe('Team Member Role Management', () => {
test("owner can update a team member's role", async ({ page }) => {
// Setup team with a regular member
const { teamAccounts, memberEmail } = await setupTeamWithMember(page);
// Get the current role badge text
const memberRow = page.getByRole('row', { name: memberEmail });
const initialRoleBadge = memberRow.locator(
'[data-test="member-role-badge"]',
);
await expect(initialRoleBadge).toHaveText('Member');
// Update the member's role to admin
await teamAccounts.updateMemberRole(memberEmail, 'owner');
// Wait for the page to fully load after the update
await page.waitForTimeout(1000);
// Verify the role was updated successfully
const updatedRoleBadge = page
.getByRole('row', { name: memberEmail })
.locator('[data-test="member-role-badge"]');
await expect(updatedRoleBadge).toHaveText('Owner');
});
});
test.describe('Team Ownership Transfer', () => {
test('owner can transfer ownership to another team member', async ({
page,
}) => {
// Setup team with an owner member (required for ownership transfer)
const { teamAccounts, ownerEmail, memberEmail } = await setupTeamWithMember(
page,
'owner',
);
// Transfer ownership to the member
await teamAccounts.transferOwnership(memberEmail, ownerEmail);
// Wait for the page to fully load after the transfer
await page.waitForTimeout(1000);
// Verify the transfer was successful by checking if the primary owner badge
// is now on the new owner's row
const memberRow = page.getByRole('row', { name: memberEmail });
// Check for the primary owner badge on the member's row
await expect(memberRow.locator('text=Primary Owner')).toBeVisible({
timeout: 5000,
});
// The original owner should no longer have the primary owner badge
const ownerRow = page.getByRole('row', { name: ownerEmail.split('@')[0] });
await expect(ownerRow.locator('text=Primary Owner')).not.toBeVisible();
});
});
test.describe('Team Account Security', () => {
test('unauthorized user cannot access team account', async ({
page,
browser,
}) => {
// 1. Create a team account with User A
const teamAccounts = new TeamAccountsPageObject(page);
const params = teamAccounts.createTeamName();
// Setup User A and create team
await teamAccounts.setup(params);
// Store team slug for later use
const teamSlug = params.slug;
// 2. Sign out User A
await page.context().clearCookies();
// 3. Create a new context for User B (to have clean cookies/session)
const userBContext = await browser.newContext();
const userBPage = await userBContext.newPage();
const userBTeamAccounts = new TeamAccountsPageObject(userBPage);
// Sign up with User B
await userBPage.goto('/auth/sign-up');
const emailB = userBTeamAccounts.auth.createRandomEmail();
await userBTeamAccounts.auth.signUp({
email: emailB,
password: 'password',
repeatPassword: 'password',
});
await userBTeamAccounts.auth.visitConfirmEmailLink(emailB);
// 4. Attempt to access the team page with User B
await userBPage.goto(`/home/${teamSlug}`);
// Check that we're not on the team page anymore (should redirect)
await expect(userBPage).toHaveURL(`/home`);
});
});