sus 0.33.1 → 0.35.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 (55) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/context/{usage.md → getting-started.md} +58 -37
  4. data/context/index.yaml +22 -0
  5. data/context/mocking.md +100 -30
  6. data/context/{shared.md → shared-contexts.md} +29 -2
  7. data/lib/sus/assertions.rb +93 -20
  8. data/lib/sus/base.rb +13 -1
  9. data/lib/sus/be.rb +84 -0
  10. data/lib/sus/be_truthy.rb +16 -0
  11. data/lib/sus/be_within.rb +25 -0
  12. data/lib/sus/clock.rb +21 -0
  13. data/lib/sus/config.rb +59 -2
  14. data/lib/sus/context.rb +28 -5
  15. data/lib/sus/describe.rb +14 -0
  16. data/lib/sus/expect.rb +23 -0
  17. data/lib/sus/file.rb +38 -0
  18. data/lib/sus/filter.rb +21 -0
  19. data/lib/sus/fixtures/temporary_directory_context.rb +27 -0
  20. data/lib/sus/fixtures.rb +1 -0
  21. data/lib/sus/have/all.rb +8 -0
  22. data/lib/sus/have/any.rb +8 -0
  23. data/lib/sus/have.rb +42 -0
  24. data/lib/sus/have_duration.rb +16 -0
  25. data/lib/sus/identity.rb +44 -1
  26. data/lib/sus/integrations.rb +1 -0
  27. data/lib/sus/it.rb +33 -0
  28. data/lib/sus/it_behaves_like.rb +16 -0
  29. data/lib/sus/let.rb +3 -0
  30. data/lib/sus/mock.rb +53 -15
  31. data/lib/sus/output/backtrace.rb +31 -1
  32. data/lib/sus/output/bar.rb +17 -0
  33. data/lib/sus/output/buffered.rb +32 -1
  34. data/lib/sus/output/lines.rb +10 -0
  35. data/lib/sus/output/messages.rb +28 -5
  36. data/lib/sus/output/null.rb +18 -4
  37. data/lib/sus/output/progress.rb +29 -1
  38. data/lib/sus/output/status.rb +13 -0
  39. data/lib/sus/output/structured.rb +14 -1
  40. data/lib/sus/output/text.rb +33 -1
  41. data/lib/sus/output/xterm.rb +11 -1
  42. data/lib/sus/output.rb +9 -0
  43. data/lib/sus/raise_exception.rb +16 -0
  44. data/lib/sus/receive.rb +85 -3
  45. data/lib/sus/registry.rb +20 -1
  46. data/lib/sus/respond_to.rb +30 -3
  47. data/lib/sus/shared.rb +16 -0
  48. data/lib/sus/tree.rb +10 -0
  49. data/lib/sus/version.rb +2 -1
  50. data/lib/sus/with.rb +18 -0
  51. data/readme.md +12 -0
  52. data/releases.md +8 -0
  53. data.tar.gz.sig +0 -0
  54. metadata +6 -4
  55. metadata.gz.sig +0 -0
data/lib/sus/mock.rb CHANGED
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2022-2024, by Samuel Williams.
4
+ # Copyright, 2022-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "expect"
7
7
 
8
8
  module Sus
9
+ # Represents a mock object that can intercept and replace method calls on a target object.
9
10
  class Mock
11
+ # Initialize a new mock for the given target.
12
+ # @parameter target [Object] The object to mock.
10
13
  def initialize(target)
11
14
  @target = target
12
15
  @interceptor = Module.new
@@ -14,21 +17,29 @@ module Sus
14
17
  @target.singleton_class.prepend(@interceptor)
15
18
  end
16
19
 
20
+ # @attribute [Object] The target object being mocked.
17
21
  attr :target
18
22
 
23
+ # Print a representation of this mock.
24
+ # @parameter output [Output] The output target.
19
25
  def print(output)
20
26
  output.write("mock ", :context, @target.inspect)
21
27
  end
22
28
 
29
+ # Clear all mocked methods from the target.
23
30
  def clear
24
31
  @interceptor.instance_methods.each do |method_name|
25
32
  @interceptor.remove_method(method_name)
26
33
  end
27
34
  end
28
35
 
36
+ # Replace a method implementation.
37
+ # @parameter method [Symbol] The method name to replace.
38
+ # @yields {|*arguments, **options, &block| ...} The replacement implementation.
39
+ # @returns [Mock] Returns self for method chaining.
29
40
  def replace(method, &hook)
30
41
  execution_context = Thread.current
31
-
42
+
32
43
  @interceptor.define_method(method) do |*arguments, **options, &block|
33
44
  if execution_context == Thread.current
34
45
  hook.call(*arguments, **options, &block)
@@ -40,30 +51,40 @@ module Sus
40
51
  return self
41
52
  end
42
53
 
54
+ # Add a hook that runs before a method is called.
55
+ # @parameter method [Symbol] The method name to hook.
56
+ # @yields {|*arguments, **options, &block| ...} The hook to execute before the method.
57
+ # @returns [Mock] Returns self for method chaining.
43
58
  def before(method, &hook)
44
59
  execution_context = Thread.current
45
-
60
+
46
61
  @interceptor.define_method(method) do |*arguments, **options, &block|
47
62
  hook.call(*arguments, **options, &block) if execution_context == Thread.current
48
63
  super(*arguments, **options, &block)
49
64
  end
50
-
65
+
51
66
  return self
52
67
  end
53
-
68
+
69
+ # Add a hook that runs after a method is called.
70
+ # @parameter method [Symbol] The method name to hook.
71
+ # @yields {|result, *arguments, **options, &block| ...} The hook to execute after the method, receiving the result as the first argument.
72
+ # @returns [Mock] Returns self for method chaining.
54
73
  def after(method, &hook)
55
74
  execution_context = Thread.current
56
-
75
+
57
76
  @interceptor.define_method(method) do |*arguments, **options, &block|
58
77
  result = super(*arguments, **options, &block)
59
78
  hook.call(result, *arguments, **options, &block) if execution_context == Thread.current
60
79
  return result
61
80
  end
62
-
81
+
63
82
  return self
64
83
  end
65
84
 
66
85
  # Wrap a method, yielding the original method as the first argument, so you can call it from within the hook.
86
+ # @parameter method [Symbol] The method name to wrap.
87
+ # @yields {|original, *arguments, **options, &block| ...} The wrapper implementation, receiving the original method as the first argument.
67
88
  def wrap(method, &hook)
68
89
  execution_context = Thread.current
69
90
 
@@ -80,46 +101,63 @@ module Sus
80
101
  end
81
102
  end
82
103
  end
83
-
104
+
105
+ # Provides mock management functionality for test cases.
84
106
  module Mocks
107
+ # Clean up all mocks after the test completes.
108
+ # @parameter error [Exception | Nil] The error that occurred, if any.
85
109
  def after(error = nil)
86
110
  super
87
111
 
88
112
  @mocks&.each_value(&:clear)
89
113
  end
90
114
 
115
+ # Create or access a mock for the given target.
116
+ # @parameter target [Object] The object to mock.
117
+ # @yields {|mock| ...} Optional block to configure the mock.
118
+ # @returns [Mock] The mock instance for the target.
91
119
  def mock(target)
92
120
  validate_mock!(target)
93
-
121
+
94
122
  mock = self.mocks[target]
95
-
123
+
96
124
  if block_given?
97
125
  yield mock
98
126
  end
99
-
127
+
100
128
  return mock
101
129
  end
102
130
 
103
131
  private
104
132
 
133
+ # Error raised when attempting to mock a frozen object.
105
134
  MockTargetError = Class.new(StandardError)
106
-
135
+
136
+ # Validate that the target can be mocked.
137
+ # @parameter target [Object] The object to validate.
138
+ # @raises [MockTargetError] If the target is frozen.
107
139
  def validate_mock!(target)
108
140
  if target.frozen?
109
141
  raise MockTargetError, "Cannot mock frozen object #{target.inspect}!"
110
142
  end
111
143
  end
112
-
144
+
145
+ # Get the mocks hash, creating it if necessary.
146
+ # @returns [Hash] A hash mapping targets to their mock instances.
113
147
  def mocks
114
148
  @mocks ||= Hash.new{|h,k| h[k] = Mock.new(k)}.compare_by_identity
115
149
  end
116
150
  end
117
-
151
+
118
152
  class Base
153
+ # Create or access a mock for the given target.
154
+ # @parameter target [Object] The object to mock.
155
+ # @yields {|mock| ...} Optional block to configure the mock.
156
+ # @returns [Mock] The mock instance for the target.
119
157
  def mock(target, &block)
120
158
  # Pull in the extra functionality:
121
159
  self.singleton_class.prepend(Mocks)
122
-
160
+
123
161
  # Redirect the method to the new functionality:
124
162
  self.mock(target, &block)
125
163
  end
@@ -5,21 +5,32 @@
5
5
 
6
6
  module Sus
7
7
  module Output
8
- # Print out a backtrace relevant to the given test identity if provided.
8
+ # Represents a backtrace for displaying error locations.
9
9
  class Backtrace
10
+ # Create a backtrace from the first caller location.
11
+ # @parameter identity [Identity, nil] Optional identity to filter by path.
12
+ # @returns [Backtrace] A new Backtrace instance.
10
13
  def self.first(identity = nil)
11
14
  # This implementation could be a little more efficient.
12
15
  self.new(caller_locations(1), identity&.path, 1)
13
16
  end
14
17
 
18
+ # Create a backtrace from an exception.
19
+ # @parameter exception [Exception] The exception to extract the backtrace from.
20
+ # @parameter identity [Identity, nil] Optional identity to filter by path.
21
+ # @returns [Backtrace] A new Backtrace instance.
15
22
  def self.for(exception, identity = nil)
16
23
  # I've disabled the root filter here, because partial backtraces are not very useful.
17
24
  # We might want to do something to improve presentation of the backtrace based on the root instead.
18
25
  self.new(extract_stack(exception), identity&.path)
19
26
  end
20
27
 
28
+ # Represents a location in a backtrace.
21
29
  Location = Struct.new(:path, :lineno, :label)
22
30
 
31
+ # Extract the stack trace from an exception.
32
+ # @parameter exception [Exception] The exception to extract from.
33
+ # @returns [Array] An array of location objects.
23
34
  def self.extract_stack(exception)
24
35
  if stack = exception.backtrace_locations
25
36
  return stack
@@ -32,16 +43,29 @@ module Sus
32
43
  end
33
44
  end
34
45
 
46
+ # Initialize a new Backtrace.
47
+ # @parameter stack [Array] The stack trace locations.
48
+ # @parameter root [String, nil] Optional root path to filter by.
49
+ # @parameter limit [Integer, nil] Optional limit on the number of frames.
35
50
  def initialize(stack, root = nil, limit = nil)
36
51
  @stack = stack
37
52
  @root = root
38
53
  @limit = limit
39
54
  end
40
55
 
56
+ # @attribute [Array] The stack trace locations.
41
57
  attr :stack
58
+
59
+ # @attribute [String, nil] The root path to filter by.
42
60
  attr :root
61
+
62
+ # @attribute [Integer, nil] The limit on the number of frames.
43
63
  attr :limit
44
64
 
65
+ # Filter the backtrace by root path and limit.
66
+ # @parameter root [String, nil] Optional root path to filter by.
67
+ # @parameter limit [Integer, nil] Optional limit on the number of frames.
68
+ # @returns [Array, Enumerator] The filtered stack trace.
45
69
  def filter(root: @root, limit: @limit)
46
70
  if root
47
71
  if limit
@@ -60,6 +84,8 @@ module Sus
60
84
  end
61
85
  end
62
86
 
87
+ # Print the backtrace to the output.
88
+ # @parameter output [Output] The output handler.
63
89
  def print(output)
64
90
  if @limit == 1
65
91
  filter.each do |frame|
@@ -74,6 +100,10 @@ module Sus
74
100
  end
75
101
  end
76
102
 
103
+ # Select items up to and matching a condition.
104
+ # @parameter things [Enumerable] The items to filter.
105
+ # @yields {|thing| ...} The condition to match.
106
+ # @returns [Array] The filtered items.
77
107
  private def up_to_and_matching(things, &block)
78
108
  preface = true
79
109
  things.select do |thing|
@@ -5,7 +5,9 @@
5
5
 
6
6
  module Sus
7
7
  module Output
8
+ # Represents a progress bar for displaying test execution progress.
8
9
  class Bar
10
+ # Unicode block characters for drawing the progress bar.
9
11
  BLOCK = [
10
12
  " ",
11
13
  "▏",
@@ -18,6 +20,10 @@ module Sus
18
20
  "█",
19
21
  ]
20
22
 
23
+ # Initialize a new progress bar.
24
+ # @parameter current [Integer] The current progress value.
25
+ # @parameter total [Integer] The total value.
26
+ # @parameter message [String, nil] Optional message to display.
21
27
  def initialize(current = 0, total = 0, message = nil)
22
28
  @maximum_message_width = 0
23
29
 
@@ -26,19 +32,30 @@ module Sus
26
32
  @message = message
27
33
  end
28
34
 
35
+ # Update the progress bar values.
36
+ # @parameter current [Integer] The current progress value.
37
+ # @parameter total [Integer] The total value.
38
+ # @parameter message [String, nil] Optional message to display.
29
39
  def update(current, total, message)
30
40
  @current = current
31
41
  @total = total
32
42
  @message = message
33
43
  end
34
44
 
45
+ # Register progress bar styling with an output handler.
46
+ # @parameter output [Output] The output handler to register with.
35
47
  def self.register(output)
36
48
  output[:progress_bar] ||= output.style(:blue, :white)
37
49
  end
38
50
 
51
+ # The minimum width for the progress bar.
39
52
  MINIMUM_WIDTH = 8
53
+
54
+ # The suffix to append to messages.
40
55
  MESSAGE_SUFFIX = ": "
41
56
 
57
+ # Print the progress bar to the output.
58
+ # @parameter output [Output] The output handler.
42
59
  def print(output)
43
60
  width = output.width
44
61
 
@@ -7,17 +7,23 @@ require "io/console"
7
7
  require "stringio"
8
8
 
9
9
  module Sus
10
- # Styled output output.
11
10
  module Output
11
+ # Represents a buffered output handler that stores output operations for later replay.
12
12
  class Buffered
13
+ # Initialize a new Buffered output handler.
14
+ # @parameter tee [Output, nil] Optional output handler to tee output to.
13
15
  def initialize(tee = nil)
14
16
  @chunks = Array.new
15
17
  @tee = tee
16
18
  end
17
19
 
20
+ # @attribute [Array] The stored output chunks.
18
21
  attr :chunks
22
+
23
+ # @attribute [Output, nil] The output handler to tee to.
19
24
  attr :tee
20
25
 
26
+ # @returns [String] A string representation of this buffered output.
21
27
  def inspect
22
28
  if @tee
23
29
  "\#<#{self.class.name} #{@chunks.size} chunks -> #{@tee.class}>"
@@ -26,39 +32,52 @@ module Sus
26
32
  end
27
33
  end
28
34
 
35
+ # Create a nested buffered output handler.
36
+ # @returns [Buffered] A new Buffered instance that tees to this one.
29
37
  def buffered
30
38
  self.class.new(self)
31
39
  end
32
40
 
41
+ # Iterate over stored chunks.
42
+ # @yields {|chunk| ...} Each stored chunk.
33
43
  def each(&block)
34
44
  @chunks.each(&block)
35
45
  end
36
46
 
47
+ # Append chunks from another buffer.
48
+ # @parameter buffer [Buffered] The buffer to append from.
37
49
  def append(buffer)
38
50
  @chunks.concat(buffer.chunks)
39
51
  @tee&.append(buffer)
40
52
  end
41
53
 
54
+ # @returns [String] The buffered output as a string.
42
55
  def string
43
56
  io = StringIO.new
44
57
  Text.new(io).append(@chunks)
45
58
  return io.string
46
59
  end
47
60
 
61
+ # The indent operation marker.
48
62
  INDENT = [:indent].freeze
49
63
 
64
+ # Increase indentation level.
50
65
  def indent
51
66
  @chunks << INDENT
52
67
  @tee&.indent
53
68
  end
54
69
 
70
+ # The outdent operation marker.
55
71
  OUTDENT = [:outdent].freeze
56
72
 
73
+ # Decrease indentation level.
57
74
  def outdent
58
75
  @chunks << OUTDENT
59
76
  @tee&.outdent
60
77
  end
61
78
 
79
+ # Execute a block with increased indentation.
80
+ # @yields {...} The block to execute.
62
81
  def indented
63
82
  self.indent
64
83
  yield
@@ -66,31 +85,43 @@ module Sus
66
85
  self.outdent
67
86
  end
68
87
 
88
+ # Write output.
89
+ # @parameter arguments [Array] The arguments to write.
69
90
  def write(*arguments)
70
91
  @chunks << [:write, *arguments]
71
92
  @tee&.write(*arguments)
72
93
  end
73
94
 
95
+ # Write output followed by a newline.
96
+ # @parameter arguments [Array] The arguments to write.
74
97
  def puts(*arguments)
75
98
  @chunks << [:puts, *arguments]
76
99
  @tee&.puts(*arguments)
77
100
  end
78
101
 
102
+ # Record an assertion.
103
+ # @parameter arguments [Array] The assertion arguments.
79
104
  def assert(*arguments)
80
105
  @chunks << [:assert, *arguments]
81
106
  @tee&.assert(*arguments)
82
107
  end
83
108
 
109
+ # Record a skip.
110
+ # @parameter arguments [Array] The skip arguments.
84
111
  def skip(*arguments)
85
112
  @chunks << [:skip, *arguments]
86
113
  @tee&.skip(*arguments)
87
114
  end
88
115
 
116
+ # Record an error.
117
+ # @parameter arguments [Array] The error arguments.
89
118
  def error(*arguments)
90
119
  @chunks << [:error, *arguments]
91
120
  @tee&.error(*arguments)
92
121
  end
93
122
 
123
+ # Record an informational message.
124
+ # @parameter arguments [Array] The message arguments.
94
125
  def inform(*arguments)
95
126
  @chunks << [:inform, *arguments]
96
127
  @tee&.inform(*arguments)
@@ -7,7 +7,10 @@ require "io/console"
7
7
 
8
8
  module Sus
9
9
  module Output
10
+ # Represents a line buffer for managing multiple lines of output on a terminal.
10
11
  class Lines
12
+ # Initialize a new Lines buffer.
13
+ # @parameter output [Output] The output handler to write to.
11
14
  def initialize(output)
12
15
  @output = output
13
16
  @lines = []
@@ -15,21 +18,28 @@ module Sus
15
18
  @current_count = 0
16
19
  end
17
20
 
21
+ # @returns [Integer] The height of the terminal.
18
22
  def height
19
23
  @output.size.first
20
24
  end
21
25
 
26
+ # Set a line at the given index.
27
+ # @parameter index [Integer] The line index.
28
+ # @parameter line [Object] The line content (should respond to #print).
22
29
  def []= index, line
23
30
  @lines[index] = line
24
31
 
25
32
  redraw(index)
26
33
  end
27
34
 
35
+ # Clear all lines.
28
36
  def clear
29
37
  @lines.clear
30
38
  write
31
39
  end
32
40
 
41
+ # Redraw a specific line or all lines.
42
+ # @parameter index [Integer] The line index to redraw.
33
43
  def redraw(index)
34
44
  if index < @current_count
35
45
  update(index, @lines[index])
@@ -1,15 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2023-2024, by Samuel Williams.
4
+ # Copyright, 2023-2025, by Samuel Williams.
5
5
 
6
6
  module Sus
7
- # Styled output output.
8
7
  module Output
8
+ # Provides message formatting methods for output handlers.
9
9
  module Messages
10
+ # The prefix for passed assertions.
10
11
  PASSED_PREFIX = [:passed, "✓ "].freeze
12
+
13
+ # The prefix for failed assertions.
11
14
  FAILED_PREFIX = [:failed, "✗ "].freeze
12
15
 
16
+ # Get the prefix for a passed assertion based on orientation.
17
+ # @parameter orientation [Boolean] The orientation of the assertions.
18
+ # @returns [Array] The prefix array.
13
19
  def pass_prefix(orientation)
14
20
  if orientation
15
21
  PASSED_PREFIX
@@ -18,6 +24,9 @@ module Sus
18
24
  end
19
25
  end
20
26
 
27
+ # Get the prefix for a failed assertion based on orientation.
28
+ # @parameter orientation [Boolean] The orientation of the assertions.
29
+ # @returns [Array] The prefix array.
21
30
  def fail_prefix(orientation)
22
31
  if orientation
23
32
  FAILED_PREFIX
@@ -26,6 +35,7 @@ module Sus
26
35
  end
27
36
  end
28
37
 
38
+ # Print an assertion result.
29
39
  # If the orientation is true, and the test passed, then it is a successful outcome.
30
40
  # If the orientation is false, and the test failed, then it is a successful outcome.
31
41
  # Otherwise, it is a failed outcome.
@@ -33,7 +43,7 @@ module Sus
33
43
  # @parameter condition [Boolean] The result of the test.
34
44
  # @parameter orientation [Boolean] The orientation of the assertions.
35
45
  # @parameter message [String] The message to display.
36
- # @parameter backtrace [Array] The backtrace to display.
46
+ # @parameter backtrace [Backtrace] The backtrace to display.
37
47
  def assert(condition, orientation, message, backtrace)
38
48
  if condition
39
49
  self.puts(:indent, *pass_prefix(orientation), message, backtrace)
@@ -42,27 +52,36 @@ module Sus
42
52
  end
43
53
  end
44
54
 
55
+ # @returns [String] The prefix for skipped tests.
45
56
  def skip_prefix
46
57
  "⏸ "
47
58
  end
48
59
 
60
+ # Print a skip message.
61
+ # @parameter reason [String] The reason for skipping.
62
+ # @parameter identity [Identity, nil] The identity where the skip occurred.
49
63
  def skip(reason, identity)
50
64
  self.puts(:indent, :skipped, skip_prefix, reason)
51
65
  end
52
66
 
67
+ # @returns [Array] The prefix for error messages.
53
68
  def error_prefix
54
69
  [:errored, "⚠ "]
55
70
  end
56
71
 
72
+ # Print an error message.
73
+ # @parameter error [Exception] The error to display.
74
+ # @parameter identity [Identity, nil] The identity where the error occurred.
75
+ # @parameter prefix [Array] Optional prefix to use.
57
76
  def error(error, identity, prefix = error_prefix)
58
77
  lines = error.message.split(/\r?\n/)
59
-
78
+
60
79
  self.puts(:indent, *prefix, error.class, ": ", lines.shift)
61
80
 
62
81
  lines.each do |line|
63
82
  self.puts(:indent, line)
64
83
  end
65
-
84
+
66
85
  self.write(Output::Backtrace.for(error, identity))
67
86
 
68
87
  if cause = error.cause
@@ -70,10 +89,14 @@ module Sus
70
89
  end
71
90
  end
72
91
 
92
+ # @returns [String] The prefix for informational messages.
73
93
  def inform_prefix
74
94
  "ℹ "
75
95
  end
76
96
 
97
+ # Print an informational message.
98
+ # @parameter message [String] The message to display.
99
+ # @parameter identity [Identity, nil] The identity where the message was generated.
77
100
  def inform(message, identity)
78
101
  self.puts(:indent, :inform, inform_prefix, message)
79
102
  end
@@ -1,42 +1,56 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2021-2024, by Samuel Williams.
4
+ # Copyright, 2021-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "messages"
7
7
 
8
8
  module Sus
9
- # Styled output output.
10
9
  module Output
10
+ # Represents a null output handler that discards all output.
11
11
  class Null
12
12
  include Messages
13
13
 
14
+ # Initialize a new Null output handler.
14
15
  def initialize
15
16
  end
16
17
 
18
+ # Create a buffered output handler.
19
+ # @returns [Buffered] A new Buffered instance.
17
20
  def buffered
18
21
  Buffered.new(nil)
19
22
  end
20
23
 
24
+ # @attribute [Hash, nil] Optional options (unused).
21
25
  attr :options
22
26
 
27
+ # Append chunks from a buffer (no-op).
28
+ # @parameter buffer [Buffered] The buffer to append from.
23
29
  def append(buffer)
24
30
  end
25
-
31
+
32
+ # Increase indentation (no-op).
26
33
  def indent
27
34
  end
28
35
 
36
+ # Decrease indentation (no-op).
29
37
  def outdent
30
38
  end
31
-
39
+
40
+ # Execute a block with indentation (no-op, just yields).
41
+ # @yields {...} The block to execute.
32
42
  def indented
33
43
  yield
34
44
  end
35
45
 
46
+ # Write output (no-op).
47
+ # @parameter arguments [Array] The arguments to write.
36
48
  def write(*arguments)
37
49
  # Do nothing.
38
50
  end
39
51
 
52
+ # Write output followed by a newline (no-op).
53
+ # @parameter arguments [Array] The arguments to write.
40
54
  def puts(*arguments)
41
55
  # Do nothing.
42
56
  end