Next.js Supabase V3 (#463)
Version 3 of the kit: - Radix UI replaced with Base UI (using the Shadcn UI patterns) - next-intl replaces react-i18next - enhanceAction deprecated; usage moved to next-safe-action - main layout now wrapped with [locale] path segment - Teams only mode - Layout updates - Zod v4 - Next.js 16.2 - Typescript 6 - All other dependencies updated - Removed deprecated Edge CSRF - Dynamic Github Action runner
This commit is contained in:
committed by
GitHub
parent
4912e402a3
commit
7ebff31475
@@ -38,10 +38,12 @@ test.describe('Account Settings', () => {
|
||||
|
||||
await Promise.all([request, response]);
|
||||
|
||||
await page.locator('[data-test="workspace-dropdown-trigger"]').click();
|
||||
|
||||
await expect(account.getProfileName()).toHaveText(name);
|
||||
});
|
||||
|
||||
test('user can update their email', async ({ page }) => {
|
||||
test('user can update their email', async () => {
|
||||
const email = account.auth.createRandomEmail();
|
||||
|
||||
await account.updateEmail(email);
|
||||
|
||||
@@ -34,17 +34,17 @@ test.describe('Admin', () => {
|
||||
await page.goto('/admin');
|
||||
|
||||
// Check all stat cards are present
|
||||
await expect(page.getByRole('heading', { name: 'Users' })).toBeVisible();
|
||||
await expect(page.getByText('Users', { exact: true })).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.getByRole('heading', { name: 'Team Accounts' }),
|
||||
page.getByText('Team Accounts', { exact: true }),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.getByRole('heading', { name: 'Paying Customers' }),
|
||||
page.getByText('Paying Customers', { exact: true }),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(page.getByRole('heading', { name: 'Trials' })).toBeVisible();
|
||||
await expect(page.getByText('Trials', { exact: true })).toBeVisible();
|
||||
|
||||
// Verify stat values are numbers
|
||||
const stats = await page.$$('.text-3xl.font-bold');
|
||||
@@ -351,5 +351,5 @@ async function selectAccount(page: Page, email: string) {
|
||||
|
||||
await link.click();
|
||||
|
||||
await page.waitForURL(/\/admin\/accounts\/[^\/]+/);
|
||||
await page.waitForURL(/\/admin\/accounts\/[^/]+/);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { test } from '@playwright/test';
|
||||
import { join } from 'node:path';
|
||||
import { cwd } from 'node:process';
|
||||
|
||||
import { AuthPageObject } from './authentication/auth.po';
|
||||
|
||||
import { join } from 'node:path';
|
||||
import { cwd } from 'node:process';
|
||||
|
||||
const testAuthFile = join(cwd(), '.auth/test@makerkit.dev.json');
|
||||
const ownerAuthFile = join(cwd(), '.auth/owner@makerkit.dev.json');
|
||||
const superAdminAuthFile = join(cwd(), '.auth/super-admin@makerkit.dev.json');
|
||||
|
||||
@@ -31,8 +31,17 @@ export class AuthPageObject {
|
||||
}
|
||||
|
||||
async signOut() {
|
||||
await this.page.click('[data-test="account-dropdown-trigger"]');
|
||||
await this.page.click('[data-test="account-dropdown-sign-out"]');
|
||||
const trigger = this.page.locator(
|
||||
'[data-test="workspace-dropdown-trigger"], [data-test="account-dropdown-trigger"]',
|
||||
);
|
||||
|
||||
await trigger.click();
|
||||
|
||||
const signOutButton = this.page.locator(
|
||||
'[data-test="workspace-sign-out"], [data-test="account-dropdown-sign-out"]',
|
||||
);
|
||||
|
||||
await signOutButton.click();
|
||||
}
|
||||
|
||||
async signIn(params: { email: string; password: string }) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { expect, test } from '@playwright/test';
|
||||
|
||||
test.describe('Healthcheck endpoint', () => {
|
||||
test('returns healthy status', async ({ request }) => {
|
||||
const response = await request.get('/healthcheck');
|
||||
const response = await request.get('/api/healthcheck');
|
||||
|
||||
expect(response.status()).toBe(200);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ export class InvitationsPageObject {
|
||||
`[data-test="invite-member-form-item"]:nth-child(${nth}) [data-test="role-selector-trigger"]`,
|
||||
);
|
||||
|
||||
await this.page.click(`[data-test="role-option-${invite.role}"]`);
|
||||
await this.page.getByRole('option', { name: invite.role }).click();
|
||||
|
||||
if (index < invites.length - 1) {
|
||||
await form.locator('[data-test="add-new-invite-button"]').click();
|
||||
|
||||
@@ -36,13 +36,13 @@ export class TeamAccountsPageObject {
|
||||
}
|
||||
|
||||
getTeamFromSelector(teamName: string) {
|
||||
return this.page.locator(`[data-test="account-selector-team"]`, {
|
||||
return this.page.locator('[data-test="workspace-team-item"]', {
|
||||
hasText: teamName,
|
||||
});
|
||||
}
|
||||
|
||||
getTeams() {
|
||||
return this.page.locator('[data-test="account-selector-team"]');
|
||||
return this.page.locator('[data-test="workspace-team-item"]');
|
||||
}
|
||||
|
||||
goToSettings() {
|
||||
@@ -83,10 +83,11 @@ export class TeamAccountsPageObject {
|
||||
|
||||
openAccountsSelector() {
|
||||
return expect(async () => {
|
||||
await this.page.click('[data-test="account-selector-trigger"]');
|
||||
await this.page.click('[data-test="workspace-dropdown-trigger"]');
|
||||
await this.page.click('[data-test="workspace-switch-submenu"]');
|
||||
|
||||
return expect(
|
||||
this.page.locator('[data-test="account-selector-content"]'),
|
||||
this.page.locator('[data-test="workspace-switch-content"]'),
|
||||
).toBeVisible();
|
||||
}).toPass();
|
||||
}
|
||||
@@ -115,7 +116,7 @@ export class TeamAccountsPageObject {
|
||||
async createTeam({ teamName, slug } = this.createTeamName()) {
|
||||
await this.openAccountsSelector();
|
||||
|
||||
await this.page.click('[data-test="create-team-account-trigger"]');
|
||||
await this.page.click('[data-test="create-team-trigger"]');
|
||||
|
||||
await this.page.fill(
|
||||
'[data-test="create-team-form"] [data-test="team-name-input"]',
|
||||
@@ -140,14 +141,13 @@ export class TeamAccountsPageObject {
|
||||
await this.openAccountsSelector();
|
||||
await expect(this.getTeamFromSelector(teamName)).toBeVisible();
|
||||
|
||||
// Close the selector
|
||||
await this.page.keyboard.press('Escape');
|
||||
await this.closeAccountsSelector();
|
||||
}
|
||||
|
||||
async createTeamWithNonLatinName(teamName: string, slug: string) {
|
||||
await this.openAccountsSelector();
|
||||
|
||||
await this.page.click('[data-test="create-team-account-trigger"]');
|
||||
await this.page.click('[data-test="create-team-trigger"]');
|
||||
|
||||
await this.page.fill(
|
||||
'[data-test="create-team-form"] [data-test="team-name-input"]',
|
||||
@@ -177,8 +177,15 @@ export class TeamAccountsPageObject {
|
||||
await this.openAccountsSelector();
|
||||
await expect(this.getTeamFromSelector(teamName)).toBeVisible();
|
||||
|
||||
// Close the selector
|
||||
await this.page.keyboard.press('Escape');
|
||||
await this.closeAccountsSelector();
|
||||
}
|
||||
|
||||
async closeAccountsSelector() {
|
||||
await this.page.locator('body').click({ position: { x: 0, y: 0 } });
|
||||
|
||||
await expect(
|
||||
this.page.locator('[data-test="workspace-switch-content"]'),
|
||||
).toBeHidden();
|
||||
}
|
||||
|
||||
getSlugField() {
|
||||
@@ -207,11 +214,10 @@ export class TeamAccountsPageObject {
|
||||
}
|
||||
|
||||
async deleteAccount(email: string) {
|
||||
await this.page.click('[data-test="delete-team-trigger"]');
|
||||
await this.otp.completeOtpVerification(email);
|
||||
|
||||
await expect(async () => {
|
||||
await this.page.click('[data-test="delete-team-trigger"]');
|
||||
|
||||
await this.otp.completeOtpVerification(email);
|
||||
|
||||
const click = this.page.click(
|
||||
'[data-test="delete-team-form-confirm-button"]',
|
||||
);
|
||||
|
||||
@@ -88,7 +88,7 @@ test.describe('Team Accounts', () => {
|
||||
await teamAccounts.createTeam();
|
||||
|
||||
await teamAccounts.openAccountsSelector();
|
||||
await page.click('[data-test="create-team-account-trigger"]');
|
||||
await page.click('[data-test="create-team-trigger"]');
|
||||
|
||||
await teamAccounts.tryCreateTeam('billing');
|
||||
|
||||
@@ -202,7 +202,7 @@ test.describe('Team Accounts', () => {
|
||||
|
||||
// Use non-Latin name to trigger the slug field visibility
|
||||
await teamAccounts.openAccountsSelector();
|
||||
await page.click('[data-test="create-team-account-trigger"]');
|
||||
await page.click('[data-test="create-team-trigger"]');
|
||||
|
||||
await page.fill(
|
||||
'[data-test="create-team-form"] [data-test="team-name-input"]',
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { AuthPageObject } from '../authentication/auth.po';
|
||||
import { TeamBillingPageObject } from './team-billing.po';
|
||||
|
||||
test.describe('Team Billing', () => {
|
||||
|
||||
@@ -38,9 +38,9 @@ export class BillingPageObject {
|
||||
// wait a bit for the webhook to be processed
|
||||
await this.page.waitForTimeout(1000);
|
||||
|
||||
return this.page
|
||||
.locator('[data-test="checkout-success-back-link"]')
|
||||
.click();
|
||||
await this.page.locator('[data-test="checkout-success-back-link"]').click();
|
||||
|
||||
await this.page.waitForURL('**/billing');
|
||||
}
|
||||
|
||||
proceedToCheckout() {
|
||||
|
||||
Reference in New Issue
Block a user