Files
jiapuapp/tests/shared-component-document-flow-contract.ps1
T
2026-07-21 07:53:08 +08:00

64 lines
4.4 KiB
PowerShell

$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent $PSScriptRoot
function Read-Utf8([string]$Path) {
[System.IO.File]::ReadAllText((Join-Path $root $Path), [System.Text.Encoding]::UTF8)
}
function Assert-Match([string]$Content, [string]$Pattern, [string]$Message) {
if ($Content -notmatch $Pattern) { throw $Message }
}
$button = Read-Utf8 'components/AppButton.vue'
$header = Read-Utf8 'components/PageHeader.vue'
$card = Read-Utf8 'components/GenealogyCard.vue'
$dialog = Read-Utf8 'components/AppDialog.vue'
$loading = Read-Utf8 'components/AppLoading.vue'
$toast = Read-Utf8 'components/AppToast.vue'
if ($button -match '(?im)(?<![-\w])position\s*:') {
throw 'AppButton must use grid overlay instead of positioning'
}
Assert-Match $button '(?s)\.app-button\s*\{[^}]*display:\s*inline-grid;[^}]*place-items:\s*center;' 'AppButton root must own the shared grid overlay'
Assert-Match $button '(?s)\.app-button--block\s*\{[^}]*display:\s*grid;' 'AppButton block variant must preserve the grid overlay'
Assert-Match $button '(?s)\.app-button__skin,\s*\.app-button__label\s*\{[^}]*grid-area:\s*1 / 1;' 'AppButton skin and label must share one grid cell'
Assert-Match $header '(?s)\.page-header--root \.header-side,\s*\.page-header--root \.header-title\s*\{[^}]*z-index:\s*2;' 'PageHeader root content must remain above decorations as flex items'
if ($header -match '(?s)\.page-header--root \.header-side,\s*\.page-header--root \.header-title\s*\{[^}]*position\s*:') {
throw 'PageHeader root content must not use positioning'
}
Assert-Match $header '(?s)\.header-icon-button\s*\{[^}]*display:\s*grid;[^}]*place-items:\s*center;' 'PageHeader icon button must use a grid overlay'
if ($header -match '(?s)\.header-icon-button\s*\{[^}]*position\s*:') {
throw 'PageHeader icon button must not be a positioning context'
}
Assert-Match $header '(?s)\.header-logo,\s*\.header-notice-icon,\s*\.notice-dot\s*\{[^}]*grid-area:\s*1 / 1;' 'PageHeader icon and notice dot must share one grid cell'
if ($header -match '(?s)\.notice-dot\s*\{[^}]*position\s*:') {
throw 'PageHeader notice dot must use grid alignment instead of positioning'
}
if ($card -match '(?im)(?<![-\w])position\s*:') {
throw 'GenealogyCard must use grid instead of positioning'
}
Assert-Match $card '(?s)\.genealogy-card\s*\{[^}]*display:\s*grid;[^}]*grid-template-columns:\s*72rpx minmax\(0, 1fr\);[^}]*column-gap:\s*22rpx;' 'GenealogyCard must own the two-column document-flow grid'
Assert-Match $card '(?s)\.row-frame\s*\{[^}]*grid-area:\s*1 / 1 / 2 / -1;[^}]*z-index:\s*1;[^}]*width:\s*calc\(100% \+ var\(--card-padding-x\) \+ var\(--card-padding-x\)\);[^}]*height:\s*calc\(100% \+ var\(--card-padding-y\) \+ var\(--card-padding-y\)\);[^}]*margin:\s*calc\(-1 \* var\(--card-padding-y\)\) calc\(-1 \* var\(--card-padding-x\)\);' 'GenealogyCard row frame must span the padded card grid above the fixed page background'
Assert-Match $card '(?s)\.surname-seal\s*\{[^}]*display:\s*grid;[^}]*grid-row:\s*1;[^}]*z-index:\s*2;[^}]*place-items:\s*center;' 'GenealogyCard surname seal must share the frame row and stay above it'
Assert-Match $card '(?s)\.card-main\s*\{[^}]*grid-row:\s*1;[^}]*z-index:\s*2;' 'GenealogyCard content must share the frame row and stay above it'
Assert-Match $card '(?s)\.surname-seal-frame,\s*\.surname-seal-copy\s*\{[^}]*grid-area:\s*1 / 1;' 'GenealogyCard seal frame and copy must share one grid cell'
if ($card -match '(?s)\.card-name\s*\{[^}]*(?:overflow:\s*hidden|text-overflow:\s*ellipsis|white-space:\s*nowrap)') {
throw 'GenealogyCard name must wrap instead of clipping data-driven content'
}
foreach ($selector in @('card-meta', 'card-updated', 'card-role')) {
if ($card -match "(?s)\.$selector\s*\{[^}]*white-space:\s*nowrap") {
throw "GenealogyCard .$selector must wrap instead of fixing text capacity"
}
}
if ($dialog -match '(?s)\.app-dialog\s*\{[^}]*position\s*:|(?s)\.app-dialog__content\s*\{[^}]*position\s*:') {
throw 'AppDialog internal content must not use positioning'
}
Assert-Match $dialog '(?s)\.app-dialog\s*\{[^}]*background:\s*url\("/static/assets/modules/auth/transparent/a01-scroll-dialog-v3\.png"\)' 'AppDialog must render its approved dialog asset as the dialog background'
if ($loading -match '(?im)(?<![-\w])position\s*:') { throw 'AppLoading must stay in its parent document flow' }
if ($toast -match '(?s)\.app-toast__copy\s*\{[^}]*position\s*:') { throw 'AppToast copy must not create an unnecessary positioning context' }
Write-Output 'SHARED-COMPONENT-DOCUMENT-FLOW-CONTRACT PASS'