Repository: onflow/flow-cli
Pull request #1354 (2024-01-23 12:19:51)

Coverage report map contract files
modified version of #1328 to add function to state in flowkit and also make it possible to creating coverage report with location mapping for different networks.

original work by @m-Peter i just added flowkit function. 


Patch:
diff --git a/cmd/flow/main.go b/cmd/flow/main.go
index 35c312ae..1b77738b 100644
--- a/cmd/flow/main.go
+++ b/cmd/flow/main.go
@@ -20,9 +20,7 @@
 package main
 
 import (
-	"fmt"
 	"os"
-	"strings"
 
 	"github.com/spf13/cobra"
 
@@ -54,34 +52,6 @@ func main() {
 	var cmd = &cobra.Command{
 		Use:              "flow",
 		TraverseChildren: true,
-		// Messaging for Cadence 1.0 upgrade
-		PersistentPreRun: func(cmd *cobra.Command, args []string) {
-			outputFlag, _ := cmd.Flags().GetString("output")
-			// If output is set to json, do not append any message
-			if outputFlag != "json" {
-
-				width := 80
-				url := "https://developers.flow.com/build/cadence-migration-guide"
-
-				// Function to center text within a given width
-				centerText := func(text string, width int) string {
-					space := (width - len(text)) / 2
-					if space < 0 {
-						space = 0
-					}
-					return fmt.Sprintf("%s%s%s", strings.Repeat(" ", space), text, strings.Repeat(" ", space))
-				}
-
-				fmt.Fprintln(os.Stderr, strings.Repeat("+", width))
-				fmt.Fprintln(os.Stderr, centerText("⚠ Upgrade to Cadence 1.0", width))
-				fmt.Fprintln(os.Stderr, centerText("The Crescendo network upgrade, including Cadence 1.0, is coming soon.", width))
-				fmt.Fprintln(os.Stderr, centerText("You may need to update your existing contracts to support this change.", width))
-				fmt.Fprintln(os.Stderr, centerText("Please visit our migration guide here:", width))
-				fmt.Fprintln(os.Stderr, centerText(url, width))
-				fmt.Fprintln(os.Stderr, strings.Repeat("+", width))
-
-			}
-		},
 	}
 
 	// quick commands
diff --git a/flowkit/gateway/emulator.go b/flowkit/gateway/emulator.go
index 7e6b0bbe..31aea3c7 100644
--- a/flowkit/gateway/emulator.go
+++ b/flowkit/gateway/emulator.go
@@ -141,20 +141,14 @@ func (g *EmulatorGateway) GetTransaction(id flow.Identifier) (*flow.Transaction,
 	return transaction, nil
 }
 
-func (g *EmulatorGateway) GetTransactionResultsByBlockID(id flow.Identifier) ([]*flow.TransactionResult, error) {
-	txr, err := g.adapter.GetTransactionResultsByBlockID(g.ctx, id)
-	if err != nil {
-		return nil, UnwrapStatusError(err)
-	}
-	return txr, nil
+func (g *EmulatorGateway) GetTransactionResultsByBlockID(_ flow.Identifier) ([]*flow.TransactionResult, error) {
+	// TODO: implement
+	panic("GetTransactionResultsByBlockID not implemented")
 }
 
-func (g *EmulatorGateway) GetTransactionsByBlockID(id flow.Identifier) ([]*flow.Transaction, error) {
-	txr, err := g.adapter.GetTransactionsByBlockID(g.ctx, id)
-	if err != nil {
-		return nil, UnwrapStatusError(err)
-	}
-	return txr, nil
+func (g *EmulatorGateway) GetTransactionsByBlockID(_ flow.Identifier) ([]*flow.Transaction, error) {
+	// TODO: implement
+	panic("GetTransactionResultsByBlockID not implemented")
 }
 
 func (g *EmulatorGateway) Ping() error {
diff --git a/flowkit/state.go b/flowkit/state.go
index 4832ab87..56b1ea48 100644
--- a/flowkit/state.go
+++ b/flowkit/state.go
@@ -23,6 +23,7 @@ import (
 	"os"
 	"path/filepath"
 
+	"github.com/onflow/cadence/runtime"
 	"github.com/onflow/flow-go-sdk/crypto"
 	"github.com/pkg/errors"
 	"golang.org/x/exp/slices"
@@ -48,6 +49,22 @@ type State struct {
 	accounts     *accounts.Accounts
 }
 
+func (p *State) CreateCoverageReport(network string) *runtime.CoverageReport {
+	coverageReport := runtime.NewCoverageReport()
+	contractsConfig := *p.Contracts()
+	locationMappings := make(map[string]string, len(contractsConfig))
+	for _, contract := range contractsConfig {
+		alias := contract.Aliases.ByNetwork(network)
+		if alias != nil {
+			locationMappings[contract.Name] = contract.Location
+		}
+	}
+
+	coverageReport.WithLocationMappings(locationMappings)
+
+	return coverageReport
+}
+
 // ReaderWriter retrieve current file reader writer.
 func (p *State) ReaderWriter() ReaderWriter {
 	return p.readerWriter
@@ -86,7 +103,6 @@ func (p *State) SaveEdited(paths []string) error {
 func (p *State) Save(path string) error {
 	p.conf.Accounts = accounts.ToConfig(*p.accounts)
 	err := p.confLoader.Save(p.conf, path)
-
 	if err != nil {
 		return fmt.Errorf("failed to save project configuration to: %s", path)
 	}
diff --git a/go.mod b/go.mod
index 144303b2..d73c8cf1 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.20
 
 require (
 	github.com/dukex/mixpanel v1.0.1
-	github.com/getsentry/sentry-go v0.26.0
+	github.com/getsentry/sentry-go v0.25.0
 	github.com/go-git/go-git/v5 v5.11.0
 	github.com/gosuri/uilive v0.0.4
 	github.com/manifoldco/promptui v0.9.0
@@ -12,7 +12,7 @@ require (
 	github.com/onflow/cadence-tools/languageserver v0.33.3
 	github.com/onflow/cadence-tools/test v0.14.5
 	github.com/onflow/fcl-dev-wallet v0.7.4
-	github.com/onflow/flixkit-go v1.1.0
+	github.com/onflow/flixkit-go v1.0.0
 	github.com/onflow/flow-cli/flowkit v1.6.1-0.20231110211255-b41f57a8b8c7
 	github.com/onflow/flow-core-contracts/lib/go/templates v1.2.4-0.20231016154253-a00dbf7c061f
 	github.com/onflow/flow-emulator v0.59.0
diff --git a/go.sum b/go.sum
index 424ea12b..a84212ff 100644
--- a/go.sum
+++ b/go.sum
@@ -314,8 +314,8 @@ github.com/gammazero/workerpool v1.1.2 h1:vuioDQbgrz4HoaCi2q1HLlOXdpbap5AET7xu5/
 github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
 github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c=
-github.com/getsentry/sentry-go v0.26.0 h1:IX3++sF6/4B5JcevhdZfdKIHfyvMmAq/UnqcyT2H6mA=
-github.com/getsentry/sentry-go v0.26.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
+github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI=
+github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
 github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
@@ -875,8 +875,8 @@ github.com/onflow/cadence-tools/test v0.14.5 h1:u1kYkotKdwKEf9c3h65mI3VMevBkHY+7
 github.com/onflow/cadence-tools/test v0.14.5/go.mod h1:ix09Bb3GQ/fZMNpSR8E+vSFItGF54fzP9gFxU7AsOIw=
 github.com/onflow/fcl-dev-wallet v0.7.4 h1:vI6t3U0AO88R/Iitn5KsnniSpbN9Lqsqwvi9EJT4C0k=
 github.com/onflow/fcl-dev-wallet v0.7.4/go.mod h1:kc42jkiuoPJmxMRFjfbRO9XvnR/3XLheaOerxVMDTiw=
-github.com/onflow/flixkit-go v1.1.0 h1:yju2lotk2LQBXUwb0rZeOtVbHW2KVSzzRRu/3rPtzok=
-github.com/onflow/flixkit-go v1.1.0/go.mod h1:KGL7oMu4uzt7s0qsNkaqGBYIt+Z38Qbf0JG56qK/Sg0=
+github.com/onflow/flixkit-go v1.0.0 h1:SY2H4iB3kW8CEOxnofJZYm3sEZXnz3x0qiWkIe4l1LI=
+github.com/onflow/flixkit-go v1.0.0/go.mod h1:KGL7oMu4uzt7s0qsNkaqGBYIt+Z38Qbf0JG56qK/Sg0=
 github.com/onflow/flow-core-contracts/lib/go/contracts v1.2.4-0.20231016154253-a00dbf7c061f h1:S8yIZw9LFXfYD1V5H9BiixihHw3GrXVPrmfplSzYaww=
 github.com/onflow/flow-core-contracts/lib/go/contracts v1.2.4-0.20231016154253-a00dbf7c061f/go.mod h1:jM6GMAL+m0hjusUgiYDNrixPQ6b9s8xjoJQoEu5bHQI=
 github.com/onflow/flow-core-contracts/lib/go/templates v1.2.4-0.20231016154253-a00dbf7c061f h1:Ep+Mpo2miWMe4pjPGIaEvEzshRep30dvNgxqk+//FrQ=
diff --git a/internal/super/flix.go b/internal/super/flix.go
index 418b2d12..64550da3 100644
--- a/internal/super/flix.go
+++ b/internal/super/flix.go
@@ -21,19 +21,20 @@ package super
 import (
 	"context"
 	"fmt"
+	"net/url"
 	"os"
+	"path/filepath"
 
 	"github.com/onflow/flixkit-go/flixkit"
 
-	"github.com/onflow/flow-go-sdk"
-	"github.com/spf13/cobra"
-
 	"github.com/onflow/flow-cli/flowkit"
 	"github.com/onflow/flow-cli/flowkit/config"
 	"github.com/onflow/flow-cli/flowkit/output"
 	"github.com/onflow/flow-cli/internal/command"
 	"github.com/onflow/flow-cli/internal/scripts"
 	"github.com/onflow/flow-cli/internal/transactions"
+
+	"github.com/spf13/cobra"
 )
 
 type flixFlags struct {
@@ -105,28 +106,17 @@ func init() {
 
 func executeCmd(
 	args []string,
-	flags command.GlobalFlags,
+	_ command.GlobalFlags,
 	logger output.Logger,
 	flow flowkit.Services,
 	state *flowkit.State,
 ) (result command.Result, err error) {
-	flixService := flixkit.NewFlixService(&flixkit.FlixServiceConfig{
+	flixService := flixkit.NewFlixService(&flixkit.Config{
 		FileReader: state,
 	})
-	return executeFlixCmd(args, flags, logger, flow, state, flixService)
-}
-
-func executeFlixCmd(
-	args []string,
-	_ command.GlobalFlags,
-	logger output.Logger,
-	flow flowkit.Services,
-	state *flowkit.State,
-	flixService flixkit.FlixService,
-) (result command.Result, err error) {
 	flixQuery := args[0]
 	ctx := context.Background()
-	cadenceWithImportsReplaced, err := flixService.GetTemplateAndReplaceImports(ctx, flixQuery, flow.Network().Name)
+	cadenceWithImportsReplaced, err := flixService.GetAndReplaceCadenceImports(ctx, flixQuery, flow.Network().Name)
 	if err != nil {
 		logger.Error("could not replace imports")
 		return nil, err
@@ -161,25 +151,37 @@ func packageCmd(
 	flow flowkit.Services,
 	state *flowkit.State,
 ) (result command.Result, err error) {
-	flixService := flixkit.NewFlixService(&flixkit.FlixServiceConfig{
+	flixService := flixkit.NewFlixService(&flixkit.Config{
 		FileReader: state,
 	})
-
-	return packageFlixCmd(args, gFlags, logger, flow, state, flixService, flags)
-}
-
-func packageFlixCmd(
-	args []string,
-	gFlags command.GlobalFlags,
-	logger output.Logger,
-	flow flowkit.Services,
-	state *flowkit.State,
-	flixService flixkit.FlixService,
-	flags flixFlags,
-) (result command.Result, err error) {
 	flixQuery := args[0]
 	ctx := context.Background()
-	out, err := flixService.GetTemplateAndCreateBinding(ctx, flixQuery, flags.Lang, gFlags.Save)
+	template, err := flixService.GetTemplate(ctx, flixQuery)
+	if err != nil {
+		return nil, err
+	}
+	if !isUrl(flixQuery) {
+		if gFlags.Save != "" {
+			// resolve template file location to relative path to be used by binding file
+			flixQuery, err = GetRelativePath(flixQuery, gFlags.Save)
+			if err != nil {
+				logger.Error("could not resolve relative path to template")
+				return nil, err
+			}
+		}
+	}
+
+	var out string
+	var gen flixkit.FclGenerator
+	switch flags.Lang {
+	case "js":
+		gen = *flixkit.NewFclJSGenerator()
+	case "ts":
+		gen = *flixkit.NewFclTSGenerator()
+	default:
+		return nil, fmt.Errorf("language %s not supported", flags.Lang)
+	}
+	out, err = gen.Generate(template, flixQuery)
 	if err != nil {
 		return nil, err
 	}
@@ -191,31 +193,14 @@ func packageFlixCmd(
 }
 
 func generateCmd(
-	args []string,
-	gFlags command.GlobalFlags,
-	logger output.Logger,
-	flow flowkit.Services,
-	state *flowkit.State,
-) (result command.Result, err error) {
-	flixService := flixkit.NewFlixService(&flixkit.FlixServiceConfig{
-		FileReader: state,
-		Logger:     logger,
-	})
-
-	return generateFlixCmd(args, gFlags, logger, flow, state, flixService, flags)
-}
-
-func generateFlixCmd(
 	args []string,
 	_ command.GlobalFlags,
 	logger output.Logger,
 	flow flowkit.Services,
 	state *flowkit.State,
-	flixService flixkit.FlixService,
-	flags flixFlags,
 ) (result command.Result, err error) {
 	cadenceFile := args[0]
-	depContracts := getDeployedContracts(state)
+
 	if cadenceFile == "" {
 		return nil, fmt.Errorf("no cadence code found")
 	}
@@ -225,12 +210,25 @@ func generateFlixCmd(
 		return nil, fmt.Errorf("could not read cadence file %s: %w", cadenceFile, err)
 	}
 
+	depContracts := GetDeployedContracts(state)
+	generator, err := flixkit.NewGenerator(depContracts, logger)
 	if err != nil {
 		return nil, fmt.Errorf("could not create flix generator %w", err)
 	}
 
 	ctx := context.Background()
-	prettyJSON, err := flixService.CreateTemplate(ctx, depContracts, string(code), flags.PreFill)
+	var template string
+	if flags.PreFill != "" {
+		flixService := flixkit.NewFlixService(&flixkit.Config{
+			FileReader: state,
+		})
+		template, err = flixService.GetTemplate(ctx, flags.PreFill)
+		if err != nil {
+			return nil, fmt.Errorf("could not parse template from pre fill %w", err)
+		}
+	}
+
+	prettyJSON, err := generator.Generate(ctx, string(code), template)
 	if err != nil {
 		return nil, fmt.Errorf("could not generate flix %w", err)
 	}
@@ -257,7 +255,24 @@ func (fr *flixResult) Oneliner() string {
 	return fr.result
 }
 
-func getDeployedContracts(state *flowkit.State) flixkit.ContractInfos {
+// GetRelativePath computes the relative path from generated file to flix json file.
+// This path is used in the binding file to reference the flix json file.
+func GetRelativePath(configFile, bindingFile string) (string, error) {
+	relPath, err := filepath.Rel(filepath.Dir(bindingFile), configFile)
+	if err != nil {
+		return "", err
+	}
+
+	// If the file is in the same directory and doesn't start with "./", prepend it.
+	if !filepath.IsAbs(relPath) && relPath[0] != '.' {
+		relPath = "./" + relPath
+	}
+
+	// Currently binding files are js, we need to convert the path to unix style
+	return filepath.ToSlash(relPath), nil
+}
+
+func GetDeployedContracts(state *flowkit.State) flixkit.ContractInfos {
 	allContracts := make(flixkit.ContractInfos)
 	depNetworks := make([]string, 0)
 	// get all configured networks in flow.json
@@ -275,23 +290,27 @@ func getDeployedContracts(state *flowkit.State) flixkit.ContractInfos {
 			if _, ok := allContracts[c.Name]; !ok {
 				allContracts[c.Name] = make(flixkit.NetworkAddressMap)
 			}
-			allContracts[c.Name][network] = c.AccountAddress.Hex()
+			allContracts[c.Name][network] = c.AccountAddress.String()
 		}
 		locAliases := state.AliasesForNetwork(config.Network{Name: network})
 		for name, addr := range locAliases {
-			address := flow.BytesToAddress([]byte(addr))
 			if isPath(name) {
 				continue
 			}
 			if _, ok := allContracts[name]; !ok {
 				allContracts[name] = make(flixkit.NetworkAddressMap)
 			}
-			allContracts[name][network] = address.Hex()
+			allContracts[name][network] = addr
 		}
 	}
 	return allContracts
 }
 
+func isUrl(str string) bool {
+	u, err := url.Parse(str)
+	return err == nil && u.Scheme != "" && u.Host != ""
+}
+
 func isPath(path string) bool {
 	_, err := os.Stat(path)
 	return err == nil
diff --git a/scaffolds.json b/scaffolds.json
index 6803d2b0..c3b58260 100644
--- a/scaffolds.json
+++ b/scaffolds.json
@@ -27,7 +27,7 @@
     "name": "FCL Web Dapp",
     "repo": "https://github.com/chasefleming/fcl-next-scaffold.git",
     "description": "Simple TypeScript web application using next.js, FCL, and Cadence.",
-    "commit": "3a5d4f87eef72cebf45f1c48c51c2b786b28f7b6",
+    "commit": "16b0975f22382e23a2d72f2e25557511e528d56b",
     "type": "web"
   },
   {
diff --git a/version.txt b/version.txt
index 285cea5d..201cd88c 100644
--- a/version.txt
+++ b/version.txt
@@ -1,1 +1,1 @@
-v1.11.0
\ No newline at end of file
+v1.9.2
\ No newline at end of file


Test patch:
diff --git a/internal/super/flix_test.go b/internal/super/flix_test.go
deleted file mode 100644
index be6d3369..00000000
--- a/internal/super/flix_test.go
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Flow CLI
- *
- * Copyright 2024 Flow Foundation, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package super
-
-import (
-	"context"
-	"testing"
-
-	"github.com/spf13/afero"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/mock"
-
-	"github.com/onflow/flixkit-go/flixkit"
-	"github.com/onflow/flow-go-sdk/crypto"
-
-	"github.com/onflow/flow-cli/flowkit"
-	"github.com/onflow/flow-cli/flowkit/config"
-	"github.com/onflow/flow-cli/flowkit/mocks"
-	"github.com/onflow/flow-cli/flowkit/output"
-	"github.com/onflow/flow-cli/flowkit/tests"
-	"github.com/onflow/flow-cli/internal/command"
-	"github.com/onflow/flow-cli/internal/util"
-)
-
-type MockFlixService struct {
-	mock.Mock
-}
-
-var TEMPLATE_STR = "{ \"f_type\": \"IniteractionTemplate\", \"f_version\": \"1.1.0\", \"id\": \"0ea\",}"
-
-func (m *MockFlixService) GetTemplate(ctx context.Context, templateName string) (string, string, error) {
-	args := m.Called(ctx, templateName)
-	return TEMPLATE_STR, args.String(0), args.Error(1)
-}
-
-var CADENCE_SCRIPT = "pub fun main() {\n    log(\"Hello, World!\")\n}"
-
-func (m *MockFlixService) GetTemplateAndReplaceImports(ctx context.Context, templateName string, network string) (*flixkit.FlowInteractionTemplateExecution, error) {
-	result := &flixkit.FlowInteractionTemplateExecution{
-		Network:       "emulator",
-		IsTransaciton: false,
-		IsScript:      true,
-		Cadence:       CADENCE_SCRIPT,
-	}
-	return result, nil
-}
-
-func (m *MockFlixService) CreateTemplate(ctx context.Context, contractInfos flixkit.ContractInfos, code string, preFill string) (string, error) {
-	args := m.Called(ctx, contractInfos, code, preFill)
-	return TEMPLATE_STR, args.Error(1)
-}
-
-var JS_CODE = "export async function request() { const info = await fcl.query({ template: flixTemplate }); return info; }"
-
-func (m *MockFlixService) GetTemplateAndCreateBinding(ctx context.Context, templateName string, lang string, destFile string) (string, error) {
-	args := m.Called(ctx, templateName, lang, destFile)
-	return JS_CODE, args.Error(1)
-}
-
-func Test_ExecuteFlixScript(t *testing.T) {
-	ctx := context.Background()
-	logger := output.NewStdoutLogger(output.NoneLog)
-	srv, state, _ := util.TestMocks(t)
-	mockFlixService := new(MockFlixService)
-	testCadenceScript := "pub fun main() {\n    log(\"Hello, World!\")\n}"
-	mockFlixService.On("GetTemplateAndReplaceImports", ctx, "templateName", "emulator").Return(&flixkit.FlowInteractionTemplateExecution{
-		Network:       "emulator",
-		IsTransaciton: false,
-		IsScript:      true,
-		Cadence:       testCadenceScript,
-	}, nil)
-
-	// Set up a mock return value for the Network method
-	mockNetwork := config.Network{
-		Name: "emulator",
-		Host: "localhost:3569",
-	}
-	srv.Network.Run(func(args mock.Arguments) {}).Return(mockNetwork, nil)
-	srv.ExecuteScript.Run(func(args mock.Arguments) {
-		script := args.Get(1).(flowkit.Script)
-		assert.Equal(t, testCadenceScript, string(script.Code))
-	}).Return(nil, nil)
-
-	result, err := executeFlixCmd([]string{"transfer-token"}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService)
-	assert.NoError(t, err)
-	assert.NotNil(t, result)
-}
-
-func Test_ExecuteFlixTransaction(t *testing.T) {
-	ctx := context.Background()
-	logger := output.NewStdoutLogger(output.NoneLog)
-	srv, state, _ := util.TestMocks(t)
-	mockFlixService := new(MockFlixService)
-	testCadenceTx := "transaction { prepare(signer: AuthAccount) { /* prepare logic */ } execute { log(\"Hello, Cadence!\") } }"
-	mockFlixService.On("GetTemplateAndReplaceImports", ctx, "templateName", "emulator").Return(&flixkit.FlowInteractionTemplateExecution{
-		Network:       "emulator",
-		IsTransaciton: false,
-		IsScript:      true,
-		Cadence:       testCadenceTx,
-	}, nil)
-
-	// Set up a mock return value for the Network method
-	mockNetwork := config.Network{
-		Name: "emulator",
-		Host: "localhost:3569",
-	}
-	srv.Network.Run(func(args mock.Arguments) {}).Return(mockNetwork, nil)
-	srv.SendTransaction.Run(func(args mock.Arguments) {
-		script := args.Get(2).(flowkit.Script)
-		assert.Equal(t, testCadenceTx, string(script.Code))
-	}).Return(nil, nil)
-
-	result, err := executeFlixCmd([]string{"transfer-token"}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService)
-	assert.NoError(t, err)
-	assert.NotNil(t, result)
-}
-
-func Test_PackageFlix(t *testing.T) {
-	ctx := context.Background()
-	logger := output.NewStdoutLogger(output.NoneLog)
-	srv, state, _ := util.TestMocks(t)
-	mockFlixService := new(MockFlixService)
-	templateName := "templateName"
-	mockFlixService.On("GetTemplateAndCreateBinding", ctx, templateName, "js", "").Return(JS_CODE, nil)
-
-	result, err := packageFlixCmd([]string{templateName}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService, flixFlags{Lang: "js"})
-	assert.NoError(t, err)
-	assert.NotNil(t, result)
-	assert.Equal(t, JS_CODE, result.String())
-}
-func Test_GenerateFlix(t *testing.T) {
-	srv := mocks.DefaultMockServices()
-	cadenceFile := "cadence.cdc"
-	cadenceCode := "pub fun main() {\n    log(\"Hello, World!\")\n}"
-
-	mockFlixService := new(MockFlixService)
-
-	configJson := []byte(`{
-		"contracts": {},
-		"accounts": {
-			"emulator-account": {
-				"address": "f8d6e0586b0a20c7",
-				"key": "dd72967fd2bd75234ae9037dd4694c1f00baad63a10c35172bf65fbb8ad74b47"
-			}
-		},
-		"networks": {
-			"emulator": "127.0.0.1.3569"
-		},
-		"deployments": {
-		}
-	}`)
-
-	af := afero.Afero{Fs: afero.NewMemMapFs()}
-	err := afero.WriteFile(af.Fs, "flow.json", configJson, 0644)
-	assert.NoError(t, err)
-	err = afero.WriteFile(af.Fs, cadenceFile, []byte(cadenceCode), 0644)
-	assert.NoError(t, err)
-	err = afero.WriteFile(af.Fs, tests.ContractHelloString.Filename, []byte(tests.ContractHelloString.Source), 0644)
-	assert.NoError(t, err)
-	paths := []string{"flow.json"}
-	state, err := flowkit.Load(paths, af)
-	assert.NotNil(t, state)
-	assert.NoError(t, err)
-	d := config.Deployment{
-		Network: "emulator",
-		Account: "emulator-account",
-		Contracts: []config.ContractDeployment{{
-			Name: tests.ContractHelloString.Name,
-			Args: nil,
-		}},
-	}
-	state.Deployments().AddOrUpdate(d)
-	c := config.Contract{
-		Name:     tests.ContractHelloString.Name,
-		Location: tests.ContractHelloString.Filename,
-	}
-	state.Contracts().AddOrUpdate(c)
-
-	contracts, err := state.DeploymentContractsByNetwork(config.Network{Name: "emulator"})
-	assert.NoError(t, err)
-	assert.Equal(t, 1, len(contracts))
-
-	logger := output.NewStdoutLogger(output.NoneLog)
-	contractInfos := make(flixkit.ContractInfos)
-	contractInfos[tests.ContractHelloString.Name] = make(flixkit.NetworkAddressMap)
-	contractInfos[tests.ContractHelloString.Name]["emulator"] = "f8d6e0586b0a20c7"
-
-	ctx := context.Background()
-	mockFlixService.On("CreateTemplate", ctx, contractInfos, cadenceCode, "").Return(TEMPLATE_STR, nil)
-
-	result, err := generateFlixCmd([]string{cadenceFile}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService, flixFlags{})
-	assert.NoError(t, err)
-	assert.NotNil(t, result)
-	assert.Equal(t, TEMPLATE_STR, result.String())
-}
-
-func Test_GenerateFlixPrefill(t *testing.T) {
-	logger := output.NewStdoutLogger(output.NoneLog)
-	srv := mocks.DefaultMockServices()
-	templateName := "templateName"
-	cadenceFile := "cadence.cdc"
-
-	var mockFS = afero.NewMemMapFs()
-	var rw = afero.Afero{Fs: mockFS}
-	err := rw.WriteFile(cadenceFile, []byte(CADENCE_SCRIPT), 0644)
-	assert.NoError(t, err)
-	state, _ := flowkit.Init(rw, crypto.ECDSA_P256, crypto.SHA3_256)
-
-	mockFlixService := new(MockFlixService)
-	ctx := context.Background()
-	mockFlixService.On("CreateTemplate", ctx, flixkit.ContractInfos{}, CADENCE_SCRIPT, templateName).Return(TEMPLATE_STR, nil)
-
-	result, err := generateFlixCmd([]string{cadenceFile}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService, flixFlags{PreFill: templateName})
-	assert.NoError(t, err)
-	assert.NotNil(t, result)
-}
diff --git a/internal/test/test.go b/internal/test/test.go
index a24dc7b9..84d96cb6 100644
--- a/internal/test/test.go
+++ b/internal/test/test.go
@@ -105,7 +105,6 @@ func run(
 	testFiles := make(map[string][]byte, 0)
 	for _, filename := range args {
 		code, err := state.ReadFile(filename)
-
 		if err != nil {
 			return nil, fmt.Errorf("error loading script file: %w", err)
 		}
@@ -153,7 +152,7 @@ func testCode(
 
 	var coverageReport *runtime.CoverageReport
 	if flags.Cover {
-		coverageReport = runtime.NewCoverageReport()
+		coverageReport = state.CreateCoverageReport("testing")
 		if flags.CoverCode == contractsCoverCode {
 			coverageReport.WithLocationFilter(
 				func(location common.Location) bool {
@@ -177,8 +176,9 @@ func testCode(
 		runner = runner.WithRandomSeed(seed)
 	}
 
-	contracts := make(map[string]common.Address, 0)
-	for _, contract := range *state.Contracts() {
+	contractsConfig := *state.Contracts()
+	contracts := make(map[string]common.Address, len(contractsConfig))
+	for _, contract := range contractsConfig {
 		alias := contract.Aliases.ByNetwork("testing")
 		if alias != nil {
 			contracts[contract.Name] = common.Address(alias.Address)
@@ -239,7 +239,6 @@ func importResolver(scriptPath string, state *flowkit.State) cdcTests.ImportReso
 	}
 
 	return func(location common.Location) (string, error) {
-
 		contract := config.Contract{}
 
 		switch location := location.(type) {
diff --git a/internal/test/test_test.go b/internal/test/test_test.go
index 653f7b68..0f61be41 100644
--- a/internal/test/test_test.go
+++ b/internal/test/test_test.go
@@ -355,6 +355,12 @@ func TestExecutingTests(t *testing.T) {
 			result.String(),
 			"Coverage: 91.8% of statements",
 		)
+
+		lcovReport, _ := coverageReport.MarshalLCOV()
+		assert.Contains(t, string(lcovReport), "TN:\nSF:FooContract.cdc\n")
+
+		jsonReport, _ := coverageReport.MarshalJSON()
+		assert.Contains(t, string(jsonReport), `{"coverage":{"FooContract.cdc":{`)
 	})
 
 	t.Run("with code coverage for contracts only", func(t *testing.T) {
@@ -447,6 +453,12 @@ func TestExecutingTests(t *testing.T) {
 			result.String(),
 			"Coverage: 100.0% of statements",
 		)
+
+		lcovReport, _ := coverageReport.MarshalLCOV()
+		assert.Contains(t, string(lcovReport), "TN:\nSF:FooContract.cdc\n")
+
+		jsonReport, _ := coverageReport.MarshalJSON()
+		assert.Contains(t, string(jsonReport), `{"coverage":{"FooContract.cdc":{`)
 	})
 
 	t.Run("with random test case execution", func(t *testing.T) {