feat: simplify testing structure into api and e2e categories

This commit is contained in:
bipproduction
2026-02-08 11:01:55 +08:00
parent 4640b72ca6
commit 0f71798389
18 changed files with 1006 additions and 62 deletions

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import api from "../src/api";
import { describe, expect, it } from "bun:test";
import api from "@/api";
describe("API Integration", () => {
it("should return 200 for health check", async () => {
@@ -27,4 +27,15 @@ describe("API Integration", () => {
// 401 is intended, 422 is returned by Elysia when the error response doesn't match the schema
expect([401, 422]).toContain(response.status);
});
});
it("should return 401 for profile update without auth", async () => {
const response = await api.handle(
new Request("http://localhost/api/profile/update", {
method: "POST",
body: JSON.stringify({ name: "New Name" }),
headers: { "Content-Type": "application/json" },
}),
);
expect([401, 422]).toContain(response.status);
});
});

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { prisma } from "../src/utils/db";
import { describe, expect, it } from "bun:test";
import { prisma } from "@/utils/db";
describe("Database Integration", () => {
it("should connect to the database and query users", async () => {
@@ -20,4 +20,4 @@ describe("Database Integration", () => {
expect(user.email).toBe(adminEmail);
}
});
});
});

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { getEnv } from "../src/utils/env";
import { describe, expect, it } from "bun:test";
import { getEnv } from "@/utils/env";
describe("Feature Utilities", () => {
describe("getEnv Utility", () => {
@@ -10,13 +10,14 @@ describe("Feature Utilities", () => {
it("should return value from process.env if available", () => {
// Mock process.env
const originalEnv = process.env;
process.env = { ...originalEnv, TEST_ENV_KEY: "test-value" };
const originalEnv = { ...process.env };
process.env.TEST_ENV_KEY = "test-value";
const val = getEnv("TEST_ENV_KEY");
expect(val).toBe("test-value");
process.env = originalEnv;
// Clean up
delete process.env.TEST_ENV_KEY;
});
});
});
});

View File

@@ -0,0 +1,113 @@
import { test, expect } from '@playwright/test';
test.describe('API Key Management', () => {
test.beforeEach(async ({ page }) => {
// Mock the session API to simulate being logged in as an admin
await page.route('**/api/session', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
data: {
user: {
id: 'user_123',
name: 'Test User',
email: 'test@example.com',
role: 'admin'
}
}
}),
});
});
// Mock the initial empty API keys list
await page.route('**/api/apikey/', async (route) => {
if (route.request().method() === 'GET') {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ apiKeys: [] }),
});
} else {
await route.continue();
}
});
});
test('should create, update, and delete an API key', async ({ page }) => {
// Go to the API Keys page
await page.goto('/dashboard/apikey');
// 1. CREATE
await page.click('button:has-text("Create New API Key")');
await page.fill('input[placeholder="Enter a descriptive name for your API key"]', 'My Test Key');
// Mock the creation response
await page.route('**/api/apikey/', async (route) => {
if (route.request().method() === 'POST') {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
apiKey: {
id: 'key_1',
name: 'My Test Key',
key: 'sk-test-key-12345',
isActive: true,
expiresAt: null,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
}
}),
});
}
});
await page.click('button:has-text("Create API Key")');
// Verify it appeared in the table
const table = page.locator('table').first();
await expect(table).toContainText('My Test Key');
await expect(table).toContainText('••••••••');
// 2. UPDATE (Toggle status)
// Mock the update response
await page.route('**/api/apikey/update', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
apiKey: {
id: 'key_1',
name: 'My Test Key',
key: 'sk-test-key-12345',
isActive: false,
expiresAt: null,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
}
}),
});
});
// Find and click the switch (Mantine Switch is usually an input type=checkbox)
await page.click('input[type="checkbox"]', { force: true });
// 3. DELETE
// Mock the delete response
await page.route('**/api/apikey/delete', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ success: true }),
});
});
await page.click('button:has(svg.tabler-icon-trash)');
await page.click('button:has-text("Delete API Key")');
// Verify it's gone
await expect(table).not.toContainText('My Test Key');
await expect(page.locator('text=No API keys created yet')).toBeVisible();
});
});

View File

@@ -0,0 +1,26 @@
import { test, expect } from '@playwright/test';
test.describe('Login Flow', () => {
test('should see signin page content', async ({ page }) => {
// Go to the signin page
await page.goto('/signin');
// Check if the signin page content is visible
await expect(page.locator('h1')).toContainText('Welcome back!');
await expect(page.locator('button:has-text("Sign in")')).toBeVisible();
await expect(page.locator('button:has-text("Continue with GitHub")')).toBeVisible();
});
test('should redirect to signin if not authenticated', async ({ page }) => {
// Clear cookies/storage to ensure we are not authenticated
await page.goto('/signin');
await page.context().clearCookies();
await page.evaluate(() => localStorage.clear());
// Try to access the profile page (which is protected)
await page.goto('/profile');
// Should be redirected back to signin
await expect(page).toHaveURL(/\/signin/);
});
});

View File

@@ -0,0 +1,27 @@
import { test, expect } from '@playwright/test';
test.describe('Signup Flow', () => {
test('should see signup page content', async ({ page }) => {
// Go to the signup page
await page.goto('/signup');
// Check if the signup page content is visible
await expect(page.locator('h1')).toContainText('Create an account');
await expect(page.locator('button:has-text("Create account")')).toBeVisible();
// Check for form fields
await expect(page.getByPlaceholder('Your name')).toBeVisible();
await expect(page.getByPlaceholder('your@email.com')).toBeVisible();
await expect(page.getByPlaceholder('Your password')).toBeVisible();
});
test('should navigate to signin page from signup', async ({ page }) => {
await page.goto('/signup');
// Click on "Sign in" link
await page.click('button:has-text("Sign in")');
// Should be redirected to signin
await expect(page).toHaveURL(/\/signin/);
});
});