@@ -26,6 +26,7 @@ import (
2626 "os"
2727 "path/filepath"
2828 "regexp"
29+ goRuntime "runtime"
2930 "strings"
3031
3132 cdcTests "github.com/onflow/cadence-tools/test"
@@ -41,6 +42,7 @@ import (
4142
4243 "github.com/onflow/flow-cli/common/branding"
4344
45+ "github.com/onflow/flow-cli/build"
4446 "github.com/onflow/flow-cli/internal/command"
4547 "github.com/onflow/flow-cli/internal/util"
4648)
@@ -184,6 +186,12 @@ func testCode(
184186 flags flagsTests ,
185187) (* result , error ) {
186188 logger := zerolog .New (zerolog.ConsoleWriter {Out : os .Stderr }).With ().Timestamp ().Logger ()
189+
190+ // Track network resolutions per file for pragma-based fork detection
191+ // Map: filename -> resolved network name
192+ fileNetworkResolutions := make (map [string ]string )
193+ var currentTestFile string
194+
187195 // Resolve network labels using flow.json state
188196 resolveNetworkFromState := func (label string ) (string , bool ) {
189197 network , err := state .Networks ().ByName (strings .ToLower (strings .TrimSpace (label )))
@@ -193,6 +201,16 @@ func testCode(
193201 if strings .TrimSpace (network .Host ) == "" {
194202 return "" , false
195203 }
204+
205+ // Track network resolution for current test file (indicates pragma-based fork usage)
206+ // Only track if it's not the default "testing" network
207+ normalizedLabel := strings .ToLower (strings .TrimSpace (label ))
208+ if currentTestFile != "" && normalizedLabel != "testing" {
209+ if _ , exists := fileNetworkResolutions [currentTestFile ]; ! exists {
210+ fileNetworkResolutions [currentTestFile ] = normalizedLabel
211+ }
212+ }
213+
196214 return network .Host , true
197215 }
198216
@@ -284,6 +302,9 @@ func testCode(
284302 testResults := make (map [string ]cdcTests.Results , 0 )
285303 exitCode := 0
286304 for scriptPath , code := range testFiles {
305+ // Set current test file for network resolution tracking
306+ currentTestFile = scriptPath
307+
287308 fileRunner := runner .
288309 WithImportResolver (importResolver (scriptPath , state )).
289310 WithFileResolver (fileResolver (scriptPath , state )).
@@ -344,6 +365,45 @@ func testCode(
344365 break
345366 }
346367 }
368+
369+ // Clear current test file after processing
370+ currentTestFile = ""
371+ }
372+
373+ // Track fork test usage metrics per file
374+ // Priority: pragma-based resolution first (more direct), then static flags
375+ for scriptPath := range testFiles {
376+ // Check if this file used pragma-based fork
377+ if resolvedNetwork , hasPragma := fileNetworkResolutions [scriptPath ]; hasPragma {
378+ // Fork mode via pragma (e.g., #fork(mainnet) in test code)
379+ command .TrackEvent ("test-fork" , map [string ]any {
380+ "fork_source" : "pragma" ,
381+ "network" : resolvedNetwork ,
382+ "chain_id" : "" ,
383+ "has_height" : false ,
384+ "version" : build .Semver (),
385+ "os" : goRuntime .GOOS ,
386+ "ci" : os .Getenv ("CI" ) != "" ,
387+ })
388+ } else if forkCfg != nil {
389+ // Fork mode via static flags (--fork or --fork-host)
390+ forkSource := "static-flag"
391+ if flags .ForkHost != "" {
392+ forkSource = "fork-host-flag"
393+ } else if flags .Fork != "" {
394+ forkSource = "fork-flag"
395+ }
396+
397+ command .TrackEvent ("test-fork" , map [string ]any {
398+ "fork_source" : forkSource ,
399+ "network" : networkLabel ,
400+ "chain_id" : forkCfg .ChainID .String (),
401+ "has_height" : forkCfg .ForkHeight > 0 ,
402+ "version" : build .Semver (),
403+ "os" : goRuntime .GOOS ,
404+ "ci" : os .Getenv ("CI" ) != "" ,
405+ })
406+ }
347407 }
348408
349409 return & result {
0 commit comments