ttytest2 1.1.0 → 1.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47258d8644be543f645de9e34a17eca3a0e38c5fb764e4e72f4d78a63a888388
4
- data.tar.gz: 4aa9221ee6fc4f5e8fda754b2cd3b9c8218d7b8cf1e7e8b67dfe2a36dd9360b8
3
+ metadata.gz: ba5f1abfa44480c3955c2c0ff48e724ea09f060aa90417caa72cdcf2b15a29bc
4
+ data.tar.gz: 904200415a856ad8e9b077ea30f5bc9dea085f966ec896e5e19d328b39039000
5
5
  SHA512:
6
- metadata.gz: f20f297c6b30fb549ade96a5a2644f11e9ad846f0e8950f5e119bcfc83a63228dcbe51b75e635fdcfeb0bd47b17122bf568e574305406582cf4a0e9978356137
7
- data.tar.gz: 0ee8c938c0b66151ba208c1769bfd5ac65277d1c62dbc3ede3976926dfef964870a7119b6003601c4f2fb0c7a90cc2d6736e8cffc9df86de81d7f6efc5c2877a
6
+ metadata.gz: 8d117e8a03132b3a0dd0c93bc0c8a864ffce023d286c98e495a7b8ddafccbdff49d7f2db49c864ceae9f88fd4529322294ec7c7b2e925806e7af721d94ba12e0
7
+ data.tar.gz: 1809000f0fea428a053449c07b7b94ca93028dfe3c91d815f0d903bb052c48736f542edb2493cd4fde39bed3c0fa495adca1bd14afccbe186c4cdf9735f54cf5
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # ttytest2
2
2
 
3
+ <a href="https://rubygems.org/gems/ttytest2">
4
+ <img src="images/ttytest2.png" alt="ttytest2 logo" style="width:70%; height:auto;">
5
+ </a>
6
+
3
7
  ttytest2 is a user acceptance test framework for CLI & shell applications.
4
8
 
5
9
  ttytest2 is a fork and a drop-in replacement for [ttytest](https://github.com/jhawthorn/ttytest).
@@ -31,6 +35,7 @@ The assertions will wait a specified amount of time (configurable, default 2 sec
31
35
 
32
36
  ## Usage
33
37
 
38
+ * Download the [gem](https://rubygems.org/gems/ttytest2) here.
34
39
  * More documentation available at [ttytest2 docs](https://www.rubydoc.info/gems/ttytest2).
35
40
  * There are more examples in the examples folder.
36
41
 
Binary file
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TTYtest
4
+ # Column Assertions for ttytest2.
5
+ module ColumnAssertions
6
+ # Asserts the contents of a single column match the value expected
7
+ # @param [Integer] col_number the column (starting from 0) to test against
8
+ # @param [String] expected the expected value of the column. Any trailing whitespace is ignored
9
+ # @raise [MatchError] if the column doesn't match exactly
10
+ def assert_column(col_number, expected)
11
+ validate(col_number)
12
+ expected = expected.rstrip
13
+
14
+ rows.each_with_index do |row, i|
15
+ break if row.nil?
16
+
17
+ next if row[col_number] == expected[i]
18
+
19
+ raise MatchError,
20
+ "expected column #{col_number} to be #{expected.inspect}\n
21
+ Entire screen:\n#{self}"
22
+ end
23
+ end
24
+
25
+ # Asserts the specified column is empty
26
+ # @param [Integer] col_number the column (starting from 0) to test against
27
+ # @raise [MatchError] if the column isn't empty
28
+ def assert_column_is_empty(col_number)
29
+ validate(col_number)
30
+
31
+ rows.each do |row|
32
+ break if row.nil?
33
+
34
+ next if row == '' || row.length < col_number + 1 || row[col_number] == ' '
35
+
36
+ raise MatchError,
37
+ "expected column #{col_number} to be empty\nEntire screen:\n#{self}"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TTYtest
4
+ # Cursor Assertions for ttytest2.
5
+ module CursorAssertions
6
+ # Asserts that the cursor is in the expected position
7
+ # @param [Integer] x cursor x (row) position, starting from 0
8
+ # @param [Integer] y cursor y (column) position, starting from 0
9
+ # @raise [MatchError] if the cursor position doesn't match
10
+ def assert_cursor_position(x, y)
11
+ expected = [x, y]
12
+ actual = [cursor_x, cursor_y]
13
+
14
+ return if actual == expected
15
+
16
+ raise MatchError,
17
+ "expected cursor to be at #{expected.inspect} but was at #{get_inspection(actual)}\nEntire screen:\n#{self}"
18
+ end
19
+
20
+ # Asserts the cursor is currently visible
21
+ # @raise [MatchError] if the cursor is hidden
22
+ def assert_cursor_visible
23
+ return if cursor_visible?
24
+
25
+ raise MatchError, "expected cursor to be visible was hidden\nEntire screen:\n#{self}"
26
+ end
27
+
28
+ # Asserts the cursor is currently hidden
29
+ # @raise [MatchError] if the cursor is visible
30
+ def assert_cursor_hidden
31
+ return if cursor_hidden?
32
+
33
+ raise MatchError, "expected cursor to be hidden was visible\nEntire screen:\n#{self}"
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TTYtest
4
+ # File Assertions for ttytest2.
5
+ module FileAssertions
6
+ # Asserts the specified file exists
7
+ # @param [String] file_path the path to the file
8
+ # @raise [MatchError] if the file is not found or is a directory/symlink
9
+ def assert_file_exists(file_path)
10
+ raise file_not_found_error(file_path) unless File.exist?(file_path)
11
+ raise file_is_dir_error(file_path) unless File.file?(file_path)
12
+ end
13
+
14
+ # Asserts the specified file does not exists
15
+ # @param [String] file_path the path to the file
16
+ # @raise [MatchError] if the file is found or is a directory/symlink
17
+ def assert_file_doesnt_exist(file_path)
18
+ return unless File.exist?(file_path) || File.file?(file_path)
19
+
20
+ raise MatchError,
21
+ "File with path #{file_path} was found or is a directory when it was asserted it did not exist.\nEntire screen:\n#{self}"
22
+ end
23
+
24
+ # Asserts the specified file contains the passed in string value
25
+ # @param [String] file_path the path to the file
26
+ # @param [String] needle the value to search for in the file
27
+ # @raise [MatchError] if the file does not contain value in variable needle
28
+ def assert_file_contains(file_path, needle)
29
+ raise file_not_found_error(file_path) unless File.exist?(file_path)
30
+ raise file_is_dir_error(file_path) unless File.file?(file_path)
31
+
32
+ file_contains = false
33
+ File.foreach(file_path) do |line|
34
+ if line.include?(needle)
35
+ file_contains = true
36
+ break
37
+ end
38
+ end
39
+ return if file_contains
40
+
41
+ raise MatchError,
42
+ "File with path #{file_path} did not contain #{needle}.\nEntire screen:\n#{self}"
43
+ end
44
+ alias assert_file_like assert_file_contains
45
+
46
+ # Asserts the specified file has the permissions specified
47
+ # @param [String] file_path the path to the file
48
+ # @param [String] permissions the expected permissions of the file (in form '644' or '775')
49
+ # @raise [MatchError] if the file has different permissions than specified
50
+ def assert_file_has_permissions(file_path, permissions)
51
+ raise file_not_found_error(file_path) unless File.exist?(file_path)
52
+ raise file_is_dir_error(file_path) unless File.file?(file_path)
53
+
54
+ file_mode = File.stat(file_path).mode
55
+ perms_octal = format('%o', file_mode)[-3...]
56
+ return if perms_octal == permissions
57
+
58
+ raise MatchError,
59
+ "File had permissions #{perms_octal}, not #{permissions} as expected.\n Entire screen:\n#{self}"
60
+ end
61
+
62
+ # Asserts the specified file has line count specified
63
+ # @param [String] file_path the path to the file
64
+ # @param [String] expected_count the expected line count of the file
65
+ # @raise [MatchError] if the file has a different line count than specified
66
+ def assert_file_has_line_count(file_path, expected_count)
67
+ raise file_not_found_error(file_path) unless File.exist?(file_path)
68
+ raise file_is_dir_error(file_path) unless File.file?(file_path)
69
+
70
+ actual_count = File.foreach(file_path).count
71
+ return if actual_count == expected_count
72
+
73
+ raise MatchError,
74
+ "File had #{actual_count} lines, not #{expected_count} lines as expected.\nEntire screen:\n#{self}"
75
+ end
76
+
77
+ private
78
+
79
+ def file_not_found_error(file_path)
80
+ raise MatchError,
81
+ "File with path #{file_path} was not found when asserted it did exist.\nEntire screen:\n#{self}"
82
+ end
83
+
84
+ def file_is_dir_error(file_path)
85
+ raise MatchError,
86
+ "File with path #{file_path} is a directory.\nEntire screen:\n#{self}"
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TTYtest
4
+ # Row Assertions for ttytest2.
5
+ module RowAssertions
6
+ # Asserts the contents of a single row match the value expected
7
+ # @param [Integer] row_number the row (starting from 0) to test against
8
+ # @param [String] expected the expected value of the row. Any trailing whitespace is ignored
9
+ # @raise [MatchError] if the row doesn't match exactly
10
+ def assert_row(row_number, expected)
11
+ validate(row_number)
12
+ expected = expected.rstrip
13
+ actual = row(row_number)
14
+
15
+ return if !actual.nil? && actual == expected
16
+
17
+ raise MatchError,
18
+ "expected row #{row_number} to be #{expected.inspect} but got #{get_inspection(actual)}\n
19
+ Entire screen:\n#{self}"
20
+ end
21
+ alias assert_line assert_row
22
+
23
+ # Asserts the specified row is empty
24
+ # @param [Integer] row_number the row (starting from 0) to test against
25
+ # @raise [MatchError] if the row isn't empty
26
+ def assert_row_is_empty(row_number)
27
+ validate(row_number)
28
+ actual = row(row_number)
29
+
30
+ return if actual == ''
31
+
32
+ raise MatchError,
33
+ "expected row #{row_number} to be empty but got #{get_inspection(actual)}\nEntire screen:\n#{self}"
34
+ end
35
+ alias assert_line_is_empty assert_row_is_empty
36
+
37
+ # Asserts the contents of a single row contains the expected string at a specific position
38
+ # @param [Integer] row_number the row (starting from 0) to test against
39
+ # @param [Integer] column_start the column position to start comparing expected against
40
+ # @param [Integer] columns_end the column position to end comparing expected against
41
+ # @param [String] expected the expected value that the row starts with. Any trailing whitespace is ignored
42
+ # @raise [MatchError] if the row doesn't match
43
+ def assert_row_at(row_number, column_start, column_end, expected)
44
+ validate(row_number)
45
+ expected = expected.rstrip
46
+ actual = row(row_number)
47
+ column_end += 1
48
+
49
+ return if !actual.nil? && actual[column_start, column_end].eql?(expected)
50
+
51
+ inspection = get_inspection_bounded(actual, column_start, column_end)
52
+
53
+ raise MatchError,
54
+ "expected row #{row_number} to contain #{expected[column_start,
55
+ column_end]} at #{column_start}-#{column_end} and got #{inspection}\nEntire screen:\n#{self}"
56
+ end
57
+ alias assert_line_at assert_row_at
58
+
59
+ # Asserts the contents of a single row contains the value expected
60
+ # @param [Integer] row_number the row (starting from 0) to test against
61
+ # @param [String] expected the expected value contained in the row. Any trailing whitespace is ignored
62
+ # @raise [MatchError] if the row doesn't match
63
+ def assert_row_like(row_number, expected)
64
+ validate(row_number)
65
+ expected = expected.rstrip
66
+ actual = row(row_number)
67
+
68
+ return if !actual.nil? && actual.include?(expected)
69
+
70
+ raise MatchError,
71
+ "expected row #{row_number} to be like #{expected.inspect} but got #{get_inspection(actual)}\nEntire screen:\n#{self}"
72
+ end
73
+ alias assert_row_contains assert_row_like
74
+ alias assert_line_contains assert_row_like
75
+ alias assert_line_like assert_row_like
76
+
77
+ # Asserts the contents of a single row starts with expected string
78
+ # @param [Integer] row_number the row (starting from 0) to test against
79
+ # @param [String] expected the expected value that the row starts with. Any trailing whitespace is ignored
80
+ # @raise [MatchError] if the row doesn't match
81
+ def assert_row_starts_with(row_number, expected)
82
+ validate(row_number)
83
+ expected = expected.rstrip
84
+ actual = row(row_number)
85
+
86
+ return if !actual.nil? && actual.start_with?(expected)
87
+
88
+ raise MatchError,
89
+ "expected row #{row_number} to start with #{expected.inspect} and got #{get_inspection(actual)}\nEntire screen:\n#{self}"
90
+ end
91
+ alias assert_line_starts_with assert_row_starts_with
92
+
93
+ # Asserts the contents of a single row end with expected
94
+ # @param [Integer] row_number the row (starting from 0) to test against
95
+ # @param [String] expected the expected value that the row starts with. Any trailing whitespace is ignored
96
+ # @raise [MatchError] if the row doesn't match
97
+ def assert_row_ends_with(row_number, expected)
98
+ validate(row_number)
99
+ expected = expected.rstrip
100
+ actual = row(row_number)
101
+
102
+ return if !actual.nil? && actual.end_with?(expected)
103
+
104
+ raise MatchError,
105
+ "expected row #{row_number} to end with #{expected.inspect} and got #{get_inspection(actual)}\nEntire screen:\n#{self}"
106
+ end
107
+ alias assert_line_ends_with assert_row_ends_with
108
+
109
+ # Asserts the contents of a single row match against the passed in regular expression
110
+ # @param [Integer] row_number the row (starting from 0) to test against
111
+ # @param [String] regexp_str the regular expression as a string that will be used to match with.
112
+ # @raise [MatchError] if the row doesn't match against the regular expression
113
+ def assert_row_regexp(row_number, regexp_str)
114
+ validate(row_number)
115
+ regexp = Regexp.new(regexp_str)
116
+ actual = row(row_number)
117
+
118
+ return if !actual.nil? && actual.match?(regexp)
119
+
120
+ raise MatchError,
121
+ "expected row #{row_number} to match regexp #{regexp_str} but it did not. Row value #{get_inspection(actual)}\nEntire screen:\n#{self}"
122
+ end
123
+ alias assert_line_regexp assert_row_regexp
124
+
125
+ # Asserts the contents of a multiple rows each match against the passed in regular expression
126
+ # @param [Integer] row_start the row (starting from 0) to test against
127
+ # @param [Integer] row_end the last row to test against
128
+ # @param [String] regexp_str the regular expression as a string that will be used to match with.
129
+ # @raise [MatchError] if the row doesn't match against the regular expression
130
+ def assert_rows_each_match_regexp(row_start, row_end, regexp_str)
131
+ validate(row_end)
132
+ regexp = Regexp.new(regexp_str)
133
+ row_end += 1 if row_end.zero?
134
+
135
+ rows.slice(row_start, row_end).each_with_index do |actual_row, index|
136
+ next if !actual_row.nil? && actual_row.match?(regexp)
137
+
138
+ raise MatchError,
139
+ "expected row #{index} to match regexp #{regexp_str} but it did not. Row value #{get_inspection(actual_row)}\nEntire screen:\n#{self}"
140
+ end
141
+ end
142
+ alias assert_lines_each_match_regexp assert_rows_each_match_regexp
143
+ end
144
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TTYtest
4
+ # Screen Assertions for ttytest2.
5
+ module ScreenAssertions
6
+ # Asserts the full contents of the terminal
7
+ # @param [String] expected the full expected contents of the terminal. Trailing whitespace on each line is ignored
8
+ # @raise [MatchError] if the terminal doesn't match the expected content
9
+ def assert_contents(expected)
10
+ matched, diff = get_diff(expected, rows)
11
+
12
+ return if matched
13
+
14
+ raise MatchError,
15
+ "screen did not match expected content:\n--- expected\n+++ actual\n#{diff.join("\n")}"
16
+ end
17
+ alias assert_matches assert_contents
18
+ alias assert_screen assert_contents
19
+
20
+ # Asserts the contents of the terminal at specified rows
21
+ # @param [String] expected the expected contents of the terminal at specified rows. Trailing whitespace on each line is ignored
22
+ # @raise [MatchError] if the terminal doesn't match the expected content
23
+ def assert_contents_at(row_start, row_end, expected)
24
+ validate(row_end)
25
+ row_end += 1 if row_end.zero?
26
+
27
+ matched, diff = get_diff(expected, rows.slice(row_start, row_end))
28
+
29
+ return if matched
30
+
31
+ raise MatchError,
32
+ "screen did not match expected content:\n--- expected\n+++ actual\n#{diff.join("\n")}"
33
+ end
34
+ alias assert_matches_at assert_contents_at
35
+ alias assert_rows assert_contents_at
36
+
37
+ # Asserts the contents of the screen include the passed in string
38
+ # @param [String] expected the string value expected to be found in the screen contents
39
+ # @raise [MatchError] if the screen does not contain the expected value
40
+ def assert_contents_include(expected)
41
+ found = false
42
+ rows.each do |row|
43
+ found = true if row.include?(expected)
44
+ end
45
+ return if found
46
+
47
+ raise MatchError,
48
+ "Expected screen contents to include #{expected}, but it was not found.\nEntire screen:\n#{self}"
49
+ end
50
+ alias assert_screen_includes assert_contents_include
51
+
52
+ # Asserts the contents of the screen are empty
53
+ # @raise [MatchError] if the screen is not empty
54
+ def assert_contents_empty
55
+ return if rows.all? { |s| s.to_s.empty? }
56
+
57
+ raise MatchError,
58
+ "Expected screen to be empty, but found content.\nEntire screen:\n#{self}"
59
+ end
60
+ alias assert_screen_empty assert_contents_empty
61
+
62
+ # Asserts the contents of the screen as a single string match the passed in regular expression
63
+ # @param [String] regexp_str the regular expression as a string that will be used to match with
64
+ # @raise [MatchError] if the screen as a string doesn't match against the regular expression
65
+ def assert_contents_match_regexp(regexp_str)
66
+ regexp = Regexp.new(regexp_str)
67
+ screen = capture.to_s
68
+
69
+ return if !screen.nil? && screen.match?(regexp)
70
+
71
+ raise MatchError,
72
+ "Expected screen contents to match regexp #{regexp_str} but they did not\nEntire screen:\n#{self}"
73
+ end
74
+ alias assert_screen_matches_regexp assert_contents_match_regexp
75
+ end
76
+ end
@@ -1,316 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'ttytest/assertions/file_assertions'
4
+ require 'ttytest/assertions/row_assertions'
5
+ require 'ttytest/assertions/column_assertions'
6
+ require 'ttytest/assertions/screen_assertions'
7
+ require 'ttytest/assertions/cursor_assertions'
8
+
3
9
  module TTYtest
4
10
  # Assertions for ttytest2.
5
11
  module Assertions
6
- # Asserts the contents of a single row match the value expected
7
- # @param [Integer] row_number the row (starting from 0) to test against
8
- # @param [String] expected the expected value of the row. Any trailing whitespace is ignored
9
- # @raise [MatchError] if the row doesn't match exactly
10
- def assert_row(row_number, expected)
11
- validate(row_number)
12
- expected = expected.rstrip
13
- actual = row(row_number)
14
-
15
- return if !actual.nil? && actual == expected
16
-
17
- raise MatchError,
18
- "expected row #{row_number} to be #{expected.inspect} but got #{get_inspection(actual)}\n
19
- Entire screen:\n#{self}"
20
- end
21
- alias assert_line assert_row
22
-
23
- # Asserts the specified row is empty
24
- # @param [Integer] row_number the row (starting from 0) to test against
25
- # @raise [MatchError] if the row isn't empty
26
- def assert_row_is_empty(row_number)
27
- validate(row_number)
28
- actual = row(row_number)
29
-
30
- return if actual == ''
31
-
32
- raise MatchError,
33
- "expected row #{row_number} to be empty but got #{get_inspection(actual)}\nEntire screen:\n#{self}"
34
- end
35
- alias assert_line_is_empty assert_row_is_empty
36
-
37
- # Asserts the contents of a single row contains the expected string at a specific position
38
- # @param [Integer] row_number the row (starting from 0) to test against
39
- # @param [Integer] column_start the column position to start comparing expected against
40
- # @param [Integer] columns_end the column position to end comparing expected against
41
- # @param [String] expected the expected value that the row starts with. Any trailing whitespace is ignored
42
- # @raise [MatchError] if the row doesn't match
43
- def assert_row_at(row_number, column_start, column_end, expected)
44
- validate(row_number)
45
- expected = expected.rstrip
46
- actual = row(row_number)
47
- column_end += 1
48
-
49
- return if !actual.nil? && actual[column_start, column_end].eql?(expected)
50
-
51
- inspection = get_inspection_bounded(actual, column_start, column_end)
52
-
53
- raise MatchError,
54
- "expected row #{row_number} to contain #{expected[column_start,
55
- column_end]} at #{column_start}-#{column_end} and got #{inspection}\nEntire screen:\n#{self}"
56
- end
57
- alias assert_line_at assert_row_at
58
-
59
- # Asserts the contents of a single row contains the value expected
60
- # @param [Integer] row_number the row (starting from 0) to test against
61
- # @param [String] expected the expected value contained in the row. Any trailing whitespace is ignored
62
- # @raise [MatchError] if the row doesn't match
63
- def assert_row_like(row_number, expected)
64
- validate(row_number)
65
- expected = expected.rstrip
66
- actual = row(row_number)
67
-
68
- return if !actual.nil? && actual.include?(expected)
69
-
70
- raise MatchError,
71
- "expected row #{row_number} to be like #{expected.inspect} but got #{get_inspection(actual)}\nEntire screen:\n#{self}"
72
- end
73
- alias assert_row_contains assert_row_like
74
- alias assert_line_contains assert_row_like
75
- alias assert_line_like assert_row_like
76
-
77
- # Asserts the contents of a single row starts with expected string
78
- # @param [Integer] row_number the row (starting from 0) to test against
79
- # @param [String] expected the expected value that the row starts with. Any trailing whitespace is ignored
80
- # @raise [MatchError] if the row doesn't match
81
- def assert_row_starts_with(row_number, expected)
82
- validate(row_number)
83
- expected = expected.rstrip
84
- actual = row(row_number)
85
-
86
- return if !actual.nil? && actual.start_with?(expected)
87
-
88
- raise MatchError,
89
- "expected row #{row_number} to start with #{expected.inspect} and got #{get_inspection(actual)}\nEntire screen:\n#{self}"
90
- end
91
- alias assert_line_starts_with assert_row_starts_with
92
-
93
- # Asserts the contents of a single row end with expected
94
- # @param [Integer] row_number the row (starting from 0) to test against
95
- # @param [String] expected the expected value that the row starts with. Any trailing whitespace is ignored
96
- # @raise [MatchError] if the row doesn't match
97
- def assert_row_ends_with(row_number, expected)
98
- validate(row_number)
99
- expected = expected.rstrip
100
- actual = row(row_number)
101
-
102
- return if !actual.nil? && actual.end_with?(expected)
103
-
104
- raise MatchError,
105
- "expected row #{row_number} to end with #{expected.inspect} and got #{get_inspection(actual)}\nEntire screen:\n#{self}"
106
- end
107
- alias assert_line_ends_with assert_row_ends_with
108
-
109
- # Asserts the contents of a single row match against the passed in regular expression
110
- # @param [Integer] row_number the row (starting from 0) to test against
111
- # @param [String] regexp_str the regular expression as a string that will be used to match with.
112
- # @raise [MatchError] if the row doesn't match against the regular expression
113
- def assert_row_regexp(row_number, regexp_str)
114
- validate(row_number)
115
- regexp = Regexp.new(regexp_str)
116
- actual = row(row_number)
117
-
118
- return if !actual.nil? && actual.match?(regexp)
119
-
120
- raise MatchError,
121
- "expected row #{row_number} to match regexp #{regexp_str} but it did not. Row value #{get_inspection(actual)}\nEntire screen:\n#{self}"
122
- end
123
- alias assert_line_regexp assert_row_regexp
124
-
125
- # Asserts the contents of a multiple rows each match against the passed in regular expression
126
- # @param [Integer] row_start the row (starting from 0) to test against
127
- # @param [Integer] row_end the last row to test against
128
- # @param [String] regexp_str the regular expression as a string that will be used to match with.
129
- # @raise [MatchError] if the row doesn't match against the regular expression
130
- def assert_rows_each_match_regexp(row_start, row_end, regexp_str)
131
- validate(row_end)
132
- regexp = Regexp.new(regexp_str)
133
- row_end += 1 if row_end.zero?
134
-
135
- rows.slice(row_start, row_end).each_with_index do |actual_row, index|
136
- next if !actual_row.nil? && actual_row.match?(regexp)
137
-
138
- raise MatchError,
139
- "expected row #{index} to match regexp #{regexp_str} but it did not. Row value #{get_inspection(actual_row)}\nEntire screen:\n#{self}"
140
- end
141
- end
142
- alias assert_lines_each_match_regexp assert_rows_each_match_regexp
143
-
144
- # Asserts that the cursor is in the expected position
145
- # @param [Integer] x cursor x (row) position, starting from 0
146
- # @param [Integer] y cursor y (column) position, starting from 0
147
- # @raise [MatchError] if the cursor position doesn't match
148
- def assert_cursor_position(x, y)
149
- expected = [x, y]
150
- actual = [cursor_x, cursor_y]
151
-
152
- return if actual == expected
153
-
154
- raise MatchError,
155
- "expected cursor to be at #{expected.inspect} but was at #{get_inspection(actual)}\nEntire screen:\n#{self}"
156
- end
157
-
158
- # Asserts the cursor is currently visible
159
- # @raise [MatchError] if the cursor is hidden
160
- def assert_cursor_visible
161
- return if cursor_visible?
162
-
163
- raise MatchError, "expected cursor to be visible was hidden\nEntire screen:\n#{self}"
164
- end
165
-
166
- # Asserts the cursor is currently hidden
167
- # @raise [MatchError] if the cursor is visible
168
- def assert_cursor_hidden
169
- return if cursor_hidden?
170
-
171
- raise MatchError, "expected cursor to be hidden was visible\nEntire screen:\n#{self}"
172
- end
173
-
174
- # Asserts the full contents of the terminal
175
- # @param [String] expected the full expected contents of the terminal. Trailing whitespace on each line is ignored
176
- # @raise [MatchError] if the terminal doesn't match the expected content
177
- def assert_contents(expected)
178
- matched, diff = get_diff(expected, rows)
179
-
180
- return if matched
181
-
182
- raise MatchError,
183
- "screen did not match expected content:\n--- expected\n+++ actual\n#{diff.join("\n")}"
184
- end
185
- alias assert_matches assert_contents
186
- alias assert_screen assert_contents
187
-
188
- # Asserts the contents of the terminal at specified rows
189
- # @param [String] expected the expected contents of the terminal at specified rows. Trailing whitespace on each line is ignored
190
- # @raise [MatchError] if the terminal doesn't match the expected content
191
- def assert_contents_at(row_start, row_end, expected)
192
- validate(row_end)
193
- row_end += 1 if row_end.zero?
194
-
195
- matched, diff = get_diff(expected, rows.slice(row_start, row_end))
196
-
197
- return if matched
198
-
199
- raise MatchError,
200
- "screen did not match expected content:\n--- expected\n+++ actual\n#{diff.join("\n")}"
201
- end
202
- alias assert_matches_at assert_contents_at
203
- alias assert_rows assert_contents_at
204
-
205
- # Asserts the contents of the screen include the passed in string
206
- # @param [String] expected the string value expected to be found in the screen contents
207
- # @raise [MatchError] if the screen does not contain the expected value
208
- def assert_contents_include(expected)
209
- found = false
210
- rows.each do |row|
211
- found = true if row.include?(expected)
212
- end
213
- return if found
214
-
215
- raise MatchError,
216
- "Expected screen contents to include #{expected}, but it was not found.\nEntire screen:\n#{self}"
217
- end
218
- alias assert_screen_includes assert_contents_include
219
-
220
- # Asserts the contents of the screen are empty
221
- # @raise [MatchError] if the screen is not empty
222
- def assert_contents_empty
223
- return if rows.all? { |s| s.to_s.empty? }
224
-
225
- raise MatchError,
226
- "Expected screen to be empty, but found content.\nEntire screen:\n#{self}"
227
- end
228
- alias assert_screen_empty assert_contents_empty
229
-
230
- # Asserts the contents of the screen as a single string match the passed in regular expression
231
- # @param [String] regexp_str the regular expression as a string that will be used to match with
232
- # @raise [MatchError] if the screen as a string doesn't match against the regular expression
233
- def assert_contents_match_regexp(regexp_str)
234
- regexp = Regexp.new(regexp_str)
235
- screen = capture.to_s
236
-
237
- return if !screen.nil? && screen.match?(regexp)
238
-
239
- raise MatchError,
240
- "Expected screen contents to match regexp #{regexp_str} but they did not\nEntire screen:\n#{self}"
241
- end
242
- alias assert_screen_matches_regexp assert_contents_match_regexp
243
-
244
- # Asserts the specified file exists
245
- # @param [String] file_path the path to the file
246
- # @raise [MatchError] if the file is not found or is a directory/symlink
247
- def assert_file_exists(file_path)
248
- raise file_not_found_error(file_path) unless File.exist?(file_path)
249
- raise file_is_dir_error(file_path) unless File.file?(file_path)
250
- end
251
-
252
- # Asserts the specified file does not exists
253
- # @param [String] file_path the path to the file
254
- # @raise [MatchError] if the file is found or is a directory/symlink
255
- def assert_file_doesnt_exist(file_path)
256
- return unless File.exist?(file_path) || File.file?(file_path)
257
-
258
- raise MatchError,
259
- "File with path #{file_path} was found or is a directory when it was asserted it did not exist.\nEntire screen:\n#{self}"
260
- end
261
-
262
- # Asserts the specified file contains the passed in string value
263
- # @param [String] file_path the path to the file
264
- # @param [String] needle the value to search for in the file
265
- # @raise [MatchError] if the file does not contain value in variable needle
266
- def assert_file_contains(file_path, needle)
267
- raise file_not_found_error(file_path) unless File.exist?(file_path)
268
- raise file_is_dir_error(file_path) unless File.file?(file_path)
269
-
270
- file_contains = false
271
- File.foreach(file_path) do |line|
272
- if line.include?(needle)
273
- file_contains = true
274
- break
275
- end
276
- end
277
- return if file_contains
278
-
279
- raise MatchError,
280
- "File with path #{file_path} did not contain #{needle}.\nEntire screen:\n#{self}"
281
- end
282
- alias assert_file_like assert_file_contains
283
-
284
- # Asserts the specified file has the permissions specified
285
- # @param [String] file_path the path to the file
286
- # @param [String] permissions the expected permissions of the file (in form '644' or '775')
287
- # @raise [MatchError] if the file has different permissions than specified
288
- def assert_file_has_permissions(file_path, permissions)
289
- raise file_not_found_error(file_path) unless File.exist?(file_path)
290
- raise file_is_dir_error(file_path) unless File.file?(file_path)
291
-
292
- file_mode = File.stat(file_path).mode
293
- perms_octal = format('%o', file_mode)[-3...]
294
- return if perms_octal == permissions
295
-
296
- raise MatchError,
297
- "File had permissions #{perms_octal}, not #{permissions} as expected.\n Entire screen:\n#{self}"
298
- end
299
-
300
- # Asserts the specified file has line count specified
301
- # @param [String] file_path the path to the file
302
- # @param [String] expected_count the expected line count of the file
303
- # @raise [MatchError] if the file has a different line count than specified
304
- def assert_file_has_line_count(file_path, expected_count)
305
- raise file_not_found_error(file_path) unless File.exist?(file_path)
306
- raise file_is_dir_error(file_path) unless File.file?(file_path)
307
-
308
- actual_count = File.foreach(file_path).count
309
- return if actual_count == expected_count
310
-
311
- raise MatchError,
312
- "File had #{actual_count} lines, not #{expected_count} lines as expected.\nEntire screen:\n#{self}"
313
- end
12
+ include TTYtest::FileAssertions
13
+ include TTYtest::RowAssertions
14
+ include TTYtest::ColumnAssertions
15
+ include TTYtest::ScreenAssertions
16
+ include TTYtest::CursorAssertions
314
17
 
315
18
  METHODS = public_instance_methods
316
19
 
@@ -358,15 +61,5 @@ module TTYtest
358
61
 
359
62
  [matched, diff]
360
63
  end
361
-
362
- def file_not_found_error(file_path)
363
- raise MatchError,
364
- "File with path #{file_path} was not found when asserted it did exist.\nEntire screen:\n#{self}"
365
- end
366
-
367
- def file_is_dir_error(file_path)
368
- raise MatchError,
369
- "File with path #{file_path} is a directory.\nEntire screen:\n#{self}"
370
- end
371
64
  end
372
65
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTYtest
4
- VERSION = '1.1.0'
4
+ VERSION = '1.2.0'
5
5
  end
data/notes.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  to push new version to github
2
- git tag v1.1.0
2
+ git tag v1.2.0
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-1.1.0.gem
7
+ gem push ttytest2-1.2.0.gem
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: 1.1.0
4
+ version: 1.2.0
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-08-06 00:00:00.000000000 Z
11
+ date: 2025-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -95,8 +95,14 @@ files:
95
95
  - README.md
96
96
  - Rakefile
97
97
  - examples/integration_tests.rb
98
+ - images/ttytest2.png
98
99
  - lib/ttytest.rb
99
100
  - lib/ttytest/assertions.rb
101
+ - lib/ttytest/assertions/column_assertions.rb
102
+ - lib/ttytest/assertions/cursor_assertions.rb
103
+ - lib/ttytest/assertions/file_assertions.rb
104
+ - lib/ttytest/assertions/row_assertions.rb
105
+ - lib/ttytest/assertions/screen_assertions.rb
100
106
  - lib/ttytest/capture.rb
101
107
  - lib/ttytest/constants.rb
102
108
  - lib/ttytest/terminal.rb