microsoft/hve-core

Public

mirrored from https://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
feat/claude-support

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

scripts/tests/extension/Prepare-Extension.Tests.ps1

518lines · modecode

1#Requires -Modules Pester
2# Copyright (c) Microsoft Corporation.
3# SPDX-License-Identifier: MIT
4
5BeforeAll {
6 . $PSScriptRoot/../../extension/Prepare-Extension.ps1
7}
8
9Describe 'Get-AllowedMaturities' {
10 It 'Returns only stable for Stable channel' {
11 $result = Get-AllowedMaturities -Channel 'Stable'
12 $result | Should -Be @('stable')
13 }
14
15 It 'Returns all maturities for PreRelease channel' {
16 $result = Get-AllowedMaturities -Channel 'PreRelease'
17 $result | Should -Contain 'stable'
18 $result | Should -Contain 'preview'
19 $result | Should -Contain 'experimental'
20 }
21
22}
23
24Describe 'Get-FrontmatterData' {
25 BeforeAll {
26 $script:tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())
27 New-Item -ItemType Directory -Path $script:tempDir -Force | Out-Null
28 }
29
30 AfterAll {
31 Remove-Item -Path $script:tempDir -Recurse -Force -ErrorAction SilentlyContinue
32 }
33
34 It 'Extracts description and maturity from frontmatter' {
35 $testFile = Join-Path $script:tempDir 'test.md'
36 @'
37---
38description: "Test description"
39maturity: preview
40---
41# Content
42'@ | Set-Content -Path $testFile
43
44 $result = Get-FrontmatterData -FilePath $testFile -FallbackDescription 'fallback'
45 $result.description | Should -Be 'Test description'
46 $result.maturity | Should -Be 'preview'
47 }
48
49 It 'Uses fallback description when not in frontmatter' {
50 $testFile = Join-Path $script:tempDir 'no-desc.md'
51 @'
52---
53maturity: stable
54---
55# Content
56'@ | Set-Content -Path $testFile
57
58 $result = Get-FrontmatterData -FilePath $testFile -FallbackDescription 'My Fallback'
59 $result.description | Should -Be 'My Fallback'
60 }
61
62 It 'Defaults maturity to stable when not specified' {
63 $testFile = Join-Path $script:tempDir 'no-maturity.md'
64 @'
65---
66description: "Desc"
67---
68# Content
69'@ | Set-Content -Path $testFile
70
71 $result = Get-FrontmatterData -FilePath $testFile -FallbackDescription 'fallback'
72 $result.maturity | Should -Be 'stable'
73 }
74}
75
76Describe 'Test-PathsExist' {
77 BeforeAll {
78 $script:tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())
79 New-Item -ItemType Directory -Path $script:tempDir -Force | Out-Null
80 $script:extDir = Join-Path $script:tempDir 'extension'
81 $script:ghDir = Join-Path $script:tempDir '.github'
82 New-Item -ItemType Directory -Path $script:extDir -Force | Out-Null
83 New-Item -ItemType Directory -Path $script:ghDir -Force | Out-Null
84 $script:pkgJson = Join-Path $script:extDir 'package.json'
85 '{}' | Set-Content -Path $script:pkgJson
86 }
87
88 AfterAll {
89 Remove-Item -Path $script:tempDir -Recurse -Force -ErrorAction SilentlyContinue
90 }
91
92 It 'Returns valid when all paths exist' {
93 $result = Test-PathsExist -ExtensionDir $script:extDir -PackageJsonPath $script:pkgJson -GitHubDir $script:ghDir
94 $result.IsValid | Should -BeTrue
95 $result.MissingPaths | Should -BeNullOrEmpty
96 }
97
98 It 'Returns invalid when extension dir missing' {
99 $nonexistentPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'nonexistent-ext-dir-12345')
100 $result = Test-PathsExist -ExtensionDir $nonexistentPath -PackageJsonPath $script:pkgJson -GitHubDir $script:ghDir
101 $result.IsValid | Should -BeFalse
102 $result.MissingPaths | Should -Contain $nonexistentPath
103 }
104
105 It 'Collects multiple missing paths' {
106 $missing1 = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'missing-path-1')
107 $missing2 = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'missing-path-2')
108 $missing3 = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'missing-path-3')
109 $result = Test-PathsExist -ExtensionDir $missing1 -PackageJsonPath $missing2 -GitHubDir $missing3
110 $result.IsValid | Should -BeFalse
111 $result.MissingPaths.Count | Should -Be 3
112 }
113}
114
115Describe 'Get-DiscoveredAgents' {
116 BeforeAll {
117 $script:tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())
118 $script:agentsDir = Join-Path $script:tempDir 'agents'
119 New-Item -ItemType Directory -Path $script:agentsDir -Force | Out-Null
120
121 # Create test agent files
122 @'
123---
124description: "Stable agent"
125maturity: stable
126---
127'@ | Set-Content -Path (Join-Path $script:agentsDir 'stable.agent.md')
128
129 @'
130---
131description: "Preview agent"
132maturity: preview
133---
134'@ | Set-Content -Path (Join-Path $script:agentsDir 'preview.agent.md')
135 }
136
137 AfterAll {
138 Remove-Item -Path $script:tempDir -Recurse -Force -ErrorAction SilentlyContinue
139 }
140
141 It 'Discovers agents matching allowed maturities' {
142 $result = Get-DiscoveredAgents -AgentsDir $script:agentsDir -AllowedMaturities @('stable', 'preview') -ExcludedAgents @()
143 $result.DirectoryExists | Should -BeTrue
144 $result.Agents.Count | Should -Be 2
145 }
146
147 It 'Filters agents by maturity' {
148 $result = Get-DiscoveredAgents -AgentsDir $script:agentsDir -AllowedMaturities @('stable') -ExcludedAgents @()
149 $result.Agents.Count | Should -Be 1
150 $result.Skipped.Count | Should -Be 1
151 }
152
153 It 'Excludes specified agents' {
154 $result = Get-DiscoveredAgents -AgentsDir $script:agentsDir -AllowedMaturities @('stable', 'preview') -ExcludedAgents @('stable')
155 $result.Agents.Count | Should -Be 1
156 }
157
158 It 'Returns empty when directory does not exist' {
159 $nonexistentPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'nonexistent-agents-dir-12345')
160 $result = Get-DiscoveredAgents -AgentsDir $nonexistentPath -AllowedMaturities @('stable') -ExcludedAgents @()
161 $result.DirectoryExists | Should -BeFalse
162 $result.Agents | Should -BeNullOrEmpty
163 }
164}
165
166Describe 'Get-DiscoveredPrompts' {
167 BeforeAll {
168 $script:tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())
169 $script:promptsDir = Join-Path $script:tempDir 'prompts'
170 $script:ghDir = Join-Path $script:tempDir '.github'
171 New-Item -ItemType Directory -Path $script:promptsDir -Force | Out-Null
172 New-Item -ItemType Directory -Path $script:ghDir -Force | Out-Null
173
174 @'
175---
176description: "Test prompt"
177maturity: stable
178---
179'@ | Set-Content -Path (Join-Path $script:promptsDir 'test.prompt.md')
180 }
181
182 AfterAll {
183 Remove-Item -Path $script:tempDir -Recurse -Force -ErrorAction SilentlyContinue
184 }
185
186 It 'Discovers prompts in directory' {
187 $result = Get-DiscoveredPrompts -PromptsDir $script:promptsDir -GitHubDir $script:ghDir -AllowedMaturities @('stable')
188 $result.DirectoryExists | Should -BeTrue
189 $result.Prompts.Count | Should -BeGreaterThan 0
190 }
191
192 It 'Returns empty when directory does not exist' {
193 $nonexistentPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'nonexistent-prompts-dir-12345')
194 $result = Get-DiscoveredPrompts -PromptsDir $nonexistentPath -GitHubDir $script:ghDir -AllowedMaturities @('stable')
195 $result.DirectoryExists | Should -BeFalse
196 }
197}
198
199Describe 'Get-DiscoveredInstructions' {
200 BeforeAll {
201 $script:tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())
202 $script:instrDir = Join-Path $script:tempDir 'instructions'
203 $script:ghDir = Join-Path $script:tempDir '.github'
204 New-Item -ItemType Directory -Path $script:instrDir -Force | Out-Null
205 New-Item -ItemType Directory -Path $script:ghDir -Force | Out-Null
206
207 @'
208---
209description: "Test instruction"
210applyTo: "**/*.ps1"
211maturity: stable
212---
213'@ | Set-Content -Path (Join-Path $script:instrDir 'test.instructions.md')
214 }
215
216 AfterAll {
217 Remove-Item -Path $script:tempDir -Recurse -Force -ErrorAction SilentlyContinue
218 }
219
220 It 'Discovers instructions in directory' {
221 $result = Get-DiscoveredInstructions -InstructionsDir $script:instrDir -GitHubDir $script:ghDir -AllowedMaturities @('stable')
222 $result.DirectoryExists | Should -BeTrue
223 $result.Instructions.Count | Should -BeGreaterThan 0
224 }
225
226 It 'Returns empty when directory does not exist' {
227 $nonexistentPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'nonexistent-instr-dir-12345')
228 $result = Get-DiscoveredInstructions -InstructionsDir $nonexistentPath -GitHubDir $script:ghDir -AllowedMaturities @('stable')
229 $result.DirectoryExists | Should -BeFalse
230 }
231}
232
233Describe 'Update-PackageJsonContributes' {
234 It 'Updates contributes section with chat participants' {
235 $packageJson = [PSCustomObject]@{
236 name = 'test-extension'
237 contributes = [PSCustomObject]@{}
238 }
239 $agents = @(
240 @{ name = 'agent1'; description = 'Desc 1' }
241 )
242 $prompts = @(
243 @{ name = 'prompt1'; description = 'Prompt desc' }
244 )
245 $instructions = @(
246 @{ name = 'instr1'; description = 'Instr desc' }
247 )
248
249 $result = Update-PackageJsonContributes -PackageJson $packageJson -ChatAgents $agents -ChatPromptFiles $prompts -ChatInstructions $instructions
250 $result.contributes | Should -Not -BeNullOrEmpty
251 }
252
253 It 'Handles empty arrays' {
254 $packageJson = [PSCustomObject]@{
255 name = 'test-extension'
256 contributes = [PSCustomObject]@{}
257 }
258
259 $result = Update-PackageJsonContributes -PackageJson $packageJson -ChatAgents @() -ChatPromptFiles @() -ChatInstructions @()
260 $result | Should -Not -BeNullOrEmpty
261 }
262}
263
264Describe 'New-PrepareResult' {
265 It 'Creates success result with counts' {
266 $result = New-PrepareResult -Success $true -AgentCount 5 -PromptCount 10 -InstructionCount 15 -Version '1.0.0'
267 $result.Success | Should -BeTrue
268 $result.AgentCount | Should -Be 5
269 $result.PromptCount | Should -Be 10
270 $result.InstructionCount | Should -Be 15
271 $result.Version | Should -Be '1.0.0'
272 $result.ErrorMessage | Should -BeNullOrEmpty
273 }
274
275 It 'Creates failure result with error message' {
276 $result = New-PrepareResult -Success $false -ErrorMessage 'Something went wrong'
277 $result.Success | Should -BeFalse
278 $result.ErrorMessage | Should -Be 'Something went wrong'
279 $result.AgentCount | Should -Be 0
280 $result.PromptCount | Should -Be 0
281 $result.InstructionCount | Should -Be 0
282 }
283
284 It 'Returns hashtable with all expected keys' {
285 $result = New-PrepareResult -Success $true
286 $result.Keys | Should -Contain 'Success'
287 $result.Keys | Should -Contain 'AgentCount'
288 $result.Keys | Should -Contain 'PromptCount'
289 $result.Keys | Should -Contain 'InstructionCount'
290 $result.Keys | Should -Contain 'Version'
291 $result.Keys | Should -Contain 'ErrorMessage'
292 }
293}
294
295Describe 'Invoke-PrepareExtension' {
296 BeforeAll {
297 $script:tempDir = Join-Path $TestDrive ([System.Guid]::NewGuid().ToString())
298 New-Item -ItemType Directory -Path $script:tempDir -Force | Out-Null
299
300 # Create extension directory with package.json
301 $script:extDir = Join-Path $script:tempDir 'extension'
302 New-Item -ItemType Directory -Path $script:extDir -Force | Out-Null
303 @'
304{
305 "name": "test-extension",
306 "version": "1.2.3",
307 "contributes": {}
308}
309'@ | Set-Content -Path (Join-Path $script:extDir 'package.json')
310
311 # Create .github structure
312 $script:ghDir = Join-Path $script:tempDir '.github'
313 $script:agentsDir = Join-Path $script:ghDir 'agents'
314 $script:promptsDir = Join-Path $script:ghDir 'prompts'
315 $script:instrDir = Join-Path $script:ghDir 'instructions'
316 New-Item -ItemType Directory -Path $script:agentsDir -Force | Out-Null
317 New-Item -ItemType Directory -Path $script:promptsDir -Force | Out-Null
318 New-Item -ItemType Directory -Path $script:instrDir -Force | Out-Null
319
320 # Create test agent
321 @'
322---
323description: "Test agent"
324maturity: stable
325---
326# Agent
327'@ | Set-Content -Path (Join-Path $script:agentsDir 'test.agent.md')
328
329 # Create test prompt
330 @'
331---
332description: "Test prompt"
333maturity: stable
334---
335# Prompt
336'@ | Set-Content -Path (Join-Path $script:promptsDir 'test.prompt.md')
337
338 # Create test instruction
339 @'
340---
341description: "Test instruction"
342applyTo: "**/*.ps1"
343maturity: stable
344---
345# Instruction
346'@ | Set-Content -Path (Join-Path $script:instrDir 'test.instructions.md')
347 }
348
349 AfterAll {
350 Remove-Item -Path $script:tempDir -Recurse -Force -ErrorAction SilentlyContinue
351 }
352
353 It 'Returns success result with correct counts' {
354 $result = Invoke-PrepareExtension `
355 -ExtensionDirectory $script:extDir `
356 -RepoRoot $script:tempDir `
357 -Channel 'Stable' `
358 -DryRun
359
360 $result.Success | Should -BeTrue
361 $result.AgentCount | Should -Be 1
362 $result.PromptCount | Should -Be 1
363 $result.InstructionCount | Should -Be 1
364 $result.Version | Should -Be '1.2.3'
365 }
366
367 It 'Fails when extension directory missing' {
368 $nonexistentPath = Join-Path $TestDrive 'nonexistent-ext-dir-12345'
369 $result = Invoke-PrepareExtension `
370 -ExtensionDirectory $nonexistentPath `
371 -RepoRoot $script:tempDir `
372 -Channel 'Stable'
373
374 $result.Success | Should -BeFalse
375 $result.ErrorMessage | Should -Match 'Required paths not found'
376 }
377
378 It 'Respects channel filtering' {
379 # Add preview agent
380 @'
381---
382description: "Preview agent"
383maturity: preview
384---
385'@ | Set-Content -Path (Join-Path $script:agentsDir 'preview.agent.md')
386
387 $stableResult = Invoke-PrepareExtension `
388 -ExtensionDirectory $script:extDir `
389 -RepoRoot $script:tempDir `
390 -Channel 'Stable' `
391 -DryRun
392
393 $preReleaseResult = Invoke-PrepareExtension `
394 -ExtensionDirectory $script:extDir `
395 -RepoRoot $script:tempDir `
396 -Channel 'PreRelease' `
397 -DryRun
398
399 $preReleaseResult.AgentCount | Should -BeGreaterThan $stableResult.AgentCount
400 }
401
402 It 'Filters prompts and instructions by maturity' {
403 # Add experimental prompt
404 @'
405---
406description: "Experimental prompt"
407maturity: experimental
408---
409'@ | Set-Content -Path (Join-Path $script:promptsDir 'experimental.prompt.md')
410
411 # Add preview instruction
412 @'
413---
414description: "Preview instruction"
415applyTo: "**/*.js"
416maturity: preview
417---
418'@ | Set-Content -Path (Join-Path $script:instrDir 'preview.instructions.md')
419
420 $stableResult = Invoke-PrepareExtension `
421 -ExtensionDirectory $script:extDir `
422 -RepoRoot $script:tempDir `
423 -Channel 'Stable' `
424 -DryRun
425
426 $preReleaseResult = Invoke-PrepareExtension `
427 -ExtensionDirectory $script:extDir `
428 -RepoRoot $script:tempDir `
429 -Channel 'PreRelease' `
430 -DryRun
431
432 # Stable should have fewer prompts and instructions than PreRelease
433 $preReleaseResult.PromptCount | Should -BeGreaterThan $stableResult.PromptCount
434 $preReleaseResult.InstructionCount | Should -BeGreaterThan $stableResult.InstructionCount
435 }
436
437 It 'Updates package.json when not DryRun' {
438 $result = Invoke-PrepareExtension `
439 -ExtensionDirectory $script:extDir `
440 -RepoRoot $script:tempDir `
441 -Channel 'Stable' `
442 -DryRun:$false
443
444 $result.Success | Should -BeTrue
445
446 $pkgJson = Get-Content -Path (Join-Path $script:extDir 'package.json') -Raw | ConvertFrom-Json
447 $pkgJson.contributes.chatAgents | Should -Not -BeNullOrEmpty
448 }
449
450 It 'Copies changelog when path provided' {
451 $changelogPath = Join-Path $script:tempDir 'CHANGELOG.md'
452 '# Changelog' | Set-Content -Path $changelogPath
453
454 $result = Invoke-PrepareExtension `
455 -ExtensionDirectory $script:extDir `
456 -RepoRoot $script:tempDir `
457 -Channel 'Stable' `
458 -ChangelogPath $changelogPath `
459 -DryRun:$false
460
461 $result.Success | Should -BeTrue
462 Test-Path (Join-Path $script:extDir 'CHANGELOG.md') | Should -BeTrue
463 }
464
465 It 'Fails when package.json has invalid JSON' {
466 $badJsonDir = Join-Path $TestDrive 'bad-json-ext'
467 New-Item -ItemType Directory -Path $badJsonDir -Force | Out-Null
468 '{ invalid json }' | Set-Content -Path (Join-Path $badJsonDir 'package.json')
469
470 # Create .github structure for this test
471 $badGhDir = Join-Path (Split-Path $badJsonDir -Parent) '.github'
472 New-Item -ItemType Directory -Path (Join-Path $badGhDir 'agents') -Force | Out-Null
473
474 $result = Invoke-PrepareExtension `
475 -ExtensionDirectory $badJsonDir `
476 -RepoRoot (Split-Path $badJsonDir -Parent) `
477 -Channel 'Stable'
478
479 $result.Success | Should -BeFalse
480 $result.ErrorMessage | Should -Match 'Failed to parse package.json'
481 }
482
483 It 'Fails when package.json missing version field' {
484 $noVersionDir = Join-Path $TestDrive 'no-version-ext'
485 New-Item -ItemType Directory -Path $noVersionDir -Force | Out-Null
486 '{"name": "test"}' | Set-Content -Path (Join-Path $noVersionDir 'package.json')
487
488 # Create .github structure for this test
489 $noVersionGhDir = Join-Path (Split-Path $noVersionDir -Parent) '.github'
490 New-Item -ItemType Directory -Path (Join-Path $noVersionGhDir 'agents') -Force | Out-Null
491
492 $result = Invoke-PrepareExtension `
493 -ExtensionDirectory $noVersionDir `
494 -RepoRoot (Split-Path $noVersionDir -Parent) `
495 -Channel 'Stable'
496
497 $result.Success | Should -BeFalse
498 $result.ErrorMessage | Should -Match "does not contain a 'version' field"
499 }
500
501 It 'Fails when version format is invalid' {
502 $badVersionDir = Join-Path $TestDrive 'bad-version-ext'
503 New-Item -ItemType Directory -Path $badVersionDir -Force | Out-Null
504 '{"name": "test", "version": "invalid"}' | Set-Content -Path (Join-Path $badVersionDir 'package.json')
505
506 # Create .github structure for this test
507 $badVersionGhDir = Join-Path (Split-Path $badVersionDir -Parent) '.github'
508 New-Item -ItemType Directory -Path (Join-Path $badVersionGhDir 'agents') -Force | Out-Null
509
510 $result = Invoke-PrepareExtension `
511 -ExtensionDirectory $badVersionDir `
512 -RepoRoot (Split-Path $badVersionDir -Parent) `
513 -Channel 'Stable'
514
515 $result.Success | Should -BeFalse
516 $result.ErrorMessage | Should -Match 'Invalid version format'
517 }
518}
519