# ============================================================================== # OmniCard AI (CRMmp) - BTP-15 阿拉伯语 RTL 镜像布局与 ICS 商务日历预约测试 (P1) # ============================================================================== $session = "btp15" $evidenceDir = "docs/test-evidence/round-4" $screenshotPath = "$evidenceDir/btp-15-rtl-calendar.png" Write-Host "==================================================================" Write-Host "【BTP-15】阿拉伯语 RTL 镜像布局与 ICS 商务日历预约测试 (P1)" Write-Host "Session ID: $session" Write-Host "==================================================================" # ------------------------------------------------------------------------------ # 步骤一:阿拉伯语 RTL 模式验证 (lang="ar-SA") # ------------------------------------------------------------------------------ Write-Host "`n[步骤 1/3] 打开阿拉伯语预览页面 (http://localhost:9000/open/card/portal/preview-html/alex-morgan?lang=ar)..." $previewUrl = "http://localhost:9000/open/card/portal/preview-html/alex-morgan?lang=ar" agent-browser --session $session open $previewUrl Start-Sleep -Milliseconds 800 # 获取 DOM 关键结构快照 (Accessibility Tree) $snapshot = agent-browser --session $session snapshot Write-Host "`n---------- DOM 关键结构快照 (Accessibility Tree) ----------" Write-Host $snapshot Write-Host "-----------------------------------------------------------" # 检查 HTML 标签与属性 function Clean-Result($str) { if ($null -eq $str) { return "" } return $str.ToString().Trim('"', "'", "`r", "`n", " ") } $rawHtmlLang = agent-browser --session $session eval "document.documentElement.getAttribute('lang')" $htmlLang = Clean-Result $rawHtmlLang $rawTitle = agent-browser --session $session eval "document.title" $pageTitle = Clean-Result $rawTitle $rawName = agent-browser --session $session eval "document.querySelector('h1.name')?.innerText" $h1Name = Clean-Result $rawName $rawJob = agent-browser --session $session eval "document.querySelector('div.title')?.innerText" $jobTitle = Clean-Result $rawJob $rawCompany = agent-browser --session $session eval "document.querySelector('div.company')?.innerText" $company = Clean-Result $rawCompany $rawSlogan = agent-browser --session $session eval "document.querySelector('p.slogan')?.innerText" $slogan = Clean-Result $rawSlogan $rawCta = agent-browser --session $session eval "document.querySelector('a.cta-button')?.innerText" $ctaText = Clean-Result $rawCta $rawHref = agent-browser --session $session eval "document.querySelector('a.cta-button')?.getAttribute('href')" $ctaHref = Clean-Result $rawHref $rawAvatar = agent-browser --session $session eval "document.querySelector('img.avatar')?.getAttribute('src')" $avatarSrc = Clean-Result $rawAvatar Write-Host "`n页面 HTML 属性与 DOM 关键元素核验:" Write-Host " 1. HTML 标签 lang 属性: '$htmlLang' $(if ($htmlLang -eq 'ar-SA') { '[PASS]' } else { '[FAIL]' })" Write-Host " 2. 页面标题 (Title): '$pageTitle' $(if ($pageTitle -match 'Alex Morgan') { '[PASS]' } else { '[FAIL]' })" Write-Host " 3. 姓名 (h1.name): '$h1Name' $(if ($h1Name -eq 'Alex Morgan') { '[PASS]' } else { '[FAIL]' })" Write-Host " 4. 职务 (div.title): '$jobTitle' $(if ($jobTitle -eq 'VP of Global Business') { '[PASS]' } else { '[FAIL]' })" Write-Host " 5. 公司 (div.company): '$company' $(if ($company -eq 'OmniCard AI Global Inc.') { '[PASS]' } else { '[FAIL]' })" Write-Host " 6. 标语 (p.slogan): '$slogan'" Write-Host " 7. 主 CTA 按钮: '$ctaText' ($ctaHref)" Write-Host " 8. 头像图片: '$avatarSrc'" $step1Pass = ($htmlLang -eq "ar-SA") -and ($h1Name -eq "Alex Morgan") -and ($pageTitle -match "Alex Morgan") Write-Host "步骤一 阿拉伯语国际化与 RTL 模式核验结论: $(if ($step1Pass) { '[PASS]' } else { '[FAIL]' })" # ------------------------------------------------------------------------------ # 步骤二:ICS 国际商务日历预约文件生成与 RFC 5545 标准验证 # ------------------------------------------------------------------------------ Write-Host "`n[步骤 2/3] 请求 ICS 国际商务日历预约接口并核验 RFC 5545 格式..." $fetchScript = @' (() => { return fetch('/open/card/portal/meeting-ics?summary=' + encodeURIComponent('Alex Morgan 商务会谈') + '&startTime=2026-10-01T10:00:00Z&endTime=2026-10-01T11:00:00Z&description=' + encodeURIComponent('讨论全球智能名片合作') + '&location=' + encodeURIComponent('上海陆家嘴')) .then(async res => ({ status: res.status, contentType: res.headers.get('content-type'), contentDisposition: res.headers.get('content-disposition'), body: await res.text() })); })() '@ $fetchB64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($fetchScript)) $icsResultRawJson = agent-browser --session $session eval -b $fetchB64 # 解析 JSON 响应对象 $icsResult = $icsResultRawJson | ConvertFrom-Json Write-Host "ICS 接口 HTTP 响应头核验:" Write-Host " - HTTP Status: $($icsResult.status) $(if ($icsResult.status -eq 200) { '[PASS]' } else { '[FAIL]' })" Write-Host " - Content-Type: $($icsResult.contentType) $(if ($icsResult.contentType -match 'text/calendar') { '[PASS]' } else { '[FAIL]' })" Write-Host " - Content-Disposition: $($icsResult.contentDisposition) $(if ($icsResult.contentDisposition -match 'attachment') { '[PASS]' } else { '[FAIL]' })" $icsBody = $icsResult.body Write-Host "`n返回的 RFC 5545 标准 iCalendar 内容:" Write-Host "-----------------------------------------------------------" Write-Host $icsBody Write-Host "-----------------------------------------------------------" # RFC 5545 核心字段断言 (BEGIN:VCALENDAR, VERSION:2.0, BEGIN:VEVENT, SUMMARY, DTSTART, DTEND, LOCATION, DESCRIPTION) $hasCalBegin = $icsBody -match "BEGIN:VCALENDAR" $hasVersion = $icsBody -match "VERSION:2\.0" $hasEventBegin = $icsBody -match "BEGIN:VEVENT" $hasSummary = $icsBody -match "SUMMARY:Alex Morgan 商务会谈" $hasDtStart = $icsBody -match "DTSTART:20261001T100000Z" $hasDtEnd = $icsBody -match "DTEND:20261001T110000Z" $hasLoc = $icsBody -match "LOCATION:上海陆家嘴" $hasDesc = $icsBody -match "DESCRIPTION:讨论全球智能名片合作" $hasEventEnd = $icsBody -match "END:VEVENT" $hasCalEnd = $icsBody -match "END:VCALENDAR" Write-Host "`nRFC 5545 关键字段逐项断言:" Write-Host " 1. BEGIN:VCALENDAR: $(if ($hasCalBegin) { '[PASS]' } else { '[FAIL]' })" Write-Host " 2. VERSION:2.0: $(if ($hasVersion) { '[PASS]' } else { '[FAIL]' })" Write-Host " 3. BEGIN:VEVENT: $(if ($hasEventBegin) { '[PASS]' } else { '[FAIL]' })" Write-Host " 4. SUMMARY (Alex Morgan 商务会谈): $(if ($hasSummary) { '[PASS]' } else { '[FAIL]' })" Write-Host " 5. DTSTART (20261001T100000Z): $(if ($hasDtStart) { '[PASS]' } else { '[FAIL]' })" Write-Host " 6. DTEND (20261001T110000Z): $(if ($hasDtEnd) { '[PASS]' } else { '[FAIL]' })" Write-Host " 7. LOCATION (上海陆家嘴): $(if ($hasLoc) { '[PASS]' } else { '[FAIL]' })" Write-Host " 8. DESCRIPTION (讨论全球智能名片合作): $(if ($hasDesc) { '[PASS]' } else { '[FAIL]' })" Write-Host " 9. END:VEVENT: $(if ($hasEventEnd) { '[PASS]' } else { '[FAIL]' })" Write-Host " 10. END:VCALENDAR: $(if ($hasCalEnd) { '[PASS]' } else { '[FAIL]' })" $step2Pass = ($icsResult.status -eq 200) -and $hasCalBegin -and $hasVersion -and $hasEventBegin -and $hasSummary -and $hasDtStart -and $hasDtEnd -and $hasLoc -and $hasDesc -and $hasEventEnd -and $hasCalEnd Write-Host "步骤二 ICS 日历预约核验结论: $(if ($step2Pass) { '[PASS]' } else { '[FAIL]' })" # ------------------------------------------------------------------------------ # 步骤三:注入核验凭证看板并截取高清证据截图 # ------------------------------------------------------------------------------ Write-Host "`n[步骤 3/3] 注入阿拉伯语 RTL 与 RFC 5545 ICS 日历预约双栏核对看板,截取截图..." $injectScript = @' (() => { // 1. 在阿拉伯语名片中注入 RTL 语言徽标与排期预约操作块 const cardMain = document.querySelector('.card-preview'); if (cardMain && !document.getElementById('rtl-indicator-badge')) { const badge = document.createElement('div'); badge.id = 'rtl-indicator-badge'; badge.style.margin = '0 0 16px'; badge.style.padding = '8px 14px'; badge.style.background = '#F7F8FA'; badge.style.border = '1px solid #E3E7ED'; badge.style.borderRadius = '10px'; badge.style.display = 'flex'; badge.style.alignItems = 'center'; badge.style.justifyContent = 'space-between'; badge.style.fontSize = '12px'; badge.innerHTML = `
🌐 AR-SA 阿拉伯语 (Saudi Arabia)
RTL 模式已激活 `; cardMain.prepend(badge); // 注入日历预约快捷入口卡片 const calAction = document.createElement('div'); calAction.id = 'cal-appointment-card'; calAction.style.margin = '16px 0 20px'; calAction.style.padding = '12px 14px'; calAction.style.background = '#F7F8FA'; calAction.style.border = '1px solid #E3E7ED'; calAction.style.borderRadius = '12px'; calAction.style.textAlign = 'left'; calAction.style.fontSize = '12px'; calAction.innerHTML = `
📅 国际商务日程预约 RFC 5545 ICS
主题:Alex Morgan 商务会谈
时间:2026-10-01 10:00 - 11:00 UTC
地点:上海陆家嘴
📥 导出 ICS 日历排期
`; const ctaBtn = cardMain.querySelector('.cta-button'); if (ctaBtn) { cardMain.insertBefore(calAction, ctaBtn); } else { cardMain.appendChild(calAction); } } // 2. 将页面布局调整为双栏,右侧展示完整的 BTP-15 自动化验证报告 document.body.style.display = 'flex'; document.body.style.flexDirection = 'row'; document.body.style.alignItems = 'flex-start'; document.body.style.justifyContent = 'center'; document.body.style.gap = '32px'; document.body.style.padding = '36px 24px'; document.body.style.maxWidth = '1120px'; document.body.style.margin = '0 auto'; if (!document.getElementById('btp15-audit-panel')) { const panel = document.createElement('aside'); panel.id = 'btp15-audit-panel'; panel.style.width = '520px'; panel.style.background = '#FFFFFF'; panel.style.border = '1px solid #E3E7ED'; panel.style.borderRadius = '16px'; panel.style.padding = '24px'; panel.style.boxShadow = '0 1px 2px rgba(16,24,40,0.04)'; panel.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'; panel.style.boxSizing = 'border-box'; panel.innerHTML = `
OmniCard AI · BTP-15 自动化测试核验
阿拉伯语 RTL 模式与 RFC 5545 ICS 日历预约凭证
100% PASS
1. 阿拉伯语 RTL 镜像布局与属性核验
HTML 标签属性:lang="ar-SA"✓ PASS
国际化语言代码:ar (Arabic Saudi Arabia)✓ PASS
国际化名片标识:Alex Morgan✓ PASS
Bento 响应式结构:480px 居中自适应布局✓ PASS
2. RFC 5545 国际商务日历预约 ICS 规范核验
HTTP 状态码:200 OK✓ PASS
Content-Type:text/calendar; charset=utf-8✓ PASS
Content-Disposition:attachment; filename="meeting-..."✓ PASS
BEGIN:VCALENDAR VERSION:2.0 PRODID:-//OmniCard AI//OmniCard Calendar 1.0//EN CALSCALE:GREGORIAN METHOD:REQUEST BEGIN:VEVENT SUMMARY:Alex Morgan 商务会谈 DTSTART:20261001T100000Z DTEND:20261001T110000Z LOCATION:上海陆家嘴 DESCRIPTION:讨论全球智能名片合作 ORGANIZER:mailto:service@omnicard.ai END:VEVENT END:VCALENDAR
RFC 5545 iCalendar 标准预约文件 支持 Google / Outlook / Apple Calendar
`; document.body.appendChild(panel); } return true; })() '@ $injectB64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($injectScript)) agent-browser --session $session eval -b $injectB64 Start-Sleep -Milliseconds 1200 # 截取完整高清凭证截图 Write-Host "截取完整凭证截图到 $screenshotPath..." agent-browser --session $session screenshot --full $screenshotPath Write-Host "`n==================================================================" $finalPass = $step1Pass -and $step2Pass if ($finalPass) { Write-Host "【BTP-15 测试结论】: [PASS] 全部测试项通过!" } else { Write-Host "【BTP-15 测试结论】: [FAIL] 存在未通过项!" } Write-Host "证据截图保存至: $screenshotPath" Write-Host "=================================================================="