@@ -12,6 +12,7 @@ import (
1212 "os/exec"
1313 "path/filepath"
1414 "time"
15+ "strings"
1516
1617 "github.com/stretchr/testify/require"
1718 "github.com/stretchr/testify/suite"
@@ -317,7 +318,7 @@ func (p *TestProject) PatchResource(resourceName, id string, patch interface{})
317318 patchJSON = string (patchBytes )
318319 }
319320
320- output , err := p .RunClient (resourceName , "patch" , id , "--patch " , patchJSON )
321+ output , err := p .RunClient (resourceName , "patch" , id , "--spec " , patchJSON )
321322 if err != nil {
322323 return nil , fmt .Errorf ("patch failed: %w\n Output: %s" , err , output )
323324 }
@@ -356,3 +357,94 @@ func (p *TestProject) AssertResourceHasSpec(t require.TestingT, resource map[str
356357 require .Equal (t , expectedValue , actualValue , "spec[%s] should match expected value" , key )
357358 }
358359}
360+
361+ // ModifyFile reads a file, applies a modification function, and writes it back
362+ func (p * TestProject ) ModifyFile (relativePath string , modifier func (string ) string ) error {
363+ path := filepath .Join (p .Dir , relativePath )
364+ content , err := os .ReadFile (path )
365+ if err != nil {
366+ return fmt .Errorf ("failed to read file %s: %w" , path , err )
367+ }
368+
369+ newContent := modifier (string (content ))
370+
371+ if err := os .WriteFile (path , []byte (newContent ), 0644 ); err != nil {
372+ return fmt .Errorf ("failed to write file %s: %w" , path , err )
373+ }
374+ return nil
375+ }
376+
377+ // Example1_CustomizeResource updates the Device spec as per Example 1
378+ func (p * TestProject ) Example1_CustomizeResource () error {
379+ // Path: pkg/resources/device/device.go
380+ relPath := filepath .Join ("pkg" , "resources" , "device" , "device.go" )
381+
382+ return p .ModifyFile (relPath , func (content string ) string {
383+ // We replace the default placeholder or the simple struct definition
384+ // with the full definition from the example
385+ target := `type DeviceSpec struct {
386+ Description string ` + "`json:\" description,omitempty\" validate:\" max=200\" `" + `
387+ // Add your spec fields here
388+ }`
389+
390+ replacement := `type DeviceSpec struct {
391+ Description string ` + "`json:\" description,omitempty\" validate:\" max=200\" `" + `
392+ IPAddress string ` + "`json:\" ipAddress,omitempty\" validate:\" omitempty,ip\" `" + `
393+ Location string ` + "`json:\" location,omitempty\" `" + `
394+ Rack string ` + "`json:\" rack,omitempty\" `" + `
395+ }`
396+ // Try specific replacement first
397+ if strings .Contains (content , target ) {
398+ return strings .Replace (content , target , replacement , 1 )
399+ }
400+
401+ // Fallback: If formatting is slightly different, try to inject just the fields
402+ // This assumes the file contains "// Add your spec fields here"
403+ fields := `IPAddress string ` + "`json:\" ipAddress,omitempty\" validate:\" omitempty,ip\" `" + `
404+ Location string ` + "`json:\" location,omitempty\" `" + `
405+ Rack string ` + "`json:\" rack,omitempty\" `"
406+
407+ return strings .Replace (content , "// Add your spec fields here" , fields , 1 )
408+ })
409+ }
410+
411+ // Example1_ConfigureServer uncomments the storage and route registration in main.go
412+ func (p * TestProject ) Example1_ConfigureServer () error {
413+ relPath := filepath .Join ("cmd" , "server" , "main.go" )
414+
415+ return p .ModifyFile (relPath , func (content string ) string {
416+ // 1. Uncomment the storage import
417+ // Expecting: // "github.com/user/device-inventory/internal/storage"
418+ // We need to be careful to match the actual module name or just the suffix
419+ lines := strings .Split (content , "\n " )
420+ var newLines []string
421+
422+ for _ , line := range lines {
423+ trimmed := strings .TrimSpace (line )
424+
425+ // Uncomment import for storage
426+ if strings .HasPrefix (trimmed , "//" ) && strings .Contains (trimmed , "/internal/storage\" " ) {
427+ line = strings .Replace (line , "// " , "" , 1 )
428+ line = strings .Replace (line , "//" , "" , 1 ) // Handle case without space
429+ }
430+
431+ // Uncomment storage init
432+ // Expecting: // storage.InitFileBackend("./data")
433+ if strings .HasPrefix (trimmed , "//" ) && strings .Contains (trimmed , "storage.InitFileBackend" ) {
434+ line = strings .Replace (line , "// " , "" , 1 )
435+ line = strings .Replace (line , "//" , "" , 1 )
436+ }
437+
438+ // Uncomment route registration
439+ // Expecting: // RegisterGeneratedRoutes(r)
440+ if strings .HasPrefix (trimmed , "//" ) && strings .Contains (trimmed , "RegisterGeneratedRoutes" ) {
441+ line = strings .Replace (line , "// " , "" , 1 )
442+ line = strings .Replace (line , "//" , "" , 1 )
443+ }
444+
445+ newLines = append (newLines , line )
446+ }
447+
448+ return strings .Join (newLines , "\n " )
449+ })
450+ }
0 commit comments