diff --git a/.github/workflows/test_integration_cli.yml b/.github/workflows/test_integration_cli.yml new file mode 100644 index 00000000..1dcd7634 --- /dev/null +++ b/.github/workflows/test_integration_cli.yml @@ -0,0 +1,36 @@ +on: + push: + branches: + - develop + pull_request: + branches: + - develop + +jobs: + integration-tests: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Install Docker Compose + run: | + sudo apt-get update + sudo apt-get install -y docker-compose + + - name: Setup .env files + run: make set-env + + - name: Start Docker Compose Services + run: make up + + - name: Install CLI + run: cd components/mdz && make install-local && cd - + + - name: Wait for services to be ready + run: sleep 10 + timeout-minutes: 2 + + - name: Run Integration Tests + run: make test_integration_cli diff --git a/Makefile b/Makefile index b8412d6c..3bd5987a 100644 --- a/Makefile +++ b/Makefile @@ -151,6 +151,9 @@ all-services: $(MAKE) -C $(LEDGER_DIR) $(COMMAND) && \ $(MAKE) -C $(TRANSACTION_DIR) $(COMMAND) +test_integration_cli: + go test -v -tags=integration ./components/mdz/test/integration/... + goreleaser: @echo "$(BLUE)Creating release snapshot...$(NC)" goreleaser release --snapshot --skip-publish --rm-dist @@ -162,4 +165,4 @@ tidy: generate-docs-all: @echo "$(BLUE)Executing command to generate swagger...$(NC)" $(MAKE) -C $(LEDGER_DIR) generate-docs && \ - $(MAKE) -C $(TRANSACTION_DIR) generate-docs \ No newline at end of file + $(MAKE) -C $(TRANSACTION_DIR) generate-docs diff --git a/components/mdz/Makefile b/components/mdz/Makefile index 9cf11973..845efb01 100644 --- a/components/mdz/Makefile +++ b/components/mdz/Makefile @@ -51,7 +51,15 @@ perfsprint: get-perfsprint-deps test: go test ./... -.PHONY : build +.PHONY: test_integration +test_integration: + go test -v -tags=integration ./test/integration/... + +.PHONY: build build: go version go build -ldflags "$(LDFLAGS)" -o ./bin/$(NAME) ./main.go + +.PHONY: install-local +install-local: build + sudo cp -r bin/mdz /usr/local/bin diff --git a/components/mdz/internal/rest/account.go b/components/mdz/internal/rest/account.go index dd80b2bb..af99a947 100644 --- a/components/mdz/internal/rest/account.go +++ b/components/mdz/internal/rest/account.go @@ -24,10 +24,12 @@ func (r *account) Create( return nil, fmt.Errorf("marshalling JSON: %v", err) } + body := bytes.NewReader(jsonData) + uri := fmt.Sprintf("%s/v1/organizations/%s/ledgers/%s/portfolios/%s/accounts", r.Factory.Env.URLAPILedger, organizationID, ledgerID, portfolioID) - req, err := http.NewRequest(http.MethodPost, uri, bytes.NewBuffer(jsonData)) + req, err := http.NewRequest(http.MethodPost, uri, body) if err != nil { return nil, errors.New("creating request: " + err.Error()) } diff --git a/components/mdz/pkg/cmd/account/create.go b/components/mdz/pkg/cmd/account/create.go index 17317b4e..dcccde68 100644 --- a/components/mdz/pkg/cmd/account/create.go +++ b/components/mdz/pkg/cmd/account/create.go @@ -107,25 +107,25 @@ func (f *factoryAccountCreate) createRequestFromFlags(account *mmodel.CreateAcco return err } - if account.Alias != nil { + if len(f.Alias) > 0 { account.Alias = &f.Alias } account.Type = f.Type - if account.ParentAccountID != nil { + if len(f.ParentAccountID) > 0 { account.ParentAccountID = &f.ParentAccountID } - if account.ProductID != nil { + if len(f.ProductID) > 0 { account.ProductID = &f.ProductID } - if account.PortfolioID != nil { + if len(f.PortfolioID) > 0 { account.PortfolioID = &f.PortfolioID } - if account.EntityID != nil { + if len(f.EntityID) > 0 { account.EntityID = &f.EntityID } @@ -153,10 +153,6 @@ func (f *factoryAccountCreate) createRequestFromFlags(account *mmodel.CreateAcco account.AllowReceiving = &allowReceive } - if account.EntityID != nil { - account.EntityID = &f.EntityID - } - var metadata map[string]any if err := json.Unmarshal([]byte(f.Metadata), &metadata); err != nil { return errors.New("Error parsing metadata: " + err.Error()) diff --git a/components/mdz/pkg/cmd/account/describe.go b/components/mdz/pkg/cmd/account/describe.go index 51886983..b06154c2 100644 --- a/components/mdz/pkg/cmd/account/describe.go +++ b/components/mdz/pkg/cmd/account/describe.go @@ -124,12 +124,23 @@ func (f *factoryAccountDescribe) describePrint(account *mmodel.Account) { tbl.AddRow("ID:", account.ID) tbl.AddRow("Asset Code:", account.AssetCode) tbl.AddRow("Name:", account.Name) - tbl.AddRow("Entity ID:", account.EntityID) + + if account.EntityID != nil { + tbl.AddRow("Entity ID:", *account.EntityID) + } + + if account.ProductID != nil { + tbl.AddRow("Product ID:", *account.ProductID) + } if account.ParentAccountID != nil { tbl.AddRow("Parent Account ID:", *account.ParentAccountID) } + if account.Alias != nil { + tbl.AddRow("Alias:", *account.Alias) + } + tbl.AddRow("Type:", account.Type) tbl.AddRow("Status Code:", account.Status.Code) diff --git a/components/mdz/pkg/cmd/root/root.go b/components/mdz/pkg/cmd/root/root.go index 33af524a..884ede77 100644 --- a/components/mdz/pkg/cmd/root/root.go +++ b/components/mdz/pkg/cmd/root/root.go @@ -3,6 +3,7 @@ package root import ( "errors" + "github.com/LerianStudio/midaz/components/mdz/pkg/cmd/account" "github.com/LerianStudio/midaz/components/mdz/pkg/cmd/asset" "github.com/LerianStudio/midaz/components/mdz/pkg/cmd/ledger" "github.com/LerianStudio/midaz/components/mdz/pkg/cmd/login" @@ -29,7 +30,7 @@ func (f *factoryRoot) setCmds(cmd *cobra.Command) { cmd.AddCommand(asset.NewCmdAsset(f.factory)) cmd.AddCommand(portfolio.NewCmdPortfolio(f.factory)) cmd.AddCommand(product.NewCmdProduct(f.factory)) - cmd.AddCommand(asset.NewCmdAsset(f.factory)) + cmd.AddCommand(account.NewCmdAccount(f.factory)) } func (f *factoryRoot) setFlags(cmd *cobra.Command) { diff --git a/components/mdz/test/integration/login_test.go b/components/mdz/test/integration/login_test.go new file mode 100644 index 00000000..878f115d --- /dev/null +++ b/components/mdz/test/integration/login_test.go @@ -0,0 +1,73 @@ +//go:build integration +// +build integration + +package integration + +import ( + "bytes" + "os" + "os/exec" + "testing" + "time" + + "github.com/Netflix/go-expect" + "gotest.tools/golden" +) + +func TestMDZLogin(t *testing.T) { + cmd := exec.Command("mdz", "login", "--username", "user_john", "--password", "Lerian@123") + + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + if err := cmd.Run(); err != nil { + t.Fatalf("Error executing command: %v\nStderr: %s", err, stderr.String()) + } + + golden.AssertBytes(t, []byte(stdout.String()), "out_login_flags.golden") +} + +func TestMDZLoginIt(t *testing.T) { + console, err := expect.NewConsole(expect.WithStdout(os.Stdout)) + if err != nil { + t.Fatalf("Error creating console: %v", err) + } + defer console.Close() + + cmd := exec.Command("mdz", "login") + cmd.Stdin = console.Tty() + cmd.Stdout = console.Tty() + cmd.Stderr = console.Tty() + + errChan := make(chan error, 1) + + go func() { + if err := cmd.Start(); err != nil { + errChan <- err + return + } + + if err := cmd.Wait(); err != nil { + errChan <- err + return + } + + errChan <- nil + }() + + time.Sleep(1 * time.Second) + down(t, console) + enter(t, console) + sendInput(t, console, "user_john") + sendInput(t, console, "Lerian@123") + time.Sleep(1 * time.Second) + + if _, err := console.ExpectString("successfully logged in"); err != nil { + t.Fatalf("Failed test: %v", err) + } + + if err := <-errChan; err != nil { + t.Fatalf("Command execution error: %v", err) + } +} diff --git a/components/mdz/test/integration/mdz.sh b/components/mdz/test/integration/mdz.sh new file mode 100644 index 00000000..837e9e29 --- /dev/null +++ b/components/mdz/test/integration/mdz.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# Setting environment variables (if necessary) +MDZ_CMD="mdz" +USERNAME="user_john" +PASSWORD="Lerian@123" +LEGAL_NAME="Soul LLCT" +DOING_BUSINESS_AS="The ledger.io" +LEGAL_DOCUMENT="48784548000104" +STATUS_CODE="ACTIVE" +DESCRIPTION="Test Ledger" +LINE1="Av Santso" +LINE2="VJ 222" +ZIP_CODE="04696040" +CITY="West" +STATE="VJ" +COUNTRY="MG" +METADATA='{"chave1": "valor1", "chave2": 2, "chave3": true}' + +# Function to execute commands and capture the output +run_command() { + echo "Executando: $1" + OUTPUT=$($1) + echo "$OUTPUT" +} + +login_output=$(run_command "$MDZ_CMD login --username $USERNAME --password $PASSWORD") +echo "$login_output" + +create_output=$(run_command "$MDZ_CMD organization create --legal-name $LEGAL_NAME --doing-business-as $DOING_BUSINESS_AS --legal-document $LEGAL_DOCUMENT --code $STATUS_CODE --description $DESCRIPTION --line1 $LINE1 --line2 $LINE2 --zip-code $ZIP_CODE --city $CITY --state $STATE --country $COUNTRY --metadata $METADATA") +echo "$create_output" + +list_output=$(run_command "$MDZ_CMD organization list") +echo "$list_output" + +ORG_ID=$(echo "$list_output" | grep -oP '[0-9a-fA-F-]{36}' | head -n 1) +if [ -z "$ORG_ID" ]; then + echo "Erro: No ID found!" + exit 1 +fi +echo "organization id: $ORG_ID" + +describe_output=$(run_command "$MDZ_CMD organization describe --organization-id $ORG_ID") +echo "$describe_output" + +update_output=$(run_command "$MDZ_CMD organization update --organization-id $ORG_ID --legal-name 'Updated Name' --doing-business-as 'Updated Business' --country 'BR'") +echo "$update_output" + +echo "Test completed!" diff --git a/components/mdz/test/integration/mdz_test.go b/components/mdz/test/integration/mdz_test.go new file mode 100644 index 00000000..bb9440d8 --- /dev/null +++ b/components/mdz/test/integration/mdz_test.go @@ -0,0 +1,238 @@ +//go:build integration +// +build integration + +package integration + +import ( + "fmt" + "math/rand" + "os/exec" + "testing" + "time" + + "github.com/icrowley/fake" + "gotest.tools/golden" +) + +func TestMDZ(t *testing.T) { + var stdout string + + stdout, _ = cmdRun(t, exec.Command("mdz", "login", + "--username", "user_john", + "--password", "Lerian@123", + )) + + golden.AssertBytes(t, []byte(stdout), "out_login_flags.golden") + + stdout, _ = cmdRun(t, exec.Command("mdz", "organization", "create", + "--legal-name", "Soul LLCT", + "--doing-business-as", "The ledger.io", + "--legal-document", "48784548000104", + "--code", "ACTIVE", + "--description", "Test Ledger", + "--line1", "Av Santso", + "--line2", "VJ 222", + "--zip-code", "04696040", + "--city", "West", + "--state", "VJ", + "--country", "MG", + "--metadata", `{"chave1": "valor1", "chave2": 2, "chave3": true}`, + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "organization", "list")) + + organizationID := getIDListOutput(t, stdout) + + stdout, _ = cmdRun(t, exec.Command("mdz", "organization", "describe", + "--organization-id", organizationID, + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "organization", "update", + "--organization-id", organizationID, + "--legal-name", fake.FirstName(), + "--doing-business-as", fake.Word(), + "--country", "BR", + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "ledger", "create", + "--organization-id", organizationID, + "--name", fake.FirstName(), + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "ledger", "list", + "--organization-id", organizationID, + )) + + ledgerID := getIDListOutput(t, stdout) + + stdout, _ = cmdRun(t, exec.Command("mdz", "ledger", "describe", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "ledger", "update", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--name", fake.FirstName(), + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "asset", "create", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--name", fake.FirstName(), + "--code", "BRL", + "--type", "currency", + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "asset", "list", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + )) + + assetID := getIDListOutput(t, stdout) + + stdout, _ = cmdRun(t, exec.Command("mdz", "asset", "describe", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--asset-id", assetID, + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "asset", "update", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--asset-id", assetID, + "--name", fake.FirstName(), + )) + + r := rand.New(rand.NewSource(time.Now().UnixNano())) + randomNumber := r.Intn(999999) + + stdout, _ = cmdRun(t, exec.Command("mdz", "portfolio", "create", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--name", fake.FirstName(), + "--entity-id", fmt.Sprint(randomNumber), + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "portfolio", "list", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + )) + + portfolioID := getIDListOutput(t, stdout) + + stdout, _ = cmdRun(t, exec.Command("mdz", "portfolio", "describe", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--portfolio-id", portfolioID, + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "portfolio", "update", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--portfolio-id", portfolioID, + "--name", fake.FirstName(), + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "product", "create", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--name", fake.FirstName(), + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "product", "list", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + )) + + productID := getIDListOutput(t, stdout) + + stdout, _ = cmdRun(t, exec.Command("mdz", "product", "describe", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--product-id", productID, + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "product", "update", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--product-id", productID, + "--name", fake.FirstName(), + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "account", "create", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--portfolio-id", portfolioID, + "--name", fake.FirstName(), + "--asset-code", "BRL", + "--type", "creditCard", + "--alias", "@wallet_luffy", + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "account", "list", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--portfolio-id", portfolioID, + )) + + accountID := getIDListOutput(t, stdout) + + stdout, _ = cmdRun(t, exec.Command("mdz", "account", "describe", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--portfolio-id", portfolioID, + "--account-id", accountID, + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "account", "update", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--portfolio-id", portfolioID, + "--account-id", accountID, + "--product-id", productID, + "--name", fake.FirstName(), + "--alias", "@wallet_"+fake.FirstName(), + )) + + t.Log("organization ID: ", organizationID) + t.Log("ledger ID: ", ledgerID) + t.Log("asset ID: ", assetID) + t.Log("portfolio ID: ", portfolioID) + t.Log("product ID: ", productID) + t.Log("account ID: ", accountID) + + stdout, _ = cmdRun(t, exec.Command("mdz", "account", "delete", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--portfolio-id", portfolioID, + "--account-id", accountID, + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "asset", "delete", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--asset-id", assetID, + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "product", "delete", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--product-id", productID, + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "portfolio", "delete", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + "--portfolio-id", portfolioID, + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "ledger", "delete", + "--organization-id", organizationID, + "--ledger-id", ledgerID, + )) + + stdout, _ = cmdRun(t, exec.Command("mdz", "organization", "delete", + "--organization-id", organizationID, + )) +} diff --git a/components/mdz/test/integration/testdata/out_login_flags.golden b/components/mdz/test/integration/testdata/out_login_flags.golden new file mode 100644 index 00000000..8d39d2ef --- /dev/null +++ b/components/mdz/test/integration/testdata/out_login_flags.golden @@ -0,0 +1 @@ +successfully logged in diff --git a/components/mdz/test/integration/testutils.go b/components/mdz/test/integration/testutils.go new file mode 100644 index 00000000..2a58aeca --- /dev/null +++ b/components/mdz/test/integration/testutils.go @@ -0,0 +1,83 @@ +//go:build integration +// +build integration + +package integration + +import ( + "bytes" + "os/exec" + "regexp" + "testing" + "time" + + "github.com/Netflix/go-expect" +) + +const interactionDelay = 500 * time.Millisecond + +// up Send up arrow +// func up(t *testing.T, console *expect.Console) { +// _, err := console.Send("\x1b[A") +// if err != nil { +// t.Fatal(err.Error()) +// } +// +// time.Sleep(interactionDelay) +// } + +// down send down arrow +func down(t *testing.T, console *expect.Console) { + _, err := console.Send("\x1b[B") + if err != nil { + t.Fatal(err.Error()) + } + + time.Sleep(interactionDelay) +} + +// enter Send Enter key +func enter(t *testing.T, console *expect.Console) { + _, err := console.Send("\r") + if err != nil { + t.Fatal(err.Error()) + } + + time.Sleep(interactionDelay) +} + +// sendInput Send a value and then Enter +func sendInput(t *testing.T, console *expect.Console, input string) { + _, err := console.Send(input + "\r") + if err != nil { + t.Fatal(err.Error()) + } + + time.Sleep(interactionDelay) +} + +// cmdRun run command and check error +func cmdRun(t *testing.T, cmd *exec.Cmd) (string, string) { + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + if err := cmd.Run(); err != nil { + t.Fatalf("Error executing command: %v\nStderr: %s", err, stderr.String()) + } + + t.Log(cmd.Stdout) + t.Log(cmd.Stderr) + + return stdout.String(), stderr.String() +} + +// getIDListOutput get id list command +func getIDListOutput(t *testing.T, stdout string) string { + re := regexp.MustCompile(`[0-9a-fA-F-]{36}`) + id := re.FindString(stdout) + if id == "" { + t.Fatal("No ID found in output") + } + + return id +} diff --git a/go.mod b/go.mod index 60a64ecd..81ff993e 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ toolchain go1.23.0 require ( github.com/Masterminds/squirrel v1.5.4 + github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 github.com/antlr4-go/antlr/v4 v4.13.1 github.com/casdoor/casdoor-go-sdk v1.3.0 github.com/charmbracelet/bubbles v0.20.0 @@ -13,6 +14,7 @@ require ( github.com/go-playground/locales v0.14.1 github.com/go-playground/universal-translator v0.18.1 github.com/gofiber/fiber/v2 v2.52.5 + github.com/icrowley/fake v0.0.0-20240710202011-f797eb4a99c0 github.com/jackc/pgx/v5 v5.7.1 github.com/jarcoal/httpmock v1.3.1 github.com/joho/godotenv v1.5.1 @@ -53,6 +55,8 @@ require ( github.com/charmbracelet/lipgloss v1.0.0 // indirect github.com/charmbracelet/x/ansi v0.4.5 // indirect github.com/charmbracelet/x/term v0.2.1 // indirect + github.com/corpix/uarand v0.0.0-20170723150923-031be390f409 // indirect + github.com/creack/pty v1.1.17 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/go-logr/logr v1.4.2 // indirect diff --git a/go.sum b/go.sum index acadcff9..baca38e7 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8 github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= @@ -43,9 +45,13 @@ github.com/charmbracelet/x/ansi v0.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSe github.com/charmbracelet/x/ansi v0.4.5/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/corpix/uarand v0.0.0-20170723150923-031be390f409 h1:9A+mfQmwzZ6KwUXPc8nHxFtKgn9VIvO3gXAOspIcE3s= +github.com/corpix/uarand v0.0.0-20170723150923-031be390f409/go.mod h1:JSm890tOkDN+M1jqN8pUGDKnzJrsVbJwSMHBY4zwz7M= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= +github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -123,6 +129,8 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/icrowley/fake v0.0.0-20240710202011-f797eb4a99c0 h1:ufr2e4uIgz/Ft0RPudkFMyVrp77buvTFxqoDvwNGVSk= +github.com/icrowley/fake v0.0.0-20240710202011-f797eb4a99c0/go.mod h1:dQ6TM/OGAe+cMws81eTe4Btv1dKxfPZ2CX+YaAFAPN4= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=