cql 1.2.1 → 1.3.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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cql.rb +18 -11
  3. data/lib/cql/dsl.rb +14 -2
  4. data/lib/cql/filters.rb +12 -6
  5. data/lib/cql/map_reduce.rb +29 -11
  6. data/lib/cql/model_dsl.rb +18 -0
  7. data/lib/cql/queriable.rb +14 -0
  8. data/lib/cql/sso_filters.rb +3 -2
  9. data/lib/cql/version.rb +1 -1
  10. data/testing/cql_test_model.rb +42 -0
  11. data/testing/cucumber/features/clauses/as_clause.feature +136 -0
  12. data/testing/cucumber/features/clauses/from_clause.feature +126 -0
  13. data/testing/cucumber/features/clauses/select_clause.feature +117 -0
  14. data/testing/cucumber/features/clauses/transform_clause.feature +153 -0
  15. data/testing/cucumber/features/clauses/with_clause.feature +363 -0
  16. data/testing/cucumber/features/dsl.feature +77 -0
  17. data/testing/cucumber/features/model_querying.feature +18 -0
  18. data/testing/cucumber/features/repository.feature +23 -0
  19. data/testing/cucumber/step_definitions/query_steps.rb +7 -0
  20. data/testing/cucumber/step_definitions/setup_steps.rb +25 -0
  21. data/testing/cucumber/step_definitions/verification_steps.rb +78 -0
  22. data/testing/cucumber/support/env.rb +24 -0
  23. data/testing/cucumber/support/transforms.rb +3 -0
  24. data/testing/fixtures/features/combined/a/f1_4_scenarios_5_so.feature +59 -0
  25. data/testing/fixtures/features/combined/a/f2_7_scenarios_2_so.feature +43 -0
  26. data/testing/fixtures/features/combined/a/f3_2_scenarios_3_so.feature +30 -0
  27. data/testing/fixtures/features/combined/b/f1_1_tag.feature +6 -0
  28. data/testing/fixtures/features/combined/b/f2_2_tags.feature +6 -0
  29. data/testing/fixtures/features/combined/b/f3_3_tags.feature +6 -0
  30. data/testing/fixtures/features/examples/basic/test_with_scenarios.feature +15 -0
  31. data/testing/fixtures/features/examples/filters/tag_count/simple.feature +21 -0
  32. data/testing/fixtures/features/examples/filters/tag_count/simple2.feature +21 -0
  33. data/testing/fixtures/features/examples/filters/tags/simple.feature +34 -0
  34. data/testing/fixtures/features/examples/filters/tags2/simple.feature +34 -0
  35. data/testing/fixtures/features/examples/filters/tags2/simple2.feature +34 -0
  36. data/testing/fixtures/features/examples/multiple_examples/test_with_scenarios.feature +43 -0
  37. data/testing/fixtures/features/examples/name_filter/name.feature +19 -0
  38. data/testing/fixtures/features/got/Lannisters.feature +24 -0
  39. data/testing/fixtures/features/got/Starks.feature +18 -0
  40. data/testing/fixtures/features/scen_outlines/basic/test_with_scenarios.feature +15 -0
  41. data/testing/fixtures/features/scen_outlines/filters/tag_count/simple.feature +21 -0
  42. data/testing/fixtures/features/scen_outlines/filters/tag_count/simple2.feature +21 -0
  43. data/testing/fixtures/features/scen_outlines/filters/tags/simple.feature +34 -0
  44. data/testing/fixtures/features/scen_outlines/filters/tags2/simple.feature +34 -0
  45. data/testing/fixtures/features/scen_outlines/filters/tags2/simple2.feature +34 -0
  46. data/testing/fixtures/features/scen_outlines/line_count/simple.feature +12 -0
  47. data/testing/fixtures/features/scen_outlines/line_count/simple2.feature +16 -0
  48. data/testing/fixtures/features/scen_outlines/line_filter/ll.feature +13 -0
  49. data/testing/fixtures/features/scen_outlines/multiple_examples/test_with_scenarios.feature +43 -0
  50. data/testing/fixtures/features/scen_outlines/name_filter/name.feature +19 -0
  51. data/testing/fixtures/features/scenario/line_count/simple.feature +9 -0
  52. data/testing/fixtures/features/scenario/line_count/simple2.feature +12 -0
  53. data/testing/fixtures/features/scenario/line_filter/ll.feature +9 -0
  54. data/testing/fixtures/features/scenario/name_filter/name.feature +13 -0
  55. data/testing/fixtures/features/scenario/simple/simple.feature +8 -0
  56. data/testing/fixtures/features/scenario/simple/test.feature +9 -0
  57. data/testing/fixtures/features/scenario/simple/test2.feature +5 -0
  58. data/testing/fixtures/features/scenario/simple/test_full.feature +22 -0
  59. data/testing/fixtures/features/scenario/simple2/test_full.feature +23 -0
  60. data/testing/fixtures/features/scenario/table/simple.feature +11 -0
  61. data/testing/fixtures/features/scenario/tag_count/simple.feature +17 -0
  62. data/testing/fixtures/features/scenario/tag_count/simple2.feature +17 -0
  63. data/testing/fixtures/features/scenario/tagged_features/simple.feature +8 -0
  64. data/testing/fixtures/features/scenario/tagged_features/test.feature +10 -0
  65. data/testing/fixtures/features/scenario/tagged_features/test2.feature +6 -0
  66. data/testing/fixtures/features/scenario/tagged_features/test_full.feature +22 -0
  67. data/testing/fixtures/features/scenario/tags/simple.feature +24 -0
  68. data/testing/fixtures/features/scenario/tags2/simple.feature +24 -0
  69. data/testing/fixtures/features/scenario/tags2/simple2.feature +24 -0
  70. data/testing/fixtures/features/scenario/tags3/simple.feature +21 -0
  71. data/testing/gemfiles/cuke_modeler0.gemfile +30 -0
  72. data/testing/gemfiles/cuke_modeler1.gemfile +30 -0
  73. data/testing/rspec/spec/dsl_spec.rb +600 -0
  74. data/testing/rspec/spec/filter_example_spec.rb +65 -0
  75. data/testing/rspec/spec/filter_feature_dsl_spec.rb +286 -0
  76. data/testing/rspec/spec/filter_sso_spec.rb +202 -0
  77. data/testing/rspec/spec/line_count_filterable_specs.rb +74 -0
  78. data/testing/rspec/spec/line_filterable_specs.rb +52 -0
  79. data/testing/rspec/spec/map_reduce_spec.rb +135 -0
  80. data/testing/rspec/spec/model_query_spec.rb +49 -0
  81. data/testing/rspec/spec/multiple_queries_spec.rb +24 -0
  82. data/testing/rspec/spec/name_filterable_specs.rb +52 -0
  83. data/testing/rspec/spec/queriable_specs.rb +45 -0
  84. data/testing/rspec/spec/repository_spec.rb +82 -0
  85. data/testing/rspec/spec/select_feature_dsl_spec.rb +114 -0
  86. data/testing/rspec/spec/select_scen_outline_dsl_spec.rb +234 -0
  87. data/testing/rspec/spec/select_scenario_dsl_spec.rb +132 -0
  88. data/testing/rspec/spec/spec_helper.rb +42 -0
  89. data/testing/rspec/spec/tag_filterable_specs.rb +107 -0
  90. metadata +170 -5
@@ -0,0 +1,600 @@
1
+ require "#{File.dirname(__FILE__)}/spec_helper"
2
+
3
+
4
+ describe 'an object that uses the DSL' do
5
+
6
+
7
+ let(:nodule) { CQL::Dsl }
8
+ let(:dsl_enabled_object) { Object.new.extend(nodule) }
9
+
10
+
11
+ describe 'invalid query structure' do
12
+
13
+ it "will complain if no 'from' clause is specified" do
14
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
15
+
16
+ expect {
17
+ gs.query do
18
+ select
19
+ features
20
+ end
21
+ }.to raise_error(ArgumentError, "A query must specify a 'from' clause")
22
+ end
23
+
24
+ it "will complain if no 'select' clause is specified" do
25
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
26
+
27
+ expect {
28
+ gs.query do
29
+ from features
30
+ end
31
+ }.to raise_error(ArgumentError, "A query must specify a 'select' clause")
32
+ end
33
+
34
+ end
35
+
36
+
37
+ describe 'clause ordering' do
38
+
39
+ it 'handles intermixed clauses' do
40
+ # Clause ordering doesn't matter as long as any given type of clause is ordered correctly with respect to its multiple uses
41
+
42
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
43
+
44
+ results = gs.query do
45
+ with { |scenario| scenario.name =~ /slurping/ }
46
+ as thing1
47
+ transform :self => lambda { |thing1| 1 }
48
+ select :self
49
+ as thing2
50
+ with scenarios => lambda { |scenario| scenario.name =~ /3/ }
51
+ from scenarios
52
+ select :self
53
+ transform :self => lambda { |thing2| 2 }
54
+ select name
55
+ end
56
+
57
+ expect(results.first).to eq('thing1' => 1, 'thing2' => 2, 'name' => 'Testing the slurping 3')
58
+ end
59
+
60
+ end
61
+
62
+
63
+ describe "select" do
64
+
65
+ it 'knows how to select attributes' do
66
+ expect(dsl_enabled_object).to respond_to(:select)
67
+ end
68
+
69
+ it 'selects one or more attributes' do
70
+ expect(dsl_enabled_object.method(:select).arity).to eq(-1)
71
+ end
72
+
73
+ it 'correctly selects a single attribute from a model' do
74
+ model = CukeModeler::CqlTestModel.new
75
+ model.attribute_1 = 'foo'
76
+
77
+ repo = CQL::Repository.new(model)
78
+
79
+ result = repo.query do
80
+ select attribute_1
81
+ from cql_test_model
82
+ end
83
+
84
+
85
+ expect(result).to eq([{'attribute_1' => 'foo'}])
86
+ end
87
+
88
+ it 'correctly selects multiple attributes from a model' do
89
+ model = CukeModeler::CqlTestModel.new
90
+ model.attribute_1 = 'foo'
91
+ model.attribute_2 = 'bar'
92
+
93
+ repo = CQL::Repository.new(model)
94
+
95
+ result = repo.query do
96
+ select attribute_1, attribute_2
97
+ from cql_test_model
98
+ end
99
+
100
+
101
+ expect(result).to eq([{'attribute_1' => 'foo',
102
+ 'attribute_2' => 'bar'}])
103
+ end
104
+
105
+
106
+ describe 'special attributes' do
107
+
108
+ it 'understands the :model attribute' do
109
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
110
+
111
+ expect { gs.query do
112
+ select :model
113
+ from features
114
+ end
115
+ }.to_not raise_error
116
+ end
117
+
118
+ it 'interprets :model in the same manner that it interprets :self' do
119
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
120
+
121
+ self_result = gs.query do
122
+ select :self
123
+ from features
124
+ end
125
+
126
+ model_result = gs.query do
127
+ select :model
128
+ from features
129
+ end
130
+
131
+ # Only checking the values of the results because they will have different :model/:self keys
132
+ expect(model_result.collect { |result| result.values }).to eq(self_result.collect { |result| result.values })
133
+ end
134
+
135
+ it 'complains if an unknown special attribute is queried' do
136
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
137
+
138
+ expect {
139
+ gs.query do
140
+ select :foo
141
+ from scenarios
142
+ end
143
+ }.to raise_error(ArgumentError, ":foo is not a valid attribute for selection.")
144
+ end
145
+
146
+ it 'uses the :self attribute by default' do
147
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
148
+
149
+ default_result = gs.query do
150
+ select
151
+ from features
152
+ end
153
+
154
+ self_result = gs.query do
155
+ select :self
156
+ from features
157
+ end
158
+
159
+ expect(self_result).to eq(default_result)
160
+ end
161
+
162
+ end
163
+
164
+
165
+ it 'complains if an unknown normal attribute is queried' do
166
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
167
+
168
+ expect {
169
+ gs.query do
170
+ select steps
171
+ from features
172
+ end
173
+ }.to raise_error(ArgumentError, "'steps' is not a valid attribute for selection from a 'CukeModeler::Feature'.")
174
+ end
175
+
176
+
177
+ describe "multiple selections" do
178
+
179
+ it 'can freely mix empty selections and attribute selections' do
180
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
181
+
182
+ base_result = gs.query do
183
+ select :self
184
+ select name
185
+ select :self
186
+ from scenarios
187
+ end
188
+
189
+
190
+ expect(
191
+ gs.query do
192
+ select
193
+ select name
194
+ select
195
+ from scenarios
196
+ end
197
+ ).to eq(base_result)
198
+ end
199
+
200
+ end
201
+ end
202
+
203
+ describe "from" do
204
+
205
+ it 'knows from what to select attributes' do
206
+ expect(dsl_enabled_object).to respond_to(:from)
207
+ end
208
+
209
+ it 'selects from one or more things' do
210
+ expect(dsl_enabled_object.method(:from).arity).to eq(-1)
211
+ end
212
+
213
+ it "can handle an empty 'from' clause" do
214
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
215
+
216
+ result = gs.query do
217
+ select name
218
+ from
219
+ end
220
+
221
+ expect(result).to eq([])
222
+ end
223
+
224
+ describe "multiple targets" do
225
+
226
+ it 'raises an exception for inapplicable attributes' do
227
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
228
+
229
+ expect {
230
+ gs.query do
231
+ select name, steps
232
+ from features
233
+ from scenarios
234
+ end
235
+ }.to raise_error(ArgumentError)
236
+ end
237
+
238
+ end
239
+
240
+ describe 'shorthand' do
241
+
242
+ it 'should consider an exact match over a pluralization' do
243
+ plural_class_model = CukeModeler::CqlTestModels.new
244
+ singular_class_model = CukeModeler::CqlTestModel.new
245
+
246
+ plural_class_model.attribute_1 = 'plural'
247
+ singular_class_model.attribute_1 = 'singular'
248
+ plural_class_model.children << singular_class_model
249
+
250
+ repo = CQL::Repository.new(plural_class_model)
251
+
252
+ result = repo.query do
253
+ select attribute_1
254
+ from cql_test_model
255
+ end
256
+
257
+ expect(result.first['attribute_1']).to eq('singular')
258
+ end
259
+
260
+ it 'raises an exception if the shorthand form of a class cannot be mapped to a real class' do
261
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
262
+
263
+ expect {
264
+ gs.query do
265
+ select name
266
+ from not_a_real_class
267
+ end
268
+ }.to raise_error(ArgumentError, "Class 'CukeModeler::NotARealClass' does not exist")
269
+
270
+ end
271
+
272
+ it 'can freely mix shorthand and long-form names' do
273
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
274
+
275
+ # All long-form
276
+ base_result = gs.query do
277
+ select name
278
+ from CukeModeler::Scenario, CukeModeler::Feature
279
+ end
280
+
281
+ # All shorthand
282
+ expect(
283
+ gs.query do
284
+ select name
285
+ from scenarios, features
286
+ end
287
+ ).to eq(base_result)
288
+
289
+ # A mix of both
290
+ expect(
291
+ gs.query do
292
+ select name
293
+ from CukeModeler::Scenario, features
294
+ end
295
+ ).to eq(base_result)
296
+ end
297
+
298
+ end
299
+
300
+
301
+ describe 'special scopes' do
302
+
303
+ it 'understands the :all scope' do
304
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
305
+
306
+ expect { gs.query do
307
+ select :model
308
+ from :all
309
+ end
310
+ }.to_not raise_error
311
+ end
312
+
313
+ it 'queries from all models when scoped to :all' do
314
+ model_1 = CukeModeler::CqlTestModel.new
315
+ model_2 = CukeModeler::CqlTestModel.new
316
+ model_3 = CukeModeler::CqlTestModel.new
317
+
318
+ model_1.children << model_2
319
+ model_1.children << model_3
320
+
321
+ repo = CQL::Repository.new(model_1)
322
+
323
+ result = repo.query do
324
+ select :model
325
+ from :all
326
+ end
327
+
328
+ expect(result).to match_array([{:model => model_1},
329
+ {:model => model_2},
330
+ {:model => model_3}])
331
+ end
332
+
333
+ end
334
+
335
+ end
336
+
337
+ describe "transform" do
338
+
339
+ describe "multiple targets" do
340
+
341
+ it 'does not apply more transforms than have been declared' do
342
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
343
+
344
+ results = gs.query do
345
+ select :self, :self, :self
346
+ as thing1, thing2, thing3
347
+ from scenarios
348
+ transform :self => lambda { |thing1| 1 }
349
+ transform :self => lambda { |thing2| 2 }
350
+ end
351
+
352
+ expect(results.first).to include('thing1' => 1, 'thing2' => 2)
353
+ expect(results.first).to_not include('thing3' => 1)
354
+ expect(results.first).to_not include('thing3' => 2)
355
+ end
356
+
357
+ end
358
+
359
+ end
360
+
361
+
362
+ describe 'with' do
363
+
364
+ it 'knows how to filter selections with certain qualities' do
365
+ expect(dsl_enabled_object).to respond_to(:with)
366
+ end
367
+
368
+
369
+ describe 'targeted' do
370
+
371
+ it 'can handle predefined filters' do
372
+ gs = CQL::Repository.new(@feature_fixtures_directory)
373
+
374
+ expect {
375
+ gs.query do
376
+ select name
377
+ from features, scenarios, outlines
378
+ with scenarios => name(/test/)
379
+ end
380
+ }.to_not raise_error
381
+ end
382
+
383
+ it 'can handle a block filter' do
384
+ gs = CQL::Repository.new(@feature_fixtures_directory)
385
+
386
+ expect {
387
+ gs.query do
388
+ select name
389
+ from features, scenarios, outlines
390
+ with scenarios => lambda { |scenario| true }
391
+ end
392
+ }.to_not raise_error
393
+ end
394
+
395
+ it 'correctly filters with a targeted block' do
396
+ gs = CQL::Repository.new(@feature_fixtures_directory)
397
+
398
+ result = gs.query do
399
+ select name
400
+ from scenarios
401
+ with scenarios => lambda { |scenario| scenario.name =~ /king of/ }
402
+ end
403
+
404
+ expect(result).to eq([{'name' => 'The king of kings'}])
405
+ end
406
+
407
+ it 'can handle shorthand targets' do
408
+ gs = CQL::Repository.new(@feature_fixtures_directory)
409
+
410
+ expect {
411
+ gs.query do
412
+ select name
413
+ from features, scenarios, outlines
414
+ with scenarios => name(/test/)
415
+ end
416
+ }.to_not raise_error
417
+ end
418
+
419
+ it 'can handle multiple targets' do
420
+ gs = CQL::Repository.new(@feature_fixtures_directory)
421
+
422
+ expect {
423
+ gs.query do
424
+ select name
425
+ from features, scenarios, outlines
426
+ with scenarios => lambda { |scenario| true },
427
+ outlines => lambda { |outline| true }
428
+ end
429
+ }.to_not raise_error
430
+ end
431
+
432
+ end
433
+
434
+ end
435
+
436
+
437
+ describe 'without' do
438
+
439
+ it 'knows how to filter selections without certain qualities' do
440
+ expect(dsl_enabled_object).to respond_to(:without)
441
+ end
442
+
443
+ it 'correctly negates a block filter' do
444
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
445
+
446
+ negated_result = gs.query do
447
+ select name
448
+ from scenarios
449
+ with { |scenario| !(scenario.source_line == 3) }
450
+ end
451
+
452
+ without_result = gs.query do
453
+ select name
454
+ from scenarios
455
+ without { |scenario| scenario.source_line == 3 }
456
+ end
457
+
458
+ expect(without_result).to eq(negated_result)
459
+ end
460
+
461
+ it 'correctly negates a targeted filter' do
462
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/simple")
463
+
464
+ negated_result = gs.query do
465
+ select :model
466
+ from features, scenarios
467
+ with scenarios => lambda { |scenario| false }
468
+ end
469
+
470
+ without_result = gs.query do
471
+ select :model
472
+ from features, scenarios
473
+ without scenarios => lambda { |scenario| true }
474
+ end
475
+
476
+ # puts "1: #{negated_result}"
477
+
478
+
479
+ expect(without_result).to eq(negated_result)
480
+ end
481
+
482
+
483
+ describe 'negating predefined filters' do
484
+
485
+ it 'correctly negates a tag count filter' do
486
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/tags2")
487
+
488
+ negated_result = gs.query do
489
+ select :model
490
+ from scenarios
491
+ with tc lt 2
492
+ end
493
+
494
+ without_result = gs.query do
495
+ select :model
496
+ from scenarios
497
+ without tc gt 1
498
+ end
499
+
500
+ expect(without_result).to eq(negated_result)
501
+ end
502
+
503
+ it 'correctly negates a name filter' do
504
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/name_filter")
505
+
506
+ negated_result = gs.query do
507
+ select :model
508
+ from scenarios
509
+ with name /name[^1]/
510
+ end
511
+
512
+ without_result = gs.query do
513
+ select :model
514
+ from scenarios
515
+ without name /name1/
516
+ end
517
+
518
+ expect(without_result).to eq(negated_result)
519
+ end
520
+
521
+ it 'correctly negates a line filter' do
522
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/line_filter")
523
+
524
+ negated_result = gs.query do
525
+ select name
526
+ from scenarios
527
+ with line 'green eggs and ham'
528
+ end
529
+
530
+ without_result = gs.query do
531
+ select name
532
+ from scenarios
533
+ without line 'some other phrase'
534
+ end
535
+
536
+ end
537
+
538
+ it 'correctly negates a tag filter' do
539
+ gs = CQL::Repository.new("#{@feature_fixtures_directory}/scenario/tags3")
540
+
541
+ negated_result = gs.query do
542
+ select :model
543
+ from scenarios
544
+ with tags '@one'
545
+ end
546
+
547
+ without_result = gs.query do
548
+ select :model
549
+ from scenarios
550
+ without tags '@two'
551
+ end
552
+
553
+ expect(without_result).to eq(negated_result)
554
+ end
555
+
556
+ end
557
+
558
+ it 'correctly negates a targeted, predefined filter' do
559
+ gs = CQL::Repository.new(@feature_fixtures_directory)
560
+
561
+ negated_result = gs.query do
562
+ select :model
563
+ from :all
564
+ with scenarios => name(/(?!test)/)
565
+ end
566
+
567
+ without_result = gs.query do
568
+ select :model
569
+ from :all
570
+ without scenarios => name(/test/)
571
+ end
572
+
573
+ expect(without_result).to eq(negated_result)
574
+ end
575
+
576
+ it 'correctly negates multiple filters' do
577
+ gs = CQL::Repository.new(@feature_fixtures_directory)
578
+
579
+ negated_result = gs.query do
580
+ select :model
581
+ from :all
582
+ with scenarios => lambda { |scenario| false },
583
+ outlines => lambda { |outline| false }
584
+ with { |model| !model.is_a?(CukeModeler::Example) }
585
+ end
586
+
587
+ without_result = gs.query do
588
+ select :model
589
+ from :all
590
+ without scenarios => lambda { |scenario| true },
591
+ outlines => lambda { |outline| true }
592
+ without { |model| model.is_a?(CukeModeler::Example) }
593
+ end
594
+
595
+ expect(without_result).to eq(negated_result)
596
+ end
597
+
598
+ end
599
+
600
+ end