Enhance E2E Tests and Configuration (#358)

* Enhance E2E Tests and Configuration

- Updated `.gitignore` to exclude `.auth/` directory for cleaner test environment.
- Added `test:fast` script in `package.json` for faster Playwright test execution.
- Configured Playwright to include a setup project for initializing tests.
- Introduced `AUTH_STATES` utility for managing authentication states in tests.
- Created `auth.setup.ts` for user authentication tests, ensuring proper login flows.
- Refactored various test files to utilize the new authentication state management, improving test reliability and maintainability.
- Adjusted team and user billing tests to streamline setup and enhance clarity.
- Refactored some dialogs
This commit is contained in:
Giancarlo Buomprisco
2025-09-21 12:28:42 +08:00
committed by GitHub
parent f157cc7f3e
commit 02e2502dcc
27 changed files with 661 additions and 407 deletions

View File

@@ -1,22 +1,33 @@
import { Page, expect } from '@playwright/test';
import { createClient } from '@supabase/supabase-js';
import test, { Page, expect } from '@playwright/test';
import { AUTH_STATES } from '../utils/auth-state';
import { Mailbox } from '../utils/mailbox';
const MFA_KEY = 'NHOHJVGPO3R3LKVPRMNIYLCDMBHUM2SE';
export class AuthPageObject {
private readonly page: Page;
private readonly mailbox: Mailbox;
static MFA_KEY = MFA_KEY;
constructor(page: Page) {
this.page = page;
this.mailbox = new Mailbox(page);
}
goToSignIn() {
return this.page.goto('/auth/sign-in');
static setupSession(user: (typeof AUTH_STATES)[keyof typeof AUTH_STATES]) {
test.use({ storageState: user });
}
goToSignUp() {
return this.page.goto('/auth/sign-up');
goToSignIn(next?: string) {
return this.page.goto(`/auth/sign-in${next ? `?next=${next}` : ''}`);
}
goToSignUp(next?: string) {
return this.page.goto(`/auth/sign-up${next ? `?next=${next}` : ''}`);
}
async signOut() {
@@ -25,7 +36,7 @@ export class AuthPageObject {
}
async signIn(params: { email: string; password: string }) {
await this.page.waitForTimeout(500);
await this.page.waitForTimeout(100);
await this.page.fill('input[name="email"]', params.email);
await this.page.fill('input[name="password"]', params.password);
@@ -37,7 +48,7 @@ export class AuthPageObject {
password: string;
repeatPassword: string;
}) {
await this.page.waitForTimeout(500);
await this.page.waitForTimeout(100);
await this.page.fill('input[name="email"]', params.email);
await this.page.fill('input[name="password"]', params.password);
@@ -108,4 +119,60 @@ export class AuthPageObject {
await this.page.fill('[name="repeatPassword"]', password);
await this.page.click('[type="submit"]');
}
async loginAsSuperAdmin(params: { next?: string }) {
await this.loginAsUser({
email: 'super-admin@makerkit.dev',
next: '/auth/verify',
});
// Complete MFA verification
await this.submitMFAVerification(MFA_KEY);
await this.page.waitForURL(params.next ?? '/home');
}
async bootstrapUser({
email,
password,
name,
}: {
email: string;
password?: string;
name: string;
}) {
const client = createClient(
'http://127.0.0.1:54321',
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU',
);
const { data, error } = await client.auth.admin.createUser({
email,
password: password || 'testingpassword',
email_confirm: true,
user_metadata: {
name,
},
});
if (error) {
throw new Error(`Failed to create user: ${error.message}`);
}
return data;
}
async loginAsUser(params: {
email: string;
password?: string;
next?: string;
}) {
await this.goToSignIn(params.next);
await this.signIn({
email: params.email,
password: params.password || 'testingpassword',
});
await this.page.waitForURL(params.next ?? '**/home');
}
}

View File

@@ -29,7 +29,9 @@ test.describe('Auth flow', () => {
await auth.visitConfirmEmailLink(email);
await page.waitForURL('**/home');
await page.waitForURL('**/home', {
timeout: 5_000,
});
});
test('will sign-in with the correct credentials', async ({ page }) => {
@@ -43,7 +45,9 @@ test.describe('Auth flow', () => {
password: 'password',
});
await page.waitForURL('**/home');
await page.waitForURL('**/home', {
timeout: 5_000,
});
expect(page.url()).toContain('/home');
@@ -62,7 +66,9 @@ test.describe('Auth flow', () => {
password: 'testingpassword',
});
await page.waitForURL('/home/settings');
await page.waitForURL('/home/settings', {
timeout: 5_000,
});
await auth.signOut();
@@ -75,17 +81,14 @@ test.describe('Protected routes', () => {
page,
}) => {
const auth = new AuthPageObject(page);
const path = '/home/settings';
await page.goto('/home/settings');
await page.goto(path);
await auth.signIn({
await auth.loginAsUser({
email: 'test@makerkit.dev',
password: 'testingpassword',
next: path,
});
await page.waitForURL('/home/settings');
expect(page.url()).toContain('/home/settings');
});
test('will redirect to the sign-in page if not authenticated', async ({
@@ -115,7 +118,9 @@ test.describe('Last auth method tracking', () => {
});
await auth.visitConfirmEmailLink(testEmail);
await page.waitForURL('**/home');
await page.waitForURL('**/home', {
timeout: 5_000,
});
// Sign out
await auth.signOut();
@@ -169,7 +174,9 @@ test.describe('Last auth method tracking', () => {
password: 'password123',
});
await page.waitForURL('**/home');
await page.waitForURL('**/home', {
timeout: 5_000,
});
// Sign out and check the method is still tracked
await auth.signOut();

View File

@@ -13,22 +13,12 @@ test.describe('Password Reset Flow', () => {
await expect(async () => {
email = auth.createRandomEmail();
await page.goto('/auth/sign-up');
await auth.signUp({
auth.bootstrapUser({
email,
password: 'password',
repeatPassword: 'password',
name: 'Test User',
});
await auth.visitConfirmEmailLink(email, {
deleteAfter: true,
subject: 'Confirm your email',
});
await page.context().clearCookies();
await page.reload();
await page.goto('/auth/password-reset');
await page.fill('[name="email"]', email);
@@ -59,13 +49,10 @@ test.describe('Password Reset Flow', () => {
await page.waitForURL('/');
await page.goto('/auth/sign-in');
await auth.signIn({
await auth.loginAsUser({
email,
password: newPassword,
});
await page.waitForURL('/home', {
timeout: 2000,
next: '/home',
});
});
});