ttytest2 0.9.13 → 1.0.1
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.
- checksums.yaml +4 -4
- data/.bundle/config +0 -0
- data/.github/workflows/test.yml +0 -0
- data/.gitignore +0 -0
- data/Gemfile +0 -0
- data/README.md +47 -2
- data/Rakefile +0 -0
- data/examples/integration_tests.rb +2 -2
- data/lib/ttytest/capture.rb +0 -0
- data/lib/ttytest/constants.rb +0 -0
- data/lib/ttytest/matchers.rb +37 -18
- data/lib/ttytest/terminal.rb +0 -0
- data/lib/ttytest/tmux/driver.rb +8 -0
- data/lib/ttytest/tmux/session.rb +2 -2
- data/lib/ttytest/tmux/tmux.conf +0 -0
- data/lib/ttytest/version.rb +1 -1
- data/lib/ttytest.rb +9 -1
- data/notes.txt +2 -2
- data/ttytest2.gemspec +0 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e4921ed7f9ec57ffb18c82a6ad29df778485f1d6d3bad878c06cdab50ba303a
|
4
|
+
data.tar.gz: c05db30206186a54ec5a5fa6b23dd333a173bb210b18aaff2201647e01ac99d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0032e2da8ae48c097f614acbf908d5860732c78c09a98fe6738490e2675a6af54e043f499eb9367a8cd362070d8988cd79400b4c546803a57282f23dce3f2dc4
|
7
|
+
data.tar.gz: 4250ea672cc1d031fe5403bd21980e2e80b06095e2dc0d67df65d94d6f35904905fc0098480afb884d5008425207537aa9c6a2b73724b3d6ff40a4fbeb53a877
|
data/.bundle/config
CHANGED
File without changes
|
data/.github/workflows/test.yml
CHANGED
File without changes
|
data/.gitignore
CHANGED
File without changes
|
data/Gemfile
CHANGED
File without changes
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@ ttytest2 is a fork and a drop-in replacement for [ttytest](https://github.com/jh
|
|
6
6
|
|
7
7
|
It works by running commands inside a tmux session, capturing the pane, and comparing the content to your assertions.
|
8
8
|
|
9
|
-
The assertions will wait a specified amount of time (default 2 seconds) for the expected content to appear.
|
9
|
+
The assertions will wait a specified amount of time (configurable, default 2 seconds) for the expected content to appear.
|
10
10
|
|
11
11
|
[](https://badge.fury.io/rb/ttytest2)
|
12
12
|
|
@@ -39,6 +39,7 @@ The assertions will wait a specified amount of time (default 2 seconds) for the
|
|
39
39
|
|
40
40
|
``` ruby
|
41
41
|
require 'ttytest'
|
42
|
+
|
42
43
|
@tty = TTYtest.new_terminal(%(PS1='$ ' /bin/sh), width: 80, height: 7)
|
43
44
|
@tty.assert_row(0, '$')
|
44
45
|
@tty.assert_cursor_position(2, 0)
|
@@ -68,6 +69,31 @@ TTY
|
|
68
69
|
# $
|
69
70
|
```
|
70
71
|
|
72
|
+
### Initializing
|
73
|
+
|
74
|
+
Call one of these methods to initialize an instance of ttytest2.
|
75
|
+
|
76
|
+
* `new_terminal(cmd, width, height)`: initialize new tmux terminal instance and run cmd.
|
77
|
+
|
78
|
+
* `new_default_sh_terminal()`: intialize new tmux terminal instance using sh, width of 80, height of 24.
|
79
|
+
|
80
|
+
* `new_sh_terminal(width, height)`: intialize new tmux terminal instance using sh and width and height parameters.
|
81
|
+
|
82
|
+
``` ruby
|
83
|
+
require 'ttytest'
|
84
|
+
|
85
|
+
# these are all equivalent
|
86
|
+
@tty = TTYtest.new_terminal(%(PS1='$ ' /bin/sh))
|
87
|
+
@tty = TTYtest.new_terminal(%(PS1='$ ' /bin/sh), width: 80, height: 24)
|
88
|
+
@tty = TTYtest.new_default_sh_terminal
|
89
|
+
@tty = TTYtest.new_sh_terminal
|
90
|
+
@tty = TTYtest.new_sh_terminal(width: 80, height: 24)
|
91
|
+
|
92
|
+
# you can also use other shells, like bash
|
93
|
+
@tty = TTYtest.new_terminal('/bin/bash')
|
94
|
+
@tty = TTYtest.new_terminal('/bin/bash', width: 80, height: 24)
|
95
|
+
```
|
96
|
+
|
71
97
|
### Assertions
|
72
98
|
|
73
99
|
The main way to use TTYtest is through assertions.
|
@@ -77,15 +103,25 @@ Assertions will be retried for up to 2 seconds when called through TTYtest::Term
|
|
77
103
|
Available assertions:
|
78
104
|
|
79
105
|
* `assert_row(row_number, expected_text)`
|
106
|
+
|
80
107
|
* `assert_row_at(row_number, column_start_position, column_end_position, expected_text)`
|
108
|
+
|
81
109
|
* `assert_row_like(row_number, expected_text)`
|
110
|
+
|
82
111
|
* `assert_row_starts_with(row_number, expected_text)`
|
112
|
+
|
83
113
|
* `assert_row_ends_with(row_number, expected_text)`
|
114
|
+
|
84
115
|
* `assert_row_regexp(row_number, regexp_str)`
|
116
|
+
|
85
117
|
* `assert_cursor_position(x: x, y: y)`
|
118
|
+
|
86
119
|
* `assert_cursor_visible`
|
120
|
+
|
87
121
|
* `assert_cursor_hidden`
|
122
|
+
|
88
123
|
* `assert_contents(lines_of_terminal)`
|
124
|
+
|
89
125
|
* `assert_contents_at(row_start, row_end, expected_text)`
|
90
126
|
|
91
127
|
### Output
|
@@ -118,21 +154,30 @@ Helper functions to make sending output easier! They use the methods above under
|
|
118
154
|
* `send_newlines(number_of_times)` # equivalent to calling send_newline number_of_times
|
119
155
|
* `send_enter` # alias for send_newline
|
120
156
|
* `send_enters(number_of_times)` # alias for send_newlines
|
157
|
+
|
121
158
|
* `send_backspace` # simulate hitting backspace, equivalent to @tty.send_keys(TTYtest::BACKSPACE)
|
122
159
|
* `send_backspaces(number_of_times)` # equivalent to calling send_backspace number_of_times
|
160
|
+
|
123
161
|
* `send_delete` # simulate hitting delete, equivalent to calling send_keys_exact(%(DC))
|
124
162
|
* `send_deletes` # equivalent to calling send_delete number_of_times
|
163
|
+
|
125
164
|
* `send_right_arrow`
|
126
165
|
* `send_right_arrows(number_of_times)`
|
166
|
+
|
127
167
|
* `send_left_arrow`
|
128
168
|
* `send_left_arrows(number_of_times)`
|
169
|
+
|
129
170
|
* `send_up_arrow`
|
130
171
|
* `send_up_arrows(number_of_times)`
|
172
|
+
|
131
173
|
* `send_down_arrow`
|
132
174
|
* `send_down_arrows(number_of_times)`
|
175
|
+
|
133
176
|
* `send_home` # simulate pressing the Home key
|
134
177
|
* `send_end` # simulate pressing the End key
|
178
|
+
|
135
179
|
* `send_clear` # clear the screen by sending clear ascii code
|
180
|
+
|
136
181
|
* `send_escape`
|
137
182
|
* `send_escapes`
|
138
183
|
|
@@ -227,7 +272,7 @@ There are some commonly used keys available as constants to make interacting wit
|
|
227
272
|
TTYtest::CLEAR # clear the screen
|
228
273
|
```
|
229
274
|
|
230
|
-
|
275
|
+
## Tips
|
231
276
|
|
232
277
|
If you are using ttyest2 to test your CLI, using sh is easier than bash because you don't have to worry about user, current working directory, etc. as shown in the examples.
|
233
278
|
|
data/Rakefile
CHANGED
File without changes
|
@@ -755,7 +755,7 @@ def stdout_and_stderr_redirection_tests(row)
|
|
755
755
|
end
|
756
756
|
|
757
757
|
row = 0
|
758
|
-
@tty = TTYtest.new_terminal(%(
|
758
|
+
@tty = TTYtest.new_terminal(%(./bin/ncsh), width: 120, height: 120)
|
759
759
|
|
760
760
|
row = startup_tests(row, true)
|
761
761
|
row = basic_tests row
|
@@ -776,7 +776,7 @@ tab_autocompletion_tests row
|
|
776
776
|
@tty.send_newline
|
777
777
|
|
778
778
|
row = 0
|
779
|
-
@tty = TTYtest.new_terminal(%(
|
779
|
+
@tty = TTYtest.new_terminal(%(./bin/ncsh), width: 180, height: 150)
|
780
780
|
row = startup_tests(row, false)
|
781
781
|
row = syntax_error_tests row
|
782
782
|
row = stderr_redirection_tests row
|
data/lib/ttytest/capture.rb
CHANGED
File without changes
|
data/lib/ttytest/constants.rb
CHANGED
File without changes
|
data/lib/ttytest/matchers.rb
CHANGED
@@ -10,6 +10,7 @@ module TTYtest
|
|
10
10
|
def assert_row(row_number, expected)
|
11
11
|
expected = expected.rstrip
|
12
12
|
actual = row(row_number)
|
13
|
+
|
13
14
|
return if actual == expected
|
14
15
|
|
15
16
|
raise MatchError,
|
@@ -26,6 +27,7 @@ module TTYtest
|
|
26
27
|
expected = expected.rstrip
|
27
28
|
actual = row(row_number)
|
28
29
|
column_end += 1
|
30
|
+
|
29
31
|
return if actual[column_start, column_end].eql?(expected)
|
30
32
|
|
31
33
|
raise MatchError,
|
@@ -41,6 +43,7 @@ module TTYtest
|
|
41
43
|
def assert_row_like(row_number, expected)
|
42
44
|
expected = expected.rstrip
|
43
45
|
actual = row(row_number)
|
46
|
+
|
44
47
|
return if actual.include?(expected)
|
45
48
|
|
46
49
|
raise MatchError,
|
@@ -55,6 +58,7 @@ module TTYtest
|
|
55
58
|
def assert_row_starts_with(row_number, expected)
|
56
59
|
expected = expected.rstrip
|
57
60
|
actual = row(row_number)
|
61
|
+
|
58
62
|
return if actual.start_with?(expected)
|
59
63
|
|
60
64
|
raise MatchError,
|
@@ -68,6 +72,7 @@ module TTYtest
|
|
68
72
|
def assert_row_ends_with(row_number, expected)
|
69
73
|
expected = expected.rstrip
|
70
74
|
actual = row(row_number)
|
75
|
+
|
71
76
|
return if actual.end_with?(expected)
|
72
77
|
|
73
78
|
raise MatchError,
|
@@ -88,6 +93,23 @@ module TTYtest
|
|
88
93
|
"expected row #{row_number} to match regexp #{regexp_str} but it did not. Row value #{actual.inspect}\nEntire screen:\n#{self}"
|
89
94
|
end
|
90
95
|
|
96
|
+
# Asserts the contents of a multiple rows each match against the passed in regular expression
|
97
|
+
# @param [Integer] row_start the row (starting from 0) to test against
|
98
|
+
# @param [Integer] row_end the last row to test against
|
99
|
+
# @param [String] regexp_str the regular expression as a string that will be used to match with.
|
100
|
+
# @raise [MatchError] if the row doesn't match against the regular expression
|
101
|
+
def assert_rows_each_match_regexp(row_start, row_end, regexp_str)
|
102
|
+
regexp = Regexp.new(regexp_str)
|
103
|
+
row_end += 1 if row_end.zero?
|
104
|
+
|
105
|
+
rows.slice(row_start, row_end).each_with_index do |actual_row, index|
|
106
|
+
next if actual_row.match?(regexp)
|
107
|
+
|
108
|
+
raise MatchError,
|
109
|
+
"expected row #{index} to match regexp #{regexp_str} but it did not. Row value #{actual_row.inspect}\nEntire screen:\n#{self}"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
91
113
|
# Asserts that the cursor is in the expected position
|
92
114
|
# @param [Integer] x cursor x (row) position, starting from 0
|
93
115
|
# @param [Integer] y cursor y (column) position, starting from 0
|
@@ -95,6 +117,7 @@ module TTYtest
|
|
95
117
|
def assert_cursor_position(x, y)
|
96
118
|
expected = [x, y]
|
97
119
|
actual = [cursor_x, cursor_y]
|
120
|
+
|
98
121
|
return if actual == expected
|
99
122
|
|
100
123
|
raise MatchError,
|
@@ -115,14 +138,11 @@ module TTYtest
|
|
115
138
|
raise MatchError, "expected cursor to be hidden was visible\nEntire screen:\n#{self}"
|
116
139
|
end
|
117
140
|
|
118
|
-
|
119
|
-
# @param [String] expected the full expected contents of the terminal. Trailing whitespace on each line is ignored
|
120
|
-
# @raise [MatchError] if the terminal doesn't match the expected content
|
121
|
-
def assert_contents(expected)
|
141
|
+
def matched(expected, actual)
|
122
142
|
expected_rows = expected.split("\n")
|
123
143
|
diff = []
|
124
144
|
matched = true
|
125
|
-
|
145
|
+
actual.each_with_index do |actual_row, index|
|
126
146
|
expected_row = (expected_rows[index] || '').rstrip
|
127
147
|
if actual_row != expected_row
|
128
148
|
diff << "-#{expected_row}"
|
@@ -133,32 +153,30 @@ module TTYtest
|
|
133
153
|
end
|
134
154
|
end
|
135
155
|
|
156
|
+
[matched, diff]
|
157
|
+
end
|
158
|
+
|
159
|
+
# Asserts the full contents of the terminal
|
160
|
+
# @param [String] expected the full expected contents of the terminal. Trailing whitespace on each line is ignored
|
161
|
+
# @raise [MatchError] if the terminal doesn't match the expected content
|
162
|
+
def assert_contents(expected)
|
163
|
+
matched, diff = matched(expected, rows)
|
164
|
+
|
136
165
|
return if matched
|
137
166
|
|
138
167
|
raise MatchError,
|
139
168
|
"screen did not match expected content:\n--- expected\n+++ actual\n#{diff.join("\n")}"
|
140
169
|
end
|
141
170
|
alias assert_matches assert_contents
|
171
|
+
alias assert_screen assert_contents
|
142
172
|
|
143
173
|
# Asserts the contents of the terminal at specified rows
|
144
174
|
# @param [String] expected the expected contents of the terminal at specified rows. Trailing whitespace on each line is ignored
|
145
175
|
# @raise [MatchError] if the terminal doesn't match the expected content
|
146
176
|
def assert_contents_at(row_start, row_end, expected)
|
147
|
-
expected_rows = expected.split("\n")
|
148
|
-
diff = []
|
149
|
-
matched = true
|
150
177
|
row_end += 1 if row_end.zero?
|
151
178
|
|
152
|
-
rows.slice(row_start, row_end)
|
153
|
-
expected_row = (expected_rows[index] || '').rstrip
|
154
|
-
if actual_row != expected_row
|
155
|
-
diff << "-#{expected_row}"
|
156
|
-
diff << "+#{actual_row}"
|
157
|
-
matched = false
|
158
|
-
else
|
159
|
-
diff << " #{actual_row}".rstrip
|
160
|
-
end
|
161
|
-
end
|
179
|
+
matched, diff = matched(expected, rows.slice(row_start, row_end))
|
162
180
|
|
163
181
|
return if matched
|
164
182
|
|
@@ -166,6 +184,7 @@ module TTYtest
|
|
166
184
|
"screen did not match expected content:\n--- expected\n+++ actual\n#{diff.join("\n")}"
|
167
185
|
end
|
168
186
|
alias assert_matches_at assert_contents_at
|
187
|
+
alias assert_rows assert_contents_at
|
169
188
|
|
170
189
|
METHODS = public_instance_methods
|
171
190
|
end
|
data/lib/ttytest/terminal.rb
CHANGED
File without changes
|
data/lib/ttytest/tmux/driver.rb
CHANGED
@@ -39,6 +39,14 @@ module TTYtest
|
|
39
39
|
Terminal.new(session)
|
40
40
|
end
|
41
41
|
|
42
|
+
def new_default_sh_terminal
|
43
|
+
new_terminal(%(PS1='$ ' /bin/sh), width: 80, height: 24)
|
44
|
+
end
|
45
|
+
|
46
|
+
def new_sh_terminal(width: 80, height: 24)
|
47
|
+
new_terminal(%(PS1='$ ' /bin/sh), width: width, height: height)
|
48
|
+
end
|
49
|
+
|
42
50
|
# @api private
|
43
51
|
def tmux(*args)
|
44
52
|
ensure_available
|
data/lib/ttytest/tmux/session.rb
CHANGED
@@ -80,9 +80,9 @@ module TTYtest
|
|
80
80
|
sleep sleep_time
|
81
81
|
end
|
82
82
|
|
83
|
-
def send_line_then_sleep_and_repeat(*lines)
|
83
|
+
def send_line_then_sleep_and_repeat(*lines, sleep_time)
|
84
84
|
lines.each do |line|
|
85
|
-
send_line_then_sleep(line)
|
85
|
+
send_line_then_sleep(line, sleep_time)
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
data/lib/ttytest/tmux/tmux.conf
CHANGED
File without changes
|
data/lib/ttytest/version.rb
CHANGED
data/lib/ttytest.rb
CHANGED
@@ -17,7 +17,15 @@ module TTYtest
|
|
17
17
|
# @param [Integer] width width of the new terminal
|
18
18
|
# @param [Integer] height height of the new terminal
|
19
19
|
# @return [Terminal] a new terminal running the specified command
|
20
|
-
|
20
|
+
|
21
|
+
# @!method new_default_sh_terminal
|
22
|
+
# Create a new terminal using '/bin/sh' with width: 80 and height: 24.
|
23
|
+
# Useful for Unixes.
|
24
|
+
|
25
|
+
# @!method new_sh_terminal(width: 80, height: 24)
|
26
|
+
# Create a new terminal using '/bin/sh' with ability to set width and height.
|
27
|
+
# Useful for Unixes.
|
28
|
+
def_delegators :driver, :new_terminal, :new_default_sh_terminal, :new_sh_terminal
|
21
29
|
end
|
22
30
|
|
23
31
|
class MatchError < StandardError; end
|
data/notes.txt
CHANGED
data/ttytest2.gemspec
CHANGED
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ttytest2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Eski
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-04-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|