markdown_exec 2.3.0 → 2.4.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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +11 -2
  3. data/CHANGELOG.md +19 -0
  4. data/Gemfile.lock +1 -1
  5. data/Rakefile +32 -8
  6. data/bats/bats.bats +33 -0
  7. data/bats/block-types.bats +56 -0
  8. data/bats/cli.bats +74 -0
  9. data/bats/fail.bats +11 -0
  10. data/bats/history.bats +34 -0
  11. data/bats/markup.bats +66 -0
  12. data/bats/mde.bats +29 -0
  13. data/bats/options.bats +92 -0
  14. data/bats/test_helper.bash +152 -0
  15. data/bin/tab_completion.sh +44 -20
  16. data/docs/dev/block-type-opts.md +10 -0
  17. data/docs/dev/block-type-port.md +24 -0
  18. data/docs/dev/block-type-vars.md +7 -0
  19. data/docs/dev/pass-through-arguments.md +8 -0
  20. data/docs/dev/specs-import.md +9 -0
  21. data/docs/dev/specs.md +83 -0
  22. data/docs/dev/text-decoration.md +7 -0
  23. data/examples/bash-blocks.md +4 -4
  24. data/examples/block-names.md +2 -2
  25. data/examples/import0.md +23 -0
  26. data/examples/import1.md +13 -0
  27. data/examples/link-blocks-vars.md +3 -3
  28. data/examples/opts-blocks-require.md +6 -6
  29. data/examples/table-markup.md +31 -0
  30. data/examples/text-markup.md +58 -0
  31. data/examples/vars-blocks.md +2 -2
  32. data/examples/wrap.md +87 -9
  33. data/lib/ansi_formatter.rb +12 -6
  34. data/lib/ansi_string.rb +153 -0
  35. data/lib/argument_processor.rb +160 -0
  36. data/lib/cached_nested_file_reader.rb +4 -2
  37. data/lib/ce_get_cost_and_usage.rb +4 -3
  38. data/lib/cli.rb +1 -1
  39. data/lib/colorize.rb +39 -11
  40. data/lib/constants.rb +17 -0
  41. data/lib/directory_searcher.rb +4 -2
  42. data/lib/doh.rb +190 -0
  43. data/lib/env.rb +1 -1
  44. data/lib/exceptions.rb +9 -6
  45. data/lib/fcb.rb +0 -199
  46. data/lib/filter.rb +18 -5
  47. data/lib/find_files.rb +8 -3
  48. data/lib/format_table.rb +406 -0
  49. data/lib/hash_delegator.rb +888 -603
  50. data/lib/hierarchy_string.rb +113 -25
  51. data/lib/input_sequencer.rb +16 -10
  52. data/lib/instance_method_wrapper.rb +2 -1
  53. data/lib/layered_hash.rb +143 -0
  54. data/lib/link_history.rb +22 -8
  55. data/lib/markdown_exec/version.rb +1 -1
  56. data/lib/markdown_exec.rb +413 -165
  57. data/lib/mdoc.rb +27 -34
  58. data/lib/menu.src.yml +825 -710
  59. data/lib/menu.yml +799 -703
  60. data/lib/namer.rb +6 -12
  61. data/lib/object_present.rb +1 -1
  62. data/lib/option_value.rb +7 -3
  63. data/lib/poly.rb +33 -14
  64. data/lib/resize_terminal.rb +60 -52
  65. data/lib/saved_assets.rb +45 -34
  66. data/lib/saved_files_matcher.rb +6 -3
  67. data/lib/streams_out.rb +7 -1
  68. data/lib/table_extractor.rb +166 -0
  69. data/lib/tap.rb +5 -6
  70. data/lib/text_analyzer.rb +144 -8
  71. metadata +26 -3
  72. data/lib/std_out_err_logger.rb +0 -119
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TableExtractor
4
+ # Extract tables from an array of text lines formatted in Markdown style
5
+ # @param [Array<String>] lines The array of text lines
6
+ # @return [Array<Hash>] An array of tables with row count, column count, and start index
7
+ def self.extract_tables(lines)
8
+ tables = []
9
+ inside_table = false
10
+ table_start = nil
11
+ row_count = 0
12
+ column_count = 0
13
+
14
+ separator_regexp = /^[ \t]*\|? *(?::?-+:?) *( *\| *(?::?-+:?) *)+\|? *$/
15
+
16
+ lines.each_with_index do |line, index|
17
+ # Match line separators with at least 2 columns
18
+ if line.strip.match?(separator_regexp)
19
+ if inside_table
20
+ # Add the current table before starting a new one
21
+ tables << {
22
+ rows: row_count,
23
+ columns: column_count,
24
+ start_index: table_start
25
+ }
26
+ end
27
+ # Start a new table
28
+ table_start = index - 1 if table_start.nil?
29
+ column_count = line.split('|').count - 1
30
+ row_count = 2 # Reset to 2 to account for the header and separator rows
31
+ inside_table = true
32
+ elsif inside_table && (line.strip.start_with?('|') || line.include?('|'))
33
+ row_count += 1
34
+ elsif inside_table
35
+ # Add the current table and reset the state
36
+ tables << {
37
+ rows: row_count,
38
+ columns: column_count,
39
+ start_index: table_start
40
+ }
41
+ inside_table = false
42
+ table_start = nil
43
+ row_count = 0
44
+ column_count = 0
45
+ end
46
+ end
47
+
48
+ # Handle case where table ends at the last line
49
+ if inside_table
50
+ tables << {
51
+ rows: row_count,
52
+ columns: column_count,
53
+ start_index: table_start
54
+ }
55
+ end
56
+
57
+ tables
58
+ end
59
+ end
60
+
61
+ return if $PROGRAM_NAME != __FILE__
62
+
63
+ require 'minitest/autorun'
64
+
65
+ class TestTableExtractor < Minitest::Test
66
+ def test_single_table
67
+ lines = [
68
+ '| Species| Genus| Family',
69
+ '|-|-|-',
70
+ '| Pongo tapanuliensis| Pongo| Hominidae',
71
+ '| | Histiophryne| Antennariidae'
72
+ ]
73
+ expected = [{ rows: 4, columns: 3, start_index: 0 }]
74
+ assert_equal expected, TableExtractor.extract_tables(lines)
75
+ end
76
+
77
+ def test_indented_table
78
+ lines = [
79
+ "\t | Species| Genus| Family",
80
+ "\t |-|-|-",
81
+ "\t | Pongo tapanuliensis| Pongo| Hominidae",
82
+ "\t | | Histiophryne| Antennariidae"
83
+ ]
84
+ expected = [{ rows: 4, columns: 3, start_index: 0 }]
85
+ assert_equal expected, TableExtractor.extract_tables(lines)
86
+ end
87
+
88
+ def test_multiple_tables
89
+ lines = [
90
+ '| Species| Genus| Family',
91
+ '|-|-|-',
92
+ '| Pongo tapanuliensis| Pongo| Hominidae',
93
+ '| | Histiophryne| Antennariidae',
94
+ '',
95
+ '| Name| Species',
96
+ '|-|-',
97
+ '| Tapanuli Orangutan| Pongo tapanuliensis'
98
+ ]
99
+ expected = [
100
+ { rows: 4, columns: 3, start_index: 0 },
101
+ { rows: 3, columns: 2, start_index: 5 }
102
+ ]
103
+ assert_equal expected, TableExtractor.extract_tables(lines)
104
+ end
105
+
106
+ def test_no_tables
107
+ lines = [
108
+ 'This is a regular line.',
109
+ 'Another regular line.'
110
+ ]
111
+ expected = []
112
+ assert_equal expected, TableExtractor.extract_tables(lines)
113
+ end
114
+
115
+ def test_inconsistent_columns
116
+ lines = [
117
+ '| Species| Genus| Family',
118
+ '|-|-',
119
+ '| Pongo tapanuliensis| Pongo| Hominidae',
120
+ '| | Histiophryne| Antennariidae',
121
+ '',
122
+ '| Name| Species',
123
+ '|-|-|-',
124
+ '| Tapanuli Orangutan| Pongo tapanuliensis'
125
+ ]
126
+ # number of columns determined from row of dividers
127
+ expected = [{ rows: 4, columns: 2, start_index: 0 },
128
+ { rows: 3, columns: 3, start_index: 5 }]
129
+ assert_equal expected, TableExtractor.extract_tables(lines)
130
+ end
131
+
132
+ def test_table_at_end_of_lines
133
+ lines = [
134
+ 'Some introductory text.',
135
+ '| Species| Genus| Family',
136
+ '|-|-|-',
137
+ '| Pongo tapanuliensis| Pongo| Hominidae',
138
+ '| | Histiophryne| Antennariidae'
139
+ ]
140
+ expected = [{ rows: 4, columns: 3, start_index: 1 }]
141
+ assert_equal expected, TableExtractor.extract_tables(lines)
142
+ end
143
+
144
+ def test_table_without_starting_pipe
145
+ lines = [
146
+ 'Some introductory text.',
147
+ 'Platform| Target Environment| Command',
148
+ '|-|-|-',
149
+ '| Pongo tapanuliensis| Pongo| Hominidae',
150
+ '| | Histiophryne| Antennariidae'
151
+ ]
152
+ expected = [{ rows: 4, columns: 3, start_index: 1 }]
153
+ assert_equal expected, TableExtractor.extract_tables(lines)
154
+ end
155
+
156
+ def test_table_with_colon_hyphens
157
+ lines = [
158
+ '| Name| Age| City',
159
+ '|:-:|:-|:-:',
160
+ '| John Doe| 30| New York',
161
+ '| Jane Doe| 25| Los Angeles'
162
+ ]
163
+ expected = [{ rows: 4, columns: 3, start_index: 0 }]
164
+ assert_equal expected, TableExtractor.extract_tables(lines)
165
+ end
166
+ end
data/lib/tap.rb CHANGED
@@ -35,8 +35,6 @@ unless defined?(Env)
35
35
  end
36
36
  end
37
37
 
38
- # rubocop:disable Metrics/ParameterLists
39
-
40
38
  ## application-level debug control
41
39
  #
42
40
  # :reek:TooManyConstants
@@ -98,8 +96,8 @@ module Tap
98
96
 
99
97
  # :reek:ControlParameter
100
98
  # :reek:LongParameterList
101
- def tap_inspect(name_ = nil, caller_first: nil, mask: TDD, name: DN, source: nil,
102
- type: nil)
99
+ def tap_inspect(name_ = nil, caller_first: nil, mask: TDD, name: DN,
100
+ source: nil, type: nil)
103
101
  return self unless $tap_enable
104
102
  return self unless (mask & $tap_mask).positive?
105
103
 
@@ -107,7 +105,8 @@ module Tap
107
105
  outs = []
108
106
  outs.push(source.to_s) if source.present?
109
107
 
110
- vs = (caller_first || caller[0]).scan(/in `?(\S+)'$/).fetch(0, []).fetch(0, '')
108
+ vs = (caller_first || caller[0]).scan(/in `?(\S+)'$/)
109
+ .fetch(0, []).fetch(0, '')
111
110
  outs.push("#{vs}()") if vs.present?
112
111
 
113
112
  outs.push(tap_named_value(name_ || name, method(fn).call))
@@ -143,7 +142,7 @@ module Tap
143
142
  # :reek:ControlParameter
144
143
  # :reek:LongParameterList
145
144
  def tap_yaml(name_ = nil, caller_first: nil, mask: TDD, name: DN, source: nil)
146
- tap_inspect name_, caller_first: (caller_first || caller[0]),
145
+ tap_inspect name_, caller_first: caller_first || caller[0],
147
146
  mask: mask, name: name, source: source, type: :yaml
148
147
  end
149
148
 
data/lib/text_analyzer.rb CHANGED
@@ -11,13 +11,17 @@ module TextAnalyzer
11
11
  # @return [Array<Hash>, Array<Array<Hash>>] an array or nested arrays of highlighted segments
12
12
  #
13
13
  # @raise [ArgumentError] if the hierarchy structure is neither a String nor an Array
14
- def self.analyze_hierarchy(hierarchy, pattern, default_color, match_color)
14
+ def self.analyze_hierarchy(
15
+ hierarchy, pattern, default_color, match_color,
16
+ text_sym: :text, style_sym: :color
17
+ )
15
18
  case hierarchy
16
19
  when String
17
20
  highlight_segments(hierarchy, pattern, default_color, match_color)
21
+
18
22
  when Hash
19
- decorated = highlight_segments(hierarchy[:text], pattern,
20
- hierarchy[:color], match_color)
23
+ decorated = highlight_segments(hierarchy[text_sym], pattern,
24
+ hierarchy[style_sym], match_color)
21
25
 
22
26
  case decorated
23
27
  when String
@@ -31,18 +35,19 @@ module TextAnalyzer
31
35
  else
32
36
  decorated
33
37
  end
38
+
34
39
  when Array
35
40
  hierarchy.map do |element|
36
41
  analyze_hierarchy(element, pattern, default_color, match_color)
37
42
  end
38
- when HierarchyString
39
43
 
44
+ when HierarchyString
40
45
  hierarchy.replace_text! do |substring|
41
- substring ### no change
46
+ substring # no change
42
47
  end
43
48
 
44
49
  else
45
- binding.irb
50
+ warn [hierarchy.class, hierarchy].inspect
46
51
  raise ArgumentError, 'Invalid hierarchy structure'
47
52
  end
48
53
  end
@@ -77,14 +82,14 @@ module TextAnalyzer
77
82
  # @yieldparam segment [String] a segment of the text
78
83
  # @yieldparam is_match [Boolean] true if the segment matches the pattern, false otherwise
79
84
  def self.yield_matches_and_non_matches(text, pattern)
80
- last_end = 0
85
+ last_end = nil
81
86
 
82
87
  text.scan(pattern) do |match|
83
88
  match_start = Regexp.last_match.begin(0)
84
89
  match_end = Regexp.last_match.end(0)
85
90
 
86
91
  # Yield the non-matching segment before the match
87
- yield text[last_end...match_start], false if match_start > last_end
92
+ yield text[(last_end || 0)...match_start], false if last_end.nil? || match_start > last_end
88
93
 
89
94
  # Yield the matching segment
90
95
  yield match.first, true
@@ -92,9 +97,140 @@ module TextAnalyzer
92
97
  last_end = match_end
93
98
  end
94
99
 
100
+ last_end ||= 0
95
101
  # Yield any remaining non-matching segment after the last match
96
102
  return unless last_end < text.length
97
103
 
98
104
  yield text[last_end..-1], false
99
105
  end
100
106
  end
107
+
108
+ return if $PROGRAM_NAME != __FILE__
109
+
110
+ require 'minitest/autorun'
111
+ require_relative 'hierarchy_string'
112
+
113
+ $default_color = :upcase
114
+ $match_color = :downcase
115
+
116
+ class TestTextAnalyzer < Minitest::Test
117
+ def test_analyze_hierarchy_with_string
118
+ text = 'This is a test string.'
119
+ pattern = /(test)/
120
+
121
+ expected_output = [[[
122
+ { text: 'This is a ', color: $default_color },
123
+ { text: 'test', color: $match_color },
124
+ { text: ' string.', color: $default_color }
125
+ ]]]
126
+
127
+ tree = HierarchyString.new([{ text: text, color: $default_color }])
128
+ assert_equal expected_output,
129
+ TextAnalyzer.analyze_hierarchy(tree.substrings, pattern, $default_color,
130
+ $match_color)
131
+ end
132
+
133
+ def test_analyze_hierarchy_with_array
134
+ hierarchy = [
135
+ 'This is a test string.',
136
+ 'Another test line.'
137
+ ]
138
+ pattern = /(test)/
139
+
140
+ expected_output = [
141
+ [
142
+ { text: 'This is a ', color: $default_color },
143
+ { text: 'test', color: $match_color },
144
+ { text: ' string.', color: $default_color }
145
+ ],
146
+ [
147
+ { text: 'Another ', color: $default_color },
148
+ { text: 'test', color: $match_color },
149
+ { text: ' line.', color: $default_color }
150
+ ]
151
+ ]
152
+
153
+ assert_equal expected_output,
154
+ TextAnalyzer.analyze_hierarchy(hierarchy, pattern,
155
+ $default_color, $match_color)
156
+ end
157
+
158
+ def test_analyze_hierarchy_with_nested_array
159
+ hierarchy = [
160
+ 'This is a test string.',
161
+ ['Another test line.', 'Yet another test.']
162
+ ]
163
+ pattern = /(test)/
164
+
165
+ expected_output = [
166
+ [
167
+ { text: 'This is a ', color: $default_color },
168
+ { text: 'test', color: $match_color },
169
+ { text: ' string.', color: $default_color }
170
+ ],
171
+ [
172
+ [
173
+ { text: 'Another ', color: $default_color },
174
+ { text: 'test', color: $match_color },
175
+ { text: ' line.', color: $default_color }
176
+ ],
177
+ [
178
+ { text: 'Yet another ', color: $default_color },
179
+ { text: 'test', color: $match_color },
180
+ { text: '.', color: $default_color }
181
+ ]
182
+ ]
183
+ ]
184
+
185
+ assert_equal expected_output,
186
+ TextAnalyzer.analyze_hierarchy(hierarchy, pattern,
187
+ $default_color, $match_color)
188
+ end
189
+
190
+ def test_analyze_hierarchy_with_invalid_type
191
+ hierarchy = 12_345
192
+ # hierarchy = HierarchyString.new([{ text: '12345', color: $default_color }])
193
+ pattern = /(test)/
194
+
195
+ assert_raises(ArgumentError) do
196
+ TextAnalyzer.analyze_hierarchy(hierarchy, pattern, $default_color,
197
+ $match_color)
198
+ end
199
+ end
200
+
201
+ def test_highlight_segments
202
+ text = 'This is a test string.'
203
+ pattern = /(test)/
204
+
205
+ expected_output = [
206
+ { text: 'This is a ', color: $default_color },
207
+ { text: 'test', color: $match_color },
208
+ { text: ' string.', color: $default_color }
209
+ ]
210
+
211
+ assert_equal expected_output,
212
+ TextAnalyzer.highlight_segments(text, pattern, $default_color,
213
+ $match_color)
214
+ end
215
+
216
+ def test_yield_matches_and_non_matches
217
+ text = 'This is a test string with multiple tests.'
218
+ pattern = /(test)/
219
+ segments = []
220
+
221
+ TextAnalyzer.yield_matches_and_non_matches(text,
222
+ pattern) do |segment, is_match|
223
+ segments << { text: segment, is_match: is_match }
224
+ end
225
+
226
+ expected_output = [
227
+ { text: 'This is a ', is_match: false },
228
+ { text: 'test', is_match: true },
229
+ { text: ' string with multiple ', is_match: false },
230
+ { text: 'test', is_match: true },
231
+ { text: 's.', is_match: false }
232
+ ]
233
+
234
+ assert_equal expected_output, segments
235
+ end
236
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: markdown_exec
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fareed Stevenson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-05 00:00:00.000000000 Z
11
+ date: 2024-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard
@@ -106,6 +106,15 @@ files:
106
106
  - assets/output_of_execution.png
107
107
  - assets/select_a_block.png
108
108
  - assets/select_a_file.png
109
+ - bats/bats.bats
110
+ - bats/block-types.bats
111
+ - bats/cli.bats
112
+ - bats/fail.bats
113
+ - bats/history.bats
114
+ - bats/markup.bats
115
+ - bats/mde.bats
116
+ - bats/options.bats
117
+ - bats/test_helper.bash
109
118
  - bin/bmde
110
119
  - bin/colorize_env_vars.sh
111
120
  - bin/console
@@ -113,6 +122,13 @@ files:
113
122
  - bin/setup
114
123
  - bin/tab_completion.sh
115
124
  - bin/tab_completion.sh.erb
125
+ - docs/dev/block-type-opts.md
126
+ - docs/dev/block-type-port.md
127
+ - docs/dev/block-type-vars.md
128
+ - docs/dev/pass-through-arguments.md
129
+ - docs/dev/specs-import.md
130
+ - docs/dev/specs.md
131
+ - docs/dev/text-decoration.md
116
132
  - examples/bash-blocks.md
117
133
  - examples/block-names.md
118
134
  - examples/block_names.md
@@ -149,9 +165,13 @@ files:
149
165
  - examples/port-blocks.md
150
166
  - examples/save.md
151
167
  - examples/search.md
168
+ - examples/table-markup.md
169
+ - examples/text-markup.md
152
170
  - examples/vars-blocks.md
153
171
  - examples/wrap.md
154
172
  - lib/ansi_formatter.rb
173
+ - lib/ansi_string.rb
174
+ - lib/argument_processor.rb
155
175
  - lib/array.rb
156
176
  - lib/array_util.rb
157
177
  - lib/block_label.rb
@@ -163,17 +183,20 @@ files:
163
183
  - lib/colorize.rb
164
184
  - lib/constants.rb
165
185
  - lib/directory_searcher.rb
186
+ - lib/doh.rb
166
187
  - lib/env.rb
167
188
  - lib/exceptions.rb
168
189
  - lib/fcb.rb
169
190
  - lib/filter.rb
170
191
  - lib/find_files.rb
192
+ - lib/format_table.rb
171
193
  - lib/fout.rb
172
194
  - lib/hash.rb
173
195
  - lib/hash_delegator.rb
174
196
  - lib/hierarchy_string.rb
175
197
  - lib/input_sequencer.rb
176
198
  - lib/instance_method_wrapper.rb
199
+ - lib/layered_hash.rb
177
200
  - lib/link_history.rb
178
201
  - lib/markdown_exec.rb
179
202
  - lib/markdown_exec/version.rb
@@ -190,9 +213,9 @@ files:
190
213
  - lib/saved_assets.rb
191
214
  - lib/saved_files_matcher.rb
192
215
  - lib/shared.rb
193
- - lib/std_out_err_logger.rb
194
216
  - lib/streams_out.rb
195
217
  - lib/string_util.rb
218
+ - lib/table_extractor.rb
196
219
  - lib/tap.rb
197
220
  - lib/text_analyzer.rb
198
221
  homepage: https://rubygems.org/gems/markdown_exec
@@ -1,119 +0,0 @@
1
- #!/usr/bin/env -S bundle exec ruby
2
- # frozen_string_literal: true
3
-
4
- # encoding=utf-8
5
- require 'logger'
6
-
7
- # Logger::LogDevice is used by Logger, the parent class of StdOutErrLogger
8
- class Logger::LogDevice
9
- # remove header
10
- def add_log_header(file); end
11
- end
12
-
13
- # Custom logger to direct info to stdout and warn and above to stderr
14
- #
15
- class StdOutErrLogger < Logger
16
- attr_reader :file
17
-
18
- # def initialize(file = nil)
19
- def initialize(file = "#{__dir__}/../tmp/hash_delegator_next_link_state.yaml")
20
- @file = file
21
- super(file || $stdout)
22
- self.formatter = proc do |_severity, _datetime, _progname, msg|
23
- "#{msg}\n"
24
- end
25
- end
26
-
27
- def add(severity, message = nil, progname = nil, &block)
28
- message = (message || block&.call || progname) if message.nil?
29
- message = "- #{message.to_json}\n"
30
- ### message = message.join("\n") if message.is_a? Array
31
- out = format_message(format_severity(severity), Time.now, progname, message)
32
- if severity == Logger::UNKNOWN # does not follow spec, outputs to stderr for IO
33
- # $stderr.puts(out)
34
- super
35
- elsif severity >= Logger::WARN
36
- if @file
37
- super
38
- else
39
- warn(out)
40
- end
41
- elsif @file
42
- super
43
- else
44
- $stdout.puts(out)
45
- end
46
- end
47
- end
48
-
49
- return if $PROGRAM_NAME != __FILE__
50
-
51
- require 'minitest/autorun'
52
-
53
- class StdOutErrLoggerTest < Minitest::Test
54
- # Redirect STDOUT and STDERR to capture them for assertions
55
- def setup
56
- @original_stdout = $stdout
57
- @original_stderr = $stderr
58
- $stdout = StringIO.new
59
- $stderr = StringIO.new
60
- end
61
-
62
- def teardown
63
- $stdout = @original_stdout
64
- $stderr = @original_stderr
65
- end
66
-
67
- def test_initialize_without_file
68
- logger = StdOutErrLogger.new
69
- assert_nil logger.file
70
- assert_equal Logger::DEBUG, logger.level
71
- end
72
-
73
- def test_initialize_with_file
74
- Tempfile.open do |file|
75
- logger = StdOutErrLogger.new(file.path)
76
- assert_equal file.path, logger.file
77
- end
78
- end
79
-
80
- def test_logging_info
81
- logger = StdOutErrLogger.new
82
- logger.info('Info message')
83
- assert_equal "Info message\n", $stdout.string
84
- assert_empty $stderr.string
85
- end
86
-
87
- def test_logging_warning
88
- logger = StdOutErrLogger.new
89
- logger.warn('Warning message')
90
- assert_empty $stdout.string
91
- assert_equal "Warning message\n", $stderr.string
92
- end
93
-
94
- def test_logging_error
95
- logger = StdOutErrLogger.new
96
- logger.error('Error message')
97
- assert_empty $stdout.string
98
- assert_equal "Error message\n", $stderr.string
99
- end
100
-
101
- def test_logging_with_array
102
- logger = StdOutErrLogger.new
103
- logger.info(['Message line 1', 'Message line 2'])
104
- assert_equal "Message line 1\nMessage line 2\n", $stdout.string
105
- end
106
-
107
- def test_logging_with_block
108
- logger = StdOutErrLogger.new
109
- logger.info { 'Block message' }
110
- assert_equal "Block message\n", $stdout.string
111
- end
112
-
113
- def test_logging_unknown_severity
114
- logger = StdOutErrLogger.new
115
- logger.add(Logger::UNKNOWN, 'Unknown severity message')
116
- assert_empty $stdout.string
117
- assert_equal "Unknown severity message\n", $stderr.string
118
- end
119
- end