mustermann19 0.3.1 → 0.3.1.1
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 +7 -0
- data/.travis.yml +4 -3
- data/README.md +680 -376
- data/lib/mustermann/ast/compiler.rb +13 -7
- data/lib/mustermann/ast/expander.rb +11 -5
- data/lib/mustermann/ast/node.rb +27 -1
- data/lib/mustermann/ast/param_scanner.rb +20 -0
- data/lib/mustermann/ast/parser.rb +131 -12
- data/lib/mustermann/ast/pattern.rb +45 -6
- data/lib/mustermann/ast/template_generator.rb +28 -0
- data/lib/mustermann/ast/validation.rb +5 -3
- data/lib/mustermann/composite.rb +103 -0
- data/lib/mustermann/expander.rb +1 -1
- data/lib/mustermann/express.rb +34 -0
- data/lib/mustermann/flask.rb +204 -0
- data/lib/mustermann/identity.rb +54 -0
- data/lib/mustermann/pattern.rb +186 -12
- data/lib/mustermann/pattern_cache.rb +49 -0
- data/lib/mustermann/pyramid.rb +25 -0
- data/lib/mustermann/regexp_based.rb +18 -1
- data/lib/mustermann/regular.rb +1 -1
- data/lib/mustermann/shell.rb +8 -0
- data/lib/mustermann/simple.rb +1 -1
- data/lib/mustermann/simple_match.rb +5 -0
- data/lib/mustermann/sinatra.rb +19 -5
- data/lib/mustermann/string_scanner.rb +314 -0
- data/lib/mustermann/template.rb +10 -0
- data/lib/mustermann/to_pattern.rb +11 -6
- data/lib/mustermann/version.rb +1 -1
- data/lib/mustermann.rb +52 -3
- data/mustermann.gemspec +1 -1
- data/spec/composite_spec.rb +147 -0
- data/spec/expander_spec.rb +15 -0
- data/spec/express_spec.rb +209 -0
- data/spec/flask_spec.rb +361 -0
- data/spec/flask_subclass_spec.rb +368 -0
- data/spec/identity_spec.rb +44 -0
- data/spec/mustermann_spec.rb +14 -0
- data/spec/pattern_spec.rb +7 -3
- data/spec/pyramid_spec.rb +101 -0
- data/spec/rails_spec.rb +76 -2
- data/spec/regular_spec.rb +25 -0
- data/spec/shell_spec.rb +33 -0
- data/spec/simple_spec.rb +25 -0
- data/spec/sinatra_spec.rb +184 -9
- data/spec/string_scanner_spec.rb +271 -0
- data/spec/support/expand_matcher.rb +7 -5
- data/spec/support/generate_template_matcher.rb +27 -0
- data/spec/support/pattern.rb +3 -0
- data/spec/support/scan_matcher.rb +63 -0
- data/spec/support.rb +2 -1
- data/spec/template_spec.rb +22 -0
- data/spec/to_pattern_spec.rb +49 -0
- metadata +47 -61
- data/internals.md +0 -64
@@ -0,0 +1,271 @@
|
|
1
|
+
require 'support'
|
2
|
+
require 'mustermann/string_scanner'
|
3
|
+
|
4
|
+
describe Mustermann::StringScanner do
|
5
|
+
include Support::ScanMatcher
|
6
|
+
|
7
|
+
subject(:scanner) { Mustermann::StringScanner.new(example_string) }
|
8
|
+
let(:example_string) { "foo bar" }
|
9
|
+
|
10
|
+
describe :scan do
|
11
|
+
it { should scan("foo") }
|
12
|
+
it { should scan(/foo/) }
|
13
|
+
it { should scan(:name) }
|
14
|
+
it { should scan(":name") }
|
15
|
+
|
16
|
+
it { should_not scan(" ") }
|
17
|
+
it { should_not scan("bar") }
|
18
|
+
|
19
|
+
example do
|
20
|
+
should scan("foo")
|
21
|
+
should scan(" ")
|
22
|
+
should scan("bar")
|
23
|
+
end
|
24
|
+
|
25
|
+
example do
|
26
|
+
scanner.position = 4
|
27
|
+
should scan("bar")
|
28
|
+
end
|
29
|
+
|
30
|
+
example do
|
31
|
+
should scan("foo")
|
32
|
+
scanner.reset
|
33
|
+
should scan("foo")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe :check do
|
38
|
+
it { should check("foo") }
|
39
|
+
it { should check(/foo/) }
|
40
|
+
it { should check(:name) }
|
41
|
+
it { should check(":name") }
|
42
|
+
|
43
|
+
it { should_not check(" ") }
|
44
|
+
it { should_not check("bar") }
|
45
|
+
|
46
|
+
example do
|
47
|
+
should check("foo")
|
48
|
+
should_not check(" ")
|
49
|
+
should_not check("bar")
|
50
|
+
should check("foo")
|
51
|
+
end
|
52
|
+
|
53
|
+
example do
|
54
|
+
scanner.position = 4
|
55
|
+
should check("bar")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe :scan_until do
|
60
|
+
it { should scan_until("foo") }
|
61
|
+
it { should scan_until(":name") }
|
62
|
+
it { should scan_until(" ") }
|
63
|
+
it { should scan_until("bar") }
|
64
|
+
it { should_not scan_until("baz") }
|
65
|
+
|
66
|
+
example do
|
67
|
+
should scan_until(" ")
|
68
|
+
should check("bar")
|
69
|
+
end
|
70
|
+
|
71
|
+
example do
|
72
|
+
should scan_until(" ")
|
73
|
+
scanner.reset
|
74
|
+
should scan("foo")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe :check_until do
|
79
|
+
it { should check_until("foo") }
|
80
|
+
it { should check_until(":name") }
|
81
|
+
it { should check_until(" ") }
|
82
|
+
it { should check_until("bar") }
|
83
|
+
it { should_not check_until("baz") }
|
84
|
+
|
85
|
+
example do
|
86
|
+
should check_until(" ")
|
87
|
+
should_not check("bar")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe :getch do
|
92
|
+
example { scanner.getch.should be == "f" }
|
93
|
+
|
94
|
+
example do
|
95
|
+
scanner.scan("foo")
|
96
|
+
scanner.getch.should be == " "
|
97
|
+
should scan("bar")
|
98
|
+
end
|
99
|
+
|
100
|
+
example do
|
101
|
+
scanner.getch
|
102
|
+
scanner.reset
|
103
|
+
should scan("foo")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe :<< do
|
108
|
+
example do
|
109
|
+
should_not scan_until("baz")
|
110
|
+
scanner << " baz"
|
111
|
+
scanner.to_s.should be == "foo bar baz"
|
112
|
+
should scan_until("baz")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe :eos? do
|
117
|
+
it { should_not be_eos }
|
118
|
+
example do
|
119
|
+
scanner.position = 7
|
120
|
+
should be_eos
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe :beginning_of_line? do
|
125
|
+
let(:example_string) { "foo\nbar" }
|
126
|
+
it { should be_beginning_of_line }
|
127
|
+
|
128
|
+
example do
|
129
|
+
scanner.position = 2
|
130
|
+
should_not be_beginning_of_line
|
131
|
+
end
|
132
|
+
|
133
|
+
example do
|
134
|
+
scanner.position = 3
|
135
|
+
should_not be_beginning_of_line
|
136
|
+
end
|
137
|
+
|
138
|
+
example do
|
139
|
+
scanner.position = 4
|
140
|
+
should be_beginning_of_line
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe :rest do
|
145
|
+
example { scanner.rest.should be == "foo bar" }
|
146
|
+
example do
|
147
|
+
scanner.position = 4
|
148
|
+
scanner.rest.should be == "bar"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe :rest_size do
|
153
|
+
example { scanner.rest_size.should be == 7 }
|
154
|
+
example do
|
155
|
+
scanner.position = 4
|
156
|
+
scanner.rest_size.should be == 3
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe :peek do
|
161
|
+
example { scanner.peek(3).should be == "foo" }
|
162
|
+
|
163
|
+
example do
|
164
|
+
scanner.peek(3).should be == "foo"
|
165
|
+
scanner.peek(3).should be == "foo"
|
166
|
+
end
|
167
|
+
|
168
|
+
example do
|
169
|
+
scanner.position = 4
|
170
|
+
scanner.peek(3).should be == "bar"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe :inspect do
|
175
|
+
example { scanner.inspect.should be == '#<Mustermann::StringScanner 0/7 @ "foo bar">' }
|
176
|
+
example do
|
177
|
+
scanner.position = 4
|
178
|
+
scanner.inspect.should be == '#<Mustermann::StringScanner 4/7 @ "foo bar">'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe :[] do
|
183
|
+
example do
|
184
|
+
should scan(:name)
|
185
|
+
scanner['name'].should be == "foo bar"
|
186
|
+
end
|
187
|
+
|
188
|
+
example do
|
189
|
+
should scan(:name, capture: /\S+/)
|
190
|
+
scanner['name'].should be == "foo"
|
191
|
+
should scan(" :name", capture: /\S+/)
|
192
|
+
scanner['name'].should be == "bar"
|
193
|
+
end
|
194
|
+
|
195
|
+
example do
|
196
|
+
should scan(":a", capture: /\S+/)
|
197
|
+
should scan(" :b", capture: /\S+/)
|
198
|
+
scanner['a'].should be == "foo"
|
199
|
+
scanner['b'].should be == "bar"
|
200
|
+
end
|
201
|
+
|
202
|
+
example do
|
203
|
+
a = scanner.scan(":a", capture: /\S+/)
|
204
|
+
b = scanner.scan(" :b", capture: /\S+/)
|
205
|
+
a.params['a'].should be == 'foo'
|
206
|
+
b.params['b'].should be == 'bar'
|
207
|
+
a.params['b'].should be_nil
|
208
|
+
b.params['a'].should be_nil
|
209
|
+
end
|
210
|
+
|
211
|
+
example do
|
212
|
+
result = scanner.check(":a", capture: /\S+/)
|
213
|
+
result.params['a'].should be == 'foo'
|
214
|
+
scanner['a'].should be_nil
|
215
|
+
end
|
216
|
+
|
217
|
+
example do
|
218
|
+
should scan(:name)
|
219
|
+
scanner.reset
|
220
|
+
scanner['name'].should be_nil
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
describe :unscan do
|
225
|
+
example do
|
226
|
+
should scan(:name, capture: /\S+/)
|
227
|
+
scanner['name'].should be == "foo"
|
228
|
+
should scan(" :name", capture: /\S+/)
|
229
|
+
scanner['name'].should be == "bar"
|
230
|
+
scanner.unscan
|
231
|
+
scanner['name'].should be == "foo"
|
232
|
+
scanner.rest.should be == " bar"
|
233
|
+
end
|
234
|
+
|
235
|
+
example do
|
236
|
+
should scan_until(" ")
|
237
|
+
scanner.unscan
|
238
|
+
scanner.rest.should be == "foo bar"
|
239
|
+
end
|
240
|
+
|
241
|
+
example do
|
242
|
+
expect { scanner.unscan }.to raise_error(Mustermann::StringScanner::ScanError,
|
243
|
+
'unscan failed: previous match record not exist')
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe :terminate do
|
248
|
+
example do
|
249
|
+
scanner.terminate
|
250
|
+
scanner.should be_eos
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
describe :to_h do
|
255
|
+
example { scanner.to_h.should be == {} }
|
256
|
+
example do
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
describe :to_s do
|
261
|
+
example { scanner.to_s.should be == "foo bar" }
|
262
|
+
end
|
263
|
+
|
264
|
+
describe :clear_cache do
|
265
|
+
example do
|
266
|
+
scanner.scan("foo")
|
267
|
+
Mustermann::StringScanner.clear_cache
|
268
|
+
Mustermann::StringScanner.cache_size.should be == 0
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
@@ -1,8 +1,9 @@
|
|
1
|
-
RSpec::Matchers.define :expand do |values = {}|
|
1
|
+
RSpec::Matchers.define :expand do |behavior = nil, values = {}|
|
2
|
+
values, behavior = behavior, nil if behavior.kind_of?(Hash)
|
2
3
|
match do |pattern|
|
3
4
|
@string ||= nil
|
4
5
|
begin
|
5
|
-
expanded = pattern.expand(values)
|
6
|
+
expanded = pattern.expand(behavior, values)
|
6
7
|
rescue Exception
|
7
8
|
false
|
8
9
|
else
|
@@ -15,8 +16,9 @@ RSpec::Matchers.define :expand do |values = {}|
|
|
15
16
|
end
|
16
17
|
|
17
18
|
failure_message do |pattern|
|
18
|
-
message =
|
19
|
-
|
19
|
+
message = "expected %p to be expandable with %p" % [pattern, values]
|
20
|
+
message << " (%p behavior)" % behavior if behavior
|
21
|
+
expanded = pattern.expand(behavior, values)
|
20
22
|
message << " and result in %p, but got %p" % [@string, expanded] if @string
|
21
23
|
message
|
22
24
|
end
|
@@ -24,4 +26,4 @@ RSpec::Matchers.define :expand do |values = {}|
|
|
24
26
|
failure_message_when_negated do |pattern|
|
25
27
|
"expected %p not to be expandable with %p" % [pattern, values]
|
26
28
|
end
|
27
|
-
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
RSpec::Matchers.define :generate_template do |template|
|
2
|
+
match { |pattern| pattern.to_templates.include? template }
|
3
|
+
|
4
|
+
failure_message do |pattern|
|
5
|
+
"expected %p to generate template %p, but only generated %s" % [
|
6
|
+
pattern, template, pattern.to_templates.map(&:inspect).join(', ')
|
7
|
+
]
|
8
|
+
end
|
9
|
+
|
10
|
+
failure_message_when_negated do |pattern|
|
11
|
+
"expected %p not to generate template %p" % [ pattern, template ]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
RSpec::Matchers.define :generate_templates do |*templates|
|
16
|
+
match { |pattern| pattern.to_templates.sort == templates.sort }
|
17
|
+
|
18
|
+
failure_message do |pattern|
|
19
|
+
"expected %p to generate templates %p, but generated %p" % [
|
20
|
+
pattern, templates.sort, pattern.to_templates.sort
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
failure_message_when_negated do |pattern|
|
25
|
+
"expected %p not to generate templates %p" % [ pattern, templates ]
|
26
|
+
end
|
27
|
+
end
|
data/spec/support/pattern.rb
CHANGED
@@ -2,6 +2,8 @@ require 'timeout'
|
|
2
2
|
|
3
3
|
module Support
|
4
4
|
module Pattern
|
5
|
+
extend RSpec::Matchers::DSL
|
6
|
+
|
5
7
|
def pattern(pattern, options = nil, &block)
|
6
8
|
description = "pattern %p" % pattern
|
7
9
|
|
@@ -17,6 +19,7 @@ module Support
|
|
17
19
|
its(:to_s) { should be == pattern }
|
18
20
|
its(:inspect) { should be == "#<#{described_class}:#{pattern.inspect}>" }
|
19
21
|
its(:names) { should be_an(Array) }
|
22
|
+
its(:to_templates) { should be == [pattern] } if described_class.name == "Mustermann::Template"
|
20
23
|
|
21
24
|
example 'string should be immune to external change' do
|
22
25
|
subject.to_s.replace "NOT THE PATTERN"
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Support
|
2
|
+
module ScanMatcher
|
3
|
+
extend RSpec::Matchers::DSL
|
4
|
+
|
5
|
+
def scan(pattern, options = {})
|
6
|
+
give_scan_result(:scan, pattern, options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def check(pattern, options = {})
|
10
|
+
give_scan_result(:check, pattern, options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def scan_until(pattern, options = {})
|
14
|
+
give_scan_result(:scan_until, pattern, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def check_until(pattern, options = {})
|
18
|
+
give_scan_result(:check_until, pattern, options)
|
19
|
+
end
|
20
|
+
|
21
|
+
matcher :give_scan_result do |method_name, pattern, options = {}|
|
22
|
+
def result_expectations
|
23
|
+
@result_expectations ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
def expect_result(description, expected, &block)
|
27
|
+
result_expectations << Proc.new do |result|
|
28
|
+
if !block.call(result)
|
29
|
+
"expected %p to %s %p matching %s" % [ result.scanner, method_name, pattern, description ]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
match do |scanner|
|
35
|
+
scanned = scanner.public_send(method_name, pattern, options)
|
36
|
+
scanned and result_expectations.all? { |e| !e.call(scanned) }
|
37
|
+
end
|
38
|
+
|
39
|
+
chain(:matching_substring) do |substring|
|
40
|
+
expected_result("the substring %p" % substring) { |r| r.to_s == substring }
|
41
|
+
end
|
42
|
+
|
43
|
+
chain(:matching_length) do |length|
|
44
|
+
expected_result("%d characters" % length) { |r| r.length == length }
|
45
|
+
end
|
46
|
+
|
47
|
+
chain(:matching_params) do |params|
|
48
|
+
expected_result("with params %p" % [params]) { |r| r.params == params }
|
49
|
+
end
|
50
|
+
|
51
|
+
failure_message do |scanner|
|
52
|
+
if scanned = scanner.public_send(method_name, pattern, options = {})
|
53
|
+
message = result_expectations.inject(nil) { |m,e| m || e.call(scanned) }
|
54
|
+
end
|
55
|
+
message || "expected %p to %s %p" % [ scanner, method_name, pattern ]
|
56
|
+
end
|
57
|
+
|
58
|
+
failure_message_when_negated do |scanner|
|
59
|
+
"expected %p not to %s %p" % [ scanner, method_name, pattern ]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/spec/support.rb
CHANGED
data/spec/template_spec.rb
CHANGED
@@ -8,6 +8,9 @@ describe Mustermann::Template do
|
|
8
8
|
pattern '' do
|
9
9
|
it { should match('') }
|
10
10
|
it { should_not match('/') }
|
11
|
+
|
12
|
+
it { should respond_to(:expand) }
|
13
|
+
it { should respond_to(:to_templates) }
|
11
14
|
end
|
12
15
|
|
13
16
|
pattern '/' do
|
@@ -812,4 +815,23 @@ describe Mustermann::Template do
|
|
812
815
|
to raise_error(Mustermann::ParseError, 'unexpected end of string while parsing "foo{bar"')
|
813
816
|
end
|
814
817
|
end
|
818
|
+
|
819
|
+
context "peeking" do
|
820
|
+
subject(:pattern) { Mustermann::Template.new("{name}bar") }
|
821
|
+
|
822
|
+
describe :peek_size do
|
823
|
+
example { pattern.peek_size("foo%20bar/blah") .should be == "foo%20bar".size }
|
824
|
+
example { pattern.peek_size("/foo bar") .should be_nil }
|
825
|
+
end
|
826
|
+
|
827
|
+
describe :peek_match do
|
828
|
+
example { pattern.peek_match("foo%20bar/blah") .to_s .should be == "foo%20bar" }
|
829
|
+
example { pattern.peek_match("/foo bar") .should be_nil }
|
830
|
+
end
|
831
|
+
|
832
|
+
describe :peek_params do
|
833
|
+
example { pattern.peek_params("foo%20bar/blah") .should be == [{"name" => "foo "}, "foo%20bar".size] }
|
834
|
+
example { pattern.peek_params("/foo bar") .should be_nil }
|
835
|
+
end
|
836
|
+
end
|
815
837
|
end
|
data/spec/to_pattern_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'support'
|
2
2
|
require 'mustermann/to_pattern'
|
3
|
+
require 'delegate'
|
3
4
|
|
4
5
|
describe Mustermann::ToPattern do
|
5
6
|
context String do
|
@@ -12,9 +13,57 @@ describe Mustermann::ToPattern do
|
|
12
13
|
example { //.to_pattern(type: :rails) .should be_a(Mustermann::Regular) }
|
13
14
|
end
|
14
15
|
|
16
|
+
context Symbol do
|
17
|
+
example { :foo.to_pattern .should be_a(Mustermann::Sinatra) }
|
18
|
+
example { :foo.to_pattern(type: :rails) .should be_a(Mustermann::Sinatra) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context Array do
|
22
|
+
example { [:foo, :bar].to_pattern .should be_a(Mustermann::Composite) }
|
23
|
+
example { [:foo, :bar].to_pattern(type: :rails) .should be_a(Mustermann::Composite) }
|
24
|
+
end
|
25
|
+
|
15
26
|
context Mustermann::Pattern do
|
16
27
|
subject(:pattern) { Mustermann.new('') }
|
17
28
|
example { pattern.to_pattern.should be == pattern }
|
18
29
|
example { pattern.to_pattern(type: :rails).should be_a(Mustermann::Sinatra) }
|
19
30
|
end
|
31
|
+
|
32
|
+
context 'custom class' do
|
33
|
+
let(:example_class) do
|
34
|
+
Class.new do
|
35
|
+
include Mustermann::ToPattern
|
36
|
+
def to_s
|
37
|
+
":foo/:bar"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
example { example_class.new.to_pattern .should be_a(Mustermann::Sinatra) }
|
43
|
+
example { example_class.new.to_pattern(type: :rails) .should be_a(Mustermann::Rails) }
|
44
|
+
example { Mustermann.new(example_class.new) .should be_a(Mustermann::Sinatra) }
|
45
|
+
example { Mustermann.new(example_class.new, type: :rails) .should be_a(Mustermann::Rails) }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'primitive delegate' do
|
49
|
+
let(:example_class) do
|
50
|
+
Class.new(DelegateClass(Array)) do
|
51
|
+
include Mustermann::ToPattern
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
example { example_class.new([:foo, :bar]).to_pattern .should be_a(Mustermann::Composite) }
|
56
|
+
example { example_class.new([:foo, :bar]).to_pattern(type: :rails) .should be_a(Mustermann::Composite) }
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'primitive subclass' do
|
60
|
+
let(:example_class) do
|
61
|
+
Class.new(Array) do
|
62
|
+
include Mustermann::ToPattern
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
example { example_class.new([:foo, :bar]).to_pattern .should be_a(Mustermann::Composite) }
|
67
|
+
example { example_class.new([:foo, :bar]).to_pattern(type: :rails) .should be_a(Mustermann::Composite) }
|
68
|
+
end
|
20
69
|
end
|