Add e2e testing for user invitation
This commit adds e2e testing for the user invitation process in the app. It introduces data-test attributes to key components in the invitation flow, assisting in test case creation. Newly created tests validate user invitation functionality including form filling, role selection, and submission.
This commit is contained in:
60
apps/e2e/tests/invitations/invitations.po.ts
Normal file
60
apps/e2e/tests/invitations/invitations.po.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { Page } from '@playwright/test';
|
||||
import { AuthPageObject } from '../authentication/auth.po';
|
||||
import { TeamAccountsPageObject } from '../team-accounts/team-accounts.po';
|
||||
|
||||
export class InvitationsPageObject {
|
||||
private readonly page: Page;
|
||||
public auth: AuthPageObject;
|
||||
public teamAccounts: TeamAccountsPageObject;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
this.auth = new AuthPageObject(page);
|
||||
this.teamAccounts = new TeamAccountsPageObject(page);
|
||||
}
|
||||
|
||||
async setup() {
|
||||
await this.teamAccounts.setup();
|
||||
}
|
||||
|
||||
public async inviteMembers(invites: Array<{
|
||||
email: string;
|
||||
role: string;
|
||||
}>) {
|
||||
const form = this.getInviteForm();
|
||||
|
||||
for (let index = 0; index < invites.length; index++) {
|
||||
const invite = invites[index];
|
||||
|
||||
if (!invite) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const nth = index + 1;
|
||||
|
||||
await this.page.fill(`[data-test="invite-member-form-item"]:nth-child(${nth}) [data-test="invite-email-input"]`, invite.email);
|
||||
await this.page.click(`[data-test="invite-member-form-item"]:nth-child(${nth}) [data-test="role-selector-trigger"]`);
|
||||
await this.page.click(`[data-test="role-option-${invite.role}"]`);
|
||||
|
||||
if (index < invites.length - 1) {
|
||||
await form.locator('[data-test="add-new-invite-button"]').click();
|
||||
}
|
||||
}
|
||||
|
||||
await form.locator('button[type="submit"]').click();
|
||||
}
|
||||
|
||||
public navigateToMembers() {
|
||||
return this.page.locator('a', {
|
||||
hasText: 'Members',
|
||||
}).click();
|
||||
}
|
||||
|
||||
async openInviteForm() {
|
||||
await this.page.locator('[data-test="invite-members-form-trigger"]').click();
|
||||
}
|
||||
|
||||
private getInviteForm() {
|
||||
return this.page.locator('[data-test="invite-members-form"]');
|
||||
}
|
||||
}
|
||||
34
apps/e2e/tests/invitations/invitations.spec.ts
Normal file
34
apps/e2e/tests/invitations/invitations.spec.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { Page, test } from '@playwright/test';
|
||||
import { InvitationsPageObject } from './invitations.po';
|
||||
|
||||
test.describe('Invitations', () => {
|
||||
let page: Page;
|
||||
let invitations: InvitationsPageObject;
|
||||
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
page = await browser.newPage();
|
||||
invitations = new InvitationsPageObject(page);
|
||||
|
||||
await invitations.setup();
|
||||
});
|
||||
|
||||
test('user invite users', async ({page}) => {
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
await invitations.navigateToMembers();
|
||||
await invitations.openInviteForm();
|
||||
|
||||
const invites = [
|
||||
{
|
||||
email: invitations.auth.createRandomEmail(),
|
||||
role: 'member'
|
||||
},
|
||||
{
|
||||
email: invitations.auth.createRandomEmail(),
|
||||
role: 'member'
|
||||
},
|
||||
];
|
||||
|
||||
await invitations.inviteMembers(invites);
|
||||
});
|
||||
});
|
||||
@@ -135,7 +135,7 @@ async function TeamAccountMembersPage({ params }: Params) {
|
||||
accountId={account.id}
|
||||
accountSlug={account.slug}
|
||||
>
|
||||
<Button size={'sm'}>
|
||||
<Button size={'sm'} data-test={'invite-members-form-trigger'}>
|
||||
<PlusCircle className={'mr-2 w-4'} />
|
||||
|
||||
<span>
|
||||
|
||||
@@ -133,7 +133,7 @@ function InviteMembersForm({
|
||||
const roleInputName = `invitations.${index}.role` as const;
|
||||
|
||||
return (
|
||||
<div key={field.id}>
|
||||
<div data-test={'invite-member-form-item'} key={field.id}>
|
||||
<div className={'flex items-end space-x-0.5 md:space-x-2'}>
|
||||
<div className={'w-7/12'}>
|
||||
<FormField
|
||||
@@ -216,7 +216,7 @@ function InviteMembersForm({
|
||||
|
||||
<div>
|
||||
<Button
|
||||
data-test={'append-new-invite-button'}
|
||||
data-test={'add-new-invite-button'}
|
||||
type={'button'}
|
||||
variant={'link'}
|
||||
size={'sm'}
|
||||
@@ -234,7 +234,7 @@ function InviteMembersForm({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button disabled={pending}>
|
||||
<Button type={'submit'} disabled={pending}>
|
||||
<Trans
|
||||
i18nKey={
|
||||
pending
|
||||
|
||||
@@ -26,7 +26,7 @@ export const MembershipRoleSelector: React.FC<{
|
||||
return (
|
||||
<SelectItem
|
||||
key={role}
|
||||
data-test={`role-item-${role}`}
|
||||
data-test={`role-option-${role}`}
|
||||
disabled={currentUserRole === role}
|
||||
value={role}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user