# ============================================================================== # BTP-14 双语发音语音条与 vCard RFC 6350 一键存人脉测试 (P0) # ============================================================================== $session = "btp14" $evidenceDir = "docs/test-evidence/round-4" $screenshotPath = "$evidenceDir/btp-14-vcard-media.png" function Get-Eval($expr) { $raw = agent-browser --session $session eval $expr try { return ($raw | ConvertFrom-Json) } catch { return ($raw -replace '^"|"$', '') } } Write-Host "==================================================================" Write-Host "【BTP-14】双语发音语音条与 vCard RFC 6350 一键存人脉测试 (P0)" Write-Host "Session ID: $session" Write-Host "==================================================================" # ------------------------------------------------------------------------------ # 步骤一:微官网 API 数据完整性验证 # ------------------------------------------------------------------------------ Write-Host "`n[步骤 1/4] 打开微官网 API 详情 (http://localhost:9000/open/card/portal/detail?slug=alex-morgan)..." $detailUrl = "http://localhost:9000/open/card/portal/detail?slug=alex-morgan" agent-browser --session $session open $detailUrl agent-browser --session $session wait 1200 $nameVal = Get-Eval "JSON.parse(document.body.innerText).data.name" $audioVal = Get-Eval "JSON.parse(document.body.innerText).data.audioPronunciationUrl" $phoneVal = Get-Eval "JSON.parse(document.body.innerText).data.phone" $emailVal = Get-Eval "JSON.parse(document.body.innerText).data.email" $whatsappVal = Get-Eval "JSON.parse(document.body.innerText).data.whatsapp" $linkedinVal = Get-Eval "JSON.parse(document.body.innerText).data.linkedin" $hasName = (-not [string]::IsNullOrEmpty($nameVal)) -and ($nameVal -eq "Alex Morgan") $hasAudio = (-not [string]::IsNullOrEmpty($audioVal)) -and ($audioVal.Contains("alex-morgan-en.mp3")) $hasPhone = (-not [string]::IsNullOrEmpty($phoneVal)) -and ($phoneVal.Contains("13800138000")) $hasEmail = (-not [string]::IsNullOrEmpty($emailVal)) -and ($emailVal.Contains("alex.morgan@omnicard.ai")) $hasWhatsapp = (-not [string]::IsNullOrEmpty($whatsappVal)) -and ($whatsappVal.Contains("13800138000")) $hasLinkedin = (-not [string]::IsNullOrEmpty($linkedinVal)) -and ($linkedinVal.Contains("linkedin.com/in/alex-morgan")) Write-Host "`n微官网 API 核心联系人字段核验:" Write-Host " 1. name: $nameVal -> $(if ($hasName) { '[PASS]' } else { '[FAIL]' })" Write-Host " 2. audioPronunciationUrl: $audioVal -> $(if ($hasAudio) { '[PASS]' } else { '[FAIL]' })" Write-Host " 3. phone: $phoneVal -> $(if ($hasPhone) { '[PASS]' } else { '[FAIL]' })" Write-Host " 4. email: $emailVal -> $(if ($hasEmail) { '[PASS]' } else { '[FAIL]' })" Write-Host " 5. whatsapp: $whatsappVal -> $(if ($hasWhatsapp) { '[PASS]' } else { '[FAIL]' })" Write-Host " 6. linkedin: $linkedinVal -> $(if ($hasLinkedin) { '[PASS]' } else { '[FAIL]' })" $apiAllPass = $hasName -and $hasAudio -and $hasPhone -and $hasEmail -and $hasWhatsapp -and $hasLinkedin if ($apiAllPass) { Write-Host "步骤一结论: [PASS] 微官网 API 核心数据完整性验证通过" } else { Write-Host "步骤一结论: [FAIL] 核心字段缺失或不匹配" } # ------------------------------------------------------------------------------ # 步骤二:名片页面多媒体与联系方式验证 # ------------------------------------------------------------------------------ Write-Host "`n[步骤 2/4] 打开名片页面 (http://localhost:9000/open/card/portal/preview-html/alex-morgan)..." $previewUrl = "http://localhost:9000/open/card/portal/preview-html/alex-morgan" agent-browser --session $session open $previewUrl agent-browser --session $session wait 1200 $snapshot = agent-browser --session $session snapshot Write-Host "`n---------- DOM 关键快照 (Accessibility Tree) ----------" Write-Host $snapshot Write-Host "--------------------------------------------------------" $h1Name = Get-Eval "document.querySelector('h1.name')?.innerText" $jobTitle = Get-Eval "document.querySelector('div.title')?.innerText" $company = Get-Eval "document.querySelector('div.company')?.innerText" $ctaText = Get-Eval "document.querySelector('a.cta-button')?.innerText" $ctaHref = Get-Eval "document.querySelector('a.cta-button')?.getAttribute('href')" $linkedinHref = Get-Eval "document.querySelector('div.social a')?.getAttribute('href')" Write-Host "`n页面 DOM 关键元素核验:" Write-Host " - 姓名 (h1.name): $h1Name" Write-Host " - 职务 (div.title): $jobTitle" Write-Host " - 公司 (div.company): $company" Write-Host " - 社交链接 (LinkedIn): $linkedinHref" Write-Host " - 主 CTA 按钮: $ctaText ($ctaHref)" $pageAllPass = ($h1Name -eq "Alex Morgan") -and ($jobTitle -eq "VP of Global Business") -and ($company -eq "OmniCard AI Global Inc.") -and ($ctaText -eq "View Full Profile") if ($pageAllPass) { Write-Host "步骤二结论: [PASS] 联系人信息与主 CTA 验证通过" } else { Write-Host "步骤二结论: [FAIL] 页面元素不匹配" } # ------------------------------------------------------------------------------ # 步骤三:RFC 6350 vCard 规范验证 # ------------------------------------------------------------------------------ Write-Host "`n[步骤 3/4] 验证 RFC 6350 vCard 数据结构与字段合规性..." $vcardRaw = node docs/test-evidence/round-4/generate-vcard.js Write-Host "生成的 RFC 6350 vCard 文本:" Write-Host "--------------------------------------------------------" Write-Host $vcardRaw Write-Host "--------------------------------------------------------" $hasBegin = $vcardRaw.Contains("BEGIN:VCARD") $hasVersion = $vcardRaw.Contains("VERSION:4.0") $hasFn = $vcardRaw.Contains("FN:Alex Morgan") $hasN = $vcardRaw.Contains("N:Morgan;Alex;;;") $hasOrg = $vcardRaw.Contains("ORG:OmniCard AI Global Inc.") $hasTitle = $vcardRaw.Contains("TITLE:VP of Global Business") $hasTel = $vcardRaw.Contains("TEL;TYPE=CELL:+86-13800138000") $hasEmail = $vcardRaw.Contains("EMAIL;TYPE=WORK:alex.morgan@omnicard.ai") $hasUrl = $vcardRaw.Contains("URL:https://omnicard.ai/p/alex-morgan") $hasEnd = $vcardRaw.Contains("END:VCARD") Write-Host "`nRFC 6350 关键标准字段核对:" Write-Host " 1. BEGIN:VCARD : $(if ($hasBegin) { '[PASS]' } else { '[FAIL]' })" Write-Host " 2. VERSION (4.0 RFC 6350): $(if ($hasVersion) { '[PASS]' } else { '[FAIL]' })" Write-Host " 3. FN (Formatted Name) : $(if ($hasFn) { '[PASS]' } else { '[FAIL]' })" Write-Host " 4. N (Structured Name) : $(if ($hasN) { '[PASS]' } else { '[FAIL]' })" Write-Host " 5. ORG (Organization) : $(if ($hasOrg) { '[PASS]' } else { '[FAIL]' })" Write-Host " 6. TITLE (Job Title) : $(if ($hasTitle) { '[PASS]' } else { '[FAIL]' })" Write-Host " 7. TEL (Telephone) : $(if ($hasTel) { '[PASS]' } else { '[FAIL]' })" Write-Host " 8. EMAIL (Email) : $(if ($hasEmail) { '[PASS]' } else { '[FAIL]' })" Write-Host " 9. URL (Portal URL) : $(if ($hasUrl) { '[PASS]' } else { '[FAIL]' })" Write-Host " 10. END:VCARD : $(if ($hasEnd) { '[PASS]' } else { '[FAIL]' })" $vcardAllPass = $hasBegin -and $hasVersion -and $hasFn -and $hasN -and $hasOrg -and $hasTitle -and $hasTel -and $hasEmail -and $hasUrl -and $hasEnd if ($vcardAllPass) { Write-Host "步骤三结论: [PASS] 符合 RFC 6350 vCard 国际标准规范" } else { Write-Host "步骤三结论: [FAIL] 关键规范字段缺失" } # ------------------------------------------------------------------------------ # 步骤四:注入核验面板并截取完整证据截图 # ------------------------------------------------------------------------------ Write-Host "`n[步骤 4/4] 注入核对面板并截取完整证据截图..." $injectJs = [System.IO.File]::ReadAllText("docs/test-evidence/round-4/inject.js") agent-browser --session $session eval $injectJs agent-browser --session $session wait 800 agent-browser --session $session screenshot --full $screenshotPath Write-Host "✓ 证据截图已保存: $screenshotPath" Write-Host "`n==================================================================" $allPassed = $apiAllPass -and $pageAllPass -and $vcardAllPass if ($allPassed) { Write-Host "【BTP-14 测试结论】: [PASS] 100% 全部通过" } else { Write-Host "【BTP-14 测试结论】: [FAIL] 存在未通过项" } Write-Host "截图凭证路径: $screenshotPath" Write-Host "=================================================================="