rspec_fixtures 0.3.0 → 0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 824a68775a4a3f44ab6c7f897de7df47431f7b1b233e4f3224cb71b9dc4ca5a1
4
- data.tar.gz: 1d8830af166d11392768543e9ab6cc924e1dc9c985c52f1906f44da3d94b77f1
3
+ metadata.gz: 45b4a358e1d0676243ab8e196d564a24004925cea26a4e4e7fea2260c207947b
4
+ data.tar.gz: 24e457d02d6cb4508da343bbce5bf55bc8c69978db0590a2fc78ea305c1aeef5
5
5
  SHA512:
6
- metadata.gz: b8a0198c92a30cbd6600598b41d74df121f64d96202d368a187a04027689301175c256ca672cfe2d34aa7e63a152382f4c27b3a771220b0bc6dbc68fa6a2d3eb
7
- data.tar.gz: 7d5687f648b7e9e5b3e2ff733a3e91495c4279103726069f91c9d53d5872386169a221c4f64c78bac55dc4127cea6bd0713972fc0ed80c34379d0c26815c2a62
6
+ metadata.gz: 5b0ba1c117b24f8f5eda492b846d6e398e284243823a64039fb8178a5921f19eaf5ccf55880a3f370a0d7f5b16f2dff174b64f994ca748fb4429ad515066ebe7
7
+ data.tar.gz: 2143684b0101b840ef918a91d8eaf55ae87cac86bcfd2772207c8c24dc93b96f57cf10bb248a79302a7e83a7d85d4f551b05bcc216779c342a649016d82b3cee
data/README.md CHANGED
@@ -17,6 +17,7 @@ content.
17
17
  ---
18
18
 
19
19
 
20
+
20
21
  Install
21
22
  --------------------------------------------------
22
23
 
@@ -31,6 +32,7 @@ gem 'rspec_fixtures'
31
32
  ```
32
33
 
33
34
 
35
+
34
36
  Usage
35
37
  --------------------------------------------------
36
38
 
@@ -51,10 +53,12 @@ describe 'ls' do
51
53
  end
52
54
  ```
53
55
 
56
+
57
+
54
58
  Matchers
55
59
  --------------------------------------------------
56
60
 
57
- ### `match_fixture`
61
+ ### `match_fixture` - Compare Strings
58
62
 
59
63
  Compare a string with a pre-approved fixture.
60
64
 
@@ -62,7 +66,8 @@ Compare a string with a pre-approved fixture.
62
66
  expect('some string').to match_fixture('fixture_filename')
63
67
  ```
64
68
 
65
- ### `output_fixture`
69
+
70
+ ### `output_fixture` - Compare STDOUT/STDERR
66
71
 
67
72
  Compare an output (stdout or stderr) with a pre-approved fixture.
68
73
 
@@ -75,6 +80,24 @@ expect{ $stderr.puts "hello" }.to output_fixture('fixture_filename').to_stderr
75
80
  ```
76
81
 
77
82
 
83
+ ### `diff` - String Similarity
84
+
85
+ Adding `diff(distance)` to either `match_fixture` or `output_fixture` will
86
+ change the matching behavior. Instead of expecting the strings to be exactly
87
+ the same, using `diff` compares the strings using the Levenshtein text
88
+ similarity algorithm.
89
+
90
+ In the below example, we allow up to 5 characters to be different.
91
+
92
+ ```ruby
93
+ expect('some string').to match_fixture('fixture_filename').diff(5)
94
+ expect{ puts 'some string' }.to output_fixture('fixture_filename').diff(5)
95
+ ```
96
+
97
+ Distance is measured using the Levenshtein algorithm.
98
+
99
+
100
+
78
101
  Configuration
79
102
  --------------------------------------------------
80
103
 
@@ -90,6 +113,7 @@ RSpec.configure do |config|
90
113
  end
91
114
  ```
92
115
 
116
+
93
117
  ### `fixtures_path`
94
118
 
95
119
  By default, fixtures are stored in `spec/fixtures`. To change the path,
@@ -99,4 +123,5 @@ add this to your `spec_helper`.
99
123
  RSpec.configure do |config|
100
124
  config.fixtures_path = 'spec/anywhere/else'
101
125
  end
102
- ```
126
+ ```
127
+
@@ -2,6 +2,8 @@ require 'colsole'
2
2
  require 'io/console'
3
3
 
4
4
  module RSpecFixtures
5
+
6
+ # Handles user input and interactive fixture approvals
5
7
  class ApprovalHandler
6
8
  include Colsole
7
9
 
@@ -1,52 +1,98 @@
1
1
  module RSpecFixtures
2
2
  module Matchers
3
3
 
4
+ # A base matcher for fixture approvals
4
5
  class Base
5
- attr_reader :fixture_name, :actual
6
+ attr_reader :fixture_name, :actual, :distance, :actual_distance
6
7
 
7
8
  def initialize(fixture_name=nil)
8
9
  @fixture_name = fixture_name
9
10
  end
10
11
 
12
+ # Called by RSpec. This will be overridden by child matchers.
11
13
  def matches?(actual)
12
- @actual = actual
13
- false
14
+ @actual ||= actual
15
+
16
+ success = strings_match?
17
+
18
+ if success or !interactive?
19
+ success
20
+ else
21
+ approve_fixture
22
+ end
23
+ end
24
+
25
+ # Provides a chained matcher to do something like:
26
+ # `expect(string).to match_fixture(file).diff(10)
27
+ # The distance argument is the max allowed Levenshtein Distance.
28
+ def diff(distance)
29
+ @distance = distance
30
+ self
14
31
  end
15
32
 
33
+ # Returns the expected value, from a fixture file
16
34
  def expected
17
35
  @expected ||= expected!
18
36
  end
19
37
 
38
+ # Called by RSpec when there is a failure
20
39
  def failure_message
21
- "expected #{actual}\nto match #{expected}"
40
+ result = "expected: #{actual}\nto match: #{expected}"
41
+
42
+ if distance
43
+ result = "#{result}\n(actual distance is #{actual_distance} instead of the expected #{distance})"
44
+ end
45
+
46
+ result
22
47
  end
23
48
 
49
+ # Lets RSpec know these matchers support diffing
24
50
  def diffable?
25
51
  true
26
52
  end
27
53
 
54
+ # Returns true if RSpec is configured to allow interactivity.
55
+ # By default, interactivity is enabled unless the environment
56
+ # variable `CI` is set.
28
57
  def interactive?
29
58
  RSpec.configuration.interactive_fixtures
30
59
  end
31
60
 
61
+ # Returns the path to the fixtures directory.
62
+ # Default: `spec/fixtures`
32
63
  def fixtures_dir
33
64
  RSpec.configuration.fixtures_path
34
65
  end
35
66
 
67
+ # Returns the path to the fixture file
36
68
  def fixture_file
37
69
  "#{fixtures_dir}/#{fixture_name}"
38
70
  end
39
71
 
40
72
  protected
41
73
 
74
+ # Asks for user approval. Used by child classes.
42
75
  def approve_fixture
43
76
  approval_handler = ApprovalHandler.new
44
77
  approval_handler.run expected, actual, fixture_file
45
78
  end
46
79
 
80
+ # Returns the actual fixture file content.
47
81
  def expected!
48
82
  File.exist?(fixture_file) ? File.read(fixture_file) : ''
49
83
  end
84
+
85
+ # Do the actual test. If .diff() was used, then distance will be
86
+ # set and then we "levenshtein it". Otherwise, compare with ==
87
+ def strings_match?
88
+ if distance
89
+ @actual_distance = String::Similarity.levenshtein_distance expected, actual
90
+ @actual_distance <= distance
91
+ else
92
+ actual == expected
93
+ end
94
+ end
95
+
50
96
  end
51
97
 
52
98
  end
@@ -1,18 +1,14 @@
1
+ require 'string-similarity'
2
+
1
3
  module RSpecFixtures
2
4
  module Matchers
5
+ # Adds the matcher to RSpec:
6
+ # `expect(string).to match_fixture(file)`
3
7
  def match_fixture(expected)
4
8
  MatchFixture.new expected
5
9
  end
6
10
 
7
11
  class MatchFixture < Base
8
- def matches?(actual)
9
- @actual = actual
10
- if actual == expected or !interactive?
11
- actual == expected
12
- else
13
- approve_fixture
14
- end
15
- end
16
12
  end
17
13
 
18
14
  end
@@ -1,30 +1,34 @@
1
1
  module RSpecFixtures
2
2
  module Matchers
3
+ # Adds the matcher to RSpec:
4
+ # `expect{ stream }.to output_fixture(file)`
3
5
  def output_fixture(expected)
4
6
  OutputFixture.new expected
5
7
  end
6
8
 
7
9
  class OutputFixture < Base
10
+ # Called by RSpec
8
11
  def matches?(block)
9
12
  return false unless block.is_a? Proc
10
13
  @actual = stream_capturer.capture block
11
-
12
- if actual == expected or !interactive?
13
- actual == expected
14
- else
15
- approve_fixture
16
- end
14
+ super
17
15
  end
18
16
 
17
+ # Lets RSpec know that this matcher requires a block.
19
18
  def supports_block_expectations?
20
19
  true
21
20
  end
22
21
 
22
+ # Adds chained matcher, to allow:
23
+ # expect{ stream }.to output_fixture(file).to_stdout
24
+ # This is the default, and only provided for completeness.
23
25
  def to_stdout
24
26
  @stream_capturer = CaptureStdout
25
27
  self
26
28
  end
27
29
 
30
+ # Adds chained matcher, to allow:
31
+ # expect{ stream }.to output_fixture(file).to_stderr
28
32
  def to_stderr
29
33
  @stream_capturer = CaptureStderr
30
34
  self
@@ -1,3 +1,4 @@
1
+ # Add our custom matchers and configuration options to RSpec
1
2
  if defined? RSpec
2
3
  RSpec.configure do |config|
3
4
  config.include RSpecFixtures::Matchers
@@ -1,4 +1,6 @@
1
1
  module RSpecFixtures
2
+ # Capture stdout and stderr
3
+ #
2
4
  # These methods are borrowed from rspec's built in matchers
3
5
  # https://github.com/rspec/rspec-expectations/blob/add9b271ecb1d65f7da5bc8a9dd8c64d81d92303/lib/rspec/matchers/built_in/output.rb
4
6
  module CaptureStdout
@@ -1,3 +1,3 @@
1
1
  module RSpecFixtures
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec_fixtures
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-08 00:00:00.000000000 Z
11
+ date: 2018-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colsole
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0.9'
111
+ - !ruby/object:Gem::Dependency
112
+ name: string-similarity
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '2.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2.0'
111
125
  description: Automatic interactive fixtures for rspec
112
126
  email: db@dannyben.com
113
127
  executables: []