镜像自地址
https://github.com/lhly/search-syntax-pro.git
已同步 2026-10-20 22:37:48 +08:00
- 新增 TwitterAdapter 实现 SearchEngineAdapter 接口 - 扩展 SearchEngine 类型包含 'twitter' - 更新适配器工厂支持 Twitter 引擎 - 添加国际化翻译支持 - 新增 Twitter 集成测试页面 - 添加 Twitter 专属语法类型和参数支持 - 实现 Twitter 高级搜索功能 - 添加单元测试覆盖 Twitter 适配器
389 行
11 KiB
HTML
389 行
11 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>Twitter 集成测试</title>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
padding: 20px;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
.container {
|
||
max-width: 1000px;
|
||
margin: 0 auto;
|
||
background: white;
|
||
border-radius: 16px;
|
||
padding: 40px;
|
||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
h1 {
|
||
color: #333;
|
||
margin-bottom: 10px;
|
||
font-size: 2rem;
|
||
}
|
||
|
||
.status {
|
||
display: inline-block;
|
||
padding: 4px 12px;
|
||
border-radius: 20px;
|
||
font-size: 0.875rem;
|
||
font-weight: 600;
|
||
margin-bottom: 30px;
|
||
}
|
||
|
||
.status.success {
|
||
background: #d4edda;
|
||
color: #155724;
|
||
}
|
||
|
||
.status.error {
|
||
background: #f8d7da;
|
||
color: #721c24;
|
||
}
|
||
|
||
.test-section {
|
||
margin-bottom: 30px;
|
||
padding: 20px;
|
||
background: #f8f9fa;
|
||
border-radius: 12px;
|
||
}
|
||
|
||
.test-section h2 {
|
||
color: #495057;
|
||
font-size: 1.25rem;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.test-item {
|
||
background: white;
|
||
padding: 15px;
|
||
margin-bottom: 10px;
|
||
border-radius: 8px;
|
||
border-left: 4px solid #667eea;
|
||
}
|
||
|
||
.test-item h3 {
|
||
color: #333;
|
||
font-size: 1rem;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.test-result {
|
||
font-family: 'Monaco', 'Courier New', monospace;
|
||
font-size: 0.875rem;
|
||
color: #495057;
|
||
background: #f1f3f5;
|
||
padding: 10px;
|
||
border-radius: 6px;
|
||
margin-top: 8px;
|
||
word-break: break-all;
|
||
}
|
||
|
||
.pass {
|
||
color: #28a745;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.fail {
|
||
color: #dc3545;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.info {
|
||
background: #e7f3ff;
|
||
border-left-color: #0066cc;
|
||
padding: 15px;
|
||
border-radius: 8px;
|
||
margin-bottom: 20px;
|
||
color: #004085;
|
||
}
|
||
|
||
button {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border: none;
|
||
padding: 12px 24px;
|
||
border-radius: 8px;
|
||
font-size: 1rem;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
transition: transform 0.2s;
|
||
}
|
||
|
||
button:hover {
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
button:active {
|
||
transform: translateY(0);
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<h1>🧪 Twitter 集成测试</h1>
|
||
<div class="status success">方案 A 实施验证</div>
|
||
|
||
<div class="info">
|
||
<strong>📋 测试目标:</strong> 验证 Twitter 搜索引擎适配器的完整功能
|
||
<br><br>
|
||
<strong>🔧 测试范围:</strong>
|
||
<ul style="margin-left: 20px; margin-top: 10px;">
|
||
<li>类型系统扩展</li>
|
||
<li>适配器工厂注册</li>
|
||
<li>查询构建逻辑</li>
|
||
<li>参数验证功能</li>
|
||
<li>UI 国际化支持</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="test-section">
|
||
<h2>✅ 测试结果总览</h2>
|
||
<div id="summary"></div>
|
||
</div>
|
||
|
||
<div class="test-section">
|
||
<h2>📝 详细测试项</h2>
|
||
<div id="tests"></div>
|
||
</div>
|
||
|
||
<button onclick="runTests()">🚀 重新运行测试</button>
|
||
</div>
|
||
|
||
<script type="module">
|
||
import { SearchAdapterFactory } from '../dist/assets/index.js'
|
||
|
||
window.runTests = async function() {
|
||
const testsDiv = document.getElementById('tests')
|
||
const summaryDiv = document.getElementById('summary')
|
||
testsDiv.innerHTML = ''
|
||
|
||
let passCount = 0
|
||
let failCount = 0
|
||
const tests = []
|
||
|
||
// 测试 1: 类型系统支持
|
||
try {
|
||
const supportedEngines = SearchAdapterFactory.getSupportedEngines()
|
||
const hasTwitter = supportedEngines.includes('twitter')
|
||
|
||
tests.push({
|
||
name: '类型系统 - Twitter 引擎支持',
|
||
pass: hasTwitter,
|
||
result: hasTwitter
|
||
? `✓ Twitter 已添加到支持的引擎列表: ${supportedEngines.join(', ')}`
|
||
: '✗ Twitter 未在支持的引擎列表中'
|
||
})
|
||
|
||
if (hasTwitter) passCount++
|
||
else failCount++
|
||
} catch (error) {
|
||
tests.push({
|
||
name: '类型系统 - Twitter 引擎支持',
|
||
pass: false,
|
||
result: `✗ 错误: ${error.message}`
|
||
})
|
||
failCount++
|
||
}
|
||
|
||
// 测试 2: 适配器实例化
|
||
try {
|
||
const adapter = SearchAdapterFactory.getAdapter('twitter')
|
||
const name = adapter.getName()
|
||
|
||
tests.push({
|
||
name: '适配器工厂 - Twitter 实例化',
|
||
pass: name === 'X (Twitter)',
|
||
result: name === 'X (Twitter)'
|
||
? `✓ 适配器名称正确: ${name}`
|
||
: `✗ 适配器名称错误: ${name}`
|
||
})
|
||
|
||
if (name === 'X (Twitter)') passCount++
|
||
else failCount++
|
||
} catch (error) {
|
||
tests.push({
|
||
name: '适配器工厂 - Twitter 实例化',
|
||
pass: false,
|
||
result: `✗ 错误: ${error.message}`
|
||
})
|
||
failCount++
|
||
}
|
||
|
||
// 测试 3: 基础查询构建
|
||
try {
|
||
const adapter = SearchAdapterFactory.getAdapter('twitter')
|
||
const url = adapter.buildQuery({
|
||
keyword: 'JavaScript',
|
||
engine: 'twitter'
|
||
})
|
||
const hasKeyword = url.includes('JavaScript')
|
||
const hasBaseUrl = url.includes('twitter.com/search')
|
||
|
||
tests.push({
|
||
name: '查询构建 - 基础关键词',
|
||
pass: hasKeyword && hasBaseUrl,
|
||
result: hasKeyword && hasBaseUrl
|
||
? `✓ URL 构建正确: ${url}`
|
||
: `✗ URL 构建错误: ${url}`
|
||
})
|
||
|
||
if (hasKeyword && hasBaseUrl) passCount++
|
||
else failCount++
|
||
} catch (error) {
|
||
tests.push({
|
||
name: '查询构建 - 基础关键词',
|
||
pass: false,
|
||
result: `✗ 错误: ${error.message}`
|
||
})
|
||
failCount++
|
||
}
|
||
|
||
// 测试 4: Twitter 特定语法
|
||
try {
|
||
const adapter = SearchAdapterFactory.getAdapter('twitter')
|
||
const url = adapter.buildQuery({
|
||
keyword: 'AI news',
|
||
engine: 'twitter',
|
||
fromUser: '@elonmusk',
|
||
minRetweets: 100,
|
||
contentFilters: ['images']
|
||
})
|
||
const decodedUrl = decodeURIComponent(url)
|
||
const hasFrom = decodedUrl.includes('from:elonmusk')
|
||
const hasMinRetweets = decodedUrl.includes('min_retweets:100')
|
||
const hasFilter = decodedUrl.includes('filter:images')
|
||
|
||
tests.push({
|
||
name: '查询构建 - Twitter 专属语法',
|
||
pass: hasFrom && hasMinRetweets && hasFilter,
|
||
result: hasFrom && hasMinRetweets && hasFilter
|
||
? `✓ Twitter 语法正确: from:, min_retweets:, filter:`
|
||
: `✗ Twitter 语法错误: ${decodedUrl}`
|
||
})
|
||
|
||
if (hasFrom && hasMinRetweets && hasFilter) passCount++
|
||
else failCount++
|
||
} catch (error) {
|
||
tests.push({
|
||
name: '查询构建 - Twitter 专属语法',
|
||
pass: false,
|
||
result: `✗ 错误: ${error.message}`
|
||
})
|
||
failCount++
|
||
}
|
||
|
||
// 测试 5: 参数验证
|
||
try {
|
||
const adapter = SearchAdapterFactory.getAdapter('twitter')
|
||
const result = adapter.validateParams({
|
||
keyword: 'test',
|
||
engine: 'twitter',
|
||
fromUser: '@valid_user',
|
||
minRetweets: 10
|
||
})
|
||
|
||
tests.push({
|
||
name: '参数验证 - 有效参数',
|
||
pass: result.isValid,
|
||
result: result.isValid
|
||
? `✓ 验证通过: 无错误`
|
||
: `✗ 验证失败: ${result.errors.join(', ')}`
|
||
})
|
||
|
||
if (result.isValid) passCount++
|
||
else failCount++
|
||
} catch (error) {
|
||
tests.push({
|
||
name: '参数验证 - 有效参数',
|
||
pass: false,
|
||
result: `✗ 错误: ${error.message}`
|
||
})
|
||
failCount++
|
||
}
|
||
|
||
// 测试 6: 语法支持检查
|
||
try {
|
||
const adapter = SearchAdapterFactory.getAdapter('twitter')
|
||
const supportedSyntax = adapter.getSupportedSyntax()
|
||
const hasFromUser = supportedSyntax.includes('from_user')
|
||
const hasToUser = supportedSyntax.includes('to_user')
|
||
const hasFilter = supportedSyntax.includes('filter')
|
||
const hasMinRetweets = supportedSyntax.includes('min_retweets')
|
||
|
||
const allSupported = hasFromUser && hasToUser && hasFilter && hasMinRetweets
|
||
|
||
tests.push({
|
||
name: '语法支持 - Twitter 专属语法类型',
|
||
pass: allSupported,
|
||
result: allSupported
|
||
? `✓ 支持所有 Twitter 语法: ${supportedSyntax.filter(s => s.includes('_')).join(', ')}`
|
||
: `✗ 缺少某些 Twitter 语法`
|
||
})
|
||
|
||
if (allSupported) passCount++
|
||
else failCount++
|
||
} catch (error) {
|
||
tests.push({
|
||
name: '语法支持 - Twitter 专属语法类型',
|
||
pass: false,
|
||
result: `✗ 错误: ${error.message}`
|
||
})
|
||
failCount++
|
||
}
|
||
|
||
// 渲染测试结果
|
||
tests.forEach(test => {
|
||
const testItem = document.createElement('div')
|
||
testItem.className = 'test-item'
|
||
testItem.innerHTML = `
|
||
<h3>${test.pass ? '✅' : '❌'} ${test.name}</h3>
|
||
<div class="test-result">${test.result}</div>
|
||
`
|
||
testsDiv.appendChild(testItem)
|
||
})
|
||
|
||
// 渲染总览
|
||
const totalTests = passCount + failCount
|
||
const passRate = totalTests > 0 ? ((passCount / totalTests) * 100).toFixed(1) : 0
|
||
|
||
summaryDiv.innerHTML = `
|
||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
|
||
<div style="background: white; padding: 20px; border-radius: 8px; text-align: center;">
|
||
<div style="font-size: 2.5rem; color: #667eea; font-weight: 700;">${totalTests}</div>
|
||
<div style="color: #6c757d; margin-top: 5px;">总测试数</div>
|
||
</div>
|
||
<div style="background: white; padding: 20px; border-radius: 8px; text-align: center;">
|
||
<div style="font-size: 2.5rem; color: #28a745; font-weight: 700;">${passCount}</div>
|
||
<div style="color: #6c757d; margin-top: 5px;">通过</div>
|
||
</div>
|
||
<div style="background: white; padding: 20px; border-radius: 8px; text-align: center;">
|
||
<div style="font-size: 2.5rem; color: #dc3545; font-weight: 700;">${failCount}</div>
|
||
<div style="color: #6c757d; margin-top: 5px;">失败</div>
|
||
</div>
|
||
<div style="background: white; padding: 20px; border-radius: 8px; text-align: center;">
|
||
<div style="font-size: 2.5rem; color: ${passRate === '100.0' ? '#28a745' : '#ffc107'}; font-weight: 700;">${passRate}%</div>
|
||
<div style="color: #6c757d; margin-top: 5px;">通过率</div>
|
||
</div>
|
||
</div>
|
||
${passRate === '100.0' ? '<div style="margin-top: 20px; padding: 15px; background: #d4edda; color: #155724; border-radius: 8px; text-align: center; font-weight: 600;">🎉 所有测试通过!Twitter 集成成功!</div>' : ''}
|
||
`
|
||
}
|
||
|
||
// 页面加载时自动运行测试
|
||
window.addEventListener('load', runTests)
|
||
</script>
|
||
</body>
|
||
</html>
|