github.com/fnando/bolt@v0.0.4-0.20231107225351-5241e4d187b8/cmd/bolt_test.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"os"
     7  	"os/exec"
     8  	"path"
     9  	"regexp"
    10  	"runtime"
    11  	"testing"
    12  	"time"
    13  
    14  	c "github.com/fnando/bolt/common"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func init() {
    19  	_, filename, _, _ := runtime.Caller(0)
    20  	dir := path.Join(path.Dir(filename), "..")
    21  	err := os.Chdir(dir)
    22  
    23  	if err != nil {
    24  		panic(err)
    25  	}
    26  }
    27  
    28  type execResult struct {
    29  	exitcode int
    30  	stdout   string
    31  	stderr   string
    32  }
    33  
    34  func read(path string) string {
    35  	contents, err := os.ReadFile(path)
    36  
    37  	if err != nil {
    38  		panic(err)
    39  	}
    40  
    41  	return string(contents)
    42  }
    43  
    44  func normalizeElapsedText(input string) string {
    45  	re := regexp.MustCompile(`Finished in ([^,]+)`)
    46  	return re.ReplaceAllString(input, "Finished in 0s")
    47  }
    48  
    49  func run(args []string, env []string) (execResult, error) {
    50  	args = append([]string{"run", "./cmd/bolt.go"}, args...)
    51  	stdout := bytes.NewBufferString("")
    52  	stderr := bytes.NewBufferString("")
    53  	dir, _ := os.Getwd()
    54  	cmd := exec.Command("go", args...)
    55  	cmd.Stderr = stderr
    56  	cmd.Stdout = stdout
    57  	cmd.Env = append(os.Environ(), env...)
    58  	cmd.Dir = dir
    59  	err := cmd.Start()
    60  
    61  	if err != nil {
    62  		return execResult{
    63  			stdout:   stdout.String(),
    64  			stderr:   stderr.String(),
    65  			exitcode: -1,
    66  		}, err
    67  	}
    68  
    69  	err = cmd.Wait()
    70  
    71  	result := execResult{
    72  		stdout:   stdout.String(),
    73  		stderr:   stderr.String(),
    74  		exitcode: 0,
    75  	}
    76  
    77  	if exiterr, ok := err.(*exec.ExitError); ok {
    78  		result.exitcode = exiterr.ExitCode()
    79  
    80  		return result, nil
    81  	}
    82  
    83  	if err != nil {
    84  		return execResult{
    85  			stdout:   stdout.String(),
    86  			stderr:   stderr.String(),
    87  			exitcode: -1,
    88  		}, err
    89  	}
    90  
    91  	return result, err
    92  }
    93  
    94  func TestMain(m *testing.M) {
    95  	c.Clock.Now = time.Now
    96  	exitcode := m.Run()
    97  	os.Exit(exitcode)
    98  }
    99  
   100  func TestRunCommand(t *testing.T) {
   101  	require.NoError(t, nil)
   102  
   103  	t.Run("Help", func(t *testing.T) {
   104  		result, err := run([]string{"run", "--help"}, []string{})
   105  
   106  		require.NoError(t, err)
   107  		require.Equal(t, read("test/expected/run-help.txt"), result.stdout)
   108  		require.Equal(t, 0, result.exitcode)
   109  	})
   110  
   111  	t.Run("SuccessReplayFile", func(t *testing.T) {
   112  		c.Clock.Now = func() time.Time {
   113  			t, _ := time.Parse(time.RFC3339, "2023-10-31T12:15:22.773212-07:00")
   114  			return t
   115  		}
   116  		result, err := run(
   117  			[]string{"run", "--no-color", "--replay", "test/replays/run-pass.txt"},
   118  			[]string{},
   119  		)
   120  
   121  		require.NoError(t, err)
   122  		require.Equal(t, read("test/expected/run-pass.txt"), normalizeElapsedText(result.stdout))
   123  		require.Equal(t, 0, result.exitcode)
   124  	})
   125  
   126  	t.Run("FailReplayFile", func(t *testing.T) {
   127  		c.Clock.Now = func() time.Time {
   128  			t, _ := time.Parse(time.RFC3339, "2023-10-26T14:41:41.05297-07:00")
   129  			return t
   130  		}
   131  		result, err := run(
   132  			[]string{"run", "--no-color", "--replay", "test/replays/run-fail.txt"},
   133  			[]string{},
   134  		)
   135  
   136  		require.NoError(t, err)
   137  		require.Equal(t, read("test/expected/run-fail.txt"), normalizeElapsedText(result.stdout))
   138  		require.Contains(t, result.stderr, "exit status 3")
   139  		require.Equal(t, 1, result.exitcode)
   140  	})
   141  
   142  	t.Run("SkipReplayFile", func(t *testing.T) {
   143  		c.Clock.Now = func() time.Time {
   144  			t, _ := time.Parse(time.RFC3339, "2023-10-26T14:41:41.05297-07:00")
   145  			return t
   146  		}
   147  		result, err := run(
   148  			[]string{"run", "--no-color", "--replay", "test/replays/run-skip.txt"},
   149  			[]string{},
   150  		)
   151  
   152  		require.NoError(t, err)
   153  		require.Equal(t, read("test/expected/run-skip.txt"), normalizeElapsedText(result.stdout))
   154  		require.Equal(t, 0, result.exitcode)
   155  	})
   156  
   157  	t.Run("CustomSymbols", func(t *testing.T) {
   158  		result, err := run(
   159  			[]string{"run", "--no-color", "--replay", "test/replays/run-mixed.txt"},
   160  			[]string{"BOLT_FAIL_SYMBOL=❌", "BOLT_PASS_SYMBOL=⚡️", "BOLT_SKIP_SYMBOL=😴"},
   161  		)
   162  
   163  		require.NoError(t, err)
   164  		require.Contains(t, result.stdout, "⚡️⚡️❌❌❌⚡️⚡️⚡️😴😴")
   165  	})
   166  
   167  	t.Run("ColorOutput", func(t *testing.T) {
   168  		result, err := run(
   169  			[]string{"run", "--replay", "test/replays/run-mixed.txt"},
   170  			[]string{},
   171  		)
   172  
   173  		require.NoError(t, err)
   174  		require.Equal(
   175  			t,
   176  			read("test/expected/run-mixed-color.txt"),
   177  			normalizeElapsedText(result.stdout),
   178  		)
   179  		require.Contains(t, result.stderr, "exit status 3")
   180  		require.Equal(t, 1, result.exitcode)
   181  	})
   182  
   183  	t.Run("CustomColorOutput", func(t *testing.T) {
   184  		result, err := run(
   185  			[]string{"run", "--replay", "test/replays/run-mixed.txt"},
   186  			[]string{
   187  				"BOLT_TEXT_COLOR=31",
   188  				"BOLT_FAIL_COLOR=32",
   189  				"BOLT_PASS_COLOR=33",
   190  				"BOLT_SKIP_COLOR=34",
   191  				"BOLT_DETAIL_COLOR=35",
   192  			},
   193  		)
   194  
   195  		require.NoError(t, err)
   196  		require.Equal(
   197  			t,
   198  			read("test/expected/run-mixed-custom-color.txt"),
   199  			normalizeElapsedText(result.stdout),
   200  		)
   201  		require.Contains(t, result.stderr, "exit status 3")
   202  		require.Equal(t, 1, result.exitcode)
   203  	})
   204  
   205  	t.Run("ReplayError", func(t *testing.T) {
   206  		result, err := run(
   207  			[]string{"run", "--replay", "test/replays/run-error.txt"},
   208  			[]string{},
   209  		)
   210  
   211  		require.NoError(t, err)
   212  		require.Equal(t, read("test/expected/run-error.txt"), result.stdout)
   213  		require.Equal(t, 1, result.exitcode)
   214  	})
   215  
   216  	t.Run("ReplayNoTests", func(t *testing.T) {
   217  		result, err := run(
   218  			[]string{"run", "--no-color", "--replay", "test/replays/run-no-tests.txt"},
   219  			[]string{},
   220  		)
   221  
   222  		require.NoError(t, err)
   223  		require.Equal(t, read("test/expected/run-no-tests.txt"), normalizeElapsedText(result.stdout))
   224  		require.Equal(t, 0, result.exitcode)
   225  	})
   226  
   227  	t.Run("JSON", func(t *testing.T) {
   228  		c.Clock.Now = func() time.Time {
   229  			t, _ := time.Parse(time.RFC3339, "2023-10-26T14:41:41.05297-07:00")
   230  			return t
   231  		}
   232  
   233  		result, err := run(
   234  			[]string{"run", "--reporter", "json", "--replay", "test/replays/run-mixed.txt"},
   235  			[]string{},
   236  		)
   237  
   238  		require.NoError(t, err)
   239  
   240  		var data any
   241  		err = json.Unmarshal([]byte(result.stdout), &data)
   242  		require.NoError(t, err)
   243  
   244  		require.Contains(t, result.stderr, "exit status 3")
   245  		require.Equal(t, 1, result.exitcode)
   246  	})
   247  
   248  	t.Run("PostRunCommand", func(t *testing.T) {
   249  		_, err := run(
   250  			[]string{"run", "--no-color", "--debug", "--replay", "test/replays/run-mixed.txt", "--post-run-command", "env | grep BOLT | sort > test/tmp/env"},
   251  			[]string{},
   252  		)
   253  
   254  		require.NoError(t, err)
   255  
   256  		content := read("test/tmp/env")
   257  
   258  		require.Contains(t, content, "BOLT_TEST_COUNT=10\n")
   259  		require.Contains(t, content, "BOLT_PASS_COUNT=5\n")
   260  		require.Contains(t, content, "BOLT_FAIL_COUNT=3\n")
   261  		require.Contains(t, content, "BOLT_SKIP_COUNT=2\n")
   262  		require.Contains(t, content, "BOLT_BENCHMARK_COUNT=0\n")
   263  		require.Contains(t, content, "BOLT_SUMMARY=")
   264  		require.Contains(t, content, "BOLT_TITLE=Failed!\n")
   265  		require.Contains(t, content, "BOLT_ELAPSED=")
   266  		require.Contains(t, content, "BOLT_ELAPSED_NANOSECONDS=")
   267  	})
   268  }