]> git.wincent.com - walrat.git/blob - spec/parser_state_spec.rb
Update to RSpec 3.1.0
[walrat.git] / spec / parser_state_spec.rb
1 # encoding: utf-8
2 # Copyright 2007-2014 Greg Hurrell. All rights reserved.
3 # Licensed under the terms of the BSD 2-clause license.
4
5 require 'spec_helper'
6
7 describe Walrat::ParserState do
8   before do
9     @base_string = 'this is the string to be parsed'
10     @state = Walrat::ParserState.new @base_string
11   end
12
13   it 'raises an ArgumentError if initialized with nil' do
14     expect do
15       Walrat::ParserState.new nil
16     end.to raise_error(ArgumentError, /nil string/)
17   end
18
19   it 'before parsing has started "remainder" should equal the entire string' do
20     @state.remainder.should == @base_string
21   end
22
23   it 'before parsing has started "remainder" should equal the entire string (when string is an empty string)' do
24     Walrat::ParserState.new('').remainder.should == ''
25   end
26
27   it 'before parsing has started "results" should be empty' do
28     @state.results.should be_empty
29   end
30
31   it '"parsed" should complain if passed nil' do
32     lambda { @state.parsed(nil) }.should raise_error(ArgumentError)
33   end
34
35   it '"skipped" should complain if passed nil' do
36     lambda { @state.skipped(nil) }.should raise_error(ArgumentError)
37   end
38
39   it '"parsed" should return the remainder of the string' do
40     @state.parsed('this is the ').should  == 'string to be parsed'
41     @state.parsed('string ').should       == 'to be parsed'
42     @state.parsed('to be parsed').should  == ''
43   end
44
45   it '"skipped" should return the remainder of the string' do
46     @state.skipped('this is the ').should == 'string to be parsed'
47     @state.skipped('string ').should      == 'to be parsed'
48     @state.skipped('to be parsed').should == ''
49   end
50
51   it '"results" should return an unwrapped parsed result (for single results)' do
52     @state.parsed('this')
53     @state.results.should == 'this'
54   end
55
56   it 'skipped substrings should not appear in "results"' do
57     @state.skipped('this')
58     @state.results.should be_empty
59   end
60
61   it 'should return an array of the parsed results (for multiple results)' do
62     @state.parsed('this ')
63     @state.parsed('is ')
64     @state.results.should == ['this ', 'is ']
65   end
66
67   it 'should work when the entire string is consumed in a single operation (using "parsed")' do
68     @state.parsed(@base_string).should == ''
69     @state.results.should == @base_string
70   end
71
72   it 'should work when the entire string is consumed in a single operation (using "skipped")' do
73     @state.skipped(@base_string).should == ''
74     @state.results.should be_empty
75   end
76
77   it '"parsed" should complain if passed something that doesn\'t respond to the "line_end" and "column_end" messages' do
78     # line_end
79     my_mock = double('Mock which does not implement #line_end').as_null_object
80     expect(my_mock).to receive(:line_end).and_raise(NoMethodError)
81     expect { @state.parsed(my_mock) }.to raise_error(NoMethodError)
82
83     # column_end
84     my_mock = double('Mock which does not implement #column_end').as_null_object
85     expect(my_mock).to receive(:column_end).and_raise(NoMethodError)
86     expect { @state.parsed(my_mock) }.to raise_error(NoMethodError)
87   end
88
89   it '"skipped" should complain if passed something that doesn\'t respond to the "line_end" and "column_end" messages' do
90     # line_end
91     my_mock = double('Mock which does not implement #line_end').as_null_object
92     expect(my_mock).to receive(:line_end).and_raise(NoMethodError)
93     expect { @state.skipped(my_mock) }.to raise_error(NoMethodError)
94
95     # column_end
96     my_mock = double('Mock which does not implement #column_end').as_null_object
97     expect(my_mock).to receive(:column_end).and_raise(NoMethodError)
98     expect { @state.skipped(my_mock) }.to raise_error(NoMethodError)
99   end
100
101   it 'should be able to mix use of "parsed" and "skipped" methods' do
102     # first example
103     @state.skipped('this is the ').should  == 'string to be parsed'
104     @state.results.should be_empty
105     @state.parsed('string ').should       == 'to be parsed'
106     @state.results.should == 'string '
107     @state.skipped('to be parsed').should  == ''
108     @state.results.should == 'string '
109
110     # second example (add this test to isolate a bug in another specification)
111     state = Walrat::ParserState.new('foo1...')
112     state.skipped('foo').should == '1...'
113     state.remainder.should == '1...'
114     state.results.should be_empty
115     state.parsed('1').should == '...'
116     state.remainder.should == '...'
117     state.results.should == '1'
118   end
119
120   it '"parsed" and "results" methods should work with multi-byte Unicode strings' do
121     # basic test
122     state = Walrat::ParserState.new('400€, foo')
123     state.remainder.should == '400€, foo'
124     state.parsed('40').should == '0€, foo'
125     state.results.should == '40'
126     state.parsed('0€, ').should == 'foo'
127     state.results.should == ['40', '0€, ']
128     state.parsed('foo').should == ''
129     state.results.should == ['40', '0€, ', 'foo']
130
131     # test with newlines before and after multi-byte chars
132     state = Walrat::ParserState.new("400\n or more €...\nfoo")
133     state.remainder.should == "400\n or more €...\nfoo"
134     state.parsed("400\n or more").should == " €...\nfoo"
135     state.results.should == "400\n or more"
136     state.parsed(' €..').should == ".\nfoo"
137     state.results.should == ["400\n or more", ' €..']
138     state.parsed(".\nfoo").should == ''
139     state.results.should == ["400\n or more", ' €..', ".\nfoo"]
140   end
141
142   it '"skipped" and "results" methods should work with multi-byte Unicode strings' do
143     state = Walrat::ParserState.new('400€, foo')
144     state.remainder.should == '400€, foo'
145     state.skipped('4').should == '00€, foo'
146     state.results.should be_empty
147     state.parsed('0').should == '0€, foo'
148     state.results.should == '0'
149     state.skipped('0€, ').should == 'foo'
150     state.results.should == '0'
151     state.parsed('foo').should == ''
152     state.results.should == ['0', 'foo']
153   end
154 end