github.com/kbehouse/nsc@v0.0.6/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  }