From 94c2f48fc84da3710e7f19c09e0125dbd8ccbd49 Mon Sep 17 00:00:00 2001 From: Tom Haile Date: Wed, 10 Jan 2024 16:27:53 -0600 Subject: [PATCH 1/4] break up methods so it can be unit tested, add more unit tests --- internal/super/flix.go | 75 +++++++++++---- internal/super/flix_test.go | 176 ++++++++++++++++++++++++++++++++++-- 2 files changed, 225 insertions(+), 26 deletions(-) diff --git a/internal/super/flix.go b/internal/super/flix.go index 4e2f194fc..d8d69be7e 100644 --- a/internal/super/flix.go +++ b/internal/super/flix.go @@ -107,7 +107,7 @@ func init() { func executeCmd( args []string, - _ command.GlobalFlags, + flags command.GlobalFlags, logger output.Logger, flow flowkit.Services, state *flowkit.State, @@ -115,6 +115,17 @@ func executeCmd( 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.GetAndReplaceCadenceImports(ctx, flixQuery, flow.Network().Name) @@ -155,6 +166,27 @@ func packageCmd( flixService := flixkit.NewFlixService(&flixkit.Config{ FileReader: state, }) + var gen flixkit.GenerateBinding + switch flags.Lang { + case "js", "javascript": + gen = flixkit.NewFclJSGenerator() + case "ts", "typescript": + gen = flixkit.NewFclTSGenerator() + default: + return nil, fmt.Errorf("language %s not supported", flags.Lang) + } + return packageFlixCmd(args, gFlags, logger, flow, state, flixService, gen) +} + +func packageFlixCmd( + args []string, + gFlags command.GlobalFlags, + logger output.Logger, + flow flowkit.Services, + state *flowkit.State, + flixService flixkit.FlixService, + generator flixkit.GenerateBinding, +) (result command.Result, err error) { flixQuery := args[0] ctx := context.Background() template, err := flixService.GetTemplate(ctx, flixQuery) @@ -172,17 +204,7 @@ func packageCmd( } } - 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) + out, err := generator.Generate(template, flixQuery) if err != nil { return nil, err } @@ -194,11 +216,33 @@ func packageCmd( } 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.Config{ + FileReader: state, + }) + depContracts := getDeployedContracts(state) + generator, err := flixkit.NewGenerator(depContracts, logger) + if err != nil { + return nil, fmt.Errorf("could not create flix generator %w", err) + } + + return generateFlixCmd(args, gFlags, logger, flow, state, flixService, generator, flags) +} + +func generateFlixCmd( args []string, _ command.GlobalFlags, logger output.Logger, flow flowkit.Services, state *flowkit.State, + flixService flixkit.FlixService, + generator flixkit.GenerateTemplate, + flags flixFlags, ) (result command.Result, err error) { cadenceFile := args[0] @@ -211,8 +255,6 @@ func generateCmd( 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) } @@ -220,9 +262,6 @@ func generateCmd( ctx := context.Background() 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) @@ -273,7 +312,7 @@ func GetRelativePath(configFile, bindingFile string) (string, error) { return filepath.ToSlash(relPath), nil } -func GetDeployedContracts(state *flowkit.State) flixkit.ContractInfos { +func getDeployedContracts(state *flowkit.State) flixkit.ContractInfos { allContracts := make(flixkit.ContractInfos) depNetworks := make([]string, 0) // get all configured networks in flow.json diff --git a/internal/super/flix_test.go b/internal/super/flix_test.go index c1b2c117b..4eaf3e6c6 100644 --- a/internal/super/flix_test.go +++ b/internal/super/flix_test.go @@ -19,17 +19,151 @@ 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" ) -func Test_flix_generate(t *testing.T) { +type MockFlixService struct { + mock.Mock +} + +func (m *MockFlixService) GetTemplate(ctx context.Context, templateName string) (string, error) { + args := m.Called(ctx, templateName) + return args.String(0), args.Error(1) +} + +func (m *MockFlixService) GetAndReplaceCadenceImports(ctx context.Context, templateName string, network string) (*flixkit.FlowInteractionTemplateExecution, error) { + result := &flixkit.FlowInteractionTemplateExecution{ + Network: "emulator", + IsTransaciton: false, + IsScript: true, + Cadence: "pub fun main() {\n log(\"Hello, World!\")\n}", + } + return result, nil +} +func Test_ExecuteFlixScript(t *testing.T) { + ctx := context.Background() + logger := output.NewStdoutLogger(output.NoneLog) + srv, state, _ := util.TestMocks(t) + mockFlixService := new(MockFlixService) + testCadence := "pub fun main() {\n log(\"Hello, World!\")\n}" + mockFlixService.On("GetAndReplaceCadenceImports", ctx, "templateName", "emulator").Return(&flixkit.FlowInteractionTemplateExecution{ + Network: "emulator", + IsTransaciton: false, + IsScript: true, + Cadence: testCadence, + }, 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, testCadence, 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) + testCadence := "transaction { prepare(signer: AuthAccount) { /* prepare logic */ } execute { log(\"Hello, Cadence!\") } }" + mockFlixService.On("GetAndReplaceCadenceImports", ctx, "templateName", "emulator").Return(&flixkit.FlowInteractionTemplateExecution{ + Network: "emulator", + IsTransaciton: false, + IsScript: true, + Cadence: testCadence, + }, 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, testCadence, 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) + +} + +type MockFclGenerator struct { + mock.Mock +} + +func (m *MockFclGenerator) Generate(flixString string, templateLocation string) (string, error) { + args := m.Called(flixString, templateLocation) + return args.String(0), args.Error(1) +} + +func Test_PackageFlix(t *testing.T) { + ctx := context.Background() + logger := output.NewStdoutLogger(output.NoneLog) + srv, state, _ := util.TestMocks(t) + mockFlixService := new(MockFlixService) + template := "{ \"f_type\": \"InteractionTemplate\", \"f_version\": \"1.1.0\", \"id\": \"0ea\",}" + templateName := "templateName" + mockFlixService.On("GetTemplate", ctx, templateName).Return(template, nil) + jsCode := "export async function request() { const info = await fcl.query({ template: flixTemplate }); return info; }" + mockFclGenerator := new(MockFclGenerator) + mockFclGenerator.On("Generate", template, templateName).Return(jsCode, nil) + + result, err := packageFlixCmd([]string{templateName}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService, mockFclGenerator) + assert.NoError(t, err) + assert.NotNil(t, result) + assert.Equal(t, jsCode, result.String()) +} + +type MockGenerateTemplate struct { + mock.Mock +} + +func (m *MockGenerateTemplate) Generate(ctx context.Context, code string, preFill string) (string, error) { + args := m.Called(ctx, code, preFill) + return args.String(0), args.Error(1) +} +func Test_GenerateFlix(t *testing.T) { + ctx := context.Background() + srv := mocks.DefaultMockServices() + template := "{ \"f_type\": \"InteractionTemplate\", \"f_version\": \"1.1.0\", \"id\": \"0ea\",}" + templateName := "templateName" + cadenceFile := "cadence.cdc" + cadenceCode := "pub fun main() {\n log(\"Hello, World!\")\n}" + + mockFlixService := new(MockFlixService) + mockFlixService.On("GetTemplate", ctx, templateName).Return(template, nil) + + mockGenerateTemplate := new(MockGenerateTemplate) + mockGenerateTemplate.On("Generate", cadenceCode, template).Return(template, nil) + configJson := []byte(`{ "contracts": {}, "accounts": { @@ -48,6 +182,8 @@ func Test_flix_generate(t *testing.T) { 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"} @@ -73,13 +209,37 @@ func Test_flix_generate(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 1, len(contracts)) - cs := GetDeployedContracts(state) - assert.Equal(t, 1, len(cs)) - networkContract := cs[tests.ContractHelloString.Name] - assert.NotNil(t, networkContract) - addr := networkContract["emulator"] - acct, err := state.Accounts().ByName("emulator-account") + logger := output.NewStdoutLogger(output.NoneLog) + + result, err := generateFlixCmd([]string{cadenceFile}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService, mockGenerateTemplate, flixFlags{}) + assert.NoError(t, err) + assert.NotNil(t, result) + assert.Equal(t, template, result.String()) +} + +func Test_GenerateFlixPrefill(t *testing.T) { + ctx := context.Background() + logger := output.NewStdoutLogger(output.NoneLog) + srv := mocks.DefaultMockServices() + template := "{ \"f_type\": \"InteractionTemplate\", \"f_version\": \"1.1.0\", \"id\": \"0ea\",}" + templateName := "templateName" + cadenceFile := "cadence.cdc" + cadenceCode := "pub fun main() {\n log(\"Hello, World!\")\n}" + + var mockFS = afero.NewMemMapFs() + var rw = afero.Afero{Fs: mockFS} + err := rw.WriteFile(cadenceFile, []byte(cadenceCode), 0644) + assert.NoError(t, err) + state, _ := flowkit.Init(rw, crypto.ECDSA_P256, crypto.SHA3_256) + + mockFlixService := new(MockFlixService) + mockFlixService.On("GetTemplate", ctx, templateName).Return(template, nil) + + mockGenerateTemplate := new(MockGenerateTemplate) + mockGenerateTemplate.On("Generate", ctx, cadenceCode, template).Return(template, nil) + + result, err := generateFlixCmd([]string{cadenceFile}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService, mockGenerateTemplate, flixFlags{PreFill: templateName}) assert.NoError(t, err) - assert.Equal(t, acct.Address.String(), addr) + assert.NotNil(t, result) } From 4bb1de4d89ae7d1f9a62cc0d73db5e4087ace08f Mon Sep 17 00:00:00 2001 From: Tom Haile Date: Wed, 10 Jan 2024 22:07:34 -0600 Subject: [PATCH 2/4] use new methods for generating binding files, update tests --- internal/super/flix.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/super/flix.go b/internal/super/flix.go index d8d69be7e..301a73aaa 100644 --- a/internal/super/flix.go +++ b/internal/super/flix.go @@ -169,9 +169,9 @@ func packageCmd( var gen flixkit.GenerateBinding switch flags.Lang { case "js", "javascript": - gen = flixkit.NewFclJSGenerator() + gen = flixkit.NewFclGeneratorJS() case "ts", "typescript": - gen = flixkit.NewFclTSGenerator() + gen = flixkit.NewFclGeneratorTS() default: return nil, fmt.Errorf("language %s not supported", flags.Lang) } From 8edd7fbec6070338a91f4ac465d8b0922a9ce0ae Mon Sep 17 00:00:00 2001 From: Tom Haile Date: Thu, 11 Jan 2024 11:50:31 -0600 Subject: [PATCH 3/4] clean up --- internal/super/flix_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/internal/super/flix_test.go b/internal/super/flix_test.go index 4eaf3e6c6..d6bb1a342 100644 --- a/internal/super/flix_test.go +++ b/internal/super/flix_test.go @@ -112,7 +112,6 @@ func Test_ExecuteFlixTransaction(t *testing.T) { result, err := executeFlixCmd([]string{"transfer-token"}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService) assert.NoError(t, err) assert.NotNil(t, result) - } type MockFclGenerator struct { @@ -162,7 +161,7 @@ func Test_GenerateFlix(t *testing.T) { mockFlixService.On("GetTemplate", ctx, templateName).Return(template, nil) mockGenerateTemplate := new(MockGenerateTemplate) - mockGenerateTemplate.On("Generate", cadenceCode, template).Return(template, nil) + mockGenerateTemplate.On("Generate", ctx, cadenceCode, "").Return(template, nil) configJson := []byte(`{ "contracts": {}, @@ -241,5 +240,4 @@ func Test_GenerateFlixPrefill(t *testing.T) { result, err := generateFlixCmd([]string{cadenceFile}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService, mockGenerateTemplate, flixFlags{PreFill: templateName}) assert.NoError(t, err) assert.NotNil(t, result) - } From 3944ccf8bb6201b7a8766f18e2b63173e0206313 Mon Sep 17 00:00:00 2001 From: Tom Haile Date: Thu, 18 Jan 2024 10:44:30 -0600 Subject: [PATCH 4/4] update version of flixkit-go used, clean up flix tests --- go.mod | 2 +- go.sum | 4 +- internal/super/flix.go | 85 +++++-------------------------- internal/super/flix_test.go | 99 +++++++++++++++++-------------------- 4 files changed, 59 insertions(+), 131 deletions(-) diff --git a/go.mod b/go.mod index d59388e3f..4cef1c1a8 100644 --- a/go.mod +++ b/go.mod @@ -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.0.2 + github.com/onflow/flixkit-go v1.1.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 65f0c2b12..240917aa1 100644 --- a/go.sum +++ b/go.sum @@ -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.0.2 h1:6PVLLb8qQj9L6cs57HUO3wszzbgPD46pc9MAGWHnb1s= -github.com/onflow/flixkit-go v1.0.2/go.mod h1:KGL7oMu4uzt7s0qsNkaqGBYIt+Z38Qbf0JG56qK/Sg0= +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/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 301a73aaa..418b2d126 100644 --- a/internal/super/flix.go +++ b/internal/super/flix.go @@ -21,9 +21,7 @@ package super import ( "context" "fmt" - "net/url" "os" - "path/filepath" "github.com/onflow/flixkit-go/flixkit" @@ -112,7 +110,7 @@ func executeCmd( flow flowkit.Services, state *flowkit.State, ) (result command.Result, err error) { - flixService := flixkit.NewFlixService(&flixkit.Config{ + flixService := flixkit.NewFlixService(&flixkit.FlixServiceConfig{ FileReader: state, }) return executeFlixCmd(args, flags, logger, flow, state, flixService) @@ -128,7 +126,7 @@ func executeFlixCmd( ) (result command.Result, err error) { flixQuery := args[0] ctx := context.Background() - cadenceWithImportsReplaced, err := flixService.GetAndReplaceCadenceImports(ctx, flixQuery, flow.Network().Name) + cadenceWithImportsReplaced, err := flixService.GetTemplateAndReplaceImports(ctx, flixQuery, flow.Network().Name) if err != nil { logger.Error("could not replace imports") return nil, err @@ -163,19 +161,11 @@ func packageCmd( flow flowkit.Services, state *flowkit.State, ) (result command.Result, err error) { - flixService := flixkit.NewFlixService(&flixkit.Config{ + flixService := flixkit.NewFlixService(&flixkit.FlixServiceConfig{ FileReader: state, }) - var gen flixkit.GenerateBinding - switch flags.Lang { - case "js", "javascript": - gen = flixkit.NewFclGeneratorJS() - case "ts", "typescript": - gen = flixkit.NewFclGeneratorTS() - default: - return nil, fmt.Errorf("language %s not supported", flags.Lang) - } - return packageFlixCmd(args, gFlags, logger, flow, state, flixService, gen) + + return packageFlixCmd(args, gFlags, logger, flow, state, flixService, flags) } func packageFlixCmd( @@ -185,26 +175,11 @@ func packageFlixCmd( flow flowkit.Services, state *flowkit.State, flixService flixkit.FlixService, - generator flixkit.GenerateBinding, + flags flixFlags, ) (result command.Result, err error) { flixQuery := args[0] ctx := context.Background() - 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 - } - } - } - - out, err := generator.Generate(template, flixQuery) + out, err := flixService.GetTemplateAndCreateBinding(ctx, flixQuery, flags.Lang, gFlags.Save) if err != nil { return nil, err } @@ -222,16 +197,12 @@ func generateCmd( flow flowkit.Services, state *flowkit.State, ) (result command.Result, err error) { - flixService := flixkit.NewFlixService(&flixkit.Config{ + flixService := flixkit.NewFlixService(&flixkit.FlixServiceConfig{ FileReader: state, + Logger: logger, }) - depContracts := getDeployedContracts(state) - generator, err := flixkit.NewGenerator(depContracts, logger) - if err != nil { - return nil, fmt.Errorf("could not create flix generator %w", err) - } - return generateFlixCmd(args, gFlags, logger, flow, state, flixService, generator, flags) + return generateFlixCmd(args, gFlags, logger, flow, state, flixService, flags) } func generateFlixCmd( @@ -241,11 +212,10 @@ func generateFlixCmd( flow flowkit.Services, state *flowkit.State, flixService flixkit.FlixService, - generator flixkit.GenerateTemplate, flags flixFlags, ) (result command.Result, err error) { cadenceFile := args[0] - + depContracts := getDeployedContracts(state) if cadenceFile == "" { return nil, fmt.Errorf("no cadence code found") } @@ -260,15 +230,7 @@ func generateFlixCmd( } ctx := context.Background() - var template string - if flags.PreFill != "" { - 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) + prettyJSON, err := flixService.CreateTemplate(ctx, depContracts, string(code), flags.PreFill) if err != nil { return nil, fmt.Errorf("could not generate flix %w", err) } @@ -295,23 +257,6 @@ func (fr *flixResult) Oneliner() string { return fr.result } -// 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) @@ -323,7 +268,6 @@ func getDeployedContracts(state *flowkit.State) flixkit.ContractInfos { // get all deployed and alias contracts for configured networks for _, network := range depNetworks { contracts, err := state.DeploymentContractsByNetwork(config.Network{Name: network}) - fmt.Println("contracts len", network, len(contracts)) if err != nil { continue } @@ -348,11 +292,6 @@ func getDeployedContracts(state *flowkit.State) flixkit.ContractInfos { 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/internal/super/flix_test.go b/internal/super/flix_test.go index d6bb1a342..be6d33692 100644 --- a/internal/super/flix_test.go +++ b/internal/super/flix_test.go @@ -42,31 +42,48 @@ type MockFlixService struct { mock.Mock } -func (m *MockFlixService) GetTemplate(ctx context.Context, templateName string) (string, error) { +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 args.String(0), args.Error(1) + return TEMPLATE_STR, args.String(0), args.Error(1) } -func (m *MockFlixService) GetAndReplaceCadenceImports(ctx context.Context, templateName string, network string) (*flixkit.FlowInteractionTemplateExecution, error) { +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: "pub fun main() {\n log(\"Hello, World!\")\n}", + 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) - testCadence := "pub fun main() {\n log(\"Hello, World!\")\n}" - mockFlixService.On("GetAndReplaceCadenceImports", ctx, "templateName", "emulator").Return(&flixkit.FlowInteractionTemplateExecution{ + 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: testCadence, + Cadence: testCadenceScript, }, nil) // Set up a mock return value for the Network method @@ -77,7 +94,7 @@ func Test_ExecuteFlixScript(t *testing.T) { 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, testCadence, string(script.Code)) + assert.Equal(t, testCadenceScript, string(script.Code)) }).Return(nil, nil) result, err := executeFlixCmd([]string{"transfer-token"}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService) @@ -90,12 +107,12 @@ func Test_ExecuteFlixTransaction(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) srv, state, _ := util.TestMocks(t) mockFlixService := new(MockFlixService) - testCadence := "transaction { prepare(signer: AuthAccount) { /* prepare logic */ } execute { log(\"Hello, Cadence!\") } }" - mockFlixService.On("GetAndReplaceCadenceImports", ctx, "templateName", "emulator").Return(&flixkit.FlowInteractionTemplateExecution{ + 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: testCadence, + Cadence: testCadenceTx, }, nil) // Set up a mock return value for the Network method @@ -106,7 +123,7 @@ func Test_ExecuteFlixTransaction(t *testing.T) { 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, testCadence, string(script.Code)) + assert.Equal(t, testCadenceTx, string(script.Code)) }).Return(nil, nil) result, err := executeFlixCmd([]string{"transfer-token"}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService) @@ -114,54 +131,25 @@ func Test_ExecuteFlixTransaction(t *testing.T) { assert.NotNil(t, result) } -type MockFclGenerator struct { - mock.Mock -} - -func (m *MockFclGenerator) Generate(flixString string, templateLocation string) (string, error) { - args := m.Called(flixString, templateLocation) - return args.String(0), args.Error(1) -} - func Test_PackageFlix(t *testing.T) { ctx := context.Background() logger := output.NewStdoutLogger(output.NoneLog) srv, state, _ := util.TestMocks(t) mockFlixService := new(MockFlixService) - template := "{ \"f_type\": \"InteractionTemplate\", \"f_version\": \"1.1.0\", \"id\": \"0ea\",}" templateName := "templateName" - mockFlixService.On("GetTemplate", ctx, templateName).Return(template, nil) - jsCode := "export async function request() { const info = await fcl.query({ template: flixTemplate }); return info; }" - mockFclGenerator := new(MockFclGenerator) - mockFclGenerator.On("Generate", template, templateName).Return(jsCode, nil) + mockFlixService.On("GetTemplateAndCreateBinding", ctx, templateName, "js", "").Return(JS_CODE, nil) - result, err := packageFlixCmd([]string{templateName}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService, mockFclGenerator) + 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, jsCode, result.String()) -} - -type MockGenerateTemplate struct { - mock.Mock -} - -func (m *MockGenerateTemplate) Generate(ctx context.Context, code string, preFill string) (string, error) { - args := m.Called(ctx, code, preFill) - return args.String(0), args.Error(1) + assert.Equal(t, JS_CODE, result.String()) } func Test_GenerateFlix(t *testing.T) { - ctx := context.Background() srv := mocks.DefaultMockServices() - template := "{ \"f_type\": \"InteractionTemplate\", \"f_version\": \"1.1.0\", \"id\": \"0ea\",}" - templateName := "templateName" cadenceFile := "cadence.cdc" cadenceCode := "pub fun main() {\n log(\"Hello, World!\")\n}" mockFlixService := new(MockFlixService) - mockFlixService.On("GetTemplate", ctx, templateName).Return(template, nil) - - mockGenerateTemplate := new(MockGenerateTemplate) - mockGenerateTemplate.On("Generate", ctx, cadenceCode, "").Return(template, nil) configJson := []byte(`{ "contracts": {}, @@ -209,35 +197,36 @@ func Test_GenerateFlix(t *testing.T) { 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" - result, err := generateFlixCmd([]string{cadenceFile}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService, mockGenerateTemplate, flixFlags{}) + 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, result.String()) + assert.Equal(t, TEMPLATE_STR, result.String()) } func Test_GenerateFlixPrefill(t *testing.T) { - ctx := context.Background() logger := output.NewStdoutLogger(output.NoneLog) srv := mocks.DefaultMockServices() - template := "{ \"f_type\": \"InteractionTemplate\", \"f_version\": \"1.1.0\", \"id\": \"0ea\",}" templateName := "templateName" cadenceFile := "cadence.cdc" - cadenceCode := "pub fun main() {\n log(\"Hello, World!\")\n}" var mockFS = afero.NewMemMapFs() var rw = afero.Afero{Fs: mockFS} - err := rw.WriteFile(cadenceFile, []byte(cadenceCode), 0644) + 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) - mockFlixService.On("GetTemplate", ctx, templateName).Return(template, nil) - - mockGenerateTemplate := new(MockGenerateTemplate) - mockGenerateTemplate.On("Generate", ctx, cadenceCode, template).Return(template, nil) + 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, mockGenerateTemplate, flixFlags{PreFill: templateName}) + result, err := generateFlixCmd([]string{cadenceFile}, command.GlobalFlags{}, logger, srv.Mock, state, mockFlixService, flixFlags{PreFill: templateName}) assert.NoError(t, err) assert.NotNil(t, result) }