ttytest2 0.8.6 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5813f48d629bc3029c7c486652b5badcedbbac19b4c24946f50f8aa9df579c8
4
- data.tar.gz: 86adb037b39d0da7cdcc9920d71f1655e8864e0171ae3fabfcb7301774908102
3
+ metadata.gz: da8ddbaf4a49037e8dda3fb31986824c75819abbee94fb7954263c36a8e63414
4
+ data.tar.gz: 7091feb0fdac4857c1c0bf47a7c8158d8c90bd48d1ff321fec53aeab185443ec
5
5
  SHA512:
6
- metadata.gz: e6fe94d8ef4c818a94b487f01efee8ab8d2c1ed828b30679eed643e4388c9e77178d00c25e761881098b47512a51f696c597a82fabfa68d9e6a569ea52b0e15e
7
- data.tar.gz: 0ce32ed7e12445f1c9d4fee55ec2f9b5c27a3890c73a1a3a52b45c39c5c1931ebc08bcc6f04bf5e55d372a03b82e4b19a2ccfee4a487a427d52047d92f3fec84
6
+ metadata.gz: baab5b496e22d73a133084b2a4d58fc2fb83c95325c02227a50847adcbb876fe23f7a71e80efd69c12c2730aff64866222004db102b21613c4e4301455c15cd8
7
+ data.tar.gz: d66c05f581f565f33c9305ec9c484346790184d64ca5bdfb4b9718d95c22b842dbd2f689634548863f93cdcaced2dc94f4048dc66e6101dba8d2ef4f4856bae9
data/README.md CHANGED
@@ -20,22 +20,34 @@ It works by running commands inside a tmux session, capturing the pane, and comp
20
20
  The main way to use TTYtest is through assertions. When called on a `TTYtest::Terminal`, each of these will be retried (for up to 2 seconds).
21
21
 
22
22
  Available assertions:
23
- * `assert_row(row_number, expected_text)`
24
- * `assert_row_like(row_number, expected_text)`
25
- * `assert_row_starts_with(row_number, expected_text)`
26
- * `assert_row_ends_with(row_number, expected_text)`
27
- * `assert_cursor_position(x: x, y: y)`
28
- * `assert_cursor_visible`
29
- * `assert_cursor_hidden`
30
- * `assert_contents(lines_of_terminal)`
31
-
32
- ### Sending output
23
+ * specify row matches expected text exactly: `assert_row(row_number, expected_text) `
24
+ * specify expected position of expected text: `assert_row_at(row_number, column_start_position, column_end_position, expected_text)`
25
+ * specify row contains expected text: `assert_row_like(row_number, expected_text)`
26
+ * specify row starts with expected text: `assert_row_starts_with(row_number, expected_text)`
27
+ * specify row ends with expected text: `assert_row_ends_with(row_number, expected_text)`
28
+ * specify the current cursor position matches expected: `assert_cursor_position(x: x, y: y)`
29
+ * specify the cursor is currently visible: `assert_cursor_visible`
30
+ * specify the cursor is currently hidden: `assert_cursor_hidden`
31
+ * specify the contents of the entire terminal window: `assert_contents(lines_of_terminal)`
32
+
33
+ ### Sending Output
33
34
 
34
35
  You can send output to the terminal with the following calls.
35
36
 
36
- * `send_keys(output)`
37
+ * `send_keys(output) # for canonical shells/cli's (or multi-character keys for noncanonical shells/cli's)`
38
+ * `send_keys_one_at_a_time(output) # for noncanonical shells/cli's`
39
+ * `send_keys_exact(output) # for sending tmux specific keys (DC for delete, Escape for ESC, etc.)`
40
+
41
+ ### Output Helpers
42
+
43
+ Helper functions to make sending output easier! They use the methods above under 'Sending Output' section under the hood.
44
+
37
45
  * `send_newline # equivalent to @tty.send_keys(%(\n))`
38
- * `send_keys_one_at_a_time(output)`
46
+ * `send_newlines(number_of_times) # equivalent to calling send_newline number_of_times`
47
+ * `send_backspace # equivalent to @tty.send_keys(TTYtest::BACKSPACE)`
48
+ * `send_backspaces(number_of_times) # equivalent to calling send_backspace number_of_times`
49
+ * `send_delete # equivalent to calling send_keys_exact(%(DC))`
50
+ * `send_deletes # equivalent to calling send_delete number_of_times`
39
51
 
40
52
  ### Example Canonical CLI/Shell
41
53
 
@@ -80,6 +92,10 @@ require 'ttytest'
80
92
  @tty.send_keys_one_at_a_time('ps')
81
93
  @tty.assert_row_ends_with(0, 'ps')
82
94
  @tty.send_keys(TTYtest:NEWLINE) # can use constants instead
95
+
96
+ @tty.assert_row_starts_with(0, ENV['USER'])
97
+ @tty.assert_row_ends_with(0, '$')
98
+ @tty.send_newline # an alternative to the 2 above methods to send \n to the terminal
83
99
  ```
84
100
 
85
101
  ### Constants
@@ -88,7 +104,6 @@ There are some commonly used keys available as constants to make interacting wit
88
104
 
89
105
  ``` ruby
90
106
  TTYtest::BACKSPACE
91
- TTYtest::DELETE
92
107
  TTYtest::TAB
93
108
  TTYtest::CTRLF
94
109
  TTYtest::CTRLC
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'ttytest'
5
+
6
+ START_COL = 19
7
+
8
+ def assert_check_new_row(row)
9
+ @tty.assert_row_starts_with(row, "#{ENV['USER']}:")
10
+ @tty.assert_row_like(row, 'ncsh')
11
+ @tty.assert_row_ends_with(row, '$')
12
+ @tty.assert_cursor_position(START_COL, row)
13
+ end
14
+
15
+ @tty = TTYtest.new_terminal(%(PS1='$ ' ./bin/ncsh), width: 80, height: 24)
16
+
17
+ row = 0
18
+
19
+ # # # # Basic Tests # # # #
20
+ puts 'Starting basic tests'
21
+
22
+ @tty.assert_row_starts_with(row, 'ncsh: startup time: ')
23
+ row += 1
24
+
25
+ assert_check_new_row(row)
26
+ @tty.send_keys(%(ls))
27
+ @tty.assert_cursor_position(START_COL + 2, 1)
28
+ @tty.send_newline
29
+ @tty.assert_row_ends_with(row, 'ls')
30
+ row += 1
31
+ @tty.assert_row_starts_with(row, 'LICENSE')
32
+ row = 9
33
+
34
+ assert_check_new_row(row)
35
+ @tty.send_keys(%(echo hello))
36
+ @tty.send_newline
37
+ row += 1
38
+ @tty.assert_row(row, 'hello')
39
+ row += 1
40
+
41
+ assert_check_new_row(row)
42
+ @tty.send_keys(%(lss)) # send a bad command
43
+ @tty.send_newline
44
+ row += 1
45
+ @tty.assert_row(row, 'ncsh: Could not find command or directory: No such file or directory')
46
+ row += 1
47
+
48
+ puts 'Starting backspace tests'
49
+
50
+ # end of line backspace
51
+ assert_check_new_row(row)
52
+ @tty.send_keys(%(l))
53
+ @tty.send_backspace
54
+ assert_check_new_row(row)
55
+
56
+ # multiple end of line backspaces
57
+ @tty.send_keys(%(lsssss))
58
+ @tty.send_backspace
59
+ @tty.send_backspace
60
+ @tty.send_backspace
61
+ @tty.send_backspace
62
+ @tty.assert_row_ends_with(row, '$ ls')
63
+ @tty.send_backspace
64
+ @tty.send_backspace
65
+ @tty.send_keys(%(echo hello)) # make sure buffer is properly formed after backspaces
66
+ @tty.send_newline
67
+ row += 1
68
+ @tty.assert_row(row, 'hello')
69
+ row += 1
70
+
71
+ # midline backspace
72
+ assert_check_new_row(row)
73
+ @tty.send_keys(%(lsssss))
74
+ @tty.assert_cursor_position(START_COL + 6, row)
75
+ @tty.send_keys(TTYtest::LEFT_ARROW)
76
+ @tty.send_keys(TTYtest::LEFT_ARROW)
77
+ @tty.assert_cursor_position(START_COL + 4, row)
78
+ @tty.send_backspace
79
+ @tty.send_backspace
80
+ @tty.send_backspace
81
+ @tty.send_backspace
82
+ @tty.assert_cursor_position(START_COL, row)
83
+ @tty.assert_row_ends_with(row, '$ ss')
84
+ @tty.send_keys(TTYtest::RIGHT_ARROW)
85
+ @tty.send_keys(TTYtest::RIGHT_ARROW)
86
+ @tty.assert_cursor_position(START_COL + 2, row)
87
+ @tty.send_backspace
88
+ @tty.send_backspace
89
+ @tty.assert_cursor_position(START_COL, row)
90
+ @tty.send_keys(%(echo hello)) # make sure buffer is properly formed after backspaces
91
+ @tty.send_newline
92
+ row += 1
93
+ @tty.assert_row(row, 'hello')
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'ttytest'
5
+
6
+ START_COL = 19
7
+
8
+ def assert_check_new_row(row)
9
+ @tty.assert_row_starts_with(row, "#{ENV['USER']}:")
10
+ @tty.assert_row_like(row, 'ncsh')
11
+ @tty.assert_row_ends_with(row, '$')
12
+ @tty.assert_cursor_position(START_COL, row)
13
+ end
14
+
15
+ @tty = TTYtest.new_terminal(%(PS1='$ ' ./bin/ncsh), width: 80, height: 24)
16
+
17
+ row = 0
18
+
19
+ # # # # Basic Tests # # # #
20
+ puts 'Starting basic tests'
21
+
22
+ @tty.assert_row_starts_with(row, 'ncsh: startup time: ')
23
+ row += 1
24
+
25
+ assert_check_new_row(row)
26
+ @tty.send_keys_one_at_a_time(%(ls))
27
+ @tty.assert_cursor_position(START_COL + 2, 1)
28
+ @tty.send_newline
29
+ @tty.assert_row_ends_with(row, 'ls')
30
+ row += 1
31
+ @tty.assert_row_starts_with(row, 'LICENSE')
32
+ row = 9
33
+
34
+ assert_check_new_row(row)
35
+ @tty.send_keys_one_at_a_time(%(echo hello))
36
+ @tty.send_newline
37
+ row += 1
38
+ @tty.assert_row(row, 'hello')
39
+ row += 1
40
+
41
+ assert_check_new_row(row)
42
+ @tty.send_keys_one_at_a_time(%(lss)) # send a bad command
43
+ @tty.send_newline
44
+ row += 1
45
+ @tty.assert_row(row, 'ncsh: Could not find command or directory: No such file or directory')
46
+ row += 1
47
+
48
+ puts 'Starting backspace tests'
49
+
50
+ # end of line backspace
51
+ assert_check_new_row(row)
52
+ @tty.send_keys_one_at_a_time(%(l))
53
+ @tty.send_backspace
54
+ assert_check_new_row(row)
55
+
56
+ # multiple end of line backspaces
57
+ @tty.send_keys_one_at_a_time(%(lsssss))
58
+ @tty.send_backspace
59
+ @tty.send_backspace
60
+ @tty.send_backspace
61
+ @tty.send_backspace
62
+ @tty.assert_row_ends_with(row, '$ ls')
63
+ @tty.send_backspace
64
+ @tty.send_backspace
65
+ @tty.send_keys_one_at_a_time(%(echo hello)) # make sure buffer is properly formed after backspaces
66
+ @tty.send_newline
67
+ row += 1
68
+ @tty.assert_row(row, 'hello')
69
+ row += 1
70
+
71
+ # midline backspace
72
+ assert_check_new_row(row)
73
+ @tty.send_keys_one_at_a_time(%(lsssss))
74
+ @tty.assert_cursor_position(START_COL + 6, row)
75
+ @tty.send_keys(TTYtest::LEFT_ARROW)
76
+ @tty.send_keys(TTYtest::LEFT_ARROW)
77
+ @tty.assert_cursor_position(START_COL + 4, row)
78
+ @tty.send_backspace
79
+ @tty.send_backspace
80
+ @tty.send_backspace
81
+ @tty.send_backspace
82
+ @tty.assert_cursor_position(START_COL, row)
83
+ @tty.assert_row_ends_with(row, '$ ss')
84
+ @tty.send_keys(TTYtest::RIGHT_ARROW)
85
+ @tty.send_keys(TTYtest::RIGHT_ARROW)
86
+ @tty.assert_cursor_position(START_COL + 2, row)
87
+ @tty.send_backspace
88
+ @tty.send_backspace
89
+ @tty.assert_cursor_position(START_COL, row)
90
+ @tty.send_keys_one_at_a_time(%(echo hello)) # make sure buffer is properly formed after backspaces
91
+ @tty.send_newline
92
+ row += 1
93
+ @tty.assert_row(row, 'hello')
@@ -3,7 +3,6 @@
3
3
  # some constants that can be used with send_keys, just to help out people creating tests
4
4
  module TTYtest
5
5
  BACKSPACE = 127.chr
6
- DELETE = '^[[3~'
7
6
  TAB = 9.chr
8
7
  CTRLF = 6.chr
9
8
  CTRLC = 3.chr
@@ -3,10 +3,10 @@
3
3
  module TTYtest
4
4
  # Assertions for ttytest2.
5
5
  module Matchers
6
- # Asserts the contents of a single row
6
+ # Asserts the contents of a single row match the value expected
7
7
  # @param [Integer] row_number the row (starting from 0) to test against
8
8
  # @param [String] expected the expected value of the row. Any trailing whitespace is ignored
9
- # @raise [MatchError] if the row doesn't match
9
+ # @raise [MatchError] if the row doesn't match exactly
10
10
  def assert_row(row_number, expected)
11
11
  expected = expected.rstrip
12
12
  actual = row(row_number)
@@ -16,7 +16,25 @@ module TTYtest
16
16
  "expected row #{row_number} to be #{expected.inspect} but got #{actual.inspect}\nEntire screen:\n#{self}"
17
17
  end
18
18
 
19
- # Asserts the contents of a single row contains expected
19
+ # Asserts the contents of a single row contains the expected string at a specific position
20
+ # @param [Integer] row_number the row (starting from 0) to test against
21
+ # @param [Integer] column_start the column position to start comparing expected against
22
+ # @param [Integer] columns_end the column position to end comparing expected against
23
+ # @param [String] expected the expected value that the row starts with. Any trailing whitespace is ignored
24
+ # @raise [MatchError] if the row doesn't match
25
+ def assert_row_at(row_number, column_start, column_end, expected)
26
+ expected = expected.rstrip
27
+ actual = row(row_number)
28
+ column_end += 1 if column_end.positive?
29
+ return if actual[column_start, column_end].eql?(expected)
30
+
31
+ raise MatchError,
32
+ "expected row #{row_number} to contain #{expected[column_start,
33
+ column_end]} at #{column_start}-#{column_end} and got #{actual[column_start,
34
+ column_end]}\nEntire screen:\n#{self}"
35
+ end
36
+
37
+ # Asserts the contents of a single row contains the value expected
20
38
  # @param [Integer] row_number the row (starting from 0) to test against
21
39
  # @param [String] expected the expected value contained in the row. Any trailing whitespace is ignored
22
40
  # @raise [MatchError] if the row doesn't match
@@ -29,7 +47,7 @@ module TTYtest
29
47
  "expected row #{row_number} to be like #{expected.inspect} but got #{actual.inspect}\nEntire screen:\n#{self}"
30
48
  end
31
49
 
32
- # Asserts the contents of a single row start with expected
50
+ # Asserts the contents of a single row starts with expected string
33
51
  # @param [Integer] row_number the row (starting from 0) to test against
34
52
  # @param [String] expected the expected value that the row starts with. Any trailing whitespace is ignored
35
53
  # @raise [MatchError] if the row doesn't match
@@ -21,13 +21,27 @@ module TTYtest
21
21
  # @!method send_keys(*keys)
22
22
  # Simulate typing keys into the terminal. For canonical cli's/shells which read line by line.
23
23
  # @param [String] keys keys to send to the terminal
24
- # @!method send_keys_one_at_a_time(*keys)
24
+ # @!method send_keys_one_at_a_time(keys)
25
25
  # Simulate typing keys into the terminal. For noncanonical cli's/shells which read character by character.
26
26
  # @param [String] keys keys to send to the terminal
27
+ # @!method send_newline
28
+ # Simulate typing enter by sending newline character to the terminal.
29
+ # @!method send_delete
30
+ # Simulate typing the delete key in the terminal.
31
+ # @!method send_backspace
32
+ # Simulate typing the backspace key in the terminal.
33
+ # @!method send_keys_exact
34
+ # Send tmux send-keys command to the terminal, such as DC or Enter, to simulate pressing that key in the terminal.
27
35
  # @!method capture
28
36
  # Capture the current state of the terminal
29
37
  # @return [Capture] instantaneous state of the terminal when called
30
- def_delegators :@driver_terminal, :send_keys, :send_keys_one_at_a_time, :send_newline, :capture
38
+ def_delegators :@driver_terminal,
39
+ :send_keys, :send_keys_one_at_a_time,
40
+ :send_newline, :send_newlines,
41
+ :send_delete, :send_deletes,
42
+ :send_backspace, :send_backspaces,
43
+ :send_keys_exact,
44
+ :capture
31
45
 
32
46
  # @!method rows
33
47
  # @return [Array<String>]
@@ -38,10 +38,15 @@ module TTYtest
38
38
  )
39
39
  end
40
40
 
41
+ # Send the array of keys as a string literal to tmux.
42
+ # Will not be interpreted as send-keys values like Enter, Escape, DC for Delete, etc.
43
+ # @param [%w()] keys the keys to send to tmux
41
44
  def send_keys(*keys)
42
45
  driver.tmux(*%W[send-keys -t #{name} -l], *keys)
43
46
  end
44
47
 
48
+ # Send a string of keys one character at a time as literals to tmux.
49
+ # @param [String] keys the keys to send one at a time to tmux
45
50
  def send_keys_one_at_a_time(keys)
46
51
  keys.split('').each do |key|
47
52
  driver.tmux(*%W[send-keys -t #{name} -l], key)
@@ -52,6 +57,43 @@ module TTYtest
52
57
  driver.tmux(*%W[send-keys -t #{name} -l], %(\n))
53
58
  end
54
59
 
60
+ def send_newlines(number_of_times)
61
+ while number_of_times.positive?
62
+ send_newline
63
+ number_of_times -= 1
64
+ end
65
+ end
66
+
67
+ def send_delete
68
+ send_keys_exact(%(DC))
69
+ end
70
+
71
+ def send_deletes(number_of_times)
72
+ while number_of_times.positive?
73
+ send_delete
74
+ number_of_times -= 1
75
+ end
76
+ end
77
+
78
+ def send_backspace
79
+ send_keys_exact(%(BSpace))
80
+ end
81
+
82
+ def send_backspaces(number_of_times)
83
+ while number_of_times.positive?
84
+ send_backspace
85
+ number_of_times -= 1
86
+ end
87
+ end
88
+
89
+ # Useful to send send-keys commands to tmux without sending them as a string literal.
90
+ # So you can send Escape for escape key, DC for delete, etc.
91
+ # Uses the same key bindings as bind-key as well. C-c represents Ctrl + C keys, F1 is F1 key, etc.
92
+ # @param [String] keys the keys to send to tmux
93
+ def send_keys_exact(keys)
94
+ driver.tmux(*%W[send-keys -t #{name}], keys)
95
+ end
96
+
55
97
  private
56
98
 
57
99
  attr_reader :driver, :name
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTYtest
4
- VERSION = '0.8.6'
4
+ VERSION = '0.9.1'
5
5
  end
data/notes.txt CHANGED
@@ -1,7 +1,7 @@
1
- to push new version to github,
2
- git tag v0.8.6
1
+ to push new version to github
2
+ git tag v0.9.1
3
3
  git push origin --tags
4
4
 
5
5
  to push new version to rubygems.org
6
6
  gem build ttytest2.gemspec
7
- gem push ttytest2-0.8.6.gem
7
+ gem push ttytest2-0.9.1.gem
data/ttytest2.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.email = ['alexeski@gmail.com']
12
12
 
13
13
  spec.summary = 'ttytest2 is an integration test framework for interactive tty applications. Based on TTYtest!'
14
- spec.description = 'ttytest2 allows running shell and/or cli applications inside of tmux and then making assertions on the output.'
14
+ spec.description = 'ttytest2 allows running shell/cli applications inside of tmux and then making assertions on the output.'
15
15
  spec.homepage = 'https://github.com/a-eski/ttytest2'
16
16
  spec.license = 'MIT'
17
17
 
@@ -24,8 +24,8 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.required_ruby_version = '>= 3.2.3'
26
26
 
27
- spec.add_development_dependency 'bundler'
27
+ spec.add_development_dependency 'bundler', '~> 2.5'
28
28
  spec.add_development_dependency 'minitest', '~> 5.0'
29
29
  spec.add_development_dependency 'rake', '~> 13.0'
30
- spec.add_development_dependency 'yard'
30
+ spec.add_development_dependency 'yard', '~> 0.9'
31
31
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ttytest2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.6
4
+ version: 0.9.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: 2024-11-15 00:00:00.000000000 Z
11
+ date: 2024-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '2.5'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '2.5'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -56,18 +56,18 @@ dependencies:
56
56
  name: yard
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '0.9'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
69
- description: ttytest2 allows running shell and/or cli applications inside of tmux
70
- and then making assertions on the output.
68
+ version: '0.9'
69
+ description: ttytest2 allows running shell/cli applications inside of tmux and then
70
+ making assertions on the output.
71
71
  email:
72
72
  - alexeski@gmail.com
73
73
  executables: []
@@ -79,6 +79,8 @@ files:
79
79
  - Gemfile
80
80
  - README.md
81
81
  - Rakefile
82
+ - examples/canonical_integration_tests.rb
83
+ - examples/noncanonical_integration_tests.rb
82
84
  - lib/ttytest.rb
83
85
  - lib/ttytest/capture.rb
84
86
  - lib/ttytest/constants.rb