@@ -253,3 +253,83 @@ Describe 'setup-dev uv bootstrap' -Tag 'Unit' {
253253 } | Should - Throw ' Failed to install uv v0.11.21'
254254 }
255255}
256+
257+ $script :GitBashPath = Join-Path $env: ProgramFiles ' Git/bin/bash.exe'
258+ $script :BashAvailable = (Test-Path - LiteralPath $script :GitBashPath ) -or
259+ $null -ne (Get-Command bash - ErrorAction SilentlyContinue)
260+
261+ Describe ' Bash launcher accessibility contracts' - Tag ' Unit' {
262+ BeforeAll {
263+ $script :RepositoryRoot = Resolve-Path (Join-Path $PSScriptRoot ' ../..' )
264+ $gitBash = if ($env: ProgramFiles ) {
265+ Join-Path $env: ProgramFiles ' Git/bin/bash.exe'
266+ }
267+ else {
268+ $null
269+ }
270+ $script :BashExecutable = if ($gitBash -and (Test-Path - LiteralPath $gitBash )) {
271+ $gitBash
272+ }
273+ else {
274+ ' bash'
275+ }
276+ function ConvertTo-BashPath {
277+ param ([string ]$Path )
278+
279+ $normalized = $Path.Replace (' \' , ' /' )
280+ if ($script :BashExecutable -ne ' bash' ) {
281+ return $normalized
282+ }
283+ if ($normalized -match ' ^([A-Za-z]):/(.*)$' ) {
284+ return " /mnt/$ ( $Matches [1 ].ToLowerInvariant()) /$ ( $Matches [2 ]) "
285+ }
286+ return $normalized
287+ }
288+
289+ $script :SetupDevBashPath = ConvertTo-BashPath (Join-Path $script :RepositoryRoot ' setup-dev.sh' )
290+ $script :ViewerStartPath = ConvertTo-BashPath (
291+ Join-Path $script :RepositoryRoot ' data-management/viewer/start.sh'
292+ )
293+ }
294+
295+ It ' Provides setup help without requiring deployment tools' - Skip:(-not $script :BashAvailable ) {
296+ $output = & $script :BashExecutable $script :SetupDevBashPath -- help 2>&1
297+
298+ $LASTEXITCODE | Should - Be 0
299+ $output -join " `n " | Should -Match ' Usage:'
300+ $output -join " `n " | Should -Match ' --config-preview'
301+ }
302+
303+ It ' Previews setup configuration without mutation' - Skip:(-not $script :BashAvailable ) {
304+ $output = & $script :BashExecutable $script :SetupDevBashPath -- config- preview 2>&1
305+
306+ $LASTEXITCODE | Should - Be 0
307+ $output -join " `n " | Should -Match ' Configuration Preview'
308+ $output -join " `n " | Should -Match ' Mutation.*None'
309+ }
310+
311+ It ' Previews Viewer configuration without ANSI output when NO_COLOR is present' - Skip:(-not $script :BashAvailable ) {
312+ $originalNoColor = $env: NO_COLOR
313+ try {
314+ $env: NO_COLOR = ' 1'
315+ $output = & $script :BashExecutable $script :ViewerStartPath -- config- preview 2>&1
316+ }
317+ finally {
318+ $env: NO_COLOR = $originalNoColor
319+ }
320+
321+ $LASTEXITCODE | Should - Be 0
322+ $text = $output -join " `n "
323+ $text | Should -Match ' Configuration Preview'
324+ $text | Should -Match ' Mutation.*None'
325+ $text | Should -Not -Match ([regex ]::Escape([char ]27 ))
326+ }
327+
328+ It ' Rejects an unknown Viewer option with visible recovery guidance' - Skip:(-not $script :BashAvailable ) {
329+ $output = & $script :BashExecutable $script :ViewerStartPath - -not - a- real- option 2>&1
330+
331+ $LASTEXITCODE | Should -Not - Be 0
332+ $output -join " `n " | Should -Match ' Unknown option.*--not-a-real-option'
333+ $output -join " `n " | Should -Match ' Usage:'
334+ }
335+ }
0 commit comments