test: add integration tests for configuration API and database operations

This commit is contained in:
张翔
2026-03-13 15:18:46 +08:00
parent 490a2172b8
commit 72745456d2
3 changed files with 566 additions and 0 deletions
@@ -0,0 +1,224 @@
import { test, expect } from '@playwright/test';
test.describe('配置API端点测试', () => {
test('GET /api/admin/config - 获取所有配置', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const response = await request.get('/api/admin/config');
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.success).toBe(true);
expect(body.configs).toBeDefined();
expect(Array.isArray(body.configs)).toBe(true);
});
test('GET /api/admin/config?category=feature - 按分类过滤', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const response = await request.get('/api/admin/config?category=feature');
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.success).toBe(true);
expect(body.configs).toBeDefined();
expect(Array.isArray(body.configs)).toBe(true);
body.configs.forEach(config => {
expect(config.category).toBe('feature');
});
});
test('GET /api/admin/config?key=xxx - 按key获取单个配置', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const response = await request.get('/api/admin/config?key=feature_services');
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.success).toBe(true);
expect(body.configs).toBeDefined();
expect(Array.isArray(body.configs)).toBe(true);
expect(body.configs.length).toBe(1);
expect(body.configs[0].key).toBe('feature_services');
});
test('POST /api/admin/config - 创建新配置', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const newConfig = {
key: 'test_config_' + Date.now(),
value: { enabled: true, testValue: 'test' },
category: 'feature',
description: '测试配置'
};
const response = await request.post('/api/admin/config', {
data: newConfig
});
expect(response.status()).toBe(201);
const body = await response.json();
expect(body.success).toBe(true);
expect(body.configs).toBeDefined();
expect(body.configs.length).toBe(1);
expect(body.configs[0].key).toBe(newConfig.key);
expect(body.configs[0].value).toEqual(newConfig.value);
});
test('POST /api/admin/config - 缺少必要字段', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const invalidConfig = {
key: 'test_config',
value: { enabled: true }
};
const response = await request.post('/api/admin/config', {
data: invalidConfig
});
expect(response.status()).toBe(400);
const body = await response.json();
expect(body.success).toBe(false);
expect(body.error).toBeDefined();
});
test('PUT /api/admin/config - 批量更新配置', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const updates = [
{ key: 'feature_services', value: { enabled: false } },
{ key: 'feature_products', value: { enabled: true } }
];
const response = await request.put('/api/admin/config', {
data: { configs: updates }
});
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.success).toBe(true);
expect(body.configs).toBeDefined();
expect(Array.isArray(body.configs)).toBe(true);
expect(body.configs.length).toBe(2);
});
test('PUT /api/admin/config - 无效的数据格式', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const invalidData = {
configs: 'not an array'
};
const response = await request.put('/api/admin/config', {
data: invalidData
});
expect(response.status()).toBe(400);
const body = await response.json();
expect(body.success).toBe(false);
expect(body.error).toBeDefined();
});
test('DELETE /api/admin/config?key=xxx - 删除配置', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const response = await request.delete('/api/admin/config?key=feature_services');
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.success).toBe(true);
expect(body.data).toBeDefined();
expect(body.data.success).toBe(true);
});
test('DELETE /api/admin/config - 缺少key参数', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const response = await request.delete('/api/admin/config');
expect(response.status()).toBe(400);
const body = await response.json();
expect(body.success).toBe(false);
expect(body.error).toBeDefined();
});
test('GET /api/config - 公开配置API', async ({ request }) => {
const response = await request.get('/api/config');
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.success).toBe(true);
expect(body.data).toBeDefined();
expect(typeof body.data).toBe('object');
});
test('API响应格式验证 - success响应', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const response = await request.get('/api/admin/config');
expect(response.status()).toBe(200);
const body = await response.json();
expect(body).toHaveProperty('success');
expect(body).toHaveProperty('configs');
expect(body.success).toBe(true);
});
test('API响应格式验证 - error响应', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const response = await request.delete('/api/admin/config');
expect(response.status()).toBe(400);
const body = await response.json();
expect(body).toHaveProperty('success');
expect(body).toHaveProperty('error');
expect(body.success).toBe(false);
});
});
@@ -0,0 +1,215 @@
import { test, expect } from '@playwright/test';
test.describe('配置数据库操作测试', () => {
test('创建配置 - 数据库插入', async ({ page, context }) => {
const adminPage = await context.newPage();
await adminPage.goto('/admin/login');
await adminPage.fill('input[type="email"]', 'admin@novalon.cn');
await adminPage.fill('input[type="password"]', 'admin123456');
await adminPage.click('button[type="submit"]');
await adminPage.waitForURL('/admin');
await adminPage.goto('/admin/settings');
await adminPage.waitForLoadState('networkidle');
const servicesConfig = adminPage.locator('text=功能配置').locator('..').locator('..');
const textarea = servicesConfig.locator('textarea').first();
await textarea.fill('test_service');
await servicesConfig.locator('button:has-text("保存")').click();
await adminPage.waitForSelector('text=保存成功', { timeout: 5000 });
await page.goto('/');
await page.waitForLoadState('networkidle');
const serviceCards = page.locator('#services .card');
const count = await serviceCards.count();
expect(count).toBeGreaterThan(0);
await adminPage.goto('/admin/settings');
await adminPage.waitForLoadState('networkidle');
const configExists = adminPage.locator('textarea').first();
expect(configExists).toBeVisible();
});
test('更新配置 - 数据库更新', async ({ page, context }) => {
const adminPage = await context.newPage();
await adminPage.goto('/admin/login');
await adminPage.fill('input[type="email"]', 'admin@novalon.cn');
await adminPage.fill('input[type="password"]', 'admin123456');
await adminPage.click('button[type="submit"]');
await adminPage.waitForURL('/admin');
await adminPage.goto('/admin/settings');
await adminPage.waitForLoadState('networkidle');
const newsConfig = adminPage.locator('text=功能配置').locator('..').locator('..');
const displayCountInput = newsConfig.locator('input[type="number"]').nth(1);
await displayCountInput.fill('5');
await newsConfig.locator('button:has-text("保存")').click();
await adminPage.waitForSelector('text=保存成功', { timeout: 5000 });
await page.goto('/');
await page.waitForLoadState('networkidle');
const newsCards = page.locator('#news .card');
const count = await newsCards.count();
expect(count).toBe(5);
await adminPage.goto('/admin/settings');
await adminPage.waitForLoadState('networkidle');
await displayCountInput.fill('10');
await newsConfig.locator('button:has-text("保存")').click();
await adminPage.waitForSelector('text=保存成功', { timeout: 5000 });
await page.goto('/');
await page.waitForLoadState('networkidle');
const newCount = await newsCards.count();
expect(newCount).toBe(10);
});
test('删除配置 - 数据库删除', async ({ page, context }) => {
const adminPage = await context.newPage();
await adminPage.goto('/admin/login');
await adminPage.fill('input[type="email"]', 'admin@novalon.cn');
await adminPage.fill('input[type="password"]', 'admin123456');
await adminPage.click('button[type="submit"]');
await adminPage.waitForURL('/admin');
await adminPage.goto('/admin/settings');
await adminPage.waitForLoadState('networkidle');
const productsConfig = adminPage.locator('text=功能配置').locator('..').locator('..');
const productsCheckbox = productsConfig.locator('input[type="checkbox"]').nth(1);
await productsCheckbox.check();
await productsConfig.locator('button:has-text("保存")').click();
await adminPage.waitForSelector('text=保存成功', { timeout: 5000 });
await page.goto('/');
await page.waitForLoadState('networkidle');
await expect(page.locator('#products')).toBeVisible();
await adminPage.goto('/admin/settings');
await adminPage.waitForLoadState('networkidle');
await productsCheckbox.uncheck();
await productsConfig.locator('button:has-text("保存")').click();
await adminPage.waitForSelector('text=保存成功', { timeout: 5000 });
await page.goto('/');
await page.waitForLoadState('networkidle');
await expect(page.locator('#products')).not.toBeVisible();
});
test('批量更新配置 - 数据库事务', async ({ page, context }) => {
const adminPage = await context.newPage();
await adminPage.goto('/admin/login');
await adminPage.fill('input[type="email"]', 'admin@novalon.cn');
await adminPage.fill('input[type="password"]', 'admin123456');
await adminPage.click('button[type="submit"]');
await adminPage.waitForURL('/admin');
await adminPage.goto('/admin/settings');
await adminPage.waitForLoadState('networkidle');
const featureConfig = adminPage.locator('text=功能配置').locator('..').locator('..');
const checkboxes = featureConfig.locator('input[type="checkbox"]');
const initialServicesState = await checkboxes.nth(0).isChecked();
const initialProductsState = await checkboxes.nth(1).isChecked();
const initialNewsState = await checkboxes.nth(2).isChecked();
await checkboxes.nth(0).setChecked(!initialServicesState);
await checkboxes.nth(1).setChecked(!initialProductsState);
await checkboxes.nth(2).setChecked(!initialNewsState);
await featureConfig.locator('button:has-text("保存")').click();
await adminPage.waitForSelector('text=保存成功', { timeout: 10000 });
await page.goto('/');
await page.waitForLoadState('networkidle');
const finalServicesVisible = await page.locator('#services').isVisible();
const finalProductsVisible = await page.locator('#products').isVisible();
const finalNewsVisible = await page.locator('#news').isVisible();
expect(finalServicesVisible).toBe(!initialServicesState);
expect(finalProductsVisible).toBe(!initialProductsState);
expect(finalNewsVisible).toBe(!initialNewsState);
});
test('配置数据完整性 - updatedAt字段更新', async ({ page, context }) => {
const adminPage = await context.newPage();
await adminPage.goto('/admin/login');
await adminPage.fill('input[type="email"]', 'admin@novalon.cn');
await adminPage.fill('input[type="password"]', 'admin123456');
await adminPage.click('button[type="submit"]');
await adminPage.waitForURL('/admin');
await adminPage.goto('/admin/settings');
await adminPage.waitForLoadState('networkidle');
const featureConfig = adminPage.locator('text=功能配置').locator('..').locator('..');
const checkbox = featureConfig.locator('input[type="checkbox"]').first();
await checkbox.check();
await featureConfig.locator('button:has-text("保存")').click();
await adminPage.waitForSelector('text=保存成功', { timeout: 5000 });
await adminPage.waitForTimeout(2000);
await checkbox.uncheck();
await featureConfig.locator('button:has-text("保存")').click();
await adminPage.waitForSelector('text=保存成功', { timeout: 5000 });
await page.goto('/');
await page.waitForLoadState('networkidle');
await expect(page.locator('#services')).not.toBeVisible();
});
test('配置查询 - 按分类过滤', async ({ page }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
await page.goto('/admin/settings');
await page.waitForLoadState('networkidle');
const featureConfig = page.locator('text=功能配置').locator('..').locator('..');
await expect(featureConfig).toBeVisible();
const featureCount = await featureConfig.locator('input[type="checkbox"]').count();
expect(featureCount).toBeGreaterThan(0);
});
test('配置查询 - 按key精确查找', async ({ page }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
await page.goto('/admin/settings');
await page.waitForLoadState('networkidle');
const featureConfig = page.locator('text=功能配置').locator('..').locator('..');
await expect(featureConfig).toBeVisible();
const checkboxes = featureConfig.locator('input[type="checkbox"]');
const count = await checkboxes.count();
expect(count).toBeGreaterThan(0);
});
});
@@ -0,0 +1,127 @@
import { test, expect } from '@playwright/test';
test.describe('配置权限验证测试', () => {
test('未登录访问配置API - GET请求', async ({ request }) => {
const response = await request.get('/api/admin/config');
expect(response.status()).toBe(403);
const body = await response.json();
expect(body.success).toBe(false);
expect(body.error).toBeDefined();
});
test('未登录访问配置API - POST请求', async ({ request }) => {
const newConfig = {
key: 'test_config',
value: { enabled: true },
category: 'feature'
};
const response = await request.post('/api/admin/config', {
data: newConfig
});
expect(response.status()).toBe(403);
const body = await response.json();
expect(body.success).toBe(false);
expect(body.error).toBeDefined();
});
test('未登录访问配置API - PUT请求', async ({ request }) => {
const updates = [
{ key: 'feature_services', value: { enabled: false } }
];
const response = await request.put('/api/admin/config', {
data: { configs: updates }
});
expect(response.status()).toBe(403);
const body = await response.json();
expect(body.success).toBe(false);
expect(body.error).toBeDefined();
});
test('未登录访问配置API - DELETE请求', async ({ request }) => {
const response = await request.delete('/api/admin/config?key=feature_services');
expect(response.status()).toBe(403);
const body = await response.json();
expect(body.success).toBe(false);
expect(body.error).toBeDefined();
});
test('管理员访问配置API - GET请求成功', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const response = await request.get('/api/admin/config');
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.success).toBe(true);
expect(body.configs).toBeDefined();
});
test('管理员访问配置API - POST请求成功', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const newConfig = {
key: 'test_config_' + Date.now(),
value: { enabled: true },
category: 'feature'
};
const response = await request.post('/api/admin/config', {
data: newConfig
});
expect(response.status()).toBe(201);
const body = await response.json();
expect(body.success).toBe(true);
expect(body.configs).toBeDefined();
});
test('管理员访问配置API - PUT请求成功', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const updates = [
{ key: 'feature_services', value: { enabled: false } }
];
const response = await request.put('/api/admin/config', {
data: { configs: updates }
});
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.success).toBe(true);
expect(body.configs).toBeDefined();
});
test('管理员访问配置API - DELETE请求成功', async ({ page, request }) => {
await page.goto('/admin/login');
await page.fill('input[type="email"]', 'admin@novalon.cn');
await page.fill('input[type="password"]', 'admin123456');
await page.click('button[type="submit"]');
await page.waitForURL('/admin');
const response = await request.delete('/api/admin/config?key=feature_services');
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.success).toBe(true);
expect(body.data).toBeDefined();
});
});