08ea5fbe98
添加用户管理视图、API和状态管理文件
255 lines
6.9 KiB
TypeScript
255 lines
6.9 KiB
TypeScript
import { test } from '@playwright/test';
|
|
import { testLogger } from '../shared/utils/test-logger';
|
|
import { testDataGenerator, UserData, RoleData, MenuData } from './test-data';
|
|
|
|
export type DataStrategy = 'real' | 'mock' | 'hybrid';
|
|
|
|
export interface DataStrategyConfig {
|
|
strategy: DataStrategy;
|
|
mockEnabled: boolean;
|
|
realDataEnabled: boolean;
|
|
autoCleanup: boolean;
|
|
}
|
|
|
|
export interface DataSnapshot {
|
|
name: string;
|
|
timestamp: number;
|
|
data: Map<string, any[]>;
|
|
}
|
|
|
|
export class DataStrategyManager {
|
|
private strategy: DataStrategy;
|
|
private config: DataStrategyConfig;
|
|
private snapshots: Map<string, DataSnapshot> = new Map();
|
|
private testData: Map<string, any[]> = new Map();
|
|
|
|
constructor(config?: Partial<DataStrategyConfig>) {
|
|
this.config = {
|
|
strategy: 'hybrid',
|
|
mockEnabled: true,
|
|
realDataEnabled: true,
|
|
autoCleanup: true,
|
|
...config
|
|
};
|
|
this.strategy = this.config.strategy;
|
|
|
|
testLogger.info(`DataStrategyManager initialized with strategy: ${this.strategy}`);
|
|
}
|
|
|
|
setStrategy(strategy: DataStrategy): void {
|
|
this.strategy = strategy;
|
|
this.config.strategy = strategy;
|
|
testLogger.info(`Data strategy changed to: ${strategy}`);
|
|
}
|
|
|
|
getStrategy(): DataStrategy {
|
|
return this.strategy;
|
|
}
|
|
|
|
getConfig(): DataStrategyConfig {
|
|
return { ...this.config };
|
|
}
|
|
|
|
selectDataSource(testTags: string[]): DataStrategy {
|
|
testLogger.debug(`Selecting data source for tags: ${testTags.join(', ')}`);
|
|
|
|
if (this.config.strategy === 'real') {
|
|
testLogger.debug('Using real data strategy (forced)');
|
|
return 'real';
|
|
}
|
|
|
|
if (this.config.strategy === 'mock') {
|
|
testLogger.debug('Using mock data strategy (forced)');
|
|
return 'mock';
|
|
}
|
|
|
|
if (this.config.strategy === 'hybrid') {
|
|
return this.selectHybridDataSource(testTags);
|
|
}
|
|
|
|
return 'mock';
|
|
}
|
|
|
|
private selectHybridDataSource(testTags: string[]): DataStrategy {
|
|
const hasSmokeTag = testTags.includes('@smoke');
|
|
const hasRegressionTag = testTags.includes('@regression');
|
|
const hasFullTag = testTags.includes('@full');
|
|
const hasCriticalTag = testTags.includes('@critical');
|
|
|
|
if (hasCriticalTag) {
|
|
testLogger.debug('Hybrid strategy: Using real data for @critical tests');
|
|
return 'real';
|
|
}
|
|
|
|
if (hasFullTag) {
|
|
testLogger.debug('Hybrid strategy: Using real data for @full tests');
|
|
return 'real';
|
|
}
|
|
|
|
if (hasRegressionTag) {
|
|
testLogger.debug('Hybrid strategy: Using hybrid data for @regression tests');
|
|
return 'hybrid';
|
|
}
|
|
|
|
if (hasSmokeTag) {
|
|
testLogger.debug('Hybrid strategy: Using mock data for @smoke tests');
|
|
return 'mock';
|
|
}
|
|
|
|
testLogger.debug('Hybrid strategy: Defaulting to mock data');
|
|
return 'mock';
|
|
}
|
|
|
|
async createData(dataType: string, data: any, testTags: string[] = []): Promise<any> {
|
|
const dataSource = this.selectDataSource(testTags);
|
|
testLogger.info(`Creating ${dataType} using ${dataSource} data source`);
|
|
|
|
if (dataSource === 'mock') {
|
|
return this.createMockData(dataType, data);
|
|
}
|
|
|
|
if (dataSource === 'real') {
|
|
return this.createRealData(dataType, data);
|
|
}
|
|
|
|
return this.createHybridData(dataType, data);
|
|
}
|
|
|
|
private createMockData(dataType: string, data: any): any {
|
|
testLogger.debug(`Creating mock data for ${dataType}`);
|
|
|
|
switch (dataType) {
|
|
case 'user':
|
|
return testDataGenerator.generateUserData(data);
|
|
case 'role':
|
|
return testDataGenerator.generateRoleData(data);
|
|
case 'menu':
|
|
return testDataGenerator.generateMenuData(data);
|
|
case 'permission':
|
|
return testDataGenerator.generatePermissionData(data);
|
|
default:
|
|
return data;
|
|
}
|
|
}
|
|
|
|
private createRealData(dataType: string, data: any): any {
|
|
testLogger.debug(`Creating real data for ${dataType} (requires API connection)`);
|
|
|
|
return data;
|
|
}
|
|
|
|
private createHybridData(dataType: string, data: any): any {
|
|
testLogger.debug(`Creating hybrid data for ${dataType}`);
|
|
|
|
const mockData = this.createMockData(dataType, data);
|
|
const realData = this.createRealData(dataType, data);
|
|
|
|
return {
|
|
...mockData,
|
|
_dataSource: 'hybrid',
|
|
_mockData: mockData,
|
|
_realData: realData
|
|
};
|
|
}
|
|
|
|
async cleanupData(dataType: string, dataId: string | number): Promise<void> {
|
|
testLogger.info(`Cleaning up ${dataType} with id: ${dataId}`);
|
|
|
|
if (this.config.autoCleanup) {
|
|
this.removeTestData(dataType, dataId);
|
|
}
|
|
}
|
|
|
|
async cleanupAll(): Promise<void> {
|
|
testLogger.info('Cleaning up all test data');
|
|
|
|
this.testData.clear();
|
|
this.snapshots.clear();
|
|
|
|
testLogger.info('All test data cleaned up');
|
|
}
|
|
|
|
async createSnapshot(snapshotName: string): Promise<DataSnapshot> {
|
|
testLogger.info(`Creating snapshot: ${snapshotName}`);
|
|
|
|
const snapshot: DataSnapshot = {
|
|
name: snapshotName,
|
|
timestamp: Date.now(),
|
|
data: new Map(this.testData)
|
|
};
|
|
|
|
this.snapshots.set(snapshotName, snapshot);
|
|
testLogger.info(`Snapshot created: ${snapshotName} at ${new Date(snapshot.timestamp).toISOString()}`);
|
|
|
|
return snapshot;
|
|
}
|
|
|
|
async rollbackToSnapshot(snapshotName: string): Promise<void> {
|
|
testLogger.info(`Rolling back to snapshot: ${snapshotName}`);
|
|
|
|
const snapshot = this.snapshots.get(snapshotName);
|
|
if (!snapshot) {
|
|
throw new Error(`Snapshot not found: ${snapshotName}`);
|
|
}
|
|
|
|
this.testData = new Map(snapshot.data);
|
|
testLogger.info(`Rolled back to snapshot: ${snapshotName}`);
|
|
}
|
|
|
|
private addTestData(dataType: string, data: any): void {
|
|
if (!this.testData.has(dataType)) {
|
|
this.testData.set(dataType, []);
|
|
}
|
|
this.testData.get(dataType)!.push(data);
|
|
}
|
|
|
|
private removeTestData(dataType: string, dataId: string | number): void {
|
|
const items = this.testData.get(dataType);
|
|
if (items) {
|
|
const index = items.findIndex(item => item.id === dataId);
|
|
if (index !== -1) {
|
|
items.splice(index, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
getTestData(dataType: string): any[] {
|
|
return this.testData.get(dataType) || [];
|
|
}
|
|
|
|
getSnapshot(snapshotName: string): DataSnapshot | undefined {
|
|
return this.snapshots.get(snapshotName);
|
|
}
|
|
|
|
getAllSnapshots(): DataSnapshot[] {
|
|
return Array.from(this.snapshots.values());
|
|
}
|
|
|
|
deleteSnapshot(snapshotName: string): void {
|
|
this.snapshots.delete(snapshotName);
|
|
testLogger.info(`Snapshot deleted: ${snapshotName}`);
|
|
}
|
|
|
|
getStatistics(): {
|
|
totalTestData: number;
|
|
totalSnapshots: number;
|
|
strategy: DataStrategy;
|
|
config: DataStrategyConfig;
|
|
} {
|
|
let totalTestData = 0;
|
|
const testDataValues = Array.from(this.testData.values());
|
|
for (const items of testDataValues) {
|
|
totalTestData += items.length;
|
|
}
|
|
|
|
return {
|
|
totalTestData,
|
|
totalSnapshots: this.snapshots.size,
|
|
strategy: this.strategy,
|
|
config: this.getConfig()
|
|
};
|
|
}
|
|
}
|
|
|
|
export const dataStrategyManager = new DataStrategyManager();
|