delta-sync
Version:
A lightweight framework for bi-directional database synchronization with automatic version tracking and conflict resolution.
285 lines (284 loc) • 11.9 kB
JavaScript
/**
* 适配器测试工具 - 用于测试任何实现了DatabaseAdapter接口的适配器
*/
export class AdapterTester {
constructor(adapter, testStoreName) {
this.testStoreName = 'adapter_test';
this.testFileContent = 'Hello, this is a test file content!';
this.adapter = adapter;
if (testStoreName) {
this.testStoreName = testStoreName;
}
}
/**
* 运行所有测试
*/
async runAllTests() {
console.log('=== 开始适配器测试 ===');
const results = {};
let allSuccess = true;
try {
// 测试初始化
results.initialization = await this.testInitialization();
allSuccess = allSuccess && results.initialization.success;
// 测试可用性
results.availability = await this.testAvailability();
allSuccess = allSuccess && results.availability.success;
// 测试基本CRUD操作
results.basicCrud = await this.testBasicCrud();
allSuccess = allSuccess && results.basicCrud.success;
// 测试批量操作
results.bulkOperations = await this.testBulkOperations();
allSuccess = allSuccess && results.bulkOperations.success;
// 测试文件操作
results.fileOperations = await this.testFileOperations();
allSuccess = allSuccess && results.fileOperations.success;
console.log('=== 适配器测试完成 ===');
if (allSuccess) {
console.log('✅ 所有测试通过');
}
else {
console.log('❌ 部分测试失败');
}
// 输出详细结果
Object.entries(results).forEach(([testName, result]) => {
console.log(`${result.success ? '✅' : '❌'} ${testName}: ${result.message}`);
});
return {
success: allSuccess,
results
};
}
catch (error) {
console.error('测试过程中出现未捕获的错误:', error);
return {
success: false,
results: {
...results,
uncaughtError: {
success: false,
message: `未捕获错误: ${error instanceof Error ? error.message : String(error)}`
}
}
};
}
}
/**
* 测试初始化功能
*/
async testInitialization() {
try {
console.log('测试初始化...');
await this.adapter.initSync();
return { success: true, message: '初始化成功' };
}
catch (error) {
console.error('初始化失败:', error);
return {
success: false,
message: `初始化失败: ${error instanceof Error ? error.message : String(error)}`
};
}
}
/**
* 测试可用性检查
*/
async testAvailability() {
try {
console.log('测试可用性...');
const available = await this.adapter.isAvailable();
if (available) {
return { success: true, message: '适配器可用' };
}
else {
return { success: false, message: '适配器不可用' };
}
}
catch (error) {
console.error('可用性检查失败:', error);
return {
success: false,
message: `可用性检查失败: ${error instanceof Error ? error.message : String(error)}`
};
}
}
/**
* 测试基本的CRUD操作
*/
async testBasicCrud() {
try {
console.log('测试基本CRUD操作...');
// 创建测试项目
const testItem = {
_delta_id: `test_item_${Date.now()}`,
_sync_status: 'pending',
_store: this.testStoreName,
_ver: Date.now()
};
// 写入
console.log('测试写入操作...');
const writeResult = await this.adapter.putBulk(this.testStoreName, [testItem]);
if (!writeResult || writeResult.length !== 1) {
return { success: false, message: '写入操作失败' };
}
// 读取
console.log('测试读取操作...');
const readResult = await this.adapter.readBulk(this.testStoreName, [testItem._delta_id]);
if (!readResult || readResult.length !== 1 || readResult[0]._delta_id !== testItem._delta_id) {
return { success: false, message: '读取操作失败' };
}
// 删除
console.log('测试删除操作...');
await this.adapter.deleteBulk(this.testStoreName, [testItem._delta_id]);
// 验证删除
const afterDeleteResult = await this.adapter.readBulk(this.testStoreName, [testItem._delta_id]);
if (afterDeleteResult && afterDeleteResult.length > 0) {
return { success: false, message: '删除操作失败' };
}
return { success: true, message: '基本CRUD操作测试通过' };
}
catch (error) {
console.error('CRUD测试失败:', error);
return {
success: false,
message: `CRUD测试失败: ${error instanceof Error ? error.message : String(error)}`
};
}
}
/**
* 测试批量操作
*/
async testBulkOperations() {
try {
console.log('测试批量操作...');
// 创建多个测试项目
const testItems = Array(5).fill(0).map((_, index) => ({
_delta_id: `bulk_test_${Date.now()}_${index}`,
_sync_status: 'pending',
_store: this.testStoreName,
_ver: Date.now(),
testValue: `测试值 ${index}`
}));
// 批量写入
console.log('测试批量写入...');
const writeResult = await this.adapter.putBulk(this.testStoreName, testItems);
if (!writeResult || writeResult.length !== testItems.length) {
return { success: false, message: '批量写入失败' };
}
// 批量读取
console.log('测试批量读取...');
const ids = testItems.map(item => item._delta_id);
const readResult = await this.adapter.readBulk(this.testStoreName, ids);
if (!readResult || readResult.length !== ids.length) {
return { success: false, message: '批量读取失败' };
}
// 测试分页读取
console.log('测试分页读取...');
const pageResult = await this.adapter.read(this.testStoreName, { limit: 3, offset: 0 });
if (!pageResult || !pageResult.items) {
return { success: false, message: '分页读取失败' };
}
// 批量删除
console.log('测试批量删除...');
await this.adapter.deleteBulk(this.testStoreName, ids);
// 验证批量删除
const afterDeleteResult = await this.adapter.readBulk(this.testStoreName, ids);
if (afterDeleteResult && afterDeleteResult.length > 0) {
return { success: false, message: '批量删除失败' };
}
return { success: true, message: '批量操作测试通过' };
}
catch (error) {
console.error('批量操作测试失败:', error);
return {
success: false,
message: `批量操作测试失败: ${error instanceof Error ? error.message : String(error)}`
};
}
}
/**
* 测试文件操作
*/
async testFileOperations() {
try {
console.log('测试文件操作...');
// 测试文件ID
const testFileId = `test_file_${Date.now()}`;
// 测试纯文本文件上传
console.log('测试文本文件上传...');
const textBlob = new Blob([this.testFileContent], { type: 'text/plain' });
const saveResult = await this.adapter.saveFile(textBlob, testFileId);
if (!saveResult || saveResult.id !== testFileId) {
return {
success: false,
message: `文件上传失败: ID不匹配,预期=${testFileId},实际=${saveResult?.id || '未返回ID'}`
};
}
// 测试文件下载
console.log('测试文件下载...');
const downloadResult = await this.adapter.readFile(testFileId);
if (!downloadResult) {
return { success: false, message: '文件下载失败: 未返回内容' };
}
// 验证文件内容
console.log('验证文件内容...');
let contentMatch = false;
if (downloadResult instanceof Blob) {
const text = await downloadResult.text();
contentMatch = text === this.testFileContent;
}
else if (downloadResult instanceof ArrayBuffer) {
const text = new TextDecoder().decode(downloadResult);
contentMatch = text === this.testFileContent;
}
if (!contentMatch) {
return { success: false, message: '文件内容验证失败: 内容不匹配' };
}
// 测试文件删除
console.log('测试文件删除...');
await this.adapter.deleteFile(testFileId);
// 验证文件是否已删除
let fileDeleted = false;
try {
await this.adapter.readFile(testFileId);
}
catch (error) {
fileDeleted = true;
}
if (!fileDeleted) {
return { success: false, message: '文件删除验证失败: 文件仍然存在' };
}
// 测试二进制文件
console.log('测试二进制文件上传和下载...');
const binaryFileId = `binary_test_${Date.now()}`;
const binaryData = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
const binaryBlob = new Blob([binaryData], { type: 'application/octet-stream' });
await this.adapter.saveFile(binaryBlob, binaryFileId);
const binaryResult = await this.adapter.readFile(binaryFileId);
if (!binaryResult) {
return { success: false, message: '二进制文件测试失败: 未能读取文件' };
}
// 清理
await this.adapter.deleteFile(binaryFileId);
// 测试Base64文件
console.log('测试Base64文件上传...');
const base64FileId = `base64_test_${Date.now()}`;
const base64Content = 'data:text/plain;base64,SGVsbG8gV29ybGQh'; // "Hello World!" in base64
await this.adapter.saveFile(base64Content, base64FileId);
const base64Result = await this.adapter.readFile(base64FileId);
if (!base64Result) {
return { success: false, message: 'Base64文件测试失败: 未能读取文件' };
}
// 清理
await this.adapter.deleteFile(base64FileId);
return { success: true, message: '文件操作测试通过' };
}
catch (error) {
console.error('文件操作测试失败:', error);
return {
success: false,
message: `文件操作测试失败: ${error instanceof Error ? error.message : String(error)}`
};
}
}
}