backspin 0.4.0 → 0.4.2

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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/.gem_release.yml +13 -0
  3. data/CHANGELOG.md +5 -7
  4. data/CLAUDE.md +7 -3
  5. data/CONTRIBUTING.md +2 -2
  6. data/Gemfile +3 -1
  7. data/Gemfile.lock +3 -1
  8. data/MATCH_ON_USAGE.md +110 -0
  9. data/README.md +7 -2
  10. data/Rakefile +5 -1
  11. data/backspin.gemspec +6 -3
  12. data/examples/match_on_example.rb +116 -0
  13. data/fixtures/backspin/all_and_fields.yml +15 -0
  14. data/fixtures/backspin/all_bypass_equality.yml +14 -0
  15. data/fixtures/backspin/all_checks_equality.yml +17 -0
  16. data/fixtures/backspin/all_for_logging.yml +13 -0
  17. data/fixtures/backspin/all_matcher_basic.yml +14 -0
  18. data/fixtures/backspin/all_matcher_custom.yml +17 -0
  19. data/fixtures/backspin/all_matcher_demo.yml +14 -0
  20. data/fixtures/backspin/all_matcher_test.yml +14 -0
  21. data/fixtures/backspin/all_mode_filter.yml +14 -0
  22. data/fixtures/backspin/all_no_short_circuit.yml +14 -0
  23. data/fixtures/backspin/all_pass_field_fail.yml +14 -0
  24. data/fixtures/backspin/all_short_circuit.yml +14 -0
  25. data/fixtures/backspin/all_skips_equality.yml +17 -0
  26. data/fixtures/backspin/all_with_equality.yml +17 -0
  27. data/fixtures/backspin/all_with_fields.yml +17 -0
  28. data/fixtures/backspin/combined_fail_demo.yml +14 -0
  29. data/fixtures/backspin/combined_matcher_demo.yml +14 -0
  30. data/fixtures/backspin/credential_filter.yml +18 -0
  31. data/fixtures/backspin/echo_hello.yml +14 -0
  32. data/fixtures/backspin/echo_verify.yml +14 -0
  33. data/fixtures/backspin/episodes_filter.yml +26 -0
  34. data/fixtures/backspin/failure_test.yml +14 -0
  35. data/fixtures/backspin/field_matcher_demo.yml +17 -0
  36. data/fixtures/backspin/field_matcher_values.yml +14 -0
  37. data/fixtures/backspin/full_data_filter.yml +17 -0
  38. data/fixtures/backspin/key_confusion_test.yml +14 -0
  39. data/fixtures/backspin/match_on_any_fail.yml +21 -0
  40. data/fixtures/backspin/match_on_bad_format.yml +14 -0
  41. data/fixtures/backspin/match_on_fail.yml +15 -0
  42. data/fixtures/backspin/match_on_invalid.yml +14 -0
  43. data/fixtures/backspin/match_on_multiple.yml +28 -0
  44. data/fixtures/backspin/match_on_nil.yml +14 -0
  45. data/fixtures/backspin/match_on_other_fields.yml +23 -0
  46. data/fixtures/backspin/match_on_run_bang.yml +16 -0
  47. data/fixtures/backspin/match_on_run_bang_fail.yml +15 -0
  48. data/fixtures/backspin/match_on_single.yml +17 -0
  49. data/fixtures/backspin/mixed_calls.yml +24 -0
  50. data/fixtures/backspin/multi_command.yml +34 -0
  51. data/fixtures/backspin/multi_command_filter.yml +26 -0
  52. data/fixtures/backspin/multi_field_filter.yml +13 -0
  53. data/fixtures/backspin/multi_system.yml +20 -0
  54. data/fixtures/backspin/nil_filter.yml +14 -0
  55. data/fixtures/backspin/none_mode_test.yml +14 -0
  56. data/fixtures/backspin/path_test.yml +17 -0
  57. data/fixtures/backspin/playback_system.yml +12 -0
  58. data/fixtures/backspin/playback_test.yml +14 -0
  59. data/fixtures/backspin/stderr_test.yml +19 -0
  60. data/fixtures/backspin/string_symbol_test.yml +14 -0
  61. data/fixtures/backspin/system_echo.yml +12 -0
  62. data/fixtures/backspin/system_false.yml +18 -0
  63. data/fixtures/backspin/timestamp_test.yml +18 -0
  64. data/fixtures/backspin/use_record_filter.yml +15 -0
  65. data/fixtures/backspin/verify_system.yml +12 -0
  66. data/fixtures/backspin/verify_system_diff.yml +11 -0
  67. data/fixtures/backspin/version_test.yml +14 -0
  68. data/lib/backspin/command.rb +1 -5
  69. data/lib/backspin/command_diff.rb +98 -16
  70. data/lib/backspin/command_result.rb +2 -4
  71. data/lib/backspin/record.rb +31 -10
  72. data/lib/backspin/record_result.rb +20 -14
  73. data/lib/backspin/recorder.rb +100 -55
  74. data/lib/backspin/version.rb +3 -1
  75. data/lib/backspin.rb +36 -175
  76. data/release.rake +97 -0
  77. data/script/lint +6 -0
  78. metadata +79 -5
data/lib/backspin.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "yaml"
2
4
  require "fileutils"
3
5
  require "open3"
@@ -21,7 +23,7 @@ module Backspin
21
23
  # Configuration for Backspin
22
24
  class Configuration
23
25
  attr_accessor :scrub_credentials
24
- # The directory where backspin will store its files - defaults to spec/backspin_data
26
+ # The directory where backspin will store its files - defaults to fixtures/backspin
25
27
  attr_accessor :backspin_dir
26
28
  # Regex patterns to scrub from saved output
27
29
  attr_reader :credential_patterns
@@ -29,7 +31,7 @@ module Backspin
29
31
  def initialize
30
32
  @scrub_credentials = true
31
33
  @credential_patterns = default_credential_patterns
32
- @backspin_dir = Pathname(Dir.pwd).join("spec", "backspin_data")
34
+ @backspin_dir = Pathname(Dir.pwd).join("fixtures", "backspin")
33
35
  end
34
36
 
35
37
  def add_credential_pattern(pattern)
@@ -50,22 +52,22 @@ module Backspin
50
52
  def default_credential_patterns
51
53
  [
52
54
  # AWS credentials
53
- /AKIA[0-9A-Z]{16}/, # AWS Access Key ID
54
- /aws_secret_access_key\s*[:=]\s*["']?([A-Za-z0-9\/+=]{40})["']?/i, # AWS Secret Key
55
- /aws_session_token\s*[:=]\s*["']?([A-Za-z0-9\/+=]+)["']?/i, # AWS Session Token
55
+ /AKIA[0-9A-Z]{16}/, # AWS Access Key ID
56
+ %r{aws_secret_access_key\s*[:=]\s*["']?([A-Za-z0-9/+=]{40})["']?}i, # AWS Secret Key
57
+ %r{aws_session_token\s*[:=]\s*["']?([A-Za-z0-9/+=]+)["']?}i, # AWS Session Token
56
58
 
57
59
  # Google Cloud credentials
58
- /AIza[0-9A-Za-z\-_]{35}/, # Google API Key
60
+ /AIza[0-9A-Za-z\-_]{35}/, # Google API Key
59
61
  /[0-9]+-[0-9A-Za-z_]{32}\.apps\.googleusercontent\.com/, # Google OAuth2 client ID
60
- /-----BEGIN (RSA )?PRIVATE KEY-----/, # Private keys
62
+ /-----BEGIN (RSA )?PRIVATE KEY-----/, # Private keys
61
63
 
62
64
  # Generic patterns
63
- /api[_-]?key\s*[:=]\s*["']?([A-Za-z0-9\-_]{20,})["']?/i, # Generic API keys
65
+ /api[_-]?key\s*[:=]\s*["']?([A-Za-z0-9\-_]{20,})["']?/i, # Generic API keys
64
66
  /auth[_-]?token\s*[:=]\s*["']?([A-Za-z0-9\-_]{20,})["']?/i, # Auth tokens
65
67
  /Bearer\s+([A-Za-z0-9\-_]+)/, # Bearer tokens
66
- /password\s*[:=]\s*["']?([^"'\s]{8,})["']?/i, # Passwords
67
- /-p([^"'\s]{8,})/, # MySQL-style password args
68
- /secret\s*[:=]\s*["']?([A-Za-z0-9\-_]{20,})["']?/i # Generic secrets
68
+ /password\s*[:=]\s*["']?([^"'\s]{8,})["']?/i, # Passwords
69
+ /-p([^"'\s]{8,})/, # MySQL-style password args
70
+ /secret\s*[:=]\s*["']?([A-Za-z0-9\-_]{20,})["']?/i # Generic secrets
69
71
  ]
70
72
  end
71
73
  end
@@ -91,7 +93,6 @@ module Backspin
91
93
  scrubbed = text.dup
92
94
  configuration.credential_patterns.each do |pattern|
93
95
  scrubbed.gsub!(pattern) do |match|
94
- # Replace with asterisks of the same length
95
96
  "*" * match.length
96
97
  end
97
98
  end
@@ -104,22 +105,39 @@ module Backspin
104
105
  # @param options [Hash] Options for recording/verification
105
106
  # @option options [Symbol] :mode (:auto) Recording mode - :auto, :record, :verify, :playback
106
107
  # @option options [Proc] :filter Custom filter for recorded data
107
- # @option options [Proc] :matcher Custom matcher for verification
108
+ # @option options [Proc, Hash] :matcher Custom matcher for verification
109
+ # - Proc: ->(recorded, actual) { ... } for full command matching
110
+ # - Hash: { stdout: ->(recorded, actual) { ... }, stderr: ->(recorded, actual) { ... } } for field-specific matching
111
+ # - Hash with :all key: { all: ->(recorded, actual) { ... }, stdout: ->(recorded, actual) { ... } } for combined matching
112
+ # When both :all and field matchers are present, both must pass for verification to succeed.
113
+ # Fields without specific matchers always use exact equality, regardless of :all presence.
108
114
  # @return [RecordResult] Result object with output and status
109
115
  def run(record_name, options = {}, &block)
110
116
  raise ArgumentError, "record_name is required" if record_name.nil? || record_name.empty?
111
117
  raise ArgumentError, "block is required" unless block_given?
112
118
 
113
- record_path = build_record_path(record_name)
119
+ record_path = Record.build_record_path(record_name)
114
120
  mode = determine_mode(options[:mode], record_path)
115
121
 
122
+ # Create or load the record based on mode
123
+ record = if mode == :record
124
+ Record.create(record_name)
125
+ else
126
+ Record.load_or_create(record_path)
127
+ end
128
+
129
+ # Create recorder with all needed context
130
+ recorder = Recorder.new(record: record, options: options, mode: mode)
131
+
132
+ # Execute the appropriate mode
116
133
  case mode
117
134
  when :record
118
- perform_recording(record_name, record_path, options, &block)
135
+ recorder.setup_recording_stubs(:capture3, :system)
136
+ recorder.perform_recording(&block)
119
137
  when :verify
120
- perform_verification(record_name, record_path, options, &block)
138
+ recorder.perform_verification(&block)
121
139
  when :playback
122
- perform_playback(record_name, record_path, options, &block)
140
+ recorder.perform_playback(&block)
123
141
  else
124
142
  raise ArgumentError, "Unknown mode: #{mode}"
125
143
  end
@@ -136,7 +154,7 @@ module Backspin
136
154
 
137
155
  if result.verified? == false
138
156
  error_message = "Backspin verification failed!\n"
139
- error_message += "Record: #{result.record_path}\n"
157
+ error_message += "Record: #{result.record.path}\n"
140
158
 
141
159
  # Use the error_message from the result which is now properly formatted
142
160
  error_message += "\n#{result.error_message}" if result.error_message
@@ -155,162 +173,5 @@ module Backspin
155
173
  # Auto mode: record if file doesn't exist, verify if it does
156
174
  File.exist?(record_path) ? :verify : :record
157
175
  end
158
-
159
- def perform_recording(_record_name, record_path, options)
160
- recorder = Recorder.new
161
- recorder.record_calls(:capture3, :system)
162
-
163
- output = yield
164
-
165
- if output.is_a?(Array) && output.size == 3
166
- stdout, stderr, status = output
167
- status_int = status.respond_to?(:exitstatus) ? status.exitstatus : status
168
- output = [stdout, stderr, status_int]
169
- end
170
-
171
- # Save the recording
172
- FileUtils.mkdir_p(File.dirname(record_path))
173
- record = Record.new(record_path)
174
- record.clear
175
- recorder.commands.each { |cmd| record.add_command(cmd) }
176
- record.save(filter: options[:filter])
177
-
178
- # Return result
179
- RecordResult.new(
180
- output: output,
181
- mode: :record,
182
- record_path: Pathname.new(record_path),
183
- commands: recorder.commands
184
- )
185
- end
186
-
187
- def perform_verification(_record_name, record_path, options)
188
- record = Record.load_or_create(record_path)
189
-
190
- raise RecordNotFoundError, "Record not found: #{record_path}" unless record.exists?
191
- raise RecordNotFoundError, "No commands found in record" if record.empty?
192
-
193
- # For verification, we need to track all commands executed
194
- recorder = Recorder.new(mode: :verify, record: record)
195
- recorder.setup_replay_stubs
196
-
197
- # Track verification results for each command
198
- command_diffs = []
199
- command_index = 0
200
-
201
- # Override stubs to verify each command as it's executed
202
- allow(Open3).to receive(:capture3).and_wrap_original do |original_method, *args|
203
- recorded_command = record.commands[command_index]
204
-
205
- if recorded_command.nil?
206
- raise RecordNotFoundError, "No more recorded commands, but tried to execute: #{args.inspect}"
207
- end
208
-
209
- if recorded_command.method_class != Open3::Capture3
210
- raise RecordNotFoundError, "Expected #{recorded_command.method_class.name} but got Open3.capture3"
211
- end
212
-
213
- # Execute the actual command
214
- stdout, stderr, status = original_method.call(*args)
215
-
216
- # Create verification result
217
- actual_result = CommandResult.new(
218
- stdout: stdout,
219
- stderr: stderr,
220
- status: status.exitstatus
221
- )
222
-
223
- # Create CommandDiff to track the comparison
224
- command_diffs << CommandDiff.new(
225
- recorded_command: recorded_command,
226
- actual_result: actual_result,
227
- matcher: options[:matcher]
228
- )
229
-
230
- command_index += 1
231
- [stdout, stderr, status]
232
- end
233
-
234
- allow_any_instance_of(Object).to receive(:system).and_wrap_original do |original_method, receiver, *args|
235
- recorded_command = record.commands[command_index]
236
-
237
- if recorded_command.nil?
238
- raise RecordNotFoundError, "No more recorded commands, but tried to execute: system #{args.inspect}"
239
- end
240
-
241
- if recorded_command.method_class != ::Kernel::System
242
- raise RecordNotFoundError, "Expected #{recorded_command.method_class.name} but got system"
243
- end
244
-
245
- # Execute the actual command
246
- result = original_method.call(receiver, *args)
247
-
248
- # Create verification result (system only gives us exit status)
249
- actual_result = CommandResult.new(
250
- stdout: "",
251
- stderr: "",
252
- status: result ? 0 : 1
253
- )
254
-
255
- # Create CommandDiff to track the comparison
256
- command_diffs << CommandDiff.new(
257
- recorded_command: recorded_command,
258
- actual_result: actual_result,
259
- matcher: options[:matcher]
260
- )
261
-
262
- command_index += 1
263
- result
264
- end
265
-
266
- # Execute block
267
- output = yield
268
-
269
- # Check if all commands were executed
270
- if command_index < record.commands.size
271
- raise RecordNotFoundError, "Expected #{record.commands.size} commands but only #{command_index} were executed"
272
- end
273
-
274
- # Overall verification status
275
- all_verified = command_diffs.all?(&:verified?)
276
-
277
- RecordResult.new(
278
- output: output,
279
- mode: :verify,
280
- verified: all_verified,
281
- record_path: Pathname.new(record_path),
282
- commands: record.commands,
283
- command_diffs: command_diffs
284
- )
285
- end
286
-
287
- def perform_playback(_record_name, record_path, _options)
288
- record = Record.load_or_create(record_path)
289
-
290
- raise RecordNotFoundError, "Record not found: #{record_path}" unless record.exists?
291
- raise RecordNotFoundError, "No commands found in record" if record.empty?
292
-
293
- # Setup replay mode - this will handle returning values for all commands
294
- recorder = Recorder.new(mode: :replay, record: record)
295
- recorder.setup_replay_stubs
296
-
297
- # Execute block (all commands will be stubbed with recorded values)
298
- output = yield
299
-
300
- RecordResult.new(
301
- output: output,
302
- mode: :playback,
303
- verified: true, # Always true for playback
304
- record_path: Pathname.new(record_path),
305
- commands: record.commands
306
- )
307
- end
308
-
309
- def build_record_path(name)
310
- backspin_dir = configuration.backspin_dir
311
- backspin_dir.mkpath
312
-
313
- File.join(backspin_dir, "#{name}.yml")
314
- end
315
176
  end
316
177
  end
data/release.rake ADDED
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+
5
+ # Simplified release tasks using gem-release
6
+ # Install with: gem install gem-release
7
+
8
+ namespace :release do
9
+ desc "Release a new version (bump, tag, release)"
10
+ task :version, [:level] do |t, args|
11
+ level = args[:level] || "patch"
12
+
13
+ # Pre-release checks
14
+ Rake::Task["release:check"].invoke
15
+
16
+ puts "\nReleasing #{level} version..."
17
+
18
+ # Use gem-release to bump, tag, and release to rubygems and github
19
+ sh "gem bump --version #{level} --github --tag --release"
20
+ end
21
+
22
+ desc "Create GitHub release for current version"
23
+ task :github do
24
+ version = Backspin::VERSION
25
+
26
+ if system("which gh > /dev/null 2>&1")
27
+ puts "\nCreating GitHub release for v#{version}..."
28
+ sh "gh release create v#{version} --title 'Release v#{version}' --generate-notes"
29
+ else
30
+ puts "\nGitHub CLI not found. Create release manually at:"
31
+ puts "https://github.com/rsanheim/backspin/releases/new?tag=v#{version}"
32
+ end
33
+ end
34
+
35
+ desc "Check if ready for release"
36
+ task :check do
37
+ require "open-uri"
38
+ require "json"
39
+
40
+ current_version = Backspin::VERSION
41
+ errors = []
42
+
43
+ # Check RubyGems for latest version
44
+ begin
45
+ gem_data = JSON.parse(URI.open("https://rubygems.org/api/v1/gems/backspin.json").read)
46
+ latest_version = gem_data["version"]
47
+
48
+ if Gem::Version.new(current_version) <= Gem::Version.new(latest_version)
49
+ errors << "Current version (#{current_version}) is not greater than latest released version (#{latest_version})"
50
+ else
51
+ puts "✓ Version #{current_version} is ready for release (latest: #{latest_version})"
52
+ end
53
+ rescue => e
54
+ puts "⚠ Could not check RubyGems version: #{e.message}"
55
+ end
56
+
57
+ # Check git status
58
+ if system("git diff --quiet && git diff --cached --quiet")
59
+ puts "✓ No uncommitted changes"
60
+ else
61
+ errors << "You have uncommitted changes"
62
+ end
63
+
64
+ # Check branch
65
+ current_branch = `git rev-parse --abbrev-ref HEAD`.strip
66
+ if current_branch != "main"
67
+ puts "⚠ Not on main branch (currently on #{current_branch})"
68
+ print "Continue anyway? (y/N): "
69
+ response = $stdin.gets.chomp
70
+ errors << "Not on main branch" unless response.downcase == "y"
71
+ else
72
+ puts "✓ On main branch"
73
+ end
74
+
75
+ unless errors.empty?
76
+ puts "\n❌ Cannot release:"
77
+ errors.each { |e| puts " - #{e}" }
78
+ abort
79
+ end
80
+
81
+ puts "\n✅ All checks passed!"
82
+ end
83
+ end
84
+
85
+ # Convenience tasks
86
+ desc "Release patch version"
87
+ task "release:patch" => ["release:version"]
88
+
89
+ desc "Release minor version"
90
+ task "release:minor" do
91
+ Rake::Task["release:version"].invoke("minor")
92
+ end
93
+
94
+ desc "Release major version"
95
+ task "release:major" do
96
+ Rake::Task["release:version"].invoke("major")
97
+ end
data/script/lint ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Run Standard Ruby linter
5
+ echo "Running Standard Ruby linter..."
6
+ bundle exec standardrb "$@"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backspin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Sanheim
@@ -9,6 +9,20 @@ bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: ostruct
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 0.5.0
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.5.0
12
26
  - !ruby/object:Gem::Dependency
13
27
  name: rspec-mocks
14
28
  requirement: !ruby/object:Gem::Requirement
@@ -24,19 +38,19 @@ dependencies:
24
38
  - !ruby/object:Gem::Version
25
39
  version: '3.0'
26
40
  - !ruby/object:Gem::Dependency
27
- name: ostruct
41
+ name: gem-release
28
42
  requirement: !ruby/object:Gem::Requirement
29
43
  requirements:
30
44
  - - "~>"
31
45
  - !ruby/object:Gem::Version
32
- version: 0.5.0
33
- type: :runtime
46
+ version: '2.2'
47
+ type: :development
34
48
  prerelease: false
35
49
  version_requirements: !ruby/object:Gem::Requirement
36
50
  requirements:
37
51
  - - "~>"
38
52
  - !ruby/object:Gem::Version
39
- version: 0.5.0
53
+ version: '2.2'
40
54
  description: Backspin is a Ruby library for characterization testing of command-line
41
55
  interfaces. Inspired by VCR's cassette-based approach, it records and replays CLI
42
56
  interactions to make testing faster and more deterministic.
@@ -47,6 +61,7 @@ extensions: []
47
61
  extra_rdoc_files: []
48
62
  files:
49
63
  - ".circleci/config.yml"
64
+ - ".gem_release.yml"
50
65
  - ".gitignore"
51
66
  - ".rspec"
52
67
  - ".standard.yml"
@@ -56,12 +71,69 @@ files:
56
71
  - Gemfile
57
72
  - Gemfile.lock
58
73
  - LICENSE.txt
74
+ - MATCH_ON_USAGE.md
59
75
  - README.md
60
76
  - Rakefile
61
77
  - backspin.gemspec
62
78
  - bin/rake
63
79
  - bin/rspec
64
80
  - bin/setup
81
+ - examples/match_on_example.rb
82
+ - fixtures/backspin/all_and_fields.yml
83
+ - fixtures/backspin/all_bypass_equality.yml
84
+ - fixtures/backspin/all_checks_equality.yml
85
+ - fixtures/backspin/all_for_logging.yml
86
+ - fixtures/backspin/all_matcher_basic.yml
87
+ - fixtures/backspin/all_matcher_custom.yml
88
+ - fixtures/backspin/all_matcher_demo.yml
89
+ - fixtures/backspin/all_matcher_test.yml
90
+ - fixtures/backspin/all_mode_filter.yml
91
+ - fixtures/backspin/all_no_short_circuit.yml
92
+ - fixtures/backspin/all_pass_field_fail.yml
93
+ - fixtures/backspin/all_short_circuit.yml
94
+ - fixtures/backspin/all_skips_equality.yml
95
+ - fixtures/backspin/all_with_equality.yml
96
+ - fixtures/backspin/all_with_fields.yml
97
+ - fixtures/backspin/combined_fail_demo.yml
98
+ - fixtures/backspin/combined_matcher_demo.yml
99
+ - fixtures/backspin/credential_filter.yml
100
+ - fixtures/backspin/echo_hello.yml
101
+ - fixtures/backspin/echo_verify.yml
102
+ - fixtures/backspin/episodes_filter.yml
103
+ - fixtures/backspin/failure_test.yml
104
+ - fixtures/backspin/field_matcher_demo.yml
105
+ - fixtures/backspin/field_matcher_values.yml
106
+ - fixtures/backspin/full_data_filter.yml
107
+ - fixtures/backspin/key_confusion_test.yml
108
+ - fixtures/backspin/match_on_any_fail.yml
109
+ - fixtures/backspin/match_on_bad_format.yml
110
+ - fixtures/backspin/match_on_fail.yml
111
+ - fixtures/backspin/match_on_invalid.yml
112
+ - fixtures/backspin/match_on_multiple.yml
113
+ - fixtures/backspin/match_on_nil.yml
114
+ - fixtures/backspin/match_on_other_fields.yml
115
+ - fixtures/backspin/match_on_run_bang.yml
116
+ - fixtures/backspin/match_on_run_bang_fail.yml
117
+ - fixtures/backspin/match_on_single.yml
118
+ - fixtures/backspin/mixed_calls.yml
119
+ - fixtures/backspin/multi_command.yml
120
+ - fixtures/backspin/multi_command_filter.yml
121
+ - fixtures/backspin/multi_field_filter.yml
122
+ - fixtures/backspin/multi_system.yml
123
+ - fixtures/backspin/nil_filter.yml
124
+ - fixtures/backspin/none_mode_test.yml
125
+ - fixtures/backspin/path_test.yml
126
+ - fixtures/backspin/playback_system.yml
127
+ - fixtures/backspin/playback_test.yml
128
+ - fixtures/backspin/stderr_test.yml
129
+ - fixtures/backspin/string_symbol_test.yml
130
+ - fixtures/backspin/system_echo.yml
131
+ - fixtures/backspin/system_false.yml
132
+ - fixtures/backspin/timestamp_test.yml
133
+ - fixtures/backspin/use_record_filter.yml
134
+ - fixtures/backspin/verify_system.yml
135
+ - fixtures/backspin/verify_system_diff.yml
136
+ - fixtures/backspin/version_test.yml
65
137
  - lib/backspin.rb
66
138
  - lib/backspin/command.rb
67
139
  - lib/backspin/command_diff.rb
@@ -70,6 +142,8 @@ files:
70
142
  - lib/backspin/record_result.rb
71
143
  - lib/backspin/recorder.rb
72
144
  - lib/backspin/version.rb
145
+ - release.rake
146
+ - script/lint
73
147
  homepage: https://github.com/rsanheim/backspin
74
148
  licenses:
75
149
  - MIT