@@ -66,7 +66,7 @@ func testCustomCodeBasicWorkflow(t *testing.T, speakeasyBinary string) {
6666 temp := setupSDKGeneration (t , speakeasyBinary , "customcodespec.yaml" )
6767
6868 httpMetadataPath := filepath .Join (temp , "models" , "components" , "httpmetadata.go" )
69- registerCustomCode (t , speakeasyBinary , temp , httpMetadataPath , 10 , "\t // custom code" )
69+ registerCustomCodeByPrefix (t , speakeasyBinary , temp , httpMetadataPath , "// Raw HTTP response" , "\t // custom code" )
7070
7171 runRegeneration (t , speakeasyBinary , temp , true )
7272 verifyCustomCodePresent (t , httpMetadataPath , "// custom code" )
@@ -79,7 +79,7 @@ func testCustomCodeConflictResolution(t *testing.T, speakeasyBinary string) {
7979 getUserByNamePath := filepath .Join (temp , "models" , "operations" , "getuserbyname.go" )
8080
8181 // Register custom code
82- registerCustomCode (t , speakeasyBinary , temp , getUserByNamePath , 10 , "\t // custom code" )
82+ registerCustomCodeByPrefix (t , speakeasyBinary , temp , getUserByNamePath , "// The name that needs to be fetched" , "\t // custom code" )
8383
8484 // Modify the spec to change line 477 from original description to "spec change"
8585 specPath := filepath .Join (temp , "customcodespec.yaml" )
@@ -131,7 +131,7 @@ func testCustomCodeConflictResolutionAcceptOurs(t *testing.T, speakeasyBinary st
131131 getUserByNamePath := filepath .Join (temp , "models" , "operations" , "getuserbyname.go" )
132132
133133 // Register custom code
134- registerCustomCode (t , speakeasyBinary , temp , getUserByNamePath , 10 , "\t // custom code" )
134+ registerCustomCodeByPrefix (t , speakeasyBinary , temp , getUserByNamePath , "// The name that needs to be fetched" , "\t // custom code" )
135135
136136 // Modify the spec to change line 477 from original description to "spec change"
137137 specPath := filepath .Join (temp , "customcodespec.yaml" )
@@ -206,7 +206,7 @@ func testCustomCodeSequentialPatchesAppliedWithRegenerationBetween(t *testing.T,
206206 getUserByNamePath := filepath .Join (temp , "models" , "operations" , "getuserbyname.go" )
207207
208208 // Step 1: Register first patch
209- registerCustomCode (t , speakeasyBinary , temp , getUserByNamePath , 10 , "\t // first custom code" )
209+ registerCustomCodeByPrefix (t , speakeasyBinary , temp , getUserByNamePath , "// The name that needs to be fetched" , "\t // first custom code" )
210210
211211 // Step 2: Verify first patch applies correctly on regeneration
212212 runRegeneration (t , speakeasyBinary , temp , true )
@@ -216,7 +216,7 @@ func testCustomCodeSequentialPatchesAppliedWithRegenerationBetween(t *testing.T,
216216 gitCommit (t , temp , "regenerated with first patch" )
217217
218218 // Step 3: Modify the same line with different content (second patch)
219- modifyLineInFile (t , getUserByNamePath , 10 , "\t // second custom code - updated" )
219+ modifyLineInFileByPrefix (t , getUserByNamePath , " \t // first custom code" , "\t // second custom code - updated" )
220220
221221 // Step 4: Register second patch (should update existing patch)
222222 customCodeCmd := exec .Command (speakeasyBinary , "customcode" , "--output" , "console" )
@@ -249,10 +249,10 @@ func testCustomCodeSequentialPatchesAppliedWithoutRegenerationBetween(t *testing
249249 getUserByNamePath := filepath .Join (temp , "models" , "operations" , "getuserbyname.go" )
250250
251251 // Step 1: Register first patch
252- registerCustomCode (t , speakeasyBinary , temp , getUserByNamePath , 10 , "\t // first custom code" )
252+ registerCustomCodeByPrefix (t , speakeasyBinary , temp , getUserByNamePath , "// The name that needs to be fetched" , "\t // first custom code" )
253253
254254 // Step 2: Immediately modify the same line with different content (NO regeneration between)
255- modifyLineInFile (t , getUserByNamePath , 10 , "\t // second custom code - updated" )
255+ modifyLineInFileByPrefix (t , getUserByNamePath , " \t // first custom code" , "\t // second custom code - updated" )
256256
257257 // Step 3: Register second patch (should update existing patch)
258258 customCodeCmd := exec .Command (speakeasyBinary , "customcode" , "--output" , "console" )
@@ -277,58 +277,6 @@ func testCustomCodeSequentialPatchesAppliedWithoutRegenerationBetween(t *testing
277277 require .NotContains (t , string (finalContent ), "// first custom code" , "File should not contain first custom code" )
278278}
279279
280- // testCustomCodeConflictDetectionDuringRegistration tests that conflicts are detected during customcode registration
281- // when the old patch conflicts with new changes
282- // func testCustomCodeConflictDetectionDuringRegistration(t *testing.T, speakeasyBinary string) {
283- // temp := setupSDKGeneration(t, speakeasyBinary, "customcodespec.yaml")
284-
285- // getUserByNamePath := filepath.Join(temp, "models", "operations", "getuserbyname.go")
286-
287- // // Step 1: Modify the file
288- // modifyLineInFile(t, getUserByNamePath, 10, "\t// first custom code")
289-
290- // // Step 2: Register first patch
291- // customCodeCmd := exec.Command(speakeasyBinary, "customcode", "--output", "console")
292- // customCodeCmd.Dir = temp
293- // customCodeOutput, customCodeErr := customCodeCmd.CombinedOutput()
294- // require.NoError(t, customCodeErr, "customcode command should succeed: %s", string(customCodeOutput))
295-
296- // // Step 3: Run and commit
297- // runRegeneration(t, speakeasyBinary, temp, true)
298- // gitCommit(t, temp, "regenerated with first patch")
299-
300- // // Step 4: Modify the same line again
301- // modifyLineInFile(t, getUserByNamePath, 10, "\t// second custom code - conflicting")
302-
303- // // Step 5: Modify the spec to change the same line (this will cause conflict during registration)
304- // specPath := filepath.Join(temp, "customcodespec.yaml")
305- // modifyLineInFile(t, specPath, 477, " description: 'spec change for conflict'")
306-
307- // // Step 5b: Commit only the spec
308- // gitAddCmd := exec.Command("git", "add", specPath)
309- // gitAddCmd.Dir = temp
310- // gitAddOutput, gitAddErr := gitAddCmd.CombinedOutput()
311- // require.NoError(t, gitAddErr, "git add spec should succeed: %s", string(gitAddOutput))
312-
313- // gitCommitCmd := exec.Command("git", "commit", "-m", "update spec")
314- // gitCommitCmd.Dir = temp
315- // gitCommitOutput, gitCommitErr := gitCommitCmd.CombinedOutput()
316- // require.NoError(t, gitCommitErr, "git commit spec should succeed: %s", string(gitCommitOutput))
317-
318- // // Step 6: Register custom code - should fail with conflict error
319- // customCodeCmd = exec.Command(speakeasyBinary, "customcode", "--output", "console")
320- // customCodeCmd.Dir = temp
321- // customCodeOutput, customCodeErr = customCodeCmd.CombinedOutput()
322-
323- // // Step 7: Validate error - conflict happens when applying existing patch
324- // require.Error(t, customCodeErr, "customcode command should fail due to conflicts: %s", string(customCodeOutput))
325- // outputStr := string(customCodeOutput)
326- // // The conflict occurs when applying the existing patch (not the new patch)
327- // // because the spec changed and the old patch no longer applies cleanly
328- // require.Contains(t, outputStr, "failed to apply existing patch", "Error message should mention failed to apply existing patch")
329- // require.Contains(t, outputStr, "with conflicts", "Error message should mention conflicts")
330- // }
331-
332280// buildSpeakeasyBinaryOnce builds the speakeasy binary and returns the path to it
333281func buildSpeakeasyBinaryOnce (t * testing.T , binaryName string ) string {
334282 t .Helper ()
@@ -443,6 +391,13 @@ func modifyLineInFile(t *testing.T, filePath string, lineNumber int, newContent
443391 require .NoError (t , writer .Flush (), "Failed to flush writer" )
444392}
445393
394+ func modifyLineInFileByPrefix (t * testing.T , filePath string , oldContentPrefix string , newContent string ) {
395+ t .Helper ()
396+
397+ lineNum := findLineNumberByPrefix (t , filePath , oldContentPrefix )
398+ modifyLineInFile (t , filePath , lineNum , newContent )
399+ }
400+
446401// setupCustomCodeTestDir creates a test directory outside the speakeasy repo
447402func setupCustomCodeTestDir (t * testing.T ) string {
448403 t .Helper ()
@@ -532,6 +487,35 @@ func setupSDKGeneration(t *testing.T, speakeasyBinary, inputDoc string) string {
532487 return temp
533488}
534489
490+ // findLineNumberByPrefix finds the line number (1-indexed) of the first line containing the prefix
491+ func findLineNumberByPrefix (t * testing.T , filePath , prefix string ) int {
492+ t .Helper ()
493+
494+ file , err := os .Open (filePath )
495+ require .NoError (t , err , "Failed to open file: %s" , filePath )
496+ defer file .Close ()
497+
498+ scanner := bufio .NewScanner (file )
499+ lineNumber := 1
500+ for scanner .Scan () {
501+ if strings .Contains (scanner .Text (), prefix ) {
502+ return lineNumber
503+ }
504+ lineNumber ++
505+ }
506+ require .NoError (t , scanner .Err (), "Failed to read file: %s" , filePath )
507+ require .Fail (t , "Could not find line with prefix: %s" , prefix )
508+ return - 1 // Never reached
509+ }
510+
511+ // registerCustomCodeByPrefix finds a line by prefix and registers custom code at that line
512+ func registerCustomCodeByPrefix (t * testing.T , speakeasyBinary , workingDir , filePath , linePrefix string , newContent string ) {
513+ t .Helper ()
514+
515+ lineNum := findLineNumberByPrefix (t , filePath , linePrefix )
516+ registerCustomCode (t , speakeasyBinary , workingDir , filePath , lineNum , newContent )
517+ }
518+
535519// registerCustomCode modifies a file and registers it as custom code
536520func registerCustomCode (t * testing.T , speakeasyBinary , workingDir , filePath string , lineNum int , newContent string ) {
537521 t .Helper ()
0 commit comments