08ea5fbe98
添加用户管理视图、API和状态管理文件
353 lines
11 KiB
TypeScript
353 lines
11 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('Web平台兼容性测试', () => {
|
|
let baseUrl: string;
|
|
|
|
test.beforeAll(async () => {
|
|
baseUrl = 'http://localhost:8081';
|
|
});
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto(baseUrl);
|
|
await page.waitForLoadState('networkidle');
|
|
});
|
|
|
|
test.describe('TC-001: 页面加载测试', () => {
|
|
test('应该能够加载页面', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const pageTitle = await page.title();
|
|
expect(pageTitle).toBeTruthy();
|
|
|
|
const bodyContent = await page.evaluate(() => document.body.innerText);
|
|
expect(bodyContent.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
test('页面应该正常显示', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const isPageVisible = await page.evaluate(() => {
|
|
return document.visibilityState === 'visible';
|
|
});
|
|
|
|
expect(isPageVisible).toBe(true);
|
|
});
|
|
|
|
test('页面加载时不应该有错误提示', async ({ page }) => {
|
|
const errors: string[] = [];
|
|
|
|
page.on('console', (msg) => {
|
|
if (msg.type() === 'error') {
|
|
errors.push(msg.text());
|
|
}
|
|
});
|
|
|
|
await page.waitForLoadState('networkidle');
|
|
await page.waitForTimeout(1500);
|
|
|
|
const criticalErrors = errors.filter(e =>
|
|
e.includes('TypeError') ||
|
|
e.includes('ReferenceError') ||
|
|
e.includes('SyntaxError')
|
|
);
|
|
|
|
expect(criticalErrors.length).toBeLessThan(3);
|
|
});
|
|
});
|
|
|
|
test.describe('TC-002: CSS变量测试', () => {
|
|
test('CSS变量应该正确设置', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
await page.waitForTimeout(1000);
|
|
|
|
const cssVars = await page.evaluate(() => {
|
|
const root = document.documentElement;
|
|
const style = getComputedStyle(root);
|
|
const properties = Array.from(style).filter(prop =>
|
|
prop.includes('--') || prop.includes('theme')
|
|
);
|
|
return properties.length;
|
|
});
|
|
|
|
expect(cssVars).toBeGreaterThan(0);
|
|
});
|
|
|
|
test('CSS变量应该能够被继承和覆盖', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
await page.waitForTimeout(1000);
|
|
|
|
const rootHasVars = await page.evaluate(() => {
|
|
const root = document.documentElement;
|
|
const style = getComputedStyle(root);
|
|
const properties = Array.from(style).filter(prop =>
|
|
prop.includes('--') || prop.includes('theme')
|
|
);
|
|
return properties.length > 0;
|
|
});
|
|
|
|
const bodyHasVars = await page.evaluate(() => {
|
|
const body = document.body;
|
|
const style = getComputedStyle(body);
|
|
const properties = Array.from(style).filter(prop =>
|
|
prop.includes('--') || prop.includes('theme')
|
|
);
|
|
return properties.length > 0;
|
|
});
|
|
|
|
expect(rootHasVars).toBe(true);
|
|
expect(bodyHasVars).toBe(true);
|
|
});
|
|
});
|
|
|
|
test.describe('TC-003: 字体系统测试', () => {
|
|
test('字体应该正确加载', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const fontsLoaded = await page.evaluate(() => {
|
|
return document.fonts.ready.then(() => {
|
|
return document.fonts.size > 0;
|
|
});
|
|
});
|
|
|
|
expect(fontsLoaded).toBe(true);
|
|
});
|
|
|
|
test('字体大小应该正确应用', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const fontSize = await page.evaluate(() => {
|
|
const body = document.body;
|
|
const style = getComputedStyle(body);
|
|
return style.fontSize;
|
|
});
|
|
|
|
expect(fontSize).toBeTruthy();
|
|
expect(fontSize).not.toBe('0px');
|
|
});
|
|
|
|
test('字体粗细应该正确应用', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const fontWeight = await page.evaluate(() => {
|
|
const body = document.body;
|
|
const style = getComputedStyle(body);
|
|
return style.fontWeight;
|
|
});
|
|
|
|
expect(fontWeight).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
test.describe('TC-004: SVG纹样测试', () => {
|
|
test('SVG纹样应该正确显示', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const svgElements = await page.evaluate(() => {
|
|
const svgs = document.querySelectorAll('svg');
|
|
return svgs.length;
|
|
});
|
|
|
|
expect(svgElements).toBeGreaterThanOrEqual(0);
|
|
});
|
|
|
|
test('SVG纹样应该能够缩放', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const svgElements = await page.evaluate(() => {
|
|
const svgs = document.querySelectorAll('svg');
|
|
return Array.from(svgs).map(svg => {
|
|
const style = getComputedStyle(svg);
|
|
return {
|
|
width: style.width,
|
|
height: style.height
|
|
};
|
|
});
|
|
});
|
|
|
|
expect(svgElements.length).toBeGreaterThanOrEqual(0);
|
|
});
|
|
|
|
test('SVG纹样应该能够应用颜色', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const svgElements = await page.evaluate(() => {
|
|
const svgs = document.querySelectorAll('svg');
|
|
return Array.from(svgs).map(svg => {
|
|
const style = getComputedStyle(svg);
|
|
return style.fill;
|
|
});
|
|
});
|
|
|
|
expect(svgElements.length).toBeGreaterThanOrEqual(0);
|
|
});
|
|
});
|
|
|
|
test.describe('TC-005: 动画效果测试', () => {
|
|
test('动画应该正常播放', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const animatedElements = await page.evaluate(() => {
|
|
const elements = document.querySelectorAll('*');
|
|
return Array.from(elements).filter(el => {
|
|
const style = getComputedStyle(el);
|
|
return style.animationName !== 'none' ||
|
|
style.transitionProperty !== 'none';
|
|
}).length;
|
|
});
|
|
|
|
expect(animatedElements).toBeGreaterThanOrEqual(0);
|
|
});
|
|
|
|
test('动画应该流畅无卡顿', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const startTime = Date.now();
|
|
await page.evaluate(() => {
|
|
return new Promise(resolve => setTimeout(resolve, 1000));
|
|
});
|
|
const endTime = Date.now();
|
|
|
|
expect(endTime - startTime).toBeLessThan(2000);
|
|
});
|
|
|
|
test('动画性能应该良好', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const performanceMetrics = await page.evaluate(() => {
|
|
if (window.performance && window.performance.memory) {
|
|
return {
|
|
usedJSHeapSize: window.performance.memory.usedJSHeapSize,
|
|
totalJSHeapSize: window.performance.memory.totalJSHeapSize
|
|
};
|
|
}
|
|
return null;
|
|
});
|
|
|
|
expect(performanceMetrics).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
test.describe('TC-006: 组件样式测试', () => {
|
|
test('日历组件样式应该正确应用', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const calendarElements = await page.evaluate(() => {
|
|
const elements = document.querySelectorAll('[class*="calendar"], [class*="Calendar"]');
|
|
return elements.length;
|
|
});
|
|
|
|
expect(calendarElements).toBeGreaterThanOrEqual(0);
|
|
});
|
|
|
|
test('导航组件样式应该正确应用', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const navElements = await page.evaluate(() => {
|
|
const elements = document.querySelectorAll('[class*="nav"], [class*="Nav"]');
|
|
return elements.length;
|
|
});
|
|
|
|
expect(navElements).toBeGreaterThanOrEqual(0);
|
|
});
|
|
|
|
test('卡片组件样式应该正确应用', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const cardElements = await page.evaluate(() => {
|
|
const elements = document.querySelectorAll('[class*="card"], [class*="Card"]');
|
|
return elements.length;
|
|
});
|
|
|
|
expect(cardElements).toBeGreaterThanOrEqual(0);
|
|
});
|
|
});
|
|
|
|
test.describe('TC-007: 页面样式测试', () => {
|
|
test('日历页面样式应该正确应用', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const pageContent = await page.evaluate(() => {
|
|
const body = document.body;
|
|
const style = getComputedStyle(body);
|
|
return {
|
|
backgroundColor: style.backgroundColor,
|
|
color: style.color
|
|
};
|
|
});
|
|
|
|
expect(pageContent.backgroundColor).toBeTruthy();
|
|
expect(pageContent.color).toBeTruthy();
|
|
});
|
|
|
|
test('页面布局应该正常', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const pageLayout = await page.evaluate(() => {
|
|
const body = document.body;
|
|
const style = getComputedStyle(body);
|
|
return {
|
|
width: style.width,
|
|
height: style.height,
|
|
display: style.display
|
|
};
|
|
});
|
|
|
|
expect(pageLayout.width).toBeTruthy();
|
|
expect(pageLayout.height).toBeTruthy();
|
|
});
|
|
|
|
test('页面响应式应该正常', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
await page.setViewportSize({ width: 375, height: 667 });
|
|
await page.waitForTimeout(500);
|
|
|
|
const mobileLayout = await page.evaluate(() => {
|
|
const body = document.body;
|
|
const style = getComputedStyle(body);
|
|
return {
|
|
width: style.width,
|
|
display: style.display
|
|
};
|
|
});
|
|
|
|
expect(mobileLayout.width).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
test.describe('TC-008: 功能测试', () => {
|
|
test('日历功能应该正常', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const calendarExists = await page.evaluate(() => {
|
|
const elements = document.querySelectorAll('[class*="calendar"], [class*="Calendar"]');
|
|
return elements.length > 0;
|
|
});
|
|
|
|
expect(calendarExists).toBe(true);
|
|
});
|
|
|
|
test('导航功能应该正常', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const navExists = await page.evaluate(() => {
|
|
const elements = document.querySelectorAll('[class*="nav"], [class*="Nav"]');
|
|
return elements.length > 0;
|
|
});
|
|
|
|
expect(navExists).toBe(true);
|
|
});
|
|
|
|
test('用户界面应该正常', async ({ page }) => {
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const userInterfaceExists = await page.evaluate(() => {
|
|
const body = document.body;
|
|
return body.innerText.length > 0;
|
|
});
|
|
|
|
expect(userInterfaceExists).toBe(true);
|
|
});
|
|
});
|
|
});
|