22 lines
3.8 KiB
PowerShell
22 lines
3.8 KiB
PowerShell
$ErrorActionPreference = 'Stop'
|
|
function Assert-Contains { param([string]$Content,[string]$Expected,[string]$Message); if($Content -notmatch [regex]::Escape($Expected)){ throw $Message } }
|
|
$root=Split-Path -Parent $PSScriptRoot
|
|
$files=@('pages/family/f01-family-feed.vue','pages/family/f02-publish-feed.vue','pages/notification/n01-message-center.vue','pages/profile/m01-profile-home.vue')
|
|
$pages=@{}
|
|
foreach($file in $files){$content=Get-Content -LiteralPath(Join-Path $root $file)-Raw -Encoding utf8;if($content-match"@/utils/api\.js|\bappApi\b"){ throw "$file must not connect the API layer" };Assert-Contains $content 'ModulePageBackground' "$file must use its module background";$pages[$file]=$content}
|
|
$g01=Get-Content -LiteralPath(Join-Path $root 'pages/genealogy/g01-my-genealogies.vue')-Raw -Encoding utf8
|
|
if($g01-notmatch"@/utils/api\.js" -or $g01-notmatch"\bappApi\.getMyGenealogies\b"){ throw 'G01 must consume its tested remote list owner' }
|
|
Assert-Contains $g01 'GenealogyPageBackground' 'G01 must use its genealogy background'
|
|
if($g01 -notmatch '(?s)<PageHeader\s+root\s+notice\s+title="我的家谱"[^>]+@notice="toNotifications"') { throw 'G01 root header must expose the notice action without a back control' }
|
|
if($pages['pages/family/f01-family-feed.vue'] -notmatch '(?s)<PageHeader\s+root\s+title="家族动态"\s+:action="hasValidContext \? ''发布'' : ''''"\s+@action="toPublish"') { throw 'F01 root header must expose publish only for a valid family context and without a back control' }
|
|
if($pages['pages/profile/m01-profile-home.vue'] -notmatch '(?s)<PageHeader\s+root\s+title="我的"[^>]+@action="toProfile"') { throw 'M01 root header must expose profile editing without a back control' }
|
|
foreach($required in @('feed-state--list','feed-state--empty','feed-state--error','@include adaptive-family-letter;','openPage("F02"')){Assert-Contains $pages['pages/family/f01-family-feed.vue'] $required "Missing F01 contract: $required"}
|
|
foreach($required in @('publish-state--form','publish-state--preview','publish-state--error','publish-state--invalid','@include adaptive-family-content;','@include adaptive-family-field;','AppButton','AppDialog','AppToast')){Assert-Contains $pages['pages/family/f02-publish-feed.vue'] $required "Missing F02 contract: $required"}
|
|
foreach($required in @('notice-state--loading','notice-state--list','notice-state--empty','notice-state--error','@include adaptive-notification-content;','AppButton','AppLoading','AppToast')){Assert-Contains $pages['pages/notification/n01-message-center.vue'] $required "Missing N01 contract: $required"}
|
|
if($pages['pages/notification/n01-message-center.vue'] -notmatch '(?s)openPage\(\s*"G10",\s*\{ genealogyId: genealogyId\.value \},\s*"N01",?\s*\)'){throw 'N01 review entry must use the registered G10 route with N01 as source'}
|
|
if($pages['pages/notification/n01-message-center.vue']-match'application-status-card\.png'){throw 'N01 must not reuse the genealogy application card'}
|
|
foreach($required in @('profile-state--ready','profile-state--error','@include adaptive-profile-summary;','brand-seal.png','auth-divider-knot.png','chevron-right.png','AppButton','openPage("M02", {}, "M01")')){Assert-Contains $pages['pages/profile/m01-profile-home.vue'] $required "Missing M01 contract: $required"}
|
|
foreach($entry in @($pages['pages/notification/n01-message-center.vue'],$pages['pages/profile/m01-profile-home.vue'])){if($entry-match'/pages/'){throw 'N01 and M01 must not embed raw business page paths'}}
|
|
foreach($forbidden in @('m01-profile-notice-card.png','m01-profile-menu-frame.png','g03-create-flow-panel.png','g06-search-input-wide.png','application-status-card.png')){if($pages['pages/profile/m01-profile-home.vue']-match[regex]::Escape($forbidden)){throw "M01 must not reuse repeated or opaque business asset: $forbidden"}}
|
|
Write-Output 'ROOT-PAGES-VISUAL-CONTRACT PASS'
|