github.com/nats-io/nsc/v2@v2.8.7-0.20240307184528-efd7023c6896/cmd/cmd_test.go (about) 1 /* 2 * Copyright 2018-2019 The NATS Authors 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package cmd 17 18 import ( 19 "bytes" 20 "io" 21 "os" 22 "strings" 23 "testing" 24 25 cli "github.com/nats-io/cliprompts/v2" 26 "github.com/spf13/cobra" 27 ) 28 29 type CmdTest struct { 30 cmd *cobra.Command 31 args []string 32 hasOutput []string 33 hasError []string 34 shouldFail bool 35 } 36 37 func BuildChain(commands []string, cmd *cobra.Command) *cobra.Command { 38 var root *cobra.Command 39 var current *cobra.Command 40 for _, n := range commands { 41 c := &cobra.Command{ 42 Use: n, 43 Args: cobra.NoArgs, 44 } 45 if current != nil { 46 current.AddCommand(c) 47 } 48 current = c 49 if root == nil { 50 root = current 51 } 52 53 } 54 current.AddCommand(cmd) 55 return root 56 } 57 58 type CmdTests []CmdTest 59 60 func (cts *CmdTests) Run(t *testing.T, chain ...string) { 61 for i, v := range *cts { 62 v.RunTest(t, chain, i) 63 } 64 } 65 66 func (c *CmdTest) String() string { 67 return strings.Join(c.args, " ") 68 } 69 70 func (c *CmdTest) RunTest(t *testing.T, chain []string, index int) { 71 root := BuildChain(chain, c.cmd) 72 stdout, stderr, err := ExecuteCmd(root, c.args...) 73 for _, v := range c.hasOutput { 74 if !strings.Contains(stdout, v) { 75 t.Fatalf("test %d command '%v' stdout doesn't have %q\nstdout:\n%s\nstderr:\n%s\n", index, c, v, stdout, stderr) 76 } 77 } 78 for _, v := range c.hasError { 79 if !strings.Contains(stderr, v) { 80 t.Fatalf("test %d command '%v' stderr doesn't have %q\nstdout:\n%s\nstderr:\n%s\n", index, c, v, stdout, stderr) 81 } 82 } 83 if c.shouldFail && err == nil { 84 t.Fatalf("test %d command '%v' should have failed but didn't\nstdout:\n%s\nstderr:\n%s\n", index, c, stdout, stderr) 85 } 86 if !c.shouldFail && err != nil { 87 t.Fatalf("test %d command '%v' should have not failed: %v", index, c, err) 88 } 89 } 90 91 func ExecuteCmd(root *cobra.Command, args ...string) (stdout string, stderr string, err error) { 92 var stderrBuf, stdoutBuf bytes.Buffer 93 root.SetOutput(&stderrBuf) 94 if len(args) == 0 { 95 args = make([]string, 0) 96 } 97 root.SetArgs(args) 98 old := os.Stdout 99 r, w, _ := os.Pipe() 100 os.Stdout = w 101 102 _, err = root.ExecuteC() 103 104 _ = w.Close() 105 os.Stdout = old 106 _, _ = io.Copy(&stdoutBuf, r) 107 108 ResetSharedFlags() 109 110 return stdoutBuf.String(), stderrBuf.String(), err 111 } 112 113 func ExecuteInteractiveCmd(root *cobra.Command, inputs []interface{}, args ...string) (stdout string, stderr string, err error) { 114 var stderrBuf, stdoutBuf bytes.Buffer 115 root.SetOutput(&stderrBuf) 116 root.SetArgs(args) 117 old := os.Stdout 118 r, w, _ := os.Pipe() 119 os.Stdout = w 120 121 InteractiveFlag = true 122 cli.SetPromptLib(cli.NewTestPrompts(inputs)) 123 _, err = root.ExecuteC() 124 cli.ResetPromptLib() 125 InteractiveFlag = false 126 127 _ = w.Close() 128 os.Stdout = old 129 _, _ = io.Copy(&stdoutBuf, r) 130 131 ResetSharedFlags() 132 133 return stdoutBuf.String(), stderrBuf.String(), err 134 }