Files
jiapuapp/tests/global-heritage-visual-system-contract.ps1
T
2026-07-21 20:59:10 +08:00

88 lines
4.4 KiB
PowerShell

$ErrorActionPreference = 'Stop'
Add-Type -AssemblyName System.Drawing
$root = Split-Path -Parent $PSScriptRoot
$componentsRoot = Join-Path $root 'components'
$pagesRoot = Join-Path $root 'pages'
function Read-Utf8([string]$Path) {
return Get-Content -Raw -Encoding UTF8 $Path
}
foreach ($component in @('AppButton.vue', 'AppDialog.vue', 'AppToast.vue', 'AppLoading.vue', 'ModulePageBackground.vue')) {
$path = Join-Path $componentsRoot $component
if (-not (Test-Path -LiteralPath $path)) { throw "Missing global visual component: $component" }
}
$button = Read-Utf8 (Join-Path $componentsRoot 'AppButton.vue')
$profiles = Read-Utf8 (Join-Path $root 'styles/adaptive-frame-profiles.scss')
if ($button -notmatch 'adaptive-scroll-button' -or $profiles -notmatch 'a01-scroll-primary-v3\.png') { throw 'AppButton does not consume the approved A-series primary scroll profile.' }
if ($button -notmatch 'adaptive-scroll-button' -or $profiles -notmatch 'a01-scroll-secondary-v3\.png') { throw 'AppButton does not consume the approved A-series secondary scroll profile.' }
$dialog = Read-Utf8 (Join-Path $componentsRoot 'AppDialog.vue')
if ($dialog -notmatch 'adaptive-auth-dialog' -or $profiles -notmatch 'a01-scroll-dialog-v3\.png') { throw 'AppDialog does not consume the approved A-series dialog profile.' }
$toast = Read-Utf8 (Join-Path $componentsRoot 'AppToast.vue')
if ($toast -notmatch 'adaptive-feedback-toast' -or $profiles -notmatch 'a01-scroll-toast-v3\.png') { throw 'AppToast does not consume the approved A-series toast profile.' }
$header = Read-Utf8 (Join-Path $componentsRoot 'PageHeader.vue')
if ($header -notmatch 'chevron-right\.png') { throw 'PageHeader does not use the approved image arrow.' }
if ($header -match '\{\{\s*backLabel\s*\}\}') { throw 'PageHeader still renders a text back label.' }
if ($header -notmatch 'scaleX\(-1\)') { throw 'PageHeader back arrow is not oriented toward the previous page.' }
$activeSources = @(
Get-ChildItem -LiteralPath $componentsRoot -Recurse -File -Filter '*.vue'
Get-ChildItem -LiteralPath $pagesRoot -Recurse -File -Filter '*.vue' | Where-Object { $_.Name -ne 'a06-auth-status.vue' }
)
foreach ($source in $activeSources) {
$content = Read-Utf8 $source.FullName
foreach ($forbidden in @(
'uni.showToast',
'uni.showModal',
'uni.showLoading',
'uni.showActionSheet',
'/static/assets/foundation/opaque/a01-primary-button.png',
'/static/assets/foundation/opaque/a01-secondary-button.png'
)) {
if ($content.Contains($forbidden)) { throw "$($source.FullName) still contains forbidden global UI path: $forbidden" }
}
}
$background = Read-Utf8 (Join-Path $componentsRoot 'ModulePageBackground.vue')
$moduleAssets = @{
tree = 'tree-page-background-long.png'
family = 'family-page-background-long.png'
records = 'records-page-background-long.png'
notification = 'notification-page-background-long.png'
profile = 'profile-page-background-long.png'
}
foreach ($entry in $moduleAssets.GetEnumerator()) {
if ($background -notmatch [regex]::Escape($entry.Value)) { throw "ModulePageBackground is missing $($entry.Key) mapping." }
$asset = Get-ChildItem -LiteralPath (Join-Path $root 'static/assets/modules') -Recurse -File -Filter $entry.Value
if (-not $asset) { throw "Missing module background asset: $($entry.Value)" }
$image = [System.Drawing.Image]::FromFile($asset.FullName)
try {
if ($image.Width -ne 1440 -or $image.Height -ne 3600) {
throw "$($entry.Value) must be 1440x3600, got $($image.Width)x$($image.Height)."
}
}
finally {
$image.Dispose()
}
}
$modulePage = Read-Utf8 (Join-Path $componentsRoot 'ModulePage.vue')
foreach ($token in @('<ModulePageBackground', '<AppButton', '<AppToast')) {
if ($modulePage -notmatch [regex]::Escape($token)) { throw "ModulePage does not consume $token." }
}
$g01 = Read-Utf8 (Join-Path $pagesRoot 'genealogy/g01-my-genealogies.vue')
if ($g01 -notmatch '(?s)\.current-meta\s*\{[^}]*color:\s*#62584c;[^}]*font-weight:\s*500;') { throw 'G01 current genealogy metadata is not using the approved readable style.' }
$genealogyCard = Read-Utf8 (Join-Path $componentsRoot 'GenealogyCard.vue')
foreach ($selector in @('card-meta', 'card-updated', 'card-role')) {
if ($genealogyCard -notmatch "(?s)\.$selector\s*\{[^}]*color:\s*#62584c;[^}]*font-weight:\s*500;") { throw "GenealogyCard $selector is not using the approved readable style." }
}
Write-Output 'PASS global heritage visual system contract'