github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/client/cli/output/output_test.go (about)

     1  package output
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/spf13/cobra"
    12  	"github.com/stretchr/testify/require"
    13  	"sigs.k8s.io/yaml"
    14  
    15  	"github.com/telepresenceio/telepresence/v2/pkg/client/cli/global"
    16  )
    17  
    18  func TestWithOutput(t *testing.T) {
    19  	expectedREStdout := "re\n"
    20  	expectedREStderr := "re_stderr\n"
    21  	expectedName := "testing"
    22  
    23  	re := func(cmd *cobra.Command, args []string) error {
    24  		stdout := cmd.OutOrStdout()
    25  		stderr := cmd.ErrOrStderr()
    26  		fmt.Fprint(stdout, expectedREStdout)
    27  		fmt.Fprint(stderr, expectedREStderr)
    28  		return nil
    29  	}
    30  
    31  	newCmdWithBufs := func() (*cobra.Command, *strings.Builder, *strings.Builder) {
    32  		stdoutBuf := strings.Builder{}
    33  		stderrBuf := strings.Builder{}
    34  		cmd := cobra.Command{}
    35  
    36  		cmd.Use = expectedName
    37  		cmd.SetOut(&stdoutBuf)
    38  		cmd.SetErr(&stderrBuf)
    39  		cmd.SetContext(context.Background())
    40  		cmd.RunE = re
    41  
    42  		cmd.PersistentFlags().String(global.FlagOutput, "default", "")
    43  
    44  		return &cmd, &stdoutBuf, &stderrBuf
    45  	}
    46  
    47  	t.Run("non-json output", func(t *testing.T) {
    48  		cmd, outBuf, errBuf := newCmdWithBufs()
    49  		_, _, err := Execute(cmd)
    50  		require.NoError(t, err)
    51  
    52  		require.Equal(t, expectedREStdout, outBuf.String(), "did not get expected stdout")
    53  		require.Equal(t, expectedREStderr, errBuf.String(), "did not get expected stderr")
    54  	})
    55  
    56  	t.Run("json output no error", func(t *testing.T) {
    57  		cmd, outBuf, errBuf := newCmdWithBufs()
    58  		cmd.SetArgs([]string{"--output=json"})
    59  		_, _, err := Execute(cmd)
    60  		require.NoError(t, err)
    61  
    62  		stdout := outBuf.String()
    63  		m := map[string]string{}
    64  		require.NoError(t, json.Unmarshal([]byte(stdout), &m), "did not get json as stdout, got: %s", stdout)
    65  		require.Equal(t, expectedREStdout, m["stdout"], "did not get expected stdout, got: %s", m["stdout"])
    66  		require.Equal(t, expectedREStderr, m["stderr"], "did not get expected stderr, got: %s", m["stderr"])
    67  		require.Equal(t, expectedName, m["cmd"], "did not get expected cmd name, got: %s", m["cmd"])
    68  
    69  		stderr := errBuf.String()
    70  		require.Empty(t, stderr, "expected empty stderr, got: %s", stderr)
    71  	})
    72  
    73  	t.Run("json output with error", func(t *testing.T) {
    74  		expectedErr := "ERROR"
    75  		cmd, outBuf, _ := newCmdWithBufs()
    76  		cmd.RunE = func(cmd *cobra.Command, args []string) error {
    77  			return errors.New(expectedErr)
    78  		}
    79  		cmd.SetArgs([]string{"--output=json"})
    80  		_, _, err := Execute(cmd)
    81  		require.Error(t, err)
    82  
    83  		stdout := outBuf.String()
    84  		m := map[string]string{}
    85  		require.NoError(t, json.Unmarshal([]byte(stdout), &m), "did not get json as stdout, got: %s", stdout)
    86  		require.Equal(t, expectedErr, m["err"], "did not get expected err, got: %s", m["err"])
    87  	})
    88  
    89  	t.Run("yaml output with error", func(t *testing.T) {
    90  		expectedErr := "ERROR"
    91  		cmd, outBuf, _ := newCmdWithBufs()
    92  		cmd.RunE = func(cmd *cobra.Command, args []string) error {
    93  			return errors.New(expectedErr)
    94  		}
    95  		cmd.SetArgs([]string{"--output=yaml"})
    96  		_, _, err := Execute(cmd)
    97  		require.Error(t, err)
    98  
    99  		stdout := outBuf.String()
   100  		m := map[string]string{}
   101  		require.NoError(t, yaml.Unmarshal([]byte(stdout), &m), "did not get yaml as stdout, got: %s", stdout)
   102  		require.Equal(t, expectedErr, m["err"], "did not get expected err, got: %s", m["err"])
   103  	})
   104  
   105  	t.Run("json output with native json", func(t *testing.T) {
   106  		expectedNativeJSONMap := map[string]float64{
   107  			"a": 1,
   108  		}
   109  		cmd, outBuf, errBuf := newCmdWithBufs()
   110  		cmd.RunE = func(cmd *cobra.Command, args []string) error {
   111  			Object(cmd.Context(), expectedNativeJSONMap, false)
   112  			return nil
   113  		}
   114  		cmd.SetArgs([]string{"--output=json"})
   115  		_, _, err := Execute(cmd)
   116  		require.NoError(t, err)
   117  
   118  		stdout := outBuf.String()
   119  		m := map[string]any{}
   120  		require.NoError(t, json.Unmarshal([]byte(stdout), &m), "did not get json as stdout, got: %s", stdout)
   121  		jsonOutputBytes, err := json.Marshal(m["stdout"])
   122  		require.NoError(t, err, "did not get json stdout as expected")
   123  		expectedJSONOutputBytes, _ := json.Marshal(expectedNativeJSONMap)
   124  
   125  		require.Equal(t, expectedJSONOutputBytes, jsonOutputBytes, "did not get expected stdout json")
   126  		stderr := errBuf.String()
   127  		require.Empty(t, stderr, "expected empty stderr, got: %s", stderr)
   128  	})
   129  
   130  	t.Run("json output with native json and other output", func(t *testing.T) {
   131  		expectedNativeJSONMap := map[string]float64{
   132  			"a": 1,
   133  		}
   134  		cmd, _, _ := newCmdWithBufs()
   135  		cmd.RunE = func(cmd *cobra.Command, args []string) error {
   136  			Object(cmd.Context(), expectedNativeJSONMap, false)
   137  			fmt.Fprintln(cmd.OutOrStdout(), "hello")
   138  			return nil
   139  		}
   140  		cmd.SetArgs([]string{"--output=json"})
   141  		require.Panics(t, func() {
   142  			_, _, _ = Execute(cmd)
   143  		})
   144  	})
   145  
   146  	t.Run("json output with other output and native json", func(t *testing.T) {
   147  		expectedNativeJSONMap := map[string]float64{
   148  			"a": 1,
   149  		}
   150  		cmd, _, _ := newCmdWithBufs()
   151  		cmd.RunE = func(cmd *cobra.Command, args []string) error {
   152  			fmt.Fprintln(cmd.OutOrStdout(), "hello")
   153  			Object(cmd.Context(), expectedNativeJSONMap, false)
   154  			return nil
   155  		}
   156  		cmd.SetArgs([]string{"--output=json"})
   157  		require.Panics(t, func() {
   158  			_, _, _ = Execute(cmd)
   159  		})
   160  	})
   161  
   162  	t.Run("json output with multiple native json", func(t *testing.T) {
   163  		expectedNativeJSONMap := map[string]float64{
   164  			"a": 1,
   165  		}
   166  		cmd, _, _ := newCmdWithBufs()
   167  		cmd.RunE = func(cmd *cobra.Command, args []string) error {
   168  			Object(cmd.Context(), expectedNativeJSONMap, false)
   169  			Object(cmd.Context(), expectedNativeJSONMap, false)
   170  			return nil
   171  		}
   172  		cmd.SetArgs([]string{"--output=json"})
   173  		require.Panics(t, func() {
   174  			_, _, _ = Execute(cmd)
   175  		})
   176  	})
   177  
   178  	t.Run("json output with overriding native json", func(t *testing.T) {
   179  		expectedNativeJSONMap := map[string]float64{
   180  			"a": 1,
   181  		}
   182  		cmd, outBuf, _ := newCmdWithBufs()
   183  		cmd.RunE = func(cmd *cobra.Command, args []string) error {
   184  			Object(cmd.Context(), expectedNativeJSONMap, true)
   185  			return nil
   186  		}
   187  		cmd.SetArgs([]string{"--output=json"})
   188  		_, _, err := Execute(cmd)
   189  		require.NoError(t, err)
   190  
   191  		stdout := outBuf.String()
   192  		m := map[string]any{}
   193  		require.NoError(t, json.Unmarshal([]byte(stdout), &m), "did not get json as stdout, got: %s", stdout)
   194  		require.Equal(t, 1.0, m["a"])
   195  	})
   196  
   197  	t.Run("json output with overriding native json and error", func(t *testing.T) {
   198  		expectedNativeMap := map[string]any{
   199  			"a": 1.0,
   200  		}
   201  		cmd, outBuf, _ := newCmdWithBufs()
   202  		cmd.RunE = func(cmd *cobra.Command, args []string) error {
   203  			Object(cmd.Context(), expectedNativeMap, true)
   204  			return errors.New("this went south")
   205  		}
   206  		cmd.SetArgs([]string{"--output=json"})
   207  		_, _, err := Execute(cmd)
   208  		require.Error(t, err)
   209  
   210  		stdout := outBuf.String()
   211  		m := map[string]any{}
   212  		require.NoError(t, json.Unmarshal([]byte(stdout), &m), "did not get json as stdout, got: %s", stdout)
   213  		require.Equal(t, m["stdout"], expectedNativeMap, "did not get expected stdout")
   214  		require.Empty(t, m["stderr"], "did not get empty stderr")
   215  		require.Equal(t, m["err"], "this went south")
   216  	})
   217  }