Skip to content

Commit

Permalink
Add RSpec matcher #parse
Browse files Browse the repository at this point in the history
  • Loading branch information
skryukov committed Dec 21, 2021
1 parent 5e006ca commit a5c586d
Show file tree
Hide file tree
Showing 8 changed files with 287 additions and 395 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ Call `Paco::Combinators.index` to get `Paco::Index` representing the current off
index.parse("Paco") #=> #<struct Paco::Index pos=0, line=1, column=1>
```

- RSpec matcher `#parse`. ([@skryukov])

Add `require "paco/rspec"` to `spec_helper.rb` to enable a special RSpec matcher `#parse`:

```ruby
subject { string("Paco") }

it { is_expected.to parse("Paco") } # just checks if parser succeeds
it { is_expected.to parse("Paco").as("Paco") } # checks if parser result is eq to value passed to `#as`
it { is_expected.to parse("Paco").fully } # checks if parser result is the same as value passed to `#parse`
```


### Changed

Expand Down
14 changes: 14 additions & 0 deletions docs/paco.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- [Paco::Combinators: Text related methods](#pacocombinators-text-related-methods)
- [Paco::Parser methods](#pacoparser-methods)
- [Debugging](#debugging)
- [Test helpers](#test-helpers)

## Usage

Expand Down Expand Up @@ -831,3 +832,16 @@ end
# {:pos=>4, :status=>:failure, :depth=>2, :parser=>"end of file"}
# ]
```

## Test helpers

Paco provides a special RSpec helper, add `require "paco/rspec"` to `spec_helper.rb` to enable `#parse` matcher:

```ruby
subject { string("Paco") }

it { is_expected.to parse("Paco") } # just checks if parser succeeds
it { is_expected.to parse("Paco").as("Paco") } # checks if parser result is eq to value passed to `#as`
it { is_expected.to parse("Paco").fully } # checks if parser result is the same as value passed to `#parse`
it { is_expected.not_to parse("paco") } # checks if parser failed
```
4 changes: 4 additions & 0 deletions lib/paco/rspec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# frozen_string_literal: true

# Utils for testing Paco
require "paco/rspec/parse_matcher"
47 changes: 47 additions & 0 deletions lib/paco/rspec/parse_matcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

RSpec::Matchers.define(:parse) do |input|
chain :as do |expected_output = nil, &block|
@expected = expected_output
@block = block
end

chain :fully do
@expected = input
end

match do |parser|
@result = parser.parse(input)
return @block.call(@result) if @block
return @expected == @result if defined?(@expected)

true
rescue Paco::ParseError => e
@error_message = e.message
false
end

failure_message do |subject|
msg = "expected output of parsing #{input.inspect} with #{subject.inspect} to"
was = (@result ? "was #{@result.inspect}" : "raised an error #{@error_message}")
return "#{msg} meet block conditions, but it didn't. It #{was}" if @block
return "#{msg} equal #{@expected.inspect}, but it #{was}" if defined?(@expected)

"expected #{subject.inspect} to successfully parse #{input.inspect}, but it #{was}"
end

failure_message_when_negated do |subject|
msg = "expected output of parsing #{input.inspect} with #{subject.inspect} not to"
return "#{msg} meet block conditions, but it did" if @block
return "#{msg} equal #{@expected.inspect}" if defined?(@expected)

"expected #{subject.inspect} to not parse #{input.inspect}, but it did"
end

description do
return "parse #{input.inspect} with block conditions" if @block
return "parse #{input.inspect} as #{@expected.inspect}" if defined?(@expected)

"parse #{input.inspect}"
end
end
Loading

0 comments on commit a5c586d

Please sign in to comment.