Repository: openshift/osdctl
Pull request #692: Added unit test case for current and customer file under org package
Author: login: amitupadh
Labels: name: lgtm
description: Indicates that a PR is ready to be merged.
name: approved
description: Indicates a PR has been approved by an approver from all required OWNERS files.
name: tide/merge-method-squash
description: Denotes a PR that should be squashed by tide when it merges.
Created: 2025-03-13T20:24:45Z | Merged: 2025-03-26T20:15:15Z

Description
This PR adds unit test cases for the current and customers commands under the org package, enhancing test coverage and improving maintainability by replacing monkey patching with dependency injection.

Code Re factoring
Updated functions to accept ocmClient as a parameter, allowing it to be mocked.
Modified current.go and customer.go to support the new approach.

Coverage Details
Increased unit test coverage for current and customers commands.

Verification
All tests pass successfully, confirming that the added tests work as expected and improve the overall test coverage.

Jira Ticket
https://issues.redhat.com/browse/OSD-28397



Diff:
diff --git a/cmd/org/current.go b/cmd/org/current.go
index 6b1065be8..c33a18c02 100644
--- a/cmd/org/current.go
+++ b/cmd/org/current.go
@@ -3,7 +3,6 @@ package org
 import (
 	"encoding/json"
 	"fmt"
-	"log"
 
 	"github.com/openshift-online/ocm-cli/pkg/arguments"
 	sdk "github.com/openshift-online/ocm-sdk-go"
@@ -18,58 +17,56 @@ var (
 		Short:         "gets current organization",
 		Args:          cobra.ArbitraryArgs,
 		SilenceErrors: true,
-		Run: func(cmd *cobra.Command, args []string) {
-			cmdutil.CheckErr(run(cmd))
+		Run: func(_ *cobra.Command, _ []string) {
+			ocmClient, err := utils.CreateConnection()
+			if err != nil {
+				cmdutil.CheckErr(err)
+			}
+			defer func() {
+				if err := ocmClient.Close(); err != nil {
+					cmdutil.CheckErr(fmt.Errorf("cannot close the ocmClient (possible memory leak): %q", err))
+				}
+			}()
+			req, err := getOrgRequest(ocmClient)
+			if err != nil {
+				cmdutil.CheckErr(err)
+			}
+			resp, err := sendRequest(req)
+			if err != nil {
+				cmdutil.CheckErr(fmt.Errorf("invalid input: %q", err))
+			}
+			orgs, err := getCurrentOrg(resp.Bytes())
+			if err != nil {
+				cmdutil.CheckErr(err)
+			}
+			printOrg(*orgs)
 		},
 	}
 )
 
-type Account struct {
+type account struct {
 	Organization Organization `json:"organization"`
 }
 
 func init() {
 	flags := currentCmd.Flags()
-
 	AddOutputFlag(flags)
 }
 
-func run(cmd *cobra.Command) error {
-	response, err := getCurrentOrg()
-	if err != nil {
-		return fmt.Errorf("invalid input: %q", err)
-	}
-
-	acc := Account{}
-	json.Unmarshal(response.Bytes(), &acc)
-	printOrg(acc.Organization)
-
-	return nil
-}
-
-func getCurrentOrg() (*sdk.Response, error) {
-	// Create OCM client to talk
-	ocmClient, err := utils.CreateConnection()
+func getCurrentOrg(data []byte) (*Organization, error) {
+	acc := account{}
+	err := json.Unmarshal(data, &acc)
 	if err != nil {
 		return nil, err
 	}
-	defer func() {
-		if err := ocmClient.Close(); err != nil {
-			fmt.Printf("Cannot close the ocmClient (possible memory leak): %q", err)
-		}
-	}()
-
-	// Now get the current org
-	return sendRequest(createGetCurrentOrgRequest(ocmClient))
+	return &acc.Organization, nil
 }
 
-func createGetCurrentOrgRequest(ocmClient *sdk.Connection) *sdk.Request {
-	// Create and populate the request:
-	request := ocmClient.Get()
-	err := arguments.ApplyPathArg(request, currentAccountApiPath)
+func getOrgRequest(ocmClient *sdk.Connection) (*sdk.Request, error) {
+	req := ocmClient.Get()
+	err := arguments.ApplyPathArg(req, currentAccountApiPath)
 	if err != nil {
-		log.Fatalf("Can't parse API path '%s': %v\n", currentAccountApiPath, err)
+		return nil, fmt.Errorf("can't parse API path '%s': %v\n", currentAccountApiPath, err)
 	}
-
-	return request
+	return req, nil
 }
diff --git a/cmd/org/current_test.go b/cmd/org/current_test.go
new file mode 100644
index 000000000..a7762f753
--- /dev/null
+++ b/cmd/org/current_test.go
@@ -0,0 +1,96 @@
+package org
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"net/http/httptest"
+	"testing"
+
+	sdk "github.com/openshift-online/ocm-sdk-go"
+)
+
+func getUserTestData() (string, error) {
+	data := map[string]interface{}{
+		"created_at": "2024-11-27T07:32:59.368563Z",
+		"email":      "kilgore.trout@redhat.com",
+		"first_name": "kilgore",
+		"href":       "/api/accounts_mgmt/v1/accounts/xyz",
+		"id":         "foobar",
+		"kind":       "Account",
+		"last_name":  "Trout",
+		"organization": map[string]interface{}{
+			"created_at":     "2019-02-15T20:26:12.542449Z",
+			"ebs_account_id": "1111111",
+			"external_id":    "2222222",
+			"href":           "/api/accounts_mgmt/v1/organizations/xyz",
+			"id":             "abc.xyz",
+			"kind":           "Organization",
+			"name":           "Kurt Vonnegut Appreciation Society",
+			"updated_at":     "2025-03-10T06:16:08.047253Z",
+		},
+		"rhit_web_user_id": "57712380",
+		"updated_at":       "2025-02-21T21:05:50.544761Z",
+		"username":         "kilgore.trout",
+	}
+	jsonData, err := json.Marshal(data)
+	if err != nil {
+		return "", fmt.Errorf("failed to marshal test data: %w", err)
+	}
+	return string(jsonData), nil
+}
+
+func TestGetCurrentOrg(t *testing.T) {
+	userData, err := getUserTestData()
+	if err != nil {
+		t.Errorf("invalid user test data")
+	}
+	orgs, err := getCurrentOrg([]byte(userData))
+	if err != nil {
+		t.Fatal(err)
+	}
+	name := "Kurt Vonnegut Appreciation Society"
+	if orgs.Name != name {
+		t.Errorf("Expected %s to equal %s", orgs.Name, name)
+	}
+	id := "abc.xyz"
+	if orgs.ID != id {
+		t.Errorf("Expected %s to equal %s", orgs.ID, id)
+	}
+}
+
+func TestGetOrgRequest(t *testing.T) {
+	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+		if r.URL.Path == tokenPath {
+			w.Write([]byte(`{"access_token": "test-token"}`))
+			return
+		}
+		userData, err := getUserTestData()
+		if err != nil {
+			t.Errorf("invalid user test data")
+		}
+		w.Write([]byte(userData))
+	}))
+	defer server.Close()
+
+	ocmClient, err := sdk.NewConnectionBuilder().
+		URL(server.URL).
+		TokenURL(server.URL+tokenPath).
+		Insecure(true).
+		Client(clientID, clientSecret).
+		Build()
+	if err != nil {
+		t.Fatalf("Failed to build connection: %v", err)
+	}
+	defer ocmClient.Close()
+
+	req, err := getOrgRequest(ocmClient)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if req.GetPath() != currentAccountApiPath {
+		t.Errorf("%s does not equal %s", req.GetPath(), currentAccountApiPath)
+	}
+}
diff --git a/cmd/org/customers.go b/cmd/org/customers.go
index 2533ca6fc..1fb30867a 100644
--- a/cmd/org/customers.go
+++ b/cmd/org/customers.go
@@ -2,9 +2,9 @@ package org
 
 import (
 	"fmt"
-	"log"
 	"os"
 
+	sdk "github.com/openshift-online/ocm-sdk-go"
 	amv1 "github.com/openshift-online/ocm-sdk-go/accountsmgmt/v1"
 	"github.com/openshift/osdctl/pkg/printer"
 	"github.com/openshift/osdctl/pkg/utils"
@@ -18,8 +18,22 @@ var (
 		Short:         "get paying/non-paying organizations",
 		Args:          cobra.ArbitraryArgs,
 		SilenceErrors: true,
-		Run: func(cmd *cobra.Command, args []string) {
-			cmdutil.CheckErr(getCustomers(cmd))
+		Run: func(_ *cobra.Command, _ []string) {
+			ocmClient, err := utils.CreateConnection()
+			if err != nil {
+				cmdutil.CheckErr(err)
+			}
+			defer func() {
+				if err := ocmClient.Close(); err != nil {
+					fmt.Printf("Cannot close the ocmClient (possible memory leak): %q", err)
+				}
+			}()
+
+			customers, err := getCustomers(ocmClient)
+			if err != nil {
+				cmdutil.CheckErr(err)
+			}
+			printCustomers(customers)
 		},
 	}
 	paying   bool   = true
@@ -51,21 +65,10 @@ func init() {
 	AddOutputFlag(flags)
 }
 
-func getCustomers(cmd *cobra.Command) error {
+func getCustomers(ocmClient *sdk.Connection) ([]Customer, error) {
 	pageSize := 1000
 	pageIndex := 1
 
-	// Create OCM client to talk
-	ocmClient, err := utils.CreateConnection()
-	if err != nil {
-		return err
-	}
-	defer func() {
-		if err := ocmClient.Close(); err != nil {
-			fmt.Printf("Cannot close the ocmClient (possible memory leak): %q", err)
-		}
-	}()
-
 	if !paying {
 		subsType = "Config"
 	}
@@ -74,14 +77,13 @@ func getCustomers(cmd *cobra.Command) error {
 	var customerList []Customer
 
 	for {
-
 		response, err := ocmClient.AccountsMgmt().V1().ResourceQuota().List().
 			Size(pageSize).
 			Page(pageIndex).
 			Parameter("search", searchQuery).
 			Send()
 		if err != nil {
-			log.Fatalf("Can't retrieve accounts: %v", err)
+			return nil, fmt.Errorf("can't retrieve accounts: %v", err)
 		}
 
 		response.Items().Each(func(resourseQuota *amv1.ResourceQuota) bool {
@@ -99,8 +101,8 @@ func getCustomers(cmd *cobra.Command) error {
 		}
 		pageIndex++
 	}
-	printCustomers(customerList)
-	return nil
+
+	return customerList, nil
 }
 
 func printCustomers(items []Customer) {
diff --git a/cmd/org/customers_test.go b/cmd/org/customers_test.go
new file mode 100644
index 000000000..0ac2262bf
--- /dev/null
+++ b/cmd/org/customers_test.go
@@ -0,0 +1,110 @@
+package org
+
+import (
+	"bytes"
+	"encoding/json"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"reflect"
+	"testing"
+
+	"github.com/golang-jwt/jwt/v5"
+	sdk "github.com/openshift-online/ocm-sdk-go"
+)
+
+var (
+	testToken, _  = jwt.New(jwt.SigningMethodHS256).SignedString([]byte("test-secret"))
+	clientID      = "fake-id"
+	clientSecret  = "fake-secret"
+	tokenPath     = "/fake-path/token"
+	testCustomers = []Customer{
+		{ID: "cust-1", OrganizationID: "org-1", SKU: "sku-1"},
+		{ID: "cust-2", OrganizationID: "org-2", SKU: "sku-2"},
+	}
+)
+
+func TestGetCustomers(t *testing.T) {
+	apiResponse := map[string]interface{}{
+		"page":  1,
+		"size":  len(testCustomers),
+		"total": len(testCustomers),
+		"items": []map[string]string{
+			{"kind": "ResourceQuota", "id": "cust-1", "organization_id": "org-1", "sku": "sku-1"},
+			{"kind": "ResourceQuota", "id": "cust-2", "organization_id": "org-2", "sku": "sku-2"},
+		},
+	}
+
+	tokenResponse := map[string]interface{}{
+		"access_token": testToken,
+		"token_type":   "Bearer",
+		"expires_in":   3600,
+	}
+
+	t.Run("Success Test", func(t *testing.T) {
+		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+			w.Header().Set("Content-Type", "application/json")
+			w.WriteHeader(http.StatusOK)
+			if r.URL.Path == tokenPath {
+				json.NewEncoder(w).Encode(tokenResponse)
+				return
+			}
+			json.NewEncoder(w).Encode(apiResponse)
+		}))
+		defer server.Close()
+
+		// Create connection
+		conn, err := sdk.NewConnectionBuilder().
+			URL(server.URL).
+			TokenURL(server.URL+tokenPath).
+			Insecure(true).
+			Client(clientID, clientSecret).
+			Build()
+		if err != nil {
+			t.Fatalf("Failed to build connection: %v", err)
+		}
+
+		customers, err := getCustomers(conn)
+
+		if err != nil {
+			t.Fatalf("getCustomers() returned an error: %v", err)
+		}
+
+		if !reflect.DeepEqual(customers, testCustomers) {
+			t.Errorf("Expected customers %+v, got %+v", testCustomers, customers)
+		}
+	})
+}
+
+func TestPrintCustomersTableOutput(t *testing.T) {
+	// Capture stdout
+	oldStdout := os.Stdout
+	r, w, _ := os.Pipe()
+	os.Stdout = w
+
+	printCustomers(testCustomers)
+
+	// Capture output and restore stdout
+	w.Close()
+	var buf bytes.Buffer
+	_, err := buf.ReadFrom(r)
+	if err != nil {
+		t.Fatal("Failed to read from stdout pipe:", err)
+	}
+	os.Stdout = oldStdout
+
+	output := buf.String()
+	if !containsAll(output, "ID", "OrganizationID", "SKU", "cust-1", "org-1", "sku-1") {
+		t.Errorf("Expected output to contain customer data. Got:\n%s", output)
+	}
+}
+
+// Helper to check if all substrings exist in a string
+func containsAll(str string, substrs ...string) bool {
+	for _, s := range substrs {
+		if !bytes.Contains([]byte(str), []byte(s)) {
+			return false
+		}
+	}
+	return true
+}
diff --git a/go.mod b/go.mod
index b8ac37870..6806ed623 100644
--- a/go.mod
+++ b/go.mod
@@ -29,6 +29,7 @@ require (
 	github.com/coreos/go-semver v0.3.1
 	github.com/deckarep/golang-set v1.8.0
 	github.com/fatih/color v1.18.0
+	github.com/golang-jwt/jwt/v5 v5.2.1
 	github.com/google/go-github/v63 v63.0.0
 	github.com/google/uuid v1.6.0
 	github.com/olekukonko/tablewriter v0.0.5
diff --git a/go.sum b/go.sum
index 0eaf402bf..f805cace4 100644
--- a/go.sum
+++ b/go.sum
@@ -263,6 +263,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
 github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
 github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
+github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc=
 github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=


Reviews:
user: login: btoll
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-14T14:39:59Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T15:04:09Z
user: login: btoll
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-14T15:19:10Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T06:03:09Z
user: login: btoll
body: The comments can be removed, as the code is already descriptive enough.

A couple of things I'm wondering:
- Is testing the `common.go` file out of scope for this ticket?  Is it even necessary?
- Do we want to be testing the print functions?  Would it be better to test that the data is being returned properly and not the formatting of it?
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-17T16:21:23Z
user: login: btoll
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-17T16:22:06Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T02:11:20Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T02:13:19Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T02:13:32Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T02:14:00Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T02:14:19Z
user: login: btoll
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-18T14:14:53Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T16:41:55Z
user: login: btoll
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-19T16:29:27Z
user: login: btoll
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-19T16:29:50Z
user: login: btoll
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-19T16:30:13Z
user: login: btoll
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-19T19:05:26Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T06:41:07Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T06:41:22Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T06:41:31Z
user: login: christophermancini
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-21T13:01:59Z
user: login: christophermancini
body: Had one nit, otherwise I think it looks ok.
state: APPROVED
author_association: NONE
submitted_at: 2025-03-21T13:03:16Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T12:43:21Z
user: login: joshbranham
body: Left one comment. Additionally can you squash your commits next time?

/label tide/merge-method-squash
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T14:21:19Z
user: login: amitupadh
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-26T18:22:10Z
user: login: btoll
body: Thanks for your work on this!
And, yeah, squashing all your commits would be sweet.
state: APPROVED
author_association: NONE
submitted_at: 2025-03-26T18:25:35Z

Review comments:
diff_hunk: @@ -1,127 +1,97 @@
 package org
 
 import (
+	"encoding/json"
 	"fmt"
-	"log"
-	"os"
 
-	amv1 "github.com/openshift-online/ocm-sdk-go/accountsmgmt/v1"
-	"github.com/openshift/osdctl/pkg/printer"
+	"github.com/openshift-online/ocm-cli/pkg/arguments"
+	sdk "github.com/openshift-online/ocm-sdk-go"
 	"github.com/openshift/osdctl/pkg/utils"
 	"github.com/spf13/cobra"
 	cmdutil "k8s.io/kubectl/pkg/cmd/util"
 )
 
-var (
-	customersCmd = &cobra.Command{
-		Use:           "customers",
-		Short:         "get paying/non-paying organizations",
-		Args:          cobra.ArbitraryArgs,
-		SilenceErrors: true,
-		Run: func(cmd *cobra.Command, args []string) {
-			cmdutil.CheckErr(getCustomers(cmd))
-		},
-	}
-	paying   bool   = true
-	subsType string = "Subscription"
-)
+var customersCmd = &cobra.Command{
+	Use:           "customers",
+	Short:         "Lists customers of the current organization",
+	Args:          cobra.NoArgs,
+	SilenceErrors: true,
+	Run: func(cmd *cobra.Command, args []string) {
+		ocmClient, err := utils.CreateConnection()
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		defer func() {
+			if err := ocmClient.Close(); err != nil {
+				cmdutil.CheckErr(fmt.Errorf("cannot close ocmClient: %v", err))
+			}
+		}()
 
-type CustomerItems struct {
-	Customers []Customer `json:"items"`
+		orgReq, err := getOrgRequest(ocmClient)
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		orgResp, err := sendRequest(orgReq)
+		if err != nil {
+			cmdutil.CheckErr(fmt.Errorf("failed to fetch current organization: %v", err))
+		}
+		org, err := getCurrentOrg(orgResp.Bytes())
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+
+		customersReq, err := getCustomersRequest(ocmClient, org.ID)
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		customersResp, err := sendRequest(customersReq)
+		if err != nil {
+			cmdutil.CheckErr(fmt.Errorf("failed to fetch customers: %v", err))
+		}
+		customers, err := parseCustomers(customersResp.Bytes())
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+
+		printCustomers(customers)
+	},
path: cmd/org/customers.go
user: login: btoll
body: Looks like you brought this logic over from `current.go`.   Do we need to do this here (i.e., get the org)?
created_at: 2025-03-14T14:39:59Z
author_association: NONE
diff_hunk: @@ -1,127 +1,97 @@
 package org
 
 import (
+	"encoding/json"
 	"fmt"
-	"log"
-	"os"
 
-	amv1 "github.com/openshift-online/ocm-sdk-go/accountsmgmt/v1"
-	"github.com/openshift/osdctl/pkg/printer"
+	"github.com/openshift-online/ocm-cli/pkg/arguments"
+	sdk "github.com/openshift-online/ocm-sdk-go"
 	"github.com/openshift/osdctl/pkg/utils"
 	"github.com/spf13/cobra"
 	cmdutil "k8s.io/kubectl/pkg/cmd/util"
 )
 
-var (
-	customersCmd = &cobra.Command{
-		Use:           "customers",
-		Short:         "get paying/non-paying organizations",
-		Args:          cobra.ArbitraryArgs,
-		SilenceErrors: true,
-		Run: func(cmd *cobra.Command, args []string) {
-			cmdutil.CheckErr(getCustomers(cmd))
-		},
-	}
-	paying   bool   = true
-	subsType string = "Subscription"
-)
+var customersCmd = &cobra.Command{
+	Use:           "customers",
+	Short:         "Lists customers of the current organization",
+	Args:          cobra.NoArgs,
+	SilenceErrors: true,
+	Run: func(cmd *cobra.Command, args []string) {
+		ocmClient, err := utils.CreateConnection()
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		defer func() {
+			if err := ocmClient.Close(); err != nil {
+				cmdutil.CheckErr(fmt.Errorf("cannot close ocmClient: %v", err))
+			}
+		}()
 
-type CustomerItems struct {
-	Customers []Customer `json:"items"`
+		orgReq, err := getOrgRequest(ocmClient)
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		orgResp, err := sendRequest(orgReq)
+		if err != nil {
+			cmdutil.CheckErr(fmt.Errorf("failed to fetch current organization: %v", err))
+		}
+		org, err := getCurrentOrg(orgResp.Bytes())
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+
+		customersReq, err := getCustomersRequest(ocmClient, org.ID)
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		customersResp, err := sendRequest(customersReq)
+		if err != nil {
+			cmdutil.CheckErr(fmt.Errorf("failed to fetch customers: %v", err))
+		}
+		customers, err := parseCustomers(customersResp.Bytes())
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+
+		printCustomers(customers)
+	},
path: cmd/org/customers.go
user: login: amitupadh
body: @btoll 
Yes, printCustomers(customers) is needed here, similar to how get the org is used in current.go.
It was also present in the initial implementation before the refactoring, so I kept it to maintain the original functionality. 

created_at: 2025-03-14T15:04:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,127 +1,97 @@
 package org
 
 import (
+	"encoding/json"
 	"fmt"
-	"log"
-	"os"
 
-	amv1 "github.com/openshift-online/ocm-sdk-go/accountsmgmt/v1"
-	"github.com/openshift/osdctl/pkg/printer"
+	"github.com/openshift-online/ocm-cli/pkg/arguments"
+	sdk "github.com/openshift-online/ocm-sdk-go"
 	"github.com/openshift/osdctl/pkg/utils"
 	"github.com/spf13/cobra"
 	cmdutil "k8s.io/kubectl/pkg/cmd/util"
 )
 
-var (
-	customersCmd = &cobra.Command{
-		Use:           "customers",
-		Short:         "get paying/non-paying organizations",
-		Args:          cobra.ArbitraryArgs,
-		SilenceErrors: true,
-		Run: func(cmd *cobra.Command, args []string) {
-			cmdutil.CheckErr(getCustomers(cmd))
-		},
-	}
-	paying   bool   = true
-	subsType string = "Subscription"
-)
+var customersCmd = &cobra.Command{
+	Use:           "customers",
+	Short:         "Lists customers of the current organization",
+	Args:          cobra.NoArgs,
+	SilenceErrors: true,
+	Run: func(cmd *cobra.Command, args []string) {
+		ocmClient, err := utils.CreateConnection()
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		defer func() {
+			if err := ocmClient.Close(); err != nil {
+				cmdutil.CheckErr(fmt.Errorf("cannot close ocmClient: %v", err))
+			}
+		}()
 
-type CustomerItems struct {
-	Customers []Customer `json:"items"`
+		orgReq, err := getOrgRequest(ocmClient)
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		orgResp, err := sendRequest(orgReq)
+		if err != nil {
+			cmdutil.CheckErr(fmt.Errorf("failed to fetch current organization: %v", err))
+		}
+		org, err := getCurrentOrg(orgResp.Bytes())
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+
+		customersReq, err := getCustomersRequest(ocmClient, org.ID)
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		customersResp, err := sendRequest(customersReq)
+		if err != nil {
+			cmdutil.CheckErr(fmt.Errorf("failed to fetch customers: %v", err))
+		}
+		customers, err := parseCustomers(customersResp.Bytes())
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+
+		printCustomers(customers)
+	},
path: cmd/org/customers.go
user: login: btoll
body: Yes, that part is fine, but I'm speaking to where you're using `getOrgRequest` and `getCurrentOrg`.  Also, it looks like you're now querying a different REST API.
created_at: 2025-03-14T15:19:09Z
author_association: NONE
diff_hunk: @@ -1,127 +1,97 @@
 package org
 
 import (
+	"encoding/json"
 	"fmt"
-	"log"
-	"os"
 
-	amv1 "github.com/openshift-online/ocm-sdk-go/accountsmgmt/v1"
-	"github.com/openshift/osdctl/pkg/printer"
+	"github.com/openshift-online/ocm-cli/pkg/arguments"
+	sdk "github.com/openshift-online/ocm-sdk-go"
 	"github.com/openshift/osdctl/pkg/utils"
 	"github.com/spf13/cobra"
 	cmdutil "k8s.io/kubectl/pkg/cmd/util"
 )
 
-var (
-	customersCmd = &cobra.Command{
-		Use:           "customers",
-		Short:         "get paying/non-paying organizations",
-		Args:          cobra.ArbitraryArgs,
-		SilenceErrors: true,
-		Run: func(cmd *cobra.Command, args []string) {
-			cmdutil.CheckErr(getCustomers(cmd))
-		},
-	}
-	paying   bool   = true
-	subsType string = "Subscription"
-)
+var customersCmd = &cobra.Command{
+	Use:           "customers",
+	Short:         "Lists customers of the current organization",
+	Args:          cobra.NoArgs,
+	SilenceErrors: true,
+	Run: func(cmd *cobra.Command, args []string) {
+		ocmClient, err := utils.CreateConnection()
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		defer func() {
+			if err := ocmClient.Close(); err != nil {
+				cmdutil.CheckErr(fmt.Errorf("cannot close ocmClient: %v", err))
+			}
+		}()
 
-type CustomerItems struct {
-	Customers []Customer `json:"items"`
+		orgReq, err := getOrgRequest(ocmClient)
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		orgResp, err := sendRequest(orgReq)
+		if err != nil {
+			cmdutil.CheckErr(fmt.Errorf("failed to fetch current organization: %v", err))
+		}
+		org, err := getCurrentOrg(orgResp.Bytes())
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+
+		customersReq, err := getCustomersRequest(ocmClient, org.ID)
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		customersResp, err := sendRequest(customersReq)
+		if err != nil {
+			cmdutil.CheckErr(fmt.Errorf("failed to fetch customers: %v", err))
+		}
+		customers, err := parseCustomers(customersResp.Bytes())
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+
+		printCustomers(customers)
+	},
path: cmd/org/customers.go
user: login: amitupadh
body: @btoll 
I acknowledge that the current implementation queries a different API than intended. I have corrected this discrepancy to ensure alignment with our objectives.

After taking a closer look at the new approach, I think it would be quite difficult to fully refactor everything without risking some unintended side effects on existing functionality. The structure of the original code doesn’t leave much room for clean, test-friendly modifications.

To work around that, I’ve used a fake server (httptest.NewServer) in the tests to simulate actual API calls. This allows us to effectively mock the responses without altering the core code too much.

I appreciate your understanding and am open  to explore alternative solutions that balance both functionality and testability.
created_at: 2025-03-17T06:03:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,9 +1,118 @@
 package org
 
 import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"reflect"
+	"regexp"
+	"strings"
 	"testing"
+	"unsafe"
+
+	sdk "github.com/openshift-online/ocm-sdk-go"
+	"github.com/stretchr/testify/assert"
 )
 
+func TestSendRequest_Success(t *testing.T) {
+	// Test constants
+	var (
+		tokenPath        = "/oauth2/token"
+		testEndpoint     = "/test-endpoint"
+		fakeClientID     = "fake-id"
+		fakeClientSecret = "fake-secret"
+	)
+
+	// Test token response
+	tokenResponse := `{
+	"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIiLCJleHAiOjI1MjQ2MDgwMDB9.signature-placeholder", 
+	"token_type": "Bearer", 
+	"expires_in": 3600
+	}`
+
+	// Test API response
+	apiResponse := `{"status": "OK"}`
+
+	// HTTP handler function
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+
+		if r.URL.Path == tokenPath {
+			w.WriteHeader(http.StatusOK)
+			w.Write([]byte(tokenResponse))
+			return
+		}
+
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte(apiResponse))
+	}
+
+	// Create server and connection
+	server := httptest.NewServer(http.HandlerFunc(handler))
+	defer server.Close()
+
+	conn, err := sdk.NewConnectionBuilder().
+		URL(server.URL).
+		TokenURL(server.URL+tokenPath).
+		Insecure(true).
+		Client(fakeClientID, fakeClientSecret).
+		Build()
+	if err != nil {
+		t.Fatalf("Failed to build connection: %v", err)
+	}
+	defer conn.Close()
+
+	// Test the function
+	req := conn.Get().Path(testEndpoint)
+	_, err = sendRequest(req)
path: cmd/org/common_test.go
user: login: btoll
body: Looks like this is testing the OCM layer.
created_at: 2025-03-17T16:12:12Z
author_association: NONE
diff_hunk: @@ -1,9 +1,118 @@
 package org
 
 import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"reflect"
+	"regexp"
+	"strings"
 	"testing"
+	"unsafe"
+
+	sdk "github.com/openshift-online/ocm-sdk-go"
+	"github.com/stretchr/testify/assert"
 )
 
+func TestSendRequest_Success(t *testing.T) {
+	// Test constants
+	var (
+		tokenPath        = "/oauth2/token"
+		testEndpoint     = "/test-endpoint"
+		fakeClientID     = "fake-id"
+		fakeClientSecret = "fake-secret"
+	)
+
+	// Test token response
+	tokenResponse := `{
+	"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIiLCJleHAiOjI1MjQ2MDgwMDB9.signature-placeholder", 
+	"token_type": "Bearer", 
+	"expires_in": 3600
+	}`
+
+	// Test API response
+	apiResponse := `{"status": "OK"}`
+
+	// HTTP handler function
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+
+		if r.URL.Path == tokenPath {
+			w.WriteHeader(http.StatusOK)
+			w.Write([]byte(tokenResponse))
+			return
+		}
+
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte(apiResponse))
+	}
+
+	// Create server and connection
+	server := httptest.NewServer(http.HandlerFunc(handler))
+	defer server.Close()
+
+	conn, err := sdk.NewConnectionBuilder().
+		URL(server.URL).
+		TokenURL(server.URL+tokenPath).
+		Insecure(true).
+		Client(fakeClientID, fakeClientSecret).
+		Build()
+	if err != nil {
+		t.Fatalf("Failed to build connection: %v", err)
+	}
+	defer conn.Close()
+
+	// Test the function
+	req := conn.Get().Path(testEndpoint)
+	_, err = sendRequest(req)
+
+	if err != nil {
+		t.Errorf("sendRequest returned an error: %v", err)
+	}
+}
+
+func TestCreateGetSubscriptionsRequest(t *testing.T) {
+	// Define test inputs
+	fakeOrgID := "o-12345"
+	fakeStatus := "Active"
+	fakeManagedOnly := true
+	fakePage := 1
+	fakeSize := 20
+
+	// Create a fake OCM client
+	ocmClient := &sdk.Connection{}
+
+	// Call the function under test
+	request := createGetSubscriptionsRequest(ocmClient, fakeOrgID, fakeStatus, fakeManagedOnly, fakePage, fakeSize)
path: cmd/org/common_test.go
user: login: btoll
body: It doesn't look like this function is being called from anywhere.  Do we want to test this?  Also, do we want to be testing functions that aren't part of the public API?
created_at: 2025-03-17T16:14:12Z
author_association: NONE
diff_hunk: @@ -40,3 +149,90 @@ func TestCheckOrgId(t *testing.T) {
 		}
 	}
 }
+
+func TestPrintJson(t *testing.T) {
+	// Test Data
+	testData := map[string]string{"name": "test", "value": "123"}
+
+	// Capture Output
+	oldStdout := os.Stdout
+	r, w, _ := os.Pipe()
+	os.Stdout = w
+
+	// Call the function
+	PrintJson(testData)
+
+	// Restore stdout
+	w.Close()
+	os.Stdout = oldStdout
+
+	// Read captured output
+	var buf bytes.Buffer
+	_, _ = buf.ReadFrom(r)
+	output := buf.String()
+
+	// Expected JSON Format
+	expectedJson, _ := json.MarshalIndent(testData, "", "  ")
+	assert.Contains(t, output, string(expectedJson))
+}
+
+var jsonOutput bool
+
+func TestPrintOrgTable(t *testing.T) {
+	jsonOutput = false // Ensure table output
+
+	org := Organization{
+		ID:         "123",
+		Name:       "Example Org",
+		ExternalID: "ext123",
+		Created:    "2023-01-01T00:00:00Z",
+		Updated:    "2023-01-02T00:00:00Z",
+	}
+
+	r, w, err := os.Pipe()
+	if err != nil {
+		t.Fatal(err)
+	}
+	oldStdout := os.Stdout
+	os.Stdout = w
+
+	printOrg(org)
+
+	w.Close()
+	os.Stdout = oldStdout
+
+	var buf bytes.Buffer
+	_, err = io.Copy(&buf, r)
+	if err != nil {
+		t.Fatal(err)
+	}
+	r.Close()
+
+	output := buf.String()
+	lines := strings.Split(strings.TrimSpace(output), "\n")
+	assert.Len(t, lines, 6) // Assuming 6 lines, no empty line at end in test
+
+	// Use regex to check each line, accounting for variable whitespace
+	assert.Regexp(t, regexp.MustCompile(`^ID:\s+123$`), lines[0])
+	assert.Regexp(t, regexp.MustCompile(`^Name:\s+Example Org$`), lines[1])
+	assert.Regexp(t, regexp.MustCompile(`^External ID:\s+ext123$`), lines[2])
+	assert.Regexp(t, regexp.MustCompile(`^Created:\s+2023-01-01T00:00:00Z$`), lines[4])
+	assert.Regexp(t, regexp.MustCompile(`^Updated:\s+2023-01-02T00:00:00Z$`), lines[5])
+}
+
+func Test_getSubscriptions(t *testing.T) {
+	t.Run("TestGetSubscriptions", func(t *testing.T) {
+		// Create a mock OCM client
+		got, err := getSubscriptions("org2", "active", true, 5, 10)
path: cmd/org/common_test.go
user: login: btoll
body: It doesn't look like this function is being called from anywhere. Do we want to test this? Also, do we want to be testing functions that aren't part of the public API?
created_at: 2025-03-17T16:15:10Z
author_association: NONE
diff_hunk: @@ -1,9 +1,118 @@
 package org
 
 import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"reflect"
+	"regexp"
+	"strings"
 	"testing"
+	"unsafe"
+
+	sdk "github.com/openshift-online/ocm-sdk-go"
+	"github.com/stretchr/testify/assert"
 )
 
+func TestSendRequest_Success(t *testing.T) {
+	// Test constants
+	var (
+		tokenPath        = "/oauth2/token"
+		testEndpoint     = "/test-endpoint"
+		fakeClientID     = "fake-id"
+		fakeClientSecret = "fake-secret"
+	)
+
+	// Test token response
+	tokenResponse := `{
+	"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIiLCJleHAiOjI1MjQ2MDgwMDB9.signature-placeholder", 
path: cmd/org/common_test.go
user: login: btoll
body: This will probably be flagged by tooling looking for secrets.
created_at: 2025-03-17T16:16:12Z
author_association: NONE
diff_hunk: @@ -0,0 +1,114 @@
+package org
+
+import (
+	"bytes"
+	"encoding/json"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"reflect"
+	"testing"
+
+	sdk "github.com/openshift-online/ocm-sdk-go"
+)
+
+var (
+	testToken     = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIiLCJleHAiOjI1MjQ2MDgwMDB9.signature-placeholder"
+	clientID      = "fake-id"
+	clientSecret  = "fake-secret"
+	tokenPath     = "/oauth2/token"
+	testCustomers = []Customer{
+		{ID: "cust-1", OrganizationID: "org-1", SKU: "sku-1"},
+		{ID: "cust-2", OrganizationID: "org-2", SKU: "sku-2"},
+	}
+)
+
+func Test_getCustomers(t *testing.T) {
+	apiResponse := map[string]interface{}{
+		"page":  1,
+		"size":  len(testCustomers),
+		"total": len(testCustomers),
+		"items": []map[string]string{
+			{"kind": "ResourceQuota", "id": "cust-1", "organization_id": "org-1", "sku": "sku-1"},
+			{"kind": "ResourceQuota", "id": "cust-2", "organization_id": "org-2", "sku": "sku-2"},
+		},
+	}
+
+	tokenResponse := map[string]interface{}{
+		"access_token": testToken,
+		"token_type":   "Bearer",
+		"expires_in":   3600,
+	}
+
+	t.Run("Success Test", func(t *testing.T) {
+		// Setup test server
+		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+			w.Header().Set("Content-Type", "application/json")
+			w.WriteHeader(http.StatusOK)
+
+			// Handle token request
+			if r.URL.Path == tokenPath {
+				json.NewEncoder(w).Encode(tokenResponse)
+				return
+			}
+
+			// Handle API request
+			json.NewEncoder(w).Encode(apiResponse)
+		}))
+		defer server.Close()
+
+		// Create connection
+		conn, err := sdk.NewConnectionBuilder().
+			URL(server.URL).
+			TokenURL(server.URL+tokenPath).
+			Insecure(true).
+			Client(clientID, clientSecret).
+			Build()
+		if err != nil {
+			t.Fatalf("Failed to build connection: %v", err)
+		}
+
+		customers, err := getCustomers(nil, conn)
path: cmd/org/customers_test.go
user: login: btoll
body: Can we just test the returned customers without spinning up a test server?
created_at: 2025-03-17T16:18:02Z
author_association: NONE
diff_hunk: @@ -1,127 +1,97 @@
 package org
 
 import (
+	"encoding/json"
 	"fmt"
-	"log"
-	"os"
 
-	amv1 "github.com/openshift-online/ocm-sdk-go/accountsmgmt/v1"
-	"github.com/openshift/osdctl/pkg/printer"
+	"github.com/openshift-online/ocm-cli/pkg/arguments"
+	sdk "github.com/openshift-online/ocm-sdk-go"
 	"github.com/openshift/osdctl/pkg/utils"
 	"github.com/spf13/cobra"
 	cmdutil "k8s.io/kubectl/pkg/cmd/util"
 )
 
-var (
-	customersCmd = &cobra.Command{
-		Use:           "customers",
-		Short:         "get paying/non-paying organizations",
-		Args:          cobra.ArbitraryArgs,
-		SilenceErrors: true,
-		Run: func(cmd *cobra.Command, args []string) {
-			cmdutil.CheckErr(getCustomers(cmd))
-		},
-	}
-	paying   bool   = true
-	subsType string = "Subscription"
-)
+var customersCmd = &cobra.Command{
+	Use:           "customers",
+	Short:         "Lists customers of the current organization",
+	Args:          cobra.NoArgs,
+	SilenceErrors: true,
+	Run: func(cmd *cobra.Command, args []string) {
+		ocmClient, err := utils.CreateConnection()
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		defer func() {
+			if err := ocmClient.Close(); err != nil {
+				cmdutil.CheckErr(fmt.Errorf("cannot close ocmClient: %v", err))
+			}
+		}()
 
-type CustomerItems struct {
-	Customers []Customer `json:"items"`
+		orgReq, err := getOrgRequest(ocmClient)
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		orgResp, err := sendRequest(orgReq)
+		if err != nil {
+			cmdutil.CheckErr(fmt.Errorf("failed to fetch current organization: %v", err))
+		}
+		org, err := getCurrentOrg(orgResp.Bytes())
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+
+		customersReq, err := getCustomersRequest(ocmClient, org.ID)
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+		customersResp, err := sendRequest(customersReq)
+		if err != nil {
+			cmdutil.CheckErr(fmt.Errorf("failed to fetch customers: %v", err))
+		}
+		customers, err := parseCustomers(customersResp.Bytes())
+		if err != nil {
+			cmdutil.CheckErr(err)
+		}
+
+		printCustomers(customers)
+	},
path: cmd/org/customers.go
user: login: btoll
body: I've added some comments that address this in a new review.
created_at: 2025-03-17T16:22:06Z
author_association: NONE
diff_hunk: @@ -0,0 +1,114 @@
+package org
+
+import (
+	"bytes"
+	"encoding/json"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"reflect"
+	"testing"
+
+	sdk "github.com/openshift-online/ocm-sdk-go"
+)
+
+var (
+	testToken     = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIiLCJleHAiOjI1MjQ2MDgwMDB9.signature-placeholder"
+	clientID      = "fake-id"
+	clientSecret  = "fake-secret"
+	tokenPath     = "/oauth2/token"
+	testCustomers = []Customer{
+		{ID: "cust-1", OrganizationID: "org-1", SKU: "sku-1"},
+		{ID: "cust-2", OrganizationID: "org-2", SKU: "sku-2"},
+	}
+)
+
+func Test_getCustomers(t *testing.T) {
+	apiResponse := map[string]interface{}{
+		"page":  1,
+		"size":  len(testCustomers),
+		"total": len(testCustomers),
+		"items": []map[string]string{
+			{"kind": "ResourceQuota", "id": "cust-1", "organization_id": "org-1", "sku": "sku-1"},
+			{"kind": "ResourceQuota", "id": "cust-2", "organization_id": "org-2", "sku": "sku-2"},
+		},
+	}
+
+	tokenResponse := map[string]interface{}{
+		"access_token": testToken,
+		"token_type":   "Bearer",
+		"expires_in":   3600,
+	}
+
+	t.Run("Success Test", func(t *testing.T) {
+		// Setup test server
+		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+			w.Header().Set("Content-Type", "application/json")
+			w.WriteHeader(http.StatusOK)
+
+			// Handle token request
+			if r.URL.Path == tokenPath {
+				json.NewEncoder(w).Encode(tokenResponse)
+				return
+			}
+
+			// Handle API request
+			json.NewEncoder(w).Encode(apiResponse)
+		}))
+		defer server.Close()
+
+		// Create connection
+		conn, err := sdk.NewConnectionBuilder().
+			URL(server.URL).
+			TokenURL(server.URL+tokenPath).
+			Insecure(true).
+			Client(clientID, clientSecret).
+			Build()
+		if err != nil {
+			t.Fatalf("Failed to build connection: %v", err)
+		}
+
+		customers, err := getCustomers(nil, conn)
path: cmd/org/customers_test.go
user: login: amitupadh
body: @btoll 

Mocking the OCM SDK turned out to be tricky due to unexported fields and lack of public builders for responses, which caused compile issues when trying to create mock data. 
Given these limitations, using a fake server seemed like the most reliable and maintainable option to simulate realistic API behavior without depending on SDK internals. 
Let me know if you'd like me to explore another approach!

Also, I mistakenly included changes to common_test.go in this PR—I have reverted those.
I'll share different PR for those changes 
created_at: 2025-03-18T02:11:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,9 +1,118 @@
 package org
 
 import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"reflect"
+	"regexp"
+	"strings"
 	"testing"
+	"unsafe"
+
+	sdk "github.com/openshift-online/ocm-sdk-go"
+	"github.com/stretchr/testify/assert"
 )
 
+func TestSendRequest_Success(t *testing.T) {
+	// Test constants
+	var (
+		tokenPath        = "/oauth2/token"
+		testEndpoint     = "/test-endpoint"
+		fakeClientID     = "fake-id"
+		fakeClientSecret = "fake-secret"
+	)
+
+	// Test token response
+	tokenResponse := `{
+	"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIiLCJleHAiOjI1MjQ2MDgwMDB9.signature-placeholder", 
+	"token_type": "Bearer", 
+	"expires_in": 3600
+	}`
+
+	// Test API response
+	apiResponse := `{"status": "OK"}`
+
+	// HTTP handler function
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+
+		if r.URL.Path == tokenPath {
+			w.WriteHeader(http.StatusOK)
+			w.Write([]byte(tokenResponse))
+			return
+		}
+
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte(apiResponse))
+	}
+
+	// Create server and connection
+	server := httptest.NewServer(http.HandlerFunc(handler))
+	defer server.Close()
+
+	conn, err := sdk.NewConnectionBuilder().
+		URL(server.URL).
+		TokenURL(server.URL+tokenPath).
+		Insecure(true).
+		Client(fakeClientID, fakeClientSecret).
+		Build()
+	if err != nil {
+		t.Fatalf("Failed to build connection: %v", err)
+	}
+	defer conn.Close()
+
+	// Test the function
+	req := conn.Get().Path(testEndpoint)
+	_, err = sendRequest(req)
+
+	if err != nil {
+		t.Errorf("sendRequest returned an error: %v", err)
+	}
+}
+
+func TestCreateGetSubscriptionsRequest(t *testing.T) {
+	// Define test inputs
+	fakeOrgID := "o-12345"
+	fakeStatus := "Active"
+	fakeManagedOnly := true
+	fakePage := 1
+	fakeSize := 20
+
+	// Create a fake OCM client
+	ocmClient := &sdk.Connection{}
+
+	// Call the function under test
+	request := createGetSubscriptionsRequest(ocmClient, fakeOrgID, fakeStatus, fakeManagedOnly, fakePage, fakeSize)
path: cmd/org/common_test.go
user: login: amitupadh
body: reverted this file changes
created_at: 2025-03-18T02:13:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,9 +1,118 @@
 package org
 
 import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"reflect"
+	"regexp"
+	"strings"
 	"testing"
+	"unsafe"
+
+	sdk "github.com/openshift-online/ocm-sdk-go"
+	"github.com/stretchr/testify/assert"
 )
 
+func TestSendRequest_Success(t *testing.T) {
+	// Test constants
+	var (
+		tokenPath        = "/oauth2/token"
+		testEndpoint     = "/test-endpoint"
+		fakeClientID     = "fake-id"
+		fakeClientSecret = "fake-secret"
+	)
+
+	// Test token response
+	tokenResponse := `{
+	"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIiLCJleHAiOjI1MjQ2MDgwMDB9.signature-placeholder", 
+	"token_type": "Bearer", 
+	"expires_in": 3600
+	}`
+
+	// Test API response
+	apiResponse := `{"status": "OK"}`
+
+	// HTTP handler function
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+
+		if r.URL.Path == tokenPath {
+			w.WriteHeader(http.StatusOK)
+			w.Write([]byte(tokenResponse))
+			return
+		}
+
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte(apiResponse))
+	}
+
+	// Create server and connection
+	server := httptest.NewServer(http.HandlerFunc(handler))
+	defer server.Close()
+
+	conn, err := sdk.NewConnectionBuilder().
+		URL(server.URL).
+		TokenURL(server.URL+tokenPath).
+		Insecure(true).
+		Client(fakeClientID, fakeClientSecret).
+		Build()
+	if err != nil {
+		t.Fatalf("Failed to build connection: %v", err)
+	}
+	defer conn.Close()
+
+	// Test the function
+	req := conn.Get().Path(testEndpoint)
+	_, err = sendRequest(req)
path: cmd/org/common_test.go
user: login: amitupadh
body: reverted this file changes
created_at: 2025-03-18T02:13:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -40,3 +149,90 @@ func TestCheckOrgId(t *testing.T) {
 		}
 	}
 }
+
+func TestPrintJson(t *testing.T) {
+	// Test Data
+	testData := map[string]string{"name": "test", "value": "123"}
+
+	// Capture Output
+	oldStdout := os.Stdout
+	r, w, _ := os.Pipe()
+	os.Stdout = w
+
+	// Call the function
+	PrintJson(testData)
+
+	// Restore stdout
+	w.Close()
+	os.Stdout = oldStdout
+
+	// Read captured output
+	var buf bytes.Buffer
+	_, _ = buf.ReadFrom(r)
+	output := buf.String()
+
+	// Expected JSON Format
+	expectedJson, _ := json.MarshalIndent(testData, "", "  ")
+	assert.Contains(t, output, string(expectedJson))
+}
+
+var jsonOutput bool
+
+func TestPrintOrgTable(t *testing.T) {
+	jsonOutput = false // Ensure table output
+
+	org := Organization{
+		ID:         "123",
+		Name:       "Example Org",
+		ExternalID: "ext123",
+		Created:    "2023-01-01T00:00:00Z",
+		Updated:    "2023-01-02T00:00:00Z",
+	}
+
+	r, w, err := os.Pipe()
+	if err != nil {
+		t.Fatal(err)
+	}
+	oldStdout := os.Stdout
+	os.Stdout = w
+
+	printOrg(org)
+
+	w.Close()
+	os.Stdout = oldStdout
+
+	var buf bytes.Buffer
+	_, err = io.Copy(&buf, r)
+	if err != nil {
+		t.Fatal(err)
+	}
+	r.Close()
+
+	output := buf.String()
+	lines := strings.Split(strings.TrimSpace(output), "\n")
+	assert.Len(t, lines, 6) // Assuming 6 lines, no empty line at end in test
+
+	// Use regex to check each line, accounting for variable whitespace
+	assert.Regexp(t, regexp.MustCompile(`^ID:\s+123$`), lines[0])
+	assert.Regexp(t, regexp.MustCompile(`^Name:\s+Example Org$`), lines[1])
+	assert.Regexp(t, regexp.MustCompile(`^External ID:\s+ext123$`), lines[2])
+	assert.Regexp(t, regexp.MustCompile(`^Created:\s+2023-01-01T00:00:00Z$`), lines[4])
+	assert.Regexp(t, regexp.MustCompile(`^Updated:\s+2023-01-02T00:00:00Z$`), lines[5])
+}
+
+func Test_getSubscriptions(t *testing.T) {
+	t.Run("TestGetSubscriptions", func(t *testing.T) {
+		// Create a mock OCM client
+		got, err := getSubscriptions("org2", "active", true, 5, 10)
path: cmd/org/common_test.go
user: login: amitupadh
body: reverted this file changes
created_at: 2025-03-18T02:14:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,9 +1,118 @@
 package org
 
 import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"reflect"
+	"regexp"
+	"strings"
 	"testing"
+	"unsafe"
+
+	sdk "github.com/openshift-online/ocm-sdk-go"
+	"github.com/stretchr/testify/assert"
 )
 
+func TestSendRequest_Success(t *testing.T) {
+	// Test constants
+	var (
+		tokenPath        = "/oauth2/token"
+		testEndpoint     = "/test-endpoint"
+		fakeClientID     = "fake-id"
+		fakeClientSecret = "fake-secret"
+	)
+
+	// Test token response
+	tokenResponse := `{
+	"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIiLCJleHAiOjI1MjQ2MDgwMDB9.signature-placeholder", 
path: cmd/org/common_test.go
user: login: amitupadh
body: reverted this file changes
created_at: 2025-03-18T02:14:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -39,4 +39,4 @@ func TestCheckOrgId(t *testing.T) {
 			}
 		}
 	}
-}
+}
path: cmd/org/common_test.go
user: login: btoll
body: Can you just remove this file?
created_at: 2025-03-18T14:14:53Z
author_association: NONE
diff_hunk: @@ -39,4 +39,4 @@ func TestCheckOrgId(t *testing.T) {
 			}
 		}
 	}
-}
+}
path: cmd/org/common_test.go
user: login: amitupadh
body: @btoll 
Removed cmd/org/common_test.go from this PR
created_at: 2025-03-18T16:41:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -19,7 +19,21 @@ var (
 		Args:          cobra.ArbitraryArgs,
 		SilenceErrors: true,
 		Run: func(cmd *cobra.Command, args []string) {
path: cmd/org/customers.go
user: login: btoll
body: `cmd` and `args` aren't used in the function body, they can be `_`.  I think that helps readability.
created_at: 2025-03-19T16:29:27Z
author_association: NONE
diff_hunk: @@ -19,7 +19,21 @@ var (
 		Args:          cobra.ArbitraryArgs,
 		SilenceErrors: true,
 		Run: func(cmd *cobra.Command, args []string) {
-			cmdutil.CheckErr(getCustomers(cmd))
+			ocmClient, err := utils.CreateConnection()
+			if err != nil {
+				cmdutil.CheckErr(err)
+			}
+			defer func() {
+				if err := ocmClient.Close(); err != nil {
+					fmt.Printf("Cannot close the ocmClient (possible memory leak): %q", err)
+				}
+			}()
+
+			customers, err := getCustomers(cmd, ocmClient)
path: cmd/org/customers.go
user: login: btoll
body: You don't need to pass `cmd` to `getCustomers`.
created_at: 2025-03-19T16:29:50Z
author_association: NONE
diff_hunk: @@ -51,21 +65,10 @@ func init() {
 	AddOutputFlag(flags)
 }
 
-func getCustomers(cmd *cobra.Command) error {
+func getCustomers(cmd *cobra.Command, ocmClient *sdk.Connection) ([]Customer, error) {
path: cmd/org/customers.go
user: login: btoll
body: This shouldn't accept `cmd`, it's not needed.
created_at: 2025-03-19T16:30:12Z
author_association: NONE
diff_hunk: @@ -0,0 +1,114 @@
+package org
+
+import (
+	"bytes"
+	"encoding/json"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"reflect"
+	"testing"
+
+	sdk "github.com/openshift-online/ocm-sdk-go"
+)
+
+var (
+	testToken     = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIiLCJleHAiOjI1MjQ2MDgwMDB9.signature-placeholder"
+	clientID      = "fake-id"
+	clientSecret  = "fake-secret"
+	tokenPath     = "/oauth2/token"
+	testCustomers = []Customer{
+		{ID: "cust-1", OrganizationID: "org-1", SKU: "sku-1"},
+		{ID: "cust-2", OrganizationID: "org-2", SKU: "sku-2"},
+	}
+)
+
+func Test_getCustomers(t *testing.T) {
+	apiResponse := map[string]interface{}{
+		"page":  1,
+		"size":  len(testCustomers),
+		"total": len(testCustomers),
+		"items": []map[string]string{
+			{"kind": "ResourceQuota", "id": "cust-1", "organization_id": "org-1", "sku": "sku-1"},
+			{"kind": "ResourceQuota", "id": "cust-2", "organization_id": "org-2", "sku": "sku-2"},
+		},
+	}
+
+	tokenResponse := map[string]interface{}{
+		"access_token": testToken,
+		"token_type":   "Bearer",
+		"expires_in":   3600,
+	}
+
+	t.Run("Success Test", func(t *testing.T) {
+		// Setup test server
+		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+			w.Header().Set("Content-Type", "application/json")
+			w.WriteHeader(http.StatusOK)
+
+			// Handle token request
+			if r.URL.Path == tokenPath {
+				json.NewEncoder(w).Encode(tokenResponse)
+				return
+			}
+
+			// Handle API request
+			json.NewEncoder(w).Encode(apiResponse)
+		}))
+		defer server.Close()
+
+		// Create connection
+		conn, err := sdk.NewConnectionBuilder().
+			URL(server.URL).
+			TokenURL(server.URL+tokenPath).
+			Insecure(true).
+			Client(clientID, clientSecret).
+			Build()
+		if err != nil {
+			t.Fatalf("Failed to build connection: %v", err)
+		}
+
+		customers, err := getCustomers(nil, conn)
path: cmd/org/customers_test.go
user: login: btoll
body: Yeah, I looked at this and it may be more trouble than it's worth right now to refactor it to make it more testable.
created_at: 2025-03-19T19:05:26Z
author_association: NONE
diff_hunk: @@ -19,7 +19,21 @@ var (
 		Args:          cobra.ArbitraryArgs,
 		SilenceErrors: true,
 		Run: func(cmd *cobra.Command, args []string) {
path: cmd/org/customers.go
user: login: amitupadh
body: Fixed  as per suggestion
created_at: 2025-03-20T06:41:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -19,7 +19,21 @@ var (
 		Args:          cobra.ArbitraryArgs,
 		SilenceErrors: true,
 		Run: func(cmd *cobra.Command, args []string) {
-			cmdutil.CheckErr(getCustomers(cmd))
+			ocmClient, err := utils.CreateConnection()
+			if err != nil {
+				cmdutil.CheckErr(err)
+			}
+			defer func() {
+				if err := ocmClient.Close(); err != nil {
+					fmt.Printf("Cannot close the ocmClient (possible memory leak): %q", err)
+				}
+			}()
+
+			customers, err := getCustomers(cmd, ocmClient)
path: cmd/org/customers.go
user: login: amitupadh
body: Fixed  as per suggestion
created_at: 2025-03-20T06:41:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -51,21 +65,10 @@ func init() {
 	AddOutputFlag(flags)
 }
 
-func getCustomers(cmd *cobra.Command) error {
+func getCustomers(cmd *cobra.Command, ocmClient *sdk.Connection) ([]Customer, error) {
path: cmd/org/customers.go
user: login: amitupadh
body: Fixed  as per suggestion
created_at: 2025-03-20T06:41:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,110 @@
+package org
+
+import (
+	"bytes"
+	"encoding/json"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"reflect"
+	"testing"
+
+	"github.com/golang-jwt/jwt/v5"
+	sdk "github.com/openshift-online/ocm-sdk-go"
+)
+
+var (
+	testToken, _  = jwt.New(jwt.SigningMethodHS256).SignedString([]byte("test-secret"))
+	clientID      = "fake-id"
+	clientSecret  = "fake-secret"
+	tokenPath     = "/fake-path/token"
+	testCustomers = []Customer{
+		{ID: "cust-1", OrganizationID: "org-1", SKU: "sku-1"},
+		{ID: "cust-2", OrganizationID: "org-2", SKU: "sku-2"},
+	}
+)
+
+func Test_getCustomers(t *testing.T) {
path: cmd/org/customers_test.go
user: login: christophermancini
body: nit: function name should be `TestGetCustomers`
created_at: 2025-03-21T13:01:59Z
author_association: NONE
diff_hunk: @@ -0,0 +1,110 @@
+package org
+
+import (
+	"bytes"
+	"encoding/json"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"reflect"
+	"testing"
+
+	"github.com/golang-jwt/jwt/v5"
+	sdk "github.com/openshift-online/ocm-sdk-go"
+)
+
+var (
+	testToken, _  = jwt.New(jwt.SigningMethodHS256).SignedString([]byte("test-secret"))
+	clientID      = "fake-id"
+	clientSecret  = "fake-secret"
+	tokenPath     = "/fake-path/token"
+	testCustomers = []Customer{
+		{ID: "cust-1", OrganizationID: "org-1", SKU: "sku-1"},
+		{ID: "cust-2", OrganizationID: "org-2", SKU: "sku-2"},
+	}
+)
+
+func Test_getCustomers(t *testing.T) {
path: cmd/org/customers_test.go
user: login: amitupadh
body: @christophermancini  Updated as per suggestion
created_at: 2025-03-24T12:43:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,81 @@
+package org
+
+import (
+	"net/http"
+	"net/http/httptest"
+	"testing"
+
+	sdk "github.com/openshift-online/ocm-sdk-go"
+)
+
+var userData = `
+{
+    "created_at": "2024-11-27T07:32:59.368563Z",
+    "email": "kilgore.trout@redhat.com",
+    "first_name": "Kilgore",
+    "href": "/api/accounts_mgmt/v1/accounts/xyz",
+    "id": "foobar",
+    "kind": "Account",
+    "last_name": "Trout",
+    "organization": {
+        "created_at": "2019-02-15T20:26:12.542449Z",
+        "ebs_account_id": "1111111",
+        "external_id": "2222222",
+        "href": "/api/accounts_mgmt/v1/organizations/xyz",
+        "id": "abc.xyz",
+        "kind": "Organization",
+        "name": "Kurt Vonnegut Appreciation Society",
+        "updated_at": "2025-03-10T06:16:08.047253Z"
+    },
+    "rhit_web_user_id": "57712380",
+    "updated_at": "2025-02-21T21:05:50.544761Z",
+    "username": "kilgore.trout"
+}
+`
path: cmd/org/current_test.go
user: login: joshbranham
body: This is a bit of a nit but can you not store this in a global variable? Maybe return it as a private func in this test file?
created_at: 2025-03-26T14:18:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,81 @@
+package org
+
+import (
+	"net/http"
+	"net/http/httptest"
+	"testing"
+
+	sdk "github.com/openshift-online/ocm-sdk-go"
+)
+
+var userData = `
+{
+    "created_at": "2024-11-27T07:32:59.368563Z",
+    "email": "kilgore.trout@redhat.com",
+    "first_name": "Kilgore",
+    "href": "/api/accounts_mgmt/v1/accounts/xyz",
+    "id": "foobar",
+    "kind": "Account",
+    "last_name": "Trout",
+    "organization": {
+        "created_at": "2019-02-15T20:26:12.542449Z",
+        "ebs_account_id": "1111111",
+        "external_id": "2222222",
+        "href": "/api/accounts_mgmt/v1/organizations/xyz",
+        "id": "abc.xyz",
+        "kind": "Organization",
+        "name": "Kurt Vonnegut Appreciation Society",
+        "updated_at": "2025-03-10T06:16:08.047253Z"
+    },
+    "rhit_web_user_id": "57712380",
+    "updated_at": "2025-02-21T21:05:50.544761Z",
+    "username": "kilgore.trout"
+}
+`
path: cmd/org/current_test.go
user: login: amitupadh
body: Thanks for the suggestion, @joshbranham ! That makes sense. 
I have updated it to return from a private function to keep the scope limited within the test file.
created_at: 2025-03-26T18:22:10Z
author_association: CONTRIBUTOR

PR comments:
user: login: openshift-ci[bot]
created_at: 2025-03-13T20:24:50Z
body: Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with `/test all`
author_association: CONTRIBUTOR
user: login: joshbranham
created_at: 2025-03-26T18:39:44Z
body: /lgtm
author_association: CONTRIBUTOR
user: login: openshift-ci[bot]
created_at: 2025-03-26T18:40:21Z
body: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/openshift/osdctl/pull/692#" title="Author self-approved">amitupadh</a>*, *<a href="https://github.com/openshift/osdctl/pull/692#pullrequestreview-2718259970" title="Approved">btoll</a>*, *<a href="https://github.com/openshift/osdctl/pull/692#pullrequestreview-2705872623" title="Approved">christophermancini</a>*, *<a href="https://github.com/openshift/osdctl/pull/692#issuecomment-2755427413" title="LGTM">joshbranham</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=openshift%2Fosdctl).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/openshift/osdctl/blob/master/OWNERS)~~ [joshbranham]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
author_association: CONTRIBUTOR
user: login: openshift-ci[bot]
created_at: 2025-03-26T20:11:44Z
body: @amitupadh: all tests **passed!**


[Full PR test history](https://prow.ci.openshift.org/pr-history?org=openshift&repo=osdctl&pr=692). [Your PR dashboard](https://prow.ci.openshift.org/pr?query=is:pr+state:open+author:amitupadh).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
author_association: CONTRIBUTOR