tty-command 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +9 -0
  3. data/examples/bash.rb +2 -2
  4. data/examples/basic.rb +2 -2
  5. data/examples/env.rb +3 -3
  6. data/examples/logger.rb +2 -2
  7. data/examples/output.rb +2 -2
  8. data/examples/pty.rb +3 -1
  9. data/examples/redirect_stderr.rb +2 -2
  10. data/examples/redirect_stdin.rb +2 -2
  11. data/examples/redirect_stdout.rb +2 -2
  12. data/examples/stdin_input.rb +2 -2
  13. data/examples/threaded.rb +3 -1
  14. data/examples/timeout.rb +7 -3
  15. data/examples/timeout_input.rb +2 -2
  16. data/examples/wait.rb +2 -2
  17. data/lib/tty/command/process_runner.rb +3 -0
  18. data/lib/tty/command/version.rb +1 -1
  19. data/spec/spec_helper.rb +78 -0
  20. data/spec/unit/binmode_spec.rb +27 -0
  21. data/spec/unit/cmd_spec.rb +152 -0
  22. data/spec/unit/dry_run_spec.rb +42 -0
  23. data/spec/unit/exit_error_spec.rb +25 -0
  24. data/spec/unit/input_spec.rb +11 -0
  25. data/spec/unit/output_spec.rb +25 -0
  26. data/spec/unit/printer_spec.rb +50 -0
  27. data/spec/unit/printers/custom_spec.rb +48 -0
  28. data/spec/unit/printers/null_spec.rb +36 -0
  29. data/spec/unit/printers/pretty_spec.rb +172 -0
  30. data/spec/unit/printers/progress_spec.rb +45 -0
  31. data/spec/unit/printers/quiet_spec.rb +71 -0
  32. data/spec/unit/pty_spec.rb +60 -0
  33. data/spec/unit/redirect_spec.rb +104 -0
  34. data/spec/unit/result_spec.rb +64 -0
  35. data/spec/unit/ruby_spec.rb +20 -0
  36. data/spec/unit/run_spec.rb +161 -0
  37. data/spec/unit/test_spec.rb +11 -0
  38. data/spec/unit/timeout_spec.rb +36 -0
  39. data/spec/unit/truncator_spec.rb +73 -0
  40. data/tty-command.gemspec +1 -1
  41. metadata +24 -10
  42. data/.gitignore +0 -9
  43. data/.rspec +0 -4
  44. data/.travis.yml +0 -29
  45. data/CODE_OF_CONDUCT.md +0 -49
  46. data/Gemfile +0 -14
  47. data/appveyor.yml +0 -26
  48. data/benchmarks/memory.rb +0 -11
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::Command, 'dry run' do
4
+ let(:output) { StringIO.new }
5
+
6
+ it "queries for dry mode" do
7
+ command = TTY::Command.new(dry_run: false)
8
+ expect(command.dry_run?).to eq(false)
9
+ end
10
+
11
+ it "runs command in dry run mode" do
12
+ uuid= 'xxxx'
13
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
14
+ command = TTY::Command.new(output: output, dry_run: true)
15
+
16
+ command.run(:echo, 'hello', 'world')
17
+
18
+ output.rewind
19
+ expect(output.read).to eq(
20
+ "[\e[32m#{uuid}\e[0m] \e[34m(dry run)\e[0m \e[33;1mecho hello world\e[0m\n")
21
+ end
22
+
23
+ it "allows to run command in dry mode" do
24
+ uuid= 'xxxx'
25
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
26
+ command = TTY::Command.new(output: output)
27
+
28
+ command.run(:echo, 'hello', 'world', dry_run: true)
29
+
30
+ output.rewind
31
+ expect(output.read).to eq(
32
+ "[\e[32m#{uuid}\e[0m] \e[34m(dry run)\e[0m \e[33;1mecho hello world\e[0m\n")
33
+ end
34
+
35
+ it "doesn't collect printout to stdin or stderr" do
36
+ cmd = TTY::Command.new(output: output, dry_run: true)
37
+ out, err = cmd.run(:echo, 'hello', 'world')
38
+
39
+ expect(out).to be_empty
40
+ expect(err).to be_empty
41
+ end
42
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::Command::ExitError, 'info' do
4
+ it "displays stdin & stdout" do
5
+ result = double(exit_status: 157, out: 'out content', err: 'err content')
6
+ error = described_class.new(:cat, result)
7
+ expect(error.message).to eq([
8
+ "Running `cat` failed with\n",
9
+ " exit status: 157\n",
10
+ " stdout: out content\n",
11
+ " stderr: err content\n"
12
+ ].join)
13
+ end
14
+
15
+ it "explains no stdin & stdout" do
16
+ result = double(exit_status: 157, out: '', err: '')
17
+ error = described_class.new(:cat, result)
18
+ expect(error.message).to eq([
19
+ "Running `cat` failed with\n",
20
+ " exit status: 157\n",
21
+ " stdout: Nothing written\n",
22
+ " stderr: Nothing written\n"
23
+ ].join)
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ RSpec.describe TTY::Command, 'input' do
2
+ it "reads user input data" do
3
+ cli = fixtures_path('cli')
4
+ output = StringIO.new
5
+ command = TTY::Command.new(output: output)
6
+
7
+ out, _ = command.run("ruby #{cli}", input: "Piotr\n")
8
+
9
+ expect(out.chomp).to eq("Your name: Piotr")
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ require 'fileutils'
4
+
5
+ RSpec.describe TTY::Command, ':output', type: :cli do
6
+ it 'runs command and prints to a file' do
7
+ stub_const('Tee', Class.new do
8
+ def initialize(file)
9
+ @file = file
10
+ end
11
+ def <<(message)
12
+ @file << message
13
+ @file.close
14
+ end
15
+ end)
16
+
17
+ file = tmp_path('foo.log')
18
+ output = Tee.new(File.open(file, 'w'))
19
+
20
+ command = TTY::Command.new(output: output, printer: :quiet)
21
+ command = command.run("echo hello")
22
+
23
+ expect(File.read(file).chomp).to eq("hello")
24
+ end
25
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::Command, ':printer' do
4
+ it "fails to find printer for nil" do
5
+ expect {
6
+ TTY::Command.new(printer: nil)
7
+ }.to raise_error(ArgumentError, /Unknown printer type ""/)
8
+ end
9
+
10
+ it "fails to find printer based on name" do
11
+ expect {
12
+ TTY::Command.new(printer: :unknown)
13
+ }.to raise_error(ArgumentError, /Unknown printer type "unknown"/)
14
+ end
15
+
16
+ it "detects null printer" do
17
+ cmd = TTY::Command.new(printer: :null)
18
+ expect(cmd.printer).to be_an_instance_of(TTY::Command::Printers::Null)
19
+ end
20
+
21
+ it "detects printer based on name" do
22
+ cmd = TTY::Command.new(printer: :progress)
23
+ expect(cmd.printer).to be_an_instance_of(TTY::Command::Printers::Progress)
24
+ end
25
+
26
+ it "uses printer based on class name" do
27
+ output = StringIO.new
28
+ printer = TTY::Command::Printers::Pretty
29
+ cmd = TTY::Command.new(output: output, printer: printer)
30
+ expect(cmd.printer).to be_an_instance_of(TTY::Command::Printers::Pretty)
31
+ end
32
+
33
+ it "uses printer based on instance" do
34
+ output = StringIO.new
35
+ printer = TTY::Command::Printers::Pretty.new(output)
36
+ cmd = TTY::Command.new(printer: printer)
37
+ expect(cmd.printer).to be_an_instance_of(TTY::Command::Printers::Pretty)
38
+ end
39
+
40
+ it "uses custom printer" do
41
+ stub_const('CustomPrinter', Class.new(TTY::Command::Printers::Abstract) do
42
+ def write(message)
43
+ output << message
44
+ end
45
+ end)
46
+ printer = CustomPrinter
47
+ cmd = TTY::Command.new(printer: printer)
48
+ expect(cmd.printer).to be_an_instance_of(CustomPrinter)
49
+ end
50
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe 'Custom Printer' do
4
+ let(:output) { StringIO.new }
5
+
6
+ before do
7
+ stub_const('CustomPrinter', Class.new(TTY::Command::Printers::Abstract) do
8
+ def write(message)
9
+ output << message
10
+ end
11
+ end)
12
+ end
13
+
14
+ it "prints command start" do
15
+ printer = CustomPrinter.new(output)
16
+ cmd = TTY::Command::Cmd.new(:echo, "'hello world'")
17
+
18
+ printer.print_command_start(cmd)
19
+ output.rewind
20
+
21
+ expect(output.string).to eq("echo \\'hello\\ world\\'")
22
+ end
23
+
24
+ it "prints command stdout data" do
25
+ printer = CustomPrinter.new(output)
26
+ cmd = TTY::Command::Cmd.new(:echo, 'hello world')
27
+
28
+ printer.print_command_out_data(cmd, 'data')
29
+ output.rewind
30
+
31
+ expect(output.string).to eq("data")
32
+ end
33
+
34
+ it "prints command exit" do
35
+ printer = CustomPrinter.new(output)
36
+ cmd = TTY::Command::Cmd.new(:echo, 'hello world')
37
+
38
+ printer.print_command_exit(cmd)
39
+ output.rewind
40
+
41
+ expect(output.string).to be_empty
42
+ end
43
+
44
+ it "accepts options" do
45
+ printer = CustomPrinter.new(output, foo: :bar)
46
+ expect(printer.options[:foo]).to eq(:bar)
47
+ end
48
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::Command::Printers::Null do
4
+ let(:output) { StringIO.new }
5
+
6
+ it "doesn't print command start or exit" do
7
+ printer = TTY::Command::Printers::Null.new(output)
8
+ cmd = TTY::Command::Cmd.new("echo hello")
9
+
10
+ printer.print_command_start(cmd)
11
+ printer.print_command_exit(cmd, 0)
12
+ output.rewind
13
+
14
+ expect(output.string).to be_empty
15
+ end
16
+
17
+ it "doesn't print command stdout data" do
18
+ printer = TTY::Command::Printers::Null.new(output)
19
+ cmd = TTY::Command::Cmd.new("echo hello")
20
+
21
+ printer.print_command_out_data(cmd, 'hello', 'world')
22
+ output.rewind
23
+
24
+ expect(output.string).to be_empty
25
+ end
26
+
27
+ it "doesn't print command stderr data" do
28
+ printer = TTY::Command::Printers::Null.new(output)
29
+ cmd = TTY::Command::Cmd.new("echo hello")
30
+
31
+ printer.print_command_err_data(cmd, 'hello', 'world')
32
+ output.rewind
33
+
34
+ expect(output.string).to be_empty
35
+ end
36
+ end
@@ -0,0 +1,172 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::Command::Printers::Pretty do
4
+ let(:output) { StringIO.new }
5
+ let(:uuid) { 'aaaaaa-xxx' }
6
+
7
+ it "prints command start in color" do
8
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
9
+ printer = TTY::Command::Printers::Pretty.new(output)
10
+ cmd = TTY::Command::Cmd.new(:echo, 'hello')
11
+
12
+ printer.print_command_start(cmd)
13
+ output.rewind
14
+
15
+ expect(output.string).
16
+ to eq("[\e[32maaaaaa\e[0m] Running \e[33;1mecho hello\e[0m\n")
17
+ end
18
+
19
+ it "prints command start without color" do
20
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
21
+ printer = TTY::Command::Printers::Pretty.new(output, color: false)
22
+ cmd = TTY::Command::Cmd.new(:echo, 'hello')
23
+
24
+ printer.print_command_start(cmd)
25
+ output.rewind
26
+
27
+ expect(output.string).to eq("[aaaaaa] Running echo hello\n")
28
+ end
29
+
30
+ it "prints command start without uuid" do
31
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
32
+ printer = TTY::Command::Printers::Pretty.new(output, uuid: false)
33
+ cmd = TTY::Command::Cmd.new(:echo, 'hello')
34
+
35
+ printer.print_command_start(cmd)
36
+ output.rewind
37
+
38
+ expect(output.string).to eq("Running \e[33;1mecho hello\e[0m\n")
39
+ end
40
+
41
+ it "prints command stdout data" do
42
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
43
+ printer = TTY::Command::Printers::Pretty.new(output)
44
+ cmd = TTY::Command::Cmd.new(:echo, 'hello')
45
+
46
+ printer.print_command_out_data(cmd, 'hello', 'world')
47
+ output.rewind
48
+
49
+ expect(output.string).to eq("[\e[32maaaaaa\e[0m] \thello world\n")
50
+ end
51
+
52
+ it "prints command stderr data" do
53
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
54
+ printer = TTY::Command::Printers::Pretty.new(output)
55
+ cmd = TTY::Command::Cmd.new(:echo, 'hello')
56
+
57
+ printer.print_command_err_data(cmd, 'hello', 'world')
58
+ output.rewind
59
+
60
+ expect(output.string).
61
+ to eq("[\e[32maaaaaa\e[0m] \t\e[31mhello world\e[0m\n")
62
+ end
63
+
64
+ it "prints successful command exit in color" do
65
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
66
+ printer = TTY::Command::Printers::Pretty.new(output)
67
+ cmd = TTY::Command::Cmd.new(:echo, 'hello')
68
+
69
+ printer.print_command_exit(cmd, 0, 5.321)
70
+ output.rewind
71
+
72
+ expect(output.string).to eq("[\e[32maaaaaa\e[0m] Finished in 5.321 seconds with exit status 0 (\e[32;1msuccessful\e[0m)\n")
73
+ end
74
+
75
+ it "prints failure command exit in color" do
76
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
77
+ printer = TTY::Command::Printers::Pretty.new(output)
78
+ cmd = TTY::Command::Cmd.new(:echo, 'hello')
79
+
80
+ printer.print_command_exit(cmd, 1, 5.321)
81
+ output.rewind
82
+
83
+ expect(output.string).to eq("[\e[32maaaaaa\e[0m] Finished in 5.321 seconds with exit status 1 (\e[31;1mfailed\e[0m)\n")
84
+ end
85
+
86
+ it "prints command exit without exit status in color" do
87
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
88
+ printer = TTY::Command::Printers::Pretty.new(output)
89
+ cmd = TTY::Command::Cmd.new(:echo, 'hello')
90
+
91
+ printer.print_command_exit(cmd, nil, 5.321)
92
+ output.rewind
93
+
94
+ expect(output.string).to eq("[\e[32maaaaaa\e[0m] Finished in 5.321 seconds (\e[31;1mfailed\e[0m)\n")
95
+ end
96
+
97
+ it "doesn't print output on success when only_output_on_error is true" do
98
+ zero_exit = fixtures_path('zero_exit')
99
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
100
+ printer = TTY::Command::Printers::Pretty
101
+ cmd = TTY::Command.new(output: output, printer: printer)
102
+
103
+ cmd.run!(:ruby, zero_exit, only_output_on_error: true)
104
+ cmd.run!(:ruby, zero_exit)
105
+
106
+ output.rewind
107
+
108
+ lines = output.readlines
109
+ lines.each { |line| line.gsub!(/\d+\.\d+(?= seconds)/, 'x') }
110
+
111
+ expect(lines).to eq([
112
+ "[\e[32maaaaaa\e[0m] Running \e[33;1mruby #{zero_exit}\e[0m\n",
113
+ "[\e[32maaaaaa\e[0m] Finished in x seconds with exit status 0 (\e[32;1msuccessful\e[0m)\n",
114
+ "[\e[32maaaaaa\e[0m] Running \e[33;1mruby #{zero_exit}\e[0m\n",
115
+ "[\e[32maaaaaa\e[0m] \tyess\n",
116
+ "[\e[32maaaaaa\e[0m] Finished in x seconds with exit status 0 (\e[32;1msuccessful\e[0m)\n"
117
+ ])
118
+ end
119
+
120
+ it "prints output on error & raises ExitError when only_output_on_error is true" do
121
+ non_zero_exit = fixtures_path('non_zero_exit')
122
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
123
+ printer = TTY::Command::Printers::Pretty
124
+ cmd = TTY::Command.new(output: output, printer: printer)
125
+
126
+ cmd.run!(:ruby, non_zero_exit, only_output_on_error: true)
127
+ cmd.run!(:ruby, non_zero_exit)
128
+
129
+ output.rewind
130
+
131
+ lines = output.readlines
132
+ lines.each { |line| line.gsub!(/\d+\.\d+(?= seconds)/, 'x') }
133
+
134
+ expect(lines).to eq([
135
+ "[\e[32maaaaaa\e[0m] Running \e[33;1mruby #{non_zero_exit}\e[0m\n",
136
+ "[\e[32maaaaaa\e[0m] \tnooo\n",
137
+ "[\e[32maaaaaa\e[0m] Finished in x seconds with exit status 1 (\e[31;1mfailed\e[0m)\n",
138
+ "[\e[32maaaaaa\e[0m] Running \e[33;1mruby #{non_zero_exit}\e[0m\n",
139
+ "[\e[32maaaaaa\e[0m] \tnooo\n",
140
+ "[\e[32maaaaaa\e[0m] Finished in x seconds with exit status 1 (\e[31;1mfailed\e[0m)\n"
141
+ ])
142
+ end
143
+
144
+ it "prints output on error when only_output_on_error is true" do
145
+ non_zero_exit = fixtures_path('non_zero_exit')
146
+ allow(SecureRandom).to receive(:uuid).and_return(uuid)
147
+ printer = TTY::Command::Printers::Pretty
148
+ cmd = TTY::Command.new(output: output, printer: printer)
149
+
150
+ expect {
151
+ cmd.run(:ruby, non_zero_exit, only_output_on_error: true)
152
+ }.to raise_error(TTY::Command::ExitError)
153
+
154
+ expect {
155
+ cmd.run(:ruby, non_zero_exit)
156
+ }.to raise_error(TTY::Command::ExitError)
157
+
158
+ output.rewind
159
+
160
+ lines = output.readlines
161
+ lines.each { |line| line.gsub!(/\d+\.\d+(?= seconds)/, 'x') }
162
+
163
+ expect(lines).to eq([
164
+ "[\e[32maaaaaa\e[0m] Running \e[33;1mruby #{non_zero_exit}\e[0m\n",
165
+ "[\e[32maaaaaa\e[0m] \tnooo\n",
166
+ "[\e[32maaaaaa\e[0m] Finished in x seconds with exit status 1 (\e[31;1mfailed\e[0m)\n",
167
+ "[\e[32maaaaaa\e[0m] Running \e[33;1mruby #{non_zero_exit}\e[0m\n",
168
+ "[\e[32maaaaaa\e[0m] \tnooo\n",
169
+ "[\e[32maaaaaa\e[0m] Finished in x seconds with exit status 1 (\e[31;1mfailed\e[0m)\n"
170
+ ])
171
+ end
172
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::Command::Printers::Progress do
4
+ let(:output) { StringIO.new }
5
+
6
+ it "doesn't print command start" do
7
+ printer = TTY::Command::Printers::Progress.new(output)
8
+ cmd = TTY::Command::Cmd.new(:echo, 'hello')
9
+
10
+ printer.print_command_start(cmd)
11
+ output.rewind
12
+
13
+ expect(output.string).to be_empty
14
+ end
15
+
16
+ it "doesn't print command stdout data" do
17
+ printer = TTY::Command::Printers::Progress.new(output)
18
+ cmd = TTY::Command::Cmd.new(:echo, 'hello')
19
+
20
+ printer.print_command_out_data(cmd, 'hello', 'world')
21
+ output.rewind
22
+
23
+ expect(output.string).to be_empty
24
+ end
25
+
26
+ it "prints successful command exit in color" do
27
+ printer = TTY::Command::Printers::Progress.new(output)
28
+ cmd = TTY::Command::Cmd.new(:echo, 'hello')
29
+
30
+ printer.print_command_exit(cmd, 0, 5.321)
31
+ output.rewind
32
+
33
+ expect(output.string).to eq("\e[32m.\e[0m")
34
+ end
35
+
36
+ it "prints failure command exit in color" do
37
+ printer = TTY::Command::Printers::Progress.new(output)
38
+ cmd = TTY::Command::Cmd.new(:echo, 'hello')
39
+
40
+ printer.print_command_exit(cmd, 1, 5.321)
41
+ output.rewind
42
+
43
+ expect(output.string).to eq("\e[31mF\e[0m")
44
+ end
45
+ end