cucumber-core 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +48 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +39 -0
  4. data/.travis.yml +2 -3
  5. data/HISTORY.md +12 -1
  6. data/README.md +37 -43
  7. data/cucumber-core.gemspec +2 -0
  8. data/lib/cucumber/core.rb +5 -2
  9. data/lib/cucumber/core/ast.rb +1 -0
  10. data/lib/cucumber/core/ast/background.rb +1 -0
  11. data/lib/cucumber/core/ast/comment.rb +1 -0
  12. data/lib/cucumber/core/ast/data_table.rb +1 -0
  13. data/lib/cucumber/core/ast/describes_itself.rb +1 -0
  14. data/lib/cucumber/core/ast/doc_string.rb +1 -0
  15. data/lib/cucumber/core/ast/empty_background.rb +1 -0
  16. data/lib/cucumber/core/ast/empty_multiline_argument.rb +1 -0
  17. data/lib/cucumber/core/ast/examples_table.rb +1 -0
  18. data/lib/cucumber/core/ast/feature.rb +1 -0
  19. data/lib/cucumber/core/ast/location.rb +1 -0
  20. data/lib/cucumber/core/ast/names.rb +1 -0
  21. data/lib/cucumber/core/ast/outline_step.rb +1 -0
  22. data/lib/cucumber/core/ast/scenario.rb +1 -0
  23. data/lib/cucumber/core/ast/scenario_outline.rb +1 -0
  24. data/lib/cucumber/core/ast/step.rb +1 -0
  25. data/lib/cucumber/core/ast/tag.rb +1 -0
  26. data/lib/cucumber/core/compiler.rb +1 -0
  27. data/lib/cucumber/core/event.rb +63 -0
  28. data/lib/cucumber/core/event_bus.rb +64 -0
  29. data/lib/cucumber/core/events.rb +69 -0
  30. data/lib/cucumber/core/filter.rb +1 -0
  31. data/lib/cucumber/core/gherkin/ast_builder.rb +14 -5
  32. data/lib/cucumber/core/gherkin/document.rb +6 -4
  33. data/lib/cucumber/core/gherkin/parser.rb +6 -4
  34. data/lib/cucumber/core/gherkin/tag_expression.rb +1 -0
  35. data/lib/cucumber/core/gherkin/writer.rb +1 -0
  36. data/lib/cucumber/core/gherkin/writer/helpers.rb +1 -0
  37. data/lib/cucumber/core/platform.rb +1 -0
  38. data/lib/cucumber/core/report/summary.rb +30 -6
  39. data/lib/cucumber/core/test/action.rb +1 -0
  40. data/lib/cucumber/core/test/around_hook.rb +1 -0
  41. data/lib/cucumber/core/test/case.rb +13 -0
  42. data/lib/cucumber/core/test/filters.rb +1 -0
  43. data/lib/cucumber/core/test/filters/locations_filter.rb +1 -0
  44. data/lib/cucumber/core/test/filters/name_filter.rb +1 -0
  45. data/lib/cucumber/core/test/filters/tag_filter.rb +1 -0
  46. data/lib/cucumber/core/test/result.rb +5 -0
  47. data/lib/cucumber/core/test/runner.rb +10 -10
  48. data/lib/cucumber/core/test/step.rb +1 -0
  49. data/lib/cucumber/core/test/timer.rb +1 -0
  50. data/lib/cucumber/core/version.rb +2 -1
  51. data/spec/capture_warnings.rb +3 -2
  52. data/spec/coverage.rb +1 -0
  53. data/spec/cucumber/core/ast/background_spec.rb +1 -0
  54. data/spec/cucumber/core/ast/data_table_spec.rb +1 -0
  55. data/spec/cucumber/core/ast/doc_string_spec.rb +2 -1
  56. data/spec/cucumber/core/ast/empty_multiline_argument_spec.rb +1 -0
  57. data/spec/cucumber/core/ast/examples_table_spec.rb +1 -0
  58. data/spec/cucumber/core/ast/location_spec.rb +1 -0
  59. data/spec/cucumber/core/ast/outline_step_spec.rb +1 -0
  60. data/spec/cucumber/core/ast/step_spec.rb +1 -0
  61. data/spec/cucumber/core/compiler_spec.rb +1 -0
  62. data/spec/cucumber/core/event_bus_spec.rb +151 -0
  63. data/spec/cucumber/core/event_spec.rb +40 -0
  64. data/spec/cucumber/core/filter_spec.rb +1 -0
  65. data/spec/cucumber/core/gherkin/parser_spec.rb +24 -0
  66. data/spec/cucumber/core/gherkin/writer_spec.rb +1 -0
  67. data/spec/cucumber/core/report/summary_spec.rb +127 -0
  68. data/spec/cucumber/core/test/action_spec.rb +1 -0
  69. data/spec/cucumber/core/test/case_spec.rb +26 -2
  70. data/spec/cucumber/core/test/duration_matcher.rb +2 -1
  71. data/spec/cucumber/core/test/filters/locations_filter_spec.rb +2 -0
  72. data/spec/cucumber/core/test/result_spec.rb +5 -0
  73. data/spec/cucumber/core/test/runner_spec.rb +44 -50
  74. data/spec/cucumber/core/test/step_spec.rb +1 -0
  75. data/spec/cucumber/core/test/timer_spec.rb +1 -0
  76. data/spec/cucumber/core_spec.rb +68 -8
  77. data/spec/readme_spec.rb +1 -0
  78. data/spec/report_api_spy.rb +1 -0
  79. metadata +42 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c1fc45a561bb99340344287c1e671c9cdfe5c3e7
4
- data.tar.gz: 71d6d270193517dec221d7a61a557abae8bdbeb0
3
+ metadata.gz: bb172018d9e05188dafca358b06cfe31d5d10575
4
+ data.tar.gz: d41a9aa632138309140db42346519eeb349ee322
5
5
  SHA512:
6
- metadata.gz: 39f345c74c57332f0022faaab37e74cbb6029d544551435a9ab0b2986af82c4c6c33f13554315bf5a01fe5e00760bedbcb131cc9454fceac38025933dd93e07d
7
- data.tar.gz: 3dfc0894b9e62ecffc08f39b85acc0bfd4ddea7e5bda3ebd11a7fe164011a383e667abee3c0158268b2fcca35607c7c3bb433c338a8ddae731fb63248867ecad
6
+ metadata.gz: 117f9542f1c84472c5cac771e2eff5284ea9be7f965d40d0e8163b13f8d455e3f1c7654467936fa4da55fd0b4de242eb6677557896239f140da1bd41156f4328
7
+ data.tar.gz: 7e911a2e55a093cfd2dd73945d31df73d2504aa5cd88bb1a06f5778d234e5803a039856597595468c408b8ee6b864f6752d575f5753e499a19793dcf3a57166f
@@ -0,0 +1,48 @@
1
+ <!-- These sections are meant as guidance for you, to help you give the kind of information we'll need to help with your issue. If a section doesn't seem to fit, just skip it.
2
+
3
+ In general: Please provide as much information as you can to help us solving your problem -->
4
+
5
+ ## Summary
6
+
7
+ <!--- Provide a general summary description of the issue -->
8
+
9
+ ## Expected Behavior
10
+
11
+ <!--- If you're describing a bug, tell us what should happen -->
12
+ <!--- If you're suggesting a change/improvement, tell us how it should work -->
13
+ <!--- Feel free to use Given / Then / Then if that helps, but please add some plain-language context too -->
14
+
15
+ ## Current Behavior
16
+
17
+ <!--- If describing a bug, tell us what happens instead of the expected behavior -->
18
+ <!--- If suggesting a change/improvement, explain the difference from current behavior -->
19
+
20
+ <!--- If you have got some output place it in the code block below. Otherwise remove it. -->
21
+ ~~~
22
+ ~~~
23
+
24
+ ## Possible Solution
25
+
26
+ <!--- Not obligatory, but suggest a fix/reason for the bug, -->
27
+ <!--- or ideas how to implement the addition or change -->
28
+
29
+ ## Steps to Reproduce (for bugs)
30
+
31
+ <!--- Provide a link to a live example, or an unambiguous set of steps to -->
32
+ <!--- reproduce this bug. Include code to reproduce, if relevant -->
33
+ 1.
34
+ 2.
35
+ 3.
36
+ 4.
37
+
38
+ ## Context & Motivation
39
+
40
+ <!--- How has this issue affected you? What are you trying to accomplish? -->
41
+ <!--- Providing context helps us come up with a solution that is most useful in the real world -->
42
+
43
+ ## Your Environment
44
+
45
+ <!--- If you're reporting a bug, include as many relevant details about the environment you experienced the bug in -->
46
+ * Version used:
47
+ * Operating System and version:
48
+ * Link to your project:
@@ -0,0 +1,39 @@
1
+ <!-- These sections are meant as guidance for you. If something doesn't fit, you can just skip it. -->
2
+
3
+ ## Summary
4
+
5
+ <!--- Provide a general summary description of your changes -->
6
+
7
+ ## Details
8
+
9
+ <!--- Describe your changes in detail -->
10
+
11
+ ## Motivation and Context
12
+
13
+ <!--- Why is this change required? What problem does it solve? -->
14
+ <!--- If it fixes an open issue, please link to the issue here. -->
15
+
16
+ ## How Has This Been Tested?
17
+
18
+ <!--- Please add tests for changes to the code, otherwise we probably won't merge it -->
19
+
20
+ <!--- Please describe in detail how you tested your changes. -->
21
+ <!--- Include details of your testing environment, tests ran to see how -->
22
+ <!--- your change affects other areas of the code, etc. -->
23
+
24
+ ## Screenshots (if appropriate):
25
+
26
+ ## Types of changes
27
+
28
+ <!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
29
+ - [ ] Bug fix (non-breaking change which fixes an issue)
30
+ - [ ] New feature (non-breaking change which adds functionality)
31
+ - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
32
+
33
+ ## Checklist:
34
+
35
+ <!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
36
+ <!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
37
+ - [ ] I've added tests for my code
38
+ - [ ] My change requires a change to the documentation.
39
+ - [ ] I have updated the documentation accordingly.
@@ -1,17 +1,16 @@
1
1
  sudo: false
2
2
 
3
3
  rvm:
4
+ - 2.3.0
4
5
  - 2.2
5
6
  - 2.1
6
7
  - 2.0.0
7
- - 1.9.3
8
- - jruby
8
+ - jruby-9.0.5.0
9
9
 
10
10
  # whitelist
11
11
  branches:
12
12
  only:
13
13
  - master
14
- - v1.x-bugfix
15
14
 
16
15
  notifications:
17
16
  email:
data/HISTORY.md CHANGED
@@ -1,9 +1,20 @@
1
- ## [In Git](https://github.com/cucumber/cucumber-ruby-core/compare/v1.5.0...v1.x-bugfix)
1
+ ## [In Git](https://github.com/cucumber/cucumber-ruby-core/compare/v1.5.0...master)
2
2
 
3
3
  ### New Features
4
4
 
5
+ * Implement equality for test cases ([#111](https://github.com/cucumber/cucumber-ruby-core/pull/111) @mattwynne)
6
+ * Implement an event bus (moved from Cucumber-Ruby) ([#106](https://github.com/cucumber/cucumber-ruby-core/pull/106) @mattwynne)
7
+ * Use frozen string literals ([#105](https://github.com/cucumber/cucumber-ruby-core/pull/105) @twalpole)
8
+
5
9
  ### Bugfixes
6
10
 
11
+ * Handle incomplete examples to scenario outlines. ([109](https://github.com/cucumber/cucumber-ruby-core/pull/109) @brasmusson)
12
+ * Add with_filtered_backtrace method to unknown result ([107](https://github.com/cucumber/cucumber-ruby-core/pull/107) @danascheider)
13
+
14
+ ### Removed Features
15
+
16
+ * Remove support for Ruby v1.9.3. ([112](https://github.com/cucumber/cucumber-ruby-core/pull/112) @brasmusson)
17
+
7
18
  ## [v1.5.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.4.0...v1.5.0)
8
19
 
9
20
  ### New Features
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # cucumber-core
1
+ #cucumber-core
2
2
 
3
3
  [![Chat with us](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/cucumber/cucumber-ruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
4
  [![Build Status](https://secure.travis-ci.org/cucumber/cucumber-ruby-core.svg)](http://travis-ci.org/cucumber/cucumber-ruby-core)
@@ -10,61 +10,59 @@ Cucumber Core is the [inner hexagon](http://alistair.cockburn.us/Hexagonal+archi
10
10
 
11
11
  It contains the core domain logic to execute Cucumber features. It has no user interface, just a Ruby API. If you're interested in how Cucumber works, or in building other tools that work with Gherkin documents, you've come to the right place.
12
12
 
13
- ## An overview
13
+ ##An overview
14
14
 
15
- The entry-point is a single method on the module `Cucumber::Core` called [`#execute`](http://rubydoc.info/gems/cucumber-core/Cucumber/Core#execute-instance_method). Here's what it does:
15
+ The entry-point is a single method on the module [`Cucumber::Core`](Cucumber/Core.html) called [`#execute`](Cucumber/Core.html#execute-instance_method). Here's what it does:
16
16
 
17
17
  1. Parses the plain-text Gherkin documents into an **AST**
18
18
  2. Compiles the AST down to **test cases**
19
- 3. Passes the activated test cases through any **filters**
20
- 4. Executes the test cases, calling back to the **report**
19
+ 3. Passes the test cases through any **filters**
20
+ 4. Executes the test cases, emitting **events** as it goes
21
21
 
22
22
  We've introduced a number of concepts here, so let's go through them in detail.
23
23
 
24
- ### The AST
24
+ ###The AST
25
25
 
26
- The Abstract Syntax Tree or [AST](http://rubydoc.info/gems/cucumber-core/Cucumber/Core/Ast) is an object graph that represents the Gherkin documents you've passed into the core. Things like [Feature](http://rubydoc.info/gems/cucumber-core/Cucumber/Core/Ast/Feature), [Scenario](http://rubydoc.info/gems/cucumber-core/Cucumber/Core/Ast/Scenario) and [ExamplesTable](ExamplesTable).
26
+ The Abstract Syntax Tree or [AST](Cucumber/Core/Ast.html) is an object graph that represents the Gherkin documents you've passed into the core. Things like [Feature](Cucumber/Core/Ast/Feature.html), [Scenario](Cucumber/Core/Ast/Scenario.html) and [ExamplesTable](Cucumber/Core/Ast/ExamplesTable.html).
27
27
 
28
28
  These are immutable value objects.
29
29
 
30
- ### Test cases
30
+ ###Test cases
31
31
 
32
32
  Your gherkin might contain scenarios, as well as examples from tables beneath a scenario outline.
33
33
 
34
- Test cases represent the general case of both of these. We compile the AST down to instances of [`Cucumber::Core::Test::Case`](http://rubydoc.info/gems/cucumber-core/Cucumber/Core/Test/Case), each containing a number of instances of [`Cucumber::Core::Test::Step`](http://rubydoc.info/gems/cucumber-core/Cucumber/Core/Test/Step). It's these that are then filtered and executed.
34
+ Test cases represent the general case of both of these. We compile the AST down to instances of [`Cucumber::Core::Test::Case`](Cucumber/Core/Test/Case.html), each containing a number of instances of [`Cucumber::Core::Test::Step`](Cucumber/Core/Test/Step.html). It's these that are then filtered and executed.
35
35
 
36
36
  Test cases and their test steps are also immutable value objects.
37
37
 
38
- ### Filters
38
+ ###Filters
39
39
 
40
40
  Once we have the test cases, and they've been activated by the mappings, you may want to pass them through a filter or two. Filters can be used to do things like activate, sort, replace or remove some of the test cases or their steps before they're executed.
41
41
 
42
- ### Report
42
+ ###Events
43
43
 
44
- A report is how you find out what is happening during your test run. As the test cases and steps are executed, messages are sent to the report.
44
+ Events are how you find out what is happening during your test run. As the test cases and steps are executed, the runner emits events to signal what's going on.
45
45
 
46
- A report needs to respond to the following methods:
46
+ The following events are emitted during a run:
47
47
 
48
- * `before_test_case(test_case)`
49
- * `after_test_case(test_case, result)`
50
- * `before_test_step(test_step)`
51
- * `after_test_step(test_test, result)`
52
- * `done`
48
+ - [`TestCaseStarting`](Cucumber/Core/Events/TestCaseStarting.html)
49
+ - [`TestStepStarting`](Cucumber/Core/Events/TestStepStarting.html)
50
+ - [`TestStepFinished`](Cucumber/Core/Events/TestStepFinished.html)
51
+ - [`TestCaseFinished`](Cucumber/Core/Events/TestCaseFinished.html)
53
52
 
54
53
  That's probably best illustrated with an example.
55
54
 
56
- ## Example
55
+ ##Example
57
56
 
58
- Here's an example of how you might use [`Cucumber::Core#execute`](http://rubydoc.info/gems/cucumber-core/Cucumber/Core#execute-instance_method)
57
+ Here's an example of how you might use [`Cucumber::Core#execute`](Cucumber/Core#execute-instance_method)
59
58
 
60
59
  ```ruby
61
60
  require 'cucumber/core'
62
61
  require 'cucumber/core/filter'
63
62
 
64
- class MyRunner
65
- include Cucumber::Core
66
- end
67
-
63
+ # This is the most complex part of the example. The filter takes test cases as input,
64
+ # activates each step with an action block, then passes a new test case with those activated
65
+ # steps in it on to the next filter in the chain.
68
66
  class ActivateSteps < Cucumber::Core::Filter.new
69
67
  def test_case(test_case)
70
68
  test_steps = test_case.test_steps.map do |step|
@@ -75,6 +73,7 @@ class ActivateSteps < Cucumber::Core::Filter.new
75
73
  end
76
74
 
77
75
  private
76
+
78
77
  def activate(step)
79
78
  case step.name
80
79
  when /fail/
@@ -87,24 +86,7 @@ class ActivateSteps < Cucumber::Core::Filter.new
87
86
  end
88
87
  end
89
88
 
90
- class Report
91
- def before_test_step(test_step)
92
- end
93
-
94
- def after_test_step(test_step, result)
95
- puts "#{test_step.name} #{result}"
96
- end
97
-
98
- def before_test_case(test_case)
99
- end
100
-
101
- def after_test_case(test_case, result)
102
- end
103
-
104
- def done
105
- end
106
- end
107
-
89
+ # Create a Gherkin document to run
108
90
  feature = Cucumber::Core::Gherkin::Document.new(__FILE__, <<-GHERKIN)
109
91
  Feature:
110
92
  Scenario:
@@ -113,7 +95,19 @@ Feature:
113
95
  And undefined
114
96
  GHERKIN
115
97
 
116
- MyRunner.new.execute([feature], Report.new, [ActivateSteps.new])
98
+ # Create a runner class that uses the Core's DSL
99
+ class MyRunner
100
+ include Cucumber::Core
101
+ end
102
+
103
+ # Now execute the feature, using the filter we built, and subscribing to
104
+ # an event so we can print the output.
105
+ MyRunner.new.execute([feature], [ActivateSteps.new]) do |events|
106
+ events.on(:test_step_finished) do |event|
107
+ test_step, result = event.test_step, event.result
108
+ puts "#{test_step.name} #{result}"
109
+ end
110
+ end
117
111
  ```
118
112
 
119
113
  If you run this little Ruby script, you should see the following output:
@@ -15,12 +15,14 @@ Gem::Specification.new do |s|
15
15
  s.required_ruby_version = ">= 1.9.3"
16
16
 
17
17
  s.add_dependency 'gherkin', '~> 4.0'
18
+ s.add_dependency 'backports', '~> 3.6'
18
19
 
19
20
  s.add_development_dependency 'bundler', '>= 1.3.5'
20
21
  s.add_development_dependency 'rake', '>= 0.9.2'
21
22
  s.add_development_dependency 'rspec', '~> 3'
22
23
  s.add_development_dependency 'unindent', '>= 1.0'
23
24
  s.add_development_dependency 'kramdown', '~> 1.4.2'
25
+ s.add_development_dependency 'yard'
24
26
 
25
27
  # For coverage reports
26
28
  s.add_development_dependency 'coveralls', '~> 0.7'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+ require 'cucumber/core/event_bus'
1
3
  require 'cucumber/core/gherkin/parser'
2
4
  require 'cucumber/core/gherkin/document'
3
5
  require 'cucumber/core/compiler'
@@ -6,8 +8,9 @@ require 'cucumber/core/test/runner'
6
8
  module Cucumber
7
9
  module Core
8
10
 
9
- def execute(gherkin_documents, report, filters = [])
10
- receiver = Test::Runner.new(report)
11
+ def execute(gherkin_documents, filters = [], event_bus = EventBus.new)
12
+ yield event_bus if block_given?
13
+ receiver = Test::Runner.new(event_bus)
11
14
  compile gherkin_documents, receiver, filters
12
15
  self
13
16
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cucumber/core/ast/comment'
2
3
  require 'cucumber/core/ast/tag'
3
4
  require 'cucumber/core/ast/feature'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cucumber/core/ast/names'
2
3
  require 'cucumber/core/ast/location'
3
4
  require 'cucumber/core/ast/describes_itself'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cucumber/core/ast/location'
2
3
 
3
4
  module Cucumber
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cucumber/core/ast/describes_itself'
2
3
  require 'cucumber/core/ast/location'
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Cucumber
2
3
  module Core
3
4
  module Ast
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cucumber/core/ast/describes_itself'
2
3
  require 'delegate'
3
4
  module Cucumber
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Cucumber
2
3
  module Core
3
4
  module Ast
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Cucumber
2
3
  module Core
3
4
  module Ast
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cucumber/core/ast/describes_itself'
2
3
  require 'cucumber/core/ast/location'
3
4
  require 'cucumber/core/ast/names'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cucumber/core/ast/describes_itself'
2
3
  require 'cucumber/core/ast/names'
3
4
  require 'cucumber/core/ast/location'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'forwardable'
2
3
  require 'cucumber/core/platform'
3
4
  module Cucumber
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Cucumber
2
3
  module Core
3
4
  module Ast
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cucumber/core/ast/location'
2
3
  require 'cucumber/core/ast/describes_itself'
3
4
  require 'cucumber/core/ast/step'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cucumber/core/ast/describes_itself'
2
3
  require 'cucumber/core/ast/names'
3
4
  require 'cucumber/core/ast/empty_background'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cucumber/core/ast/names'
2
3
  require 'cucumber/core/ast/location'
3
4
  require 'cucumber/core/ast/describes_itself'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cucumber/core/ast/describes_itself'
2
3
  require 'cucumber/core/ast/location'
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Cucumber
2
3
  module Core
3
4
  module Ast
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cucumber/core/test/case'
2
3
  require 'cucumber/core/test/step'
3
4
 
@@ -0,0 +1,63 @@
1
+ require 'backports/2.1.0/array/to_h'
2
+
3
+ module Cucumber
4
+ module Core
5
+ class Event
6
+
7
+ # Macro to generate new sub-classes of {Event} with
8
+ # attribute readers.
9
+ def self.new(*attributes)
10
+ # Use normal constructor for subclasses of Event
11
+ return super if self.ancestors.index(Event) > 0
12
+
13
+ Class.new(Event) do
14
+ attr_reader(*attributes)
15
+
16
+ define_method(:initialize) do |*args|
17
+ attributes.zip(args) do |name, value|
18
+ instance_variable_set "@#{name}".to_sym, value
19
+ end
20
+ end
21
+
22
+ define_method(:attributes) do
23
+ attributes.map { |attribute| self.send(attribute) }
24
+ end
25
+
26
+ define_method(:to_h) do
27
+ attributes.reduce({}) { |result, attribute|
28
+ value = self.send(attribute)
29
+ result[attribute] = value
30
+ result
31
+ }
32
+ end
33
+
34
+ define_method(:event_id) do
35
+ self.class.event_id
36
+ end
37
+ end
38
+ end
39
+
40
+
41
+ class << self
42
+
43
+ # @return [Symbol] the underscored name of the class to be used
44
+ #  as the key in an event registry.
45
+ def event_id
46
+ underscore(self.name.split("::").last).to_sym
47
+ end
48
+
49
+ private
50
+
51
+ def underscore(string)
52
+ string.to_s.gsub(/::/, '/').
53
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
54
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
55
+ tr("-", "_").
56
+ downcase
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+ end
63
+ end