/** * 存储适配器集成测试 * 验证不同存储适配器类型的功能和兼容性 */ // @ts-ignore import { StorageFactory } from '../../src/adapters/StorageFactory'; import { StorageAdapter, StorageConfig, QueryCondition, SortOption } from '../../src/interfaces/StorageAdapter'; // @ts-ignore import { storagePluginLoader } from '../../src/adapters/StoragePluginLoader'; import { Domain } from '../../src/models/Domain'; import { DomainManagerFactory } from '../../src/dao/DomainManagerFactory'; import { DomainManager } from '../../src/interfaces/DomainManager'; import { StandardStoragePlugin } from '../../src/plugins/builtins/StandardStoragePlugin'; import { FileSystemStorageAdapter } from '../../src/adapters/storage/FileSystemStorageAdapter'; // @ts-ignore import * as fs from 'fs-extra'; import * as path from 'path'; describe('Storage Adapters Integration Tests', () => { // 测试数据 const testDomains = [ { name: 'example.com', targetAddress: '192.168.1.1', recordType: 'A', admin: 'admin@example.com', enabled: true, description: 'Test domain 1' }, { name: 'test.org', targetAddress: '192.168.1.2', recordType: 'A', admin: 'admin@test.org', enabled: false, description: 'Test domain 2' }, { name: 'demo.net', targetAddress: '192.168.1.3', recordType: 'A', admin: 'admin@demo.net', enabled: true, description: 'Test domain 3' }, ] as any[]; // 文件系统存储的测试目录 const testDataDir = path.join(process.cwd(), 'test-data'); // 在所有测试前准备 beforeAll(async () => { // 加载标准存储插件 const plugin = new StandardStoragePlugin(); plugin.initialize(); }); // 在每个测试前清理测试目录 beforeEach(async () => { // 清理测试目录 if (await fs.pathExists(testDataDir)) { await fs.remove(testDataDir); } // 确保测试目录存在 await fs.ensureDir(testDataDir); }); // 在所有测试后清理 afterAll(async () => { // 清理测试目录 if (await fs.pathExists(testDataDir)) { await fs.remove(testDataDir); } // 清理StorageFactory中注册的适配器 // 注意:在实际生产环境中不建议这样做,但对于测试来说是必要的 jest.resetModules(); }); // 测试内存存储适配器 describe('Memory Storage Adapter', () => { let adapter: StorageAdapter; beforeEach(async () => { // 创建内存存储适配器 adapter = StorageFactory.createAdapter('memory'); await adapter.initialize({ type: 'memory' }); }); afterEach(async () => { // 关闭适配器,释放资源 if (adapter) { await adapter.close(); } }); test('should initialize and be available', async () => { expect(await adapter.isAvailable()).toBe(true); }); test('should create and retrieve items', async () => { // 创建测试数据 const createdDomain = await adapter.create('domains', testDomains[0]); // 验证创建成功 expect(createdDomain).toBeDefined(); expect((createdDomain as any).id).toBeDefined(); expect((createdDomain as any).name).toBe(testDomains[0].name); // 获取数据 const retrievedDomain = await adapter.getById('domains', (createdDomain as any).id); // 验证获取成功 expect(retrievedDomain).toBeDefined(); expect((retrievedDomain as any)?.id).toBe((createdDomain as any).id); }); test('should find items with query conditions', async () => { // 创建测试数据 for (const domain of testDomains) { await adapter.create('domains', domain); } // 查询启用状态的域名 const query: QueryCondition = { enabled: true }; const result = await adapter.find('domains', query); // 验证查询结果 expect(result.data.length).toBeGreaterThan(0); result.data.forEach((domain: any) => { expect(domain.enabled).toBe(true); }); }); test('should update and delete items', async () => { // 创建测试数据 const createdDomain = await adapter.create('domains', testDomains[0]); // 更新数据 const updatedDomain = await adapter.update('domains', (createdDomain as any).id, { enabled: false, description: 'Updated description' }); // 验证更新成功 expect(updatedDomain).toBeDefined(); expect(updatedDomain?.enabled).toBe(false); expect(updatedDomain?.description).toBe('Updated description'); // 删除数据 const deleted = await adapter.delete('domains', (createdDomain as any).id); // 验证删除成功 expect(deleted).toBe(true); // 确认数据已删除 const notFound = await adapter.getById('domains', (createdDomain as any).id); expect(notFound).toBeNull(); }); test('should support bulk operations', async () => { // 批量创建数据 const createdDomains = await adapter.bulkCreate('domains', testDomains); // 验证批量创建成功 expect(createdDomains.length).toBe(testDomains.length); createdDomains.forEach(domain => { expect((domain as any).id).toBeDefined(); }); }); test('should support sorting and pagination', async () => { // 创建测试数据 for (const domain of testDomains) { await adapter.create('domains', domain); } // 排序和分页查询 const sort: SortOption = { name: 'asc' // 按名称升序 }; const result = await adapter.find('domains', {}, 0, 2, sort); // 验证结果 expect(result.data.length).toBe(2); expect(result.total).toBeGreaterThanOrEqual(3); // 至少有3条记录 // 验证排序 for (let i = 1; i < result.data.length; i++) { expect((result.data[i] as any).name >= (result.data[i-1] as any).name).toBe(true); } }); }); // 测试文件系统存储适配器 describe('File System Storage Adapter', () => { let adapter: StorageAdapter; beforeEach(async () => { // 创建文件系统存储适配器 adapter = StorageFactory.createAdapter('file'); await adapter.initialize({ type: 'file', options: { dataDir: testDataDir } }); }); afterEach(async () => { // 关闭适配器,释放资源 if (adapter) { await adapter.close(); } }); test('should initialize and be available', async () => { expect(await adapter.isAvailable()).toBe(true); }); test('should create and retrieve items', async () => { // 创建测试数据 const createdDomain = await adapter.create('domains', testDomains[0]); // 验证创建成功 expect(createdDomain).toBeDefined(); expect((createdDomain as any).id).toBeDefined(); expect((createdDomain as any).name).toBe(testDomains[0].name); // 获取数据 const retrievedDomain = await adapter.getById('domains', (createdDomain as any).id); // 验证获取成功 expect(retrievedDomain).toBeDefined(); expect((retrievedDomain as any)?.id).toBe((createdDomain as any).id); }); test('should find items with query conditions', async () => { // 创建测试数据 for (const domain of testDomains) { await adapter.create('domains', domain); } // 查询启用状态的域名 const query: QueryCondition = { enabled: true }; const result = await adapter.find('domains', query); // 验证查询结果 expect(result.data.length).toBeGreaterThan(0); result.data.forEach((domain: any) => { expect(domain.enabled).toBe(true); }); }); test('should update and delete items', async () => { // 创建测试数据 const createdDomain = await adapter.create('domains', testDomains[0]); // 更新数据 const updateData = { enabled: false, description: 'Updated description' }; const updatedDomain = await adapter.update('domains', (createdDomain as any).id, updateData); // 验证更新成功 expect(updatedDomain).toBeDefined(); expect(updatedDomain?.enabled).toBe(false); expect(updatedDomain?.description).toBe('Updated description'); // 删除数据 const deleted = await adapter.delete('domains', (createdDomain as any).id); // 验证删除成功 expect(deleted).toBe(true); // 确认数据已删除 const notFound = await adapter.getById('domains', (createdDomain as any).id); expect(notFound).toBeNull(); }); test('should support bulk operations', async () => { // 批量创建数据 const createdDomains = await adapter.bulkCreate('domains', testDomains); // 验证批量创建成功 expect(createdDomains.length).toBe(testDomains.length); createdDomains.forEach(domain => { expect((domain as any).id).toBeDefined(); }); // 分别验证每个创建的数据项都可以被单独查询到 for (const createdDomain of createdDomains) { const id = (createdDomain as any).id; const foundDomain = await adapter.getById('domains', id); expect(foundDomain).toBeDefined(); expect((foundDomain as any).id).toBe(id); } // 验证批量数据可以被查询到 - check that we got at least the right number, not exact count const result = await adapter.find('domains'); expect(result.total).toBeGreaterThanOrEqual(testDomains.length); }); test('should support sorting and pagination', async () => { // 创建测试数据 for (const domain of testDomains) { await adapter.create('domains', domain); } // 排序和分页查询 const sort: SortOption = { name: 'asc' // 按名称升序 }; const result = await adapter.find('domains', {}, 0, 2, sort); // 验证结果 expect(result.data.length).toBe(2); expect(result.total).toBeGreaterThanOrEqual(3); // 至少有3条记录 // 验证排序 for (let i = 1; i < result.data.length; i++) { expect((result.data[i] as any).name >= (result.data[i-1] as any).name).toBe(true); } }); test('should handle file extension configuration', async () => { // 关闭当前适配器 await adapter.close(); // 创建带有自定义文件扩展名的适配器 const customAdapter = StorageFactory.createAdapter('file'); await customAdapter.initialize({ type: 'file', options: { dataDir: testDataDir, fileExtension: 'txt' } }); try { // 创建测试数据 const createdDomain = await customAdapter.create('domains', testDomains[0]); // 验证创建成功 expect(createdDomain).toBeDefined(); expect((createdDomain as any).id).toBeDefined(); } finally { await customAdapter.close(); } }); test('should handle pretty print configuration', async () => { // 关闭当前适配器 await adapter.close(); // 创建带有prettyPrint选项的适配器 const prettyAdapter = StorageFactory.createAdapter('file'); await prettyAdapter.initialize({ type: 'file', options: { dataDir: testDataDir, prettyPrint: true } }); try { // 创建测试数据 const createdDomain = await prettyAdapter.create('domains', testDomains[0]); // 验证创建成功 expect(createdDomain).toBeDefined(); } finally { await prettyAdapter.close(); } }); }); // 测试与DomainManager的集成 describe('Integration with DomainManager', () => { test('should work with memory storage', async () => { // 创建内存存储适配器 const adapter = StorageFactory.createAdapter('memory'); await adapter.initialize({ type: 'memory' }); try { // 创建DomainManager const domainManager = await DomainManagerFactory.create(adapter); // 测试DomainManager的创建功能 const domain = await (domainManager as any).createDomain({ name: 'integration-test.com', description: 'Integration test domain', targetAddress: '192.168.1.1', recordType: 'A', admin: 'admin@integration-test.com', enabled: true }); // 验证创建成功 expect(domain).toBeDefined(); expect(domain.id).toBeDefined(); // 测试DomainManager的查询功能 const foundDomain = await (domainManager as any).getDomainById(domain.id); // 验证查询成功 expect(foundDomain).toBeDefined(); expect(foundDomain?.id).toBe(domain.id); } finally { // 关闭适配器,释放资源 await adapter.close(); } }); test('should work with file system storage', async () => { // 创建文件系统存储适配器 const adapter = StorageFactory.createAdapter('file'); await adapter.initialize({ type: 'file', options: { dataDir: testDataDir } }); try { // 创建DomainManager const domainManager = await DomainManagerFactory.create(adapter); // 使用唯一的域名名称,避免冲突 const uniqueDomainName = `fs-integration-test-${Date.now()}.com`; // 测试DomainManager的创建功能 const domain = await (domainManager as any).createDomain({ name: uniqueDomainName, description: 'File system integration test domain', targetAddress: '192.168.1.1', recordType: 'A', admin: 'admin@fs-integration-test.com', enabled: true }); // 验证创建成功 expect(domain).toBeDefined(); expect(domain.id).toBeDefined(); // 测试DomainManager的查询功能 const foundDomain = await (domainManager as any).getDomainById(domain.id); // 验证查询成功 expect(foundDomain).toBeDefined(); expect(foundDomain?.id).toBe(domain.id); } finally { // 关闭适配器,释放资源 await adapter.close(); } }); }); // 测试插件系统 describe('Storage Plugin System', () => { test('should load plugins and register adapters', async () => { // 检查插件加载 const loadedPlugins = storagePluginLoader.getLoadedPlugins(); expect(Array.isArray(loadedPlugins)).toBe(true); // 检查适配器是否可通过类型名称创建 const adapterTypes = ['memory', 'file', 'filesystem']; const adapters: StorageAdapter[] = []; for (const type of adapterTypes) { try { const adapter = StorageFactory.createAdapter(type); expect(adapter).toBeDefined(); await adapter.initialize({ type }); expect(await adapter.isAvailable()).toBe(true); adapters.push(adapter); } catch (error) { expect(error).toBeUndefined(); } } // 关闭所有创建的适配器 for (const adapter of adapters) { await adapter.close(); } }); }); });