feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
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();
|
||||
Reference in New Issue
Block a user