594 lines
19 KiB
HTML
594 lines
19 KiB
HTML
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="zh-CN">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title>员工导入状态持久化功能测试</title>
|
|||
|
|
<style>
|
|||
|
|
body {
|
|||
|
|
font-family: 'Courier New', monospace;
|
|||
|
|
max-width: 1200px;
|
|||
|
|
margin: 20px auto;
|
|||
|
|
padding: 20px;
|
|||
|
|
background-color: #f5f5f5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.test-container {
|
|||
|
|
background: white;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
padding: 30px;
|
|||
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
h1 {
|
|||
|
|
color: #333;
|
|||
|
|
border-bottom: 3px solid #409eff;
|
|||
|
|
padding-bottom: 10px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
h2 {
|
|||
|
|
color: #666;
|
|||
|
|
margin-top: 30px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.test-section {
|
|||
|
|
margin: 20px 0;
|
|||
|
|
padding: 15px;
|
|||
|
|
border-left: 4px solid #409eff;
|
|||
|
|
background: #f9f9f9;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.status-pass {
|
|||
|
|
color: #67c23a;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.status-fail {
|
|||
|
|
color: #f56c6c;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.status-info {
|
|||
|
|
color: #909399;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.code {
|
|||
|
|
background: #2d2d2d;
|
|||
|
|
color: #f8f8f2;
|
|||
|
|
padding: 15px;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
overflow-x: auto;
|
|||
|
|
font-size: 13px;
|
|||
|
|
line-height: 1.5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.summary {
|
|||
|
|
background: #e6f7ff;
|
|||
|
|
border: 2px solid #1890ff;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
padding: 20px;
|
|||
|
|
margin: 30px 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.summary h3 {
|
|||
|
|
margin-top: 0;
|
|||
|
|
color: #1890ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
button {
|
|||
|
|
background: #409eff;
|
|||
|
|
color: white;
|
|||
|
|
border: none;
|
|||
|
|
padding: 12px 24px;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
cursor: pointer;
|
|||
|
|
font-size: 16px;
|
|||
|
|
margin: 5px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
button:hover {
|
|||
|
|
background: #66b1ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
button:disabled {
|
|||
|
|
background: #ccc;
|
|||
|
|
cursor: not-allowed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.log {
|
|||
|
|
background: #2d2d2d;
|
|||
|
|
color: #f8f8f2;
|
|||
|
|
padding: 15px;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
max-height: 400px;
|
|||
|
|
overflow-y: auto;
|
|||
|
|
font-size: 12px;
|
|||
|
|
line-height: 1.4;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.log-entry {
|
|||
|
|
margin: 5px 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.log-success { color: #67c23a; }
|
|||
|
|
.log-error { color: #f56c6c; }
|
|||
|
|
.log-warning { color: #e6a23c; }
|
|||
|
|
.log-info { color: #909399; }
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div class="test-container">
|
|||
|
|
<h1>员工导入状态持久化功能 - 测试套件</h1>
|
|||
|
|
|
|||
|
|
<div style="margin: 20px 0;">
|
|||
|
|
<button id="runAllTests" onclick="runAllTests()">运行所有测试</button>
|
|||
|
|
<button onclick="clearResults()">清除结果</button>
|
|||
|
|
<button onclick="clearLocalStorage()">清除localStorage</button>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div id="log" class="log">
|
|||
|
|
<div class="log-entry log-info">点击"运行所有测试"按钮开始测试...</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div id="results"></div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
const BASE_URL = 'http://localhost:8080';
|
|||
|
|
let authToken = '';
|
|||
|
|
|
|||
|
|
function log(message, type = 'info') {
|
|||
|
|
const logDiv = document.getElementById('log');
|
|||
|
|
const entry = document.createElement('div');
|
|||
|
|
entry.className = `log-entry log-${type}`;
|
|||
|
|
entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
|
|||
|
|
logDiv.appendChild(entry);
|
|||
|
|
logDiv.scrollTop = logDiv.scrollHeight;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function clearResults() {
|
|||
|
|
document.getElementById('results').innerHTML = '';
|
|||
|
|
document.getElementById('log').innerHTML = '<div class="log-entry log-info">日志已清除</div>';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function clearLocalStorage() {
|
|||
|
|
localStorage.removeItem('employee_import_last_task');
|
|||
|
|
log('localStorage已清除', 'info');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function formatJSON(obj) {
|
|||
|
|
return JSON.stringify(obj, null, 2);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 模拟后端ImportStatusVO返回的数据
|
|||
|
|
function simulateImportSuccess() {
|
|||
|
|
log('=== 测试1: 模拟导入成功场景 ===', 'info');
|
|||
|
|
|
|||
|
|
const mockSuccessResult = {
|
|||
|
|
taskId: 'task_' + Date.now(),
|
|||
|
|
status: 'SUCCESS',
|
|||
|
|
totalCount: 100,
|
|||
|
|
successCount: 100,
|
|||
|
|
failureCount: 0,
|
|||
|
|
progress: 100,
|
|||
|
|
message: '导入完成'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
log('模拟后端返回数据: ' + formatJSON(mockSuccessResult), 'info');
|
|||
|
|
|
|||
|
|
// 模拟前端saveImportTaskToStorage方法
|
|||
|
|
const taskData = {
|
|||
|
|
taskId: mockSuccessResult.taskId,
|
|||
|
|
status: mockSuccessResult.status,
|
|||
|
|
hasFailures: mockSuccessResult.failureCount > 0,
|
|||
|
|
totalCount: mockSuccessResult.totalCount,
|
|||
|
|
successCount: mockSuccessResult.successCount,
|
|||
|
|
failureCount: mockSuccessResult.failureCount,
|
|||
|
|
saveTime: Date.now()
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
localStorage.setItem('employee_import_last_task', JSON.stringify(taskData));
|
|||
|
|
log('✅ 已保存到localStorage', 'success');
|
|||
|
|
log('保存的数据: ' + formatJSON(taskData), 'info');
|
|||
|
|
|
|||
|
|
return mockSuccessResult;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function simulateImportWithFailures() {
|
|||
|
|
log('=== 测试2: 模拟导入部分失败场景 ===', 'info');
|
|||
|
|
|
|||
|
|
const mockFailureResult = {
|
|||
|
|
taskId: 'task_' + Date.now(),
|
|||
|
|
status: 'SUCCESS',
|
|||
|
|
totalCount: 100,
|
|||
|
|
successCount: 95,
|
|||
|
|
failureCount: 5,
|
|||
|
|
progress: 100,
|
|||
|
|
message: '导入完成'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
log('模拟后端返回数据: ' + formatJSON(mockFailureResult), 'info');
|
|||
|
|
|
|||
|
|
const taskData = {
|
|||
|
|
taskId: mockFailureResult.taskId,
|
|||
|
|
status: mockFailureResult.status,
|
|||
|
|
hasFailures: mockFailureResult.failureCount > 0,
|
|||
|
|
totalCount: mockFailureResult.totalCount,
|
|||
|
|
successCount: mockFailureResult.successCount,
|
|||
|
|
failureCount: mockFailureResult.failureCount,
|
|||
|
|
saveTime: Date.now()
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
localStorage.setItem('employee_import_last_task', JSON.stringify(taskData));
|
|||
|
|
log('✅ 已保存到localStorage(包含失败记录)', 'success');
|
|||
|
|
log('保存的数据: ' + formatJSON(taskData), 'info');
|
|||
|
|
|
|||
|
|
return mockFailureResult;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function verifyStorageData() {
|
|||
|
|
log('=== 测试3: 验证localStorage数据 ===', 'info');
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const data = localStorage.getItem('employee_import_last_task');
|
|||
|
|
|
|||
|
|
if (!data) {
|
|||
|
|
log('❌ localStorage中没有找到导入任务数据', 'error');
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const task = JSON.parse(data);
|
|||
|
|
log('✅ 成功读取localStorage数据', 'success');
|
|||
|
|
log('读取的数据: ' + formatJSON(task), 'info');
|
|||
|
|
|
|||
|
|
// 验证必要字段
|
|||
|
|
const requiredFields = ['taskId', 'status', 'hasFailures', 'totalCount', 'successCount', 'failureCount', 'saveTime'];
|
|||
|
|
const missingFields = requiredFields.filter(field => !(field in task));
|
|||
|
|
|
|||
|
|
if (missingFields.length > 0) {
|
|||
|
|
log('❌ 缺少必要字段: ' + missingFields.join(', '), 'error');
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log('✅ 所有必要字段都存在', 'success');
|
|||
|
|
|
|||
|
|
// 验证字段类型
|
|||
|
|
const typeChecks = [
|
|||
|
|
{ field: 'taskId', expected: 'string', actual: typeof task.taskId },
|
|||
|
|
{ field: 'status', expected: 'string', actual: typeof task.status },
|
|||
|
|
{ field: 'hasFailures', expected: 'boolean', actual: typeof task.hasFailures },
|
|||
|
|
{ field: 'saveTime', expected: 'number', actual: typeof task.saveTime }
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
let allTypesCorrect = true;
|
|||
|
|
typeChecks.forEach(check => {
|
|||
|
|
if (check.actual !== check.expected) {
|
|||
|
|
log(`❌ ${check.field}字段类型错误,期望${check.expected},实际${check.actual}`, 'error');
|
|||
|
|
allTypesCorrect = false;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (allTypesCorrect) {
|
|||
|
|
log('✅ 所有字段类型正确', 'success');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 验证时间戳合理性
|
|||
|
|
const now = Date.now();
|
|||
|
|
const timeDiff = now - task.saveTime;
|
|||
|
|
|
|||
|
|
if (timeDiff < 0 || timeDiff > 60000) {
|
|||
|
|
log('⚠️ saveTime时间戳异常,时间差: ' + timeDiff + 'ms', 'warning');
|
|||
|
|
} else {
|
|||
|
|
log('✅ saveTime时间戳正常', 'success');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return task;
|
|||
|
|
} catch (error) {
|
|||
|
|
log('❌ 解析localStorage数据失败: ' + error.message, 'error');
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function testRestoreState() {
|
|||
|
|
log('=== 测试4: 测试状态恢复逻辑 ===', 'info');
|
|||
|
|
|
|||
|
|
const task = verifyStorageData();
|
|||
|
|
|
|||
|
|
if (!task) {
|
|||
|
|
log('❌ 无法恢复状态:localStorage数据无效', 'error');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 模拟restoreImportState()方法的逻辑
|
|||
|
|
const restoredState = {
|
|||
|
|
showFailureButton: false,
|
|||
|
|
currentTaskId: null
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (task.hasFailures && task.taskId) {
|
|||
|
|
restoredState.currentTaskId = task.taskId;
|
|||
|
|
restoredState.showFailureButton = true;
|
|||
|
|
log('✅ 检测到失败记录,应该显示"查看导入失败记录"按钮', 'success');
|
|||
|
|
log(' - showFailureButton: ' + restoredState.showFailureButton, 'info');
|
|||
|
|
log(' - currentTaskId: ' + restoredState.currentTaskId, 'info');
|
|||
|
|
} else {
|
|||
|
|
log('✅ 没有失败记录,不显示按钮', 'success');
|
|||
|
|
log(' - showFailureButton: ' + restoredState.showFailureButton, 'info');
|
|||
|
|
log(' - currentTaskId: ' + restoredState.currentTaskId, 'info');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return restoredState;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function testExpiredData() {
|
|||
|
|
log('=== 测试5: 测试过期数据处理 ===', 'info');
|
|||
|
|
|
|||
|
|
const eightDaysAgo = Date.now() - (8 * 24 * 60 * 60 * 1000);
|
|||
|
|
|
|||
|
|
const expiredTask = {
|
|||
|
|
taskId: 'expired_task',
|
|||
|
|
status: 'SUCCESS',
|
|||
|
|
hasFailures: true,
|
|||
|
|
totalCount: 100,
|
|||
|
|
successCount: 90,
|
|||
|
|
failureCount: 10,
|
|||
|
|
saveTime: eightDaysAgo
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
localStorage.setItem('employee_import_last_task', JSON.stringify(expiredTask));
|
|||
|
|
log('已创建过期数据(8天前)', 'info');
|
|||
|
|
|
|||
|
|
// 模拟getImportTaskFromStorage()的过期检查逻辑
|
|||
|
|
const sevenDays = 7 * 24 * 60 * 60 * 1000;
|
|||
|
|
const isExpired = Date.now() - expiredTask.saveTime > sevenDays;
|
|||
|
|
|
|||
|
|
if (isExpired) {
|
|||
|
|
localStorage.removeItem('employee_import_last_task');
|
|||
|
|
log('✅ 检测到过期数据,已清除', 'success');
|
|||
|
|
return true;
|
|||
|
|
} else {
|
|||
|
|
log('❌ 过期检查逻辑异常', 'error');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function testClearHistory() {
|
|||
|
|
log('=== 测试6: 测试清除导入历史功能 ===', 'info');
|
|||
|
|
|
|||
|
|
const testTask = {
|
|||
|
|
taskId: 'test_clear_task',
|
|||
|
|
status: 'SUCCESS',
|
|||
|
|
hasFailures: true,
|
|||
|
|
totalCount: 50,
|
|||
|
|
successCount: 45,
|
|||
|
|
failureCount: 5,
|
|||
|
|
saveTime: Date.now()
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
localStorage.setItem('employee_import_last_task', JSON.stringify(testTask));
|
|||
|
|
log('已创建测试数据', 'info');
|
|||
|
|
|
|||
|
|
// 模拟clearImportHistory()方法
|
|||
|
|
localStorage.removeItem('employee_import_last_task');
|
|||
|
|
log('✅ 已清除导入历史', 'success');
|
|||
|
|
|
|||
|
|
const data = localStorage.getItem('employee_import_last_task');
|
|||
|
|
if (data === null) {
|
|||
|
|
log('✅ 验证成功:导入历史已完全清除', 'success');
|
|||
|
|
return true;
|
|||
|
|
} else {
|
|||
|
|
log('❌ 清除失败:localStorage中仍有数据', 'error');
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function testFieldConsistency() {
|
|||
|
|
log('=== 测试7: 测试字段名一致性 ===', 'info');
|
|||
|
|
|
|||
|
|
// 模拟后端ImportStatusVO返回的数据
|
|||
|
|
const backendData = {
|
|||
|
|
taskId: 'task_test',
|
|||
|
|
status: 'SUCCESS',
|
|||
|
|
totalCount: 100,
|
|||
|
|
successCount: 95,
|
|||
|
|
failureCount: 5,
|
|||
|
|
progress: 100
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
log('后端ImportStatusVO返回: ' + formatJSON(backendData), 'info');
|
|||
|
|
|
|||
|
|
// 模拟前端saveImportTaskToStorage调用的数据
|
|||
|
|
const frontendSaveData = {
|
|||
|
|
taskId: backendData.taskId,
|
|||
|
|
status: backendData.status,
|
|||
|
|
hasFailures: backendData.failureCount > 0,
|
|||
|
|
totalCount: backendData.totalCount,
|
|||
|
|
successCount: backendData.successCount,
|
|||
|
|
failureCount: backendData.failureCount
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
log('前端保存数据: ' + formatJSON(frontendSaveData), 'info');
|
|||
|
|
|
|||
|
|
// 验证字段映射
|
|||
|
|
const fieldMappings = [
|
|||
|
|
{ backend: 'taskId', frontend: 'taskId' },
|
|||
|
|
{ backend: 'status', frontend: 'status' },
|
|||
|
|
{ backend: 'totalCount', frontend: 'totalCount' },
|
|||
|
|
{ backend: 'successCount', frontend: 'successCount' },
|
|||
|
|
{ backend: 'failureCount', frontend: 'failureCount' }
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
let allMatch = true;
|
|||
|
|
fieldMappings.forEach(mapping => {
|
|||
|
|
const backendValue = backendData[mapping.backend];
|
|||
|
|
const frontendValue = frontendSaveData[mapping.frontend];
|
|||
|
|
|
|||
|
|
if (backendValue === frontendValue) {
|
|||
|
|
log(`✅ ${mapping.backend} → ${mapping.frontend}: 值一致 (${backendValue})`, 'success');
|
|||
|
|
} else {
|
|||
|
|
log(`❌ ${mapping.backend} → ${mapping.frontend}: 值不一致`, 'error');
|
|||
|
|
allMatch = false;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 验证saveTime字段会在saveImportTaskToStorage中自动添加
|
|||
|
|
log('✅ saveTime字段在saveImportTaskToStorage方法中自动添加', 'info');
|
|||
|
|
|
|||
|
|
return allMatch;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function displayResults(results) {
|
|||
|
|
const resultsDiv = document.getElementById('results');
|
|||
|
|
|
|||
|
|
let html = '<div class="summary">';
|
|||
|
|
html += '<h3>测试结果汇总</h3>';
|
|||
|
|
html += '<table style="width: 100%; border-collapse: collapse;">';
|
|||
|
|
html += '<tr style="border-bottom: 1px solid #ddd;">';
|
|||
|
|
html += '<th style="padding: 10px; text-align: left;">测试项目</th>';
|
|||
|
|
html += '<th style="padding: 10px; text-align: left;">结果</th>';
|
|||
|
|
html += '</tr>';
|
|||
|
|
|
|||
|
|
const testNames = {
|
|||
|
|
importSuccess: '导入成功场景',
|
|||
|
|
importWithFailures: '导入部分失败场景',
|
|||
|
|
restoreState: '状态恢复逻辑',
|
|||
|
|
expiredData: '过期数据处理',
|
|||
|
|
clearHistory: '清除导入历史',
|
|||
|
|
fieldConsistency: '字段名一致性'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
let passCount = 0;
|
|||
|
|
let failCount = 0;
|
|||
|
|
|
|||
|
|
Object.keys(results).forEach(key => {
|
|||
|
|
const status = results[key] ? '✅ PASS' : '❌ FAIL';
|
|||
|
|
const statusClass = results[key] ? 'status-pass' : 'status-fail';
|
|||
|
|
const testName = testNames[key] || key;
|
|||
|
|
|
|||
|
|
html += '<tr style="border-bottom: 1px solid #eee;">';
|
|||
|
|
html += `<td style="padding: 10px;">${testName}</td>`;
|
|||
|
|
html += `<td style="padding: 10px;" class="${statusClass}">${status}</td>`;
|
|||
|
|
html += '</tr>';
|
|||
|
|
|
|||
|
|
if (results[key]) {
|
|||
|
|
passCount++;
|
|||
|
|
} else {
|
|||
|
|
failCount++;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
html += '</table>';
|
|||
|
|
html += '<p style="margin-top: 20px; font-size: 16px;">';
|
|||
|
|
html += `<strong>总计:</strong> ${passCount + failCount} 个测试 | `;
|
|||
|
|
html += `<span class="status-pass">通过: ${passCount} 个</span> | `;
|
|||
|
|
html += `<span class="status-fail">失败: ${failCount} 个</span>`;
|
|||
|
|
html += '</p>';
|
|||
|
|
|
|||
|
|
if (failCount === 0) {
|
|||
|
|
html += '<p style="margin-top: 15px; font-size: 18px; color: #67c23a;">';
|
|||
|
|
html += '🎉 <strong>所有测试通过!</strong> 导入状态持久化功能正常工作。';
|
|||
|
|
html += '</p>';
|
|||
|
|
} else {
|
|||
|
|
html += '<p style="margin-top: 15px; font-size: 18px; color: #f56c6c;">';
|
|||
|
|
html += '⚠️ <strong>部分测试失败</strong>,请检查相关功能。';
|
|||
|
|
html += '</p>';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
html += '</div>';
|
|||
|
|
|
|||
|
|
resultsDiv.innerHTML = html;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function runAllTests() {
|
|||
|
|
const btn = document.getElementById('runAllTests');
|
|||
|
|
btn.disabled = true;
|
|||
|
|
btn.textContent = '测试运行中...';
|
|||
|
|
|
|||
|
|
document.getElementById('log').innerHTML = '';
|
|||
|
|
document.getElementById('results').innerHTML = '';
|
|||
|
|
|
|||
|
|
log('╔════════════════════════════════════════════════════════════╗', 'info');
|
|||
|
|
log('║ 员工导入状态持久化功能 - 完整测试套件 ║', 'info');
|
|||
|
|
log('╚════════════════════════════════════════════════════════════╝', 'info');
|
|||
|
|
|
|||
|
|
// 清理环境
|
|||
|
|
localStorage.removeItem('employee_import_last_task');
|
|||
|
|
log('✅ 测试环境已清理', 'success');
|
|||
|
|
|
|||
|
|
const results = {
|
|||
|
|
importSuccess: false,
|
|||
|
|
importWithFailures: false,
|
|||
|
|
restoreState: false,
|
|||
|
|
expiredData: false,
|
|||
|
|
clearHistory: false,
|
|||
|
|
fieldConsistency: false
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 测试1: 导入成功场景
|
|||
|
|
try {
|
|||
|
|
localStorage.removeItem('employee_import_last_task');
|
|||
|
|
simulateImportSuccess();
|
|||
|
|
const task = verifyStorageData();
|
|||
|
|
results.importSuccess = (task !== null && !task.hasFailures);
|
|||
|
|
} catch (error) {
|
|||
|
|
log('❌ 导入成功场景测试失败: ' + error.message, 'error');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 测试2: 导入部分失败场景
|
|||
|
|
try {
|
|||
|
|
localStorage.removeItem('employee_import_last_task');
|
|||
|
|
simulateImportWithFailures();
|
|||
|
|
const task = verifyStorageData();
|
|||
|
|
results.importWithFailures = (task !== null && task.hasFailures);
|
|||
|
|
} catch (error) {
|
|||
|
|
log('❌ 导入部分失败场景测试失败: ' + error.message, 'error');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 测试3: 状态恢复
|
|||
|
|
try {
|
|||
|
|
const state = testRestoreState();
|
|||
|
|
results.restoreState = (state !== false && state.showFailureButton === true);
|
|||
|
|
} catch (error) {
|
|||
|
|
log('❌ 状态恢复测试失败: ' + error.message, 'error');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 测试4: 过期数据处理
|
|||
|
|
try {
|
|||
|
|
localStorage.removeItem('employee_import_last_task');
|
|||
|
|
results.expiredData = testExpiredData();
|
|||
|
|
} catch (error) {
|
|||
|
|
log('❌ 过期数据处理测试失败: ' + error.message, 'error');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 测试5: 清除导入历史
|
|||
|
|
try {
|
|||
|
|
results.clearHistory = testClearHistory();
|
|||
|
|
} catch (error) {
|
|||
|
|
log('❌ 清除导入历史测试失败: ' + error.message, 'error');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 测试6: 字段名一致性
|
|||
|
|
try {
|
|||
|
|
localStorage.removeItem('employee_import_last_task');
|
|||
|
|
results.fieldConsistency = testFieldConsistency();
|
|||
|
|
} catch (error) {
|
|||
|
|
log('❌ 字段名一致性测试失败: ' + error.message, 'error');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
log('╔════════════════════════════════════════════════════════════╗', 'info');
|
|||
|
|
log('║ 测试完成 ║', 'info');
|
|||
|
|
log('╚════════════════════════════════════════════════════════════╝', 'info');
|
|||
|
|
|
|||
|
|
displayResults(results);
|
|||
|
|
|
|||
|
|
// 清理测试数据
|
|||
|
|
localStorage.removeItem('employee_import_last_task');
|
|||
|
|
log('✅ 测试数据已清理', 'success');
|
|||
|
|
|
|||
|
|
btn.disabled = false;
|
|||
|
|
btn.textContent = '运行所有测试';
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|