cucumber-core 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.rspec +1 -0
  4. data/.ruby-gemset +1 -0
  5. data/.travis.yml +16 -0
  6. data/Gemfile +2 -0
  7. data/LICENSE +20 -0
  8. data/README.md +9 -0
  9. data/Rakefile +24 -0
  10. data/cucumber-core.gemspec +32 -0
  11. data/lib/cucumber/core.rb +37 -0
  12. data/lib/cucumber/core/ast.rb +13 -0
  13. data/lib/cucumber/core/ast/background.rb +33 -0
  14. data/lib/cucumber/core/ast/comment.rb +17 -0
  15. data/lib/cucumber/core/ast/data_table.rb +326 -0
  16. data/lib/cucumber/core/ast/describes_itself.rb +16 -0
  17. data/lib/cucumber/core/ast/doc_string.rb +83 -0
  18. data/lib/cucumber/core/ast/empty_background.rb +12 -0
  19. data/lib/cucumber/core/ast/examples_table.rb +95 -0
  20. data/lib/cucumber/core/ast/feature.rb +62 -0
  21. data/lib/cucumber/core/ast/location.rb +140 -0
  22. data/lib/cucumber/core/ast/multiline_argument.rb +33 -0
  23. data/lib/cucumber/core/ast/names.rb +19 -0
  24. data/lib/cucumber/core/ast/outline_step.rb +51 -0
  25. data/lib/cucumber/core/ast/scenario.rb +43 -0
  26. data/lib/cucumber/core/ast/scenario_outline.rb +44 -0
  27. data/lib/cucumber/core/ast/step.rb +38 -0
  28. data/lib/cucumber/core/ast/tag.rb +14 -0
  29. data/lib/cucumber/core/compiler.rb +136 -0
  30. data/lib/cucumber/core/gherkin/ast_builder.rb +315 -0
  31. data/lib/cucumber/core/gherkin/document.rb +20 -0
  32. data/lib/cucumber/core/gherkin/parser.rb +45 -0
  33. data/lib/cucumber/core/gherkin/writer.rb +220 -0
  34. data/lib/cucumber/core/gherkin/writer/helpers.rb +178 -0
  35. data/lib/cucumber/core/platform.rb +30 -0
  36. data/lib/cucumber/core/test/case.rb +143 -0
  37. data/lib/cucumber/core/test/filters.rb +48 -0
  38. data/lib/cucumber/core/test/filters/tag_filter.rb +110 -0
  39. data/lib/cucumber/core/test/hook_compiler.rb +109 -0
  40. data/lib/cucumber/core/test/mapper.rb +56 -0
  41. data/lib/cucumber/core/test/mapping.rb +67 -0
  42. data/lib/cucumber/core/test/result.rb +191 -0
  43. data/lib/cucumber/core/test/runner.rb +149 -0
  44. data/lib/cucumber/core/test/step.rb +69 -0
  45. data/lib/cucumber/core/test/timer.rb +31 -0
  46. data/lib/cucumber/core/version.rb +9 -0
  47. data/lib/cucumber/initializer.rb +18 -0
  48. data/spec/capture_warnings.rb +68 -0
  49. data/spec/coverage.rb +10 -0
  50. data/spec/cucumber/core/ast/data_table_spec.rb +139 -0
  51. data/spec/cucumber/core/ast/doc_string_spec.rb +77 -0
  52. data/spec/cucumber/core/ast/examples_table_spec.rb +87 -0
  53. data/spec/cucumber/core/ast/location_spec.rb +105 -0
  54. data/spec/cucumber/core/ast/outline_step_spec.rb +77 -0
  55. data/spec/cucumber/core/ast/step_spec.rb +44 -0
  56. data/spec/cucumber/core/compiler_spec.rb +249 -0
  57. data/spec/cucumber/core/gherkin/parser_spec.rb +182 -0
  58. data/spec/cucumber/core/gherkin/writer_spec.rb +332 -0
  59. data/spec/cucumber/core/test/case_spec.rb +416 -0
  60. data/spec/cucumber/core/test/hook_compiler_spec.rb +78 -0
  61. data/spec/cucumber/core/test/mapper_spec.rb +68 -0
  62. data/spec/cucumber/core/test/mapping_spec.rb +103 -0
  63. data/spec/cucumber/core/test/result_spec.rb +178 -0
  64. data/spec/cucumber/core/test/runner_spec.rb +265 -0
  65. data/spec/cucumber/core/test/step_spec.rb +58 -0
  66. data/spec/cucumber/core/test/timer_spec.rb +13 -0
  67. data/spec/cucumber/core_spec.rb +419 -0
  68. data/spec/cucumber/initializer_spec.rb +49 -0
  69. metadata +221 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ea9227a0b067303f1aa77c9f4f05e75a73a74da6
4
+ data.tar.gz: 5ec7e76b3ec7fe9e093e5091a0e7e80156153aea
5
+ SHA512:
6
+ metadata.gz: 9b8b2ce54523d97a6107b334342578af32f865281ceccb891f035cd55d0df119f267f510713e3e893ed6cb4a6be4af278648f22f3c77364ec0cc5d7e4ab15635
7
+ data.tar.gz: faae23fd3346d6957260ea77836ec6162e15d562017723d6328e5f386eecc3c4628fbe54513d579febcf97118303ece2d2ef9de505f5cab2752a897683c62b9a
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1 @@
1
+ cucumber
@@ -0,0 +1,16 @@
1
+ rvm:
2
+ - 2.1.0
3
+ - 2.0.0
4
+ - 1.9.3
5
+ - jruby
6
+
7
+ # whitelist
8
+ branches:
9
+ only:
10
+ - master
11
+
12
+ notifications:
13
+ email:
14
+ - cukes-devs@googlegroups.com
15
+ irc:
16
+ - "irc.freenode.org#cucumber"
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (C) 2013 The Cucumber Organisation
2
+
3
+ MIT License (Expat)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,9 @@
1
+ cucumber-ruby-core
2
+ ==================
3
+
4
+ [![Build Status](https://secure.travis-ci.org/cucumber/cucumber-ruby-core.png)](http://travis-ci.org/cucumber/cucumber-ruby-core)
5
+ [![Code
6
+ Climate](https://codeclimate.com/github/cucumber/cucumber-ruby-core.png)](https://codeclimate.com/github/cucumber/cucumber-ruby-core)
7
+ [![Coverage Status](https://coveralls.io/repos/cucumber/cucumber-ruby-core/badge.png?branch=master)](https://coveralls.io/r/cucumber/cucumber-ruby-core?branch=master)
8
+
9
+ Core library for the Ruby flavour of Cucumber
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ $:.unshift File.expand_path("../lib", __FILE__)
7
+
8
+ require "rspec/core/rake_task"
9
+ RSpec::Core::RakeTask.new(:spec) do |t|
10
+ t.ruby_opts = %w[-r./spec/coverage -w]
11
+ t.rspec_opts = %w[--color]
12
+ end
13
+
14
+ require_relative 'spec/capture_warnings'
15
+ include CaptureWarnings
16
+ namespace :spec do
17
+ task :warnings do
18
+ report_warnings do
19
+ Rake::Task['spec'].invoke
20
+ end
21
+ end
22
+ end
23
+
24
+ task default: ['spec:warnings']
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
3
+ require "cucumber/core/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'cucumber-core'
7
+ s.version = Cucumber::Core::Version
8
+ s.authors = ["Aslak Hellesøy", "Matt Wynne", "Steve Tooke", "Oleg Sukhodolsky", "Tom Brand"]
9
+ s.description = 'Core library for the Cucumber BDD app'
10
+ s.summary = "cucumber-core-#{s.version}"
11
+ s.email = 'cukes@googlegroups.com'
12
+ s.homepage = "http://cukes.info"
13
+ s.platform = Gem::Platform::RUBY
14
+ s.license = "MIT"
15
+ s.required_ruby_version = ">= 1.9.3"
16
+
17
+ s.add_dependency 'gherkin', '~> 2.12.0'
18
+
19
+ s.add_development_dependency 'bundler', '>= 1.3.5'
20
+ s.add_development_dependency 'rake', '>= 0.9.2'
21
+ s.add_development_dependency 'rspec', '>= 2.13'
22
+ s.add_development_dependency 'unindent', '>= 1.0'
23
+
24
+ # For coverage reports
25
+ s.add_development_dependency 'coveralls', '~> 0.7'
26
+
27
+ s.rubygems_version = ">= 1.6.1"
28
+ s.files = `git ls-files`.split("\n").reject {|path| path =~ /\.gitignore$/ }
29
+ s.test_files = `git ls-files -- spec/*`.split("\n")
30
+ s.rdoc_options = ["--charset=UTF-8"]
31
+ s.require_path = "lib"
32
+ end
@@ -0,0 +1,37 @@
1
+ require 'cucumber/core/gherkin/parser'
2
+ require 'cucumber/core/compiler'
3
+ require 'cucumber/core/test/runner'
4
+ require 'cucumber/core/test/mapper'
5
+ require 'cucumber/core/test/hook_compiler'
6
+
7
+ module Cucumber
8
+ module Core
9
+
10
+ def parse(gherkin_documents, compiler)
11
+ parser = Core::Gherkin::Parser.new(compiler)
12
+ gherkin_documents.each do |document|
13
+ parser.document document
14
+ end
15
+ parser.done
16
+ self
17
+ end
18
+
19
+ def compile(gherkin_documents, last_receiver, filters = [])
20
+ first_receiver = filters.reduce(last_receiver) do |receiver, (filter_type, args)|
21
+ filter_type.new(*args + [receiver])
22
+ end
23
+ compiler = Compiler.new(first_receiver)
24
+ parse gherkin_documents, compiler
25
+ self
26
+ end
27
+
28
+ def execute(gherkin_documents, mappings, report, filters = [], run_options = {})
29
+ receiver = Test::Runner.new(report, run_options)
30
+ filters << [Test::HookCompiler, [mappings]]
31
+ filters << [Test::Mapper, [mappings]]
32
+ compile gherkin_documents, receiver, filters
33
+ self
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,13 @@
1
+ require 'cucumber/core/ast/comment'
2
+ require 'cucumber/core/ast/tag'
3
+ require 'cucumber/core/ast/feature'
4
+ require 'cucumber/core/ast/empty_background'
5
+ require 'cucumber/core/ast/background'
6
+ require 'cucumber/core/ast/scenario'
7
+ require 'cucumber/core/ast/step'
8
+ require 'cucumber/core/ast/multiline_argument'
9
+ require 'cucumber/core/ast/doc_string'
10
+ require 'cucumber/core/ast/data_table'
11
+ require 'cucumber/core/ast/scenario_outline'
12
+ require 'cucumber/core/ast/outline_step'
13
+ require 'cucumber/core/ast/examples_table'
@@ -0,0 +1,33 @@
1
+ require 'cucumber/initializer'
2
+ require 'cucumber/core/ast/names'
3
+ require 'cucumber/core/ast/location'
4
+ require 'cucumber/core/ast/describes_itself'
5
+
6
+ module Cucumber
7
+ module Core
8
+ module Ast
9
+ class Background
10
+ include Names
11
+ include HasLocation
12
+ include DescribesItself
13
+
14
+ include Cucumber.initializer(:gherkin_statement, :language, :location, :comments, :keyword, :title, :description, :raw_steps)
15
+
16
+ attr_accessor :feature
17
+ attr_accessor :comments, :keyword, :location
18
+ attr_reader :gherkin_statement
19
+
20
+ def children
21
+ raw_steps
22
+ end
23
+
24
+ private
25
+
26
+ def description_for_visitors
27
+ :background
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ require 'cucumber/initializer'
2
+ require 'cucumber/core/ast/location'
3
+
4
+ module Cucumber
5
+ module Core
6
+ module Ast
7
+ class Comment
8
+ include HasLocation
9
+ include Cucumber.initializer :location, :value
10
+
11
+ def to_s
12
+ value
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,326 @@
1
+ require 'gherkin/rubify'
2
+ require 'gherkin/lexer/i18n_lexer'
3
+ require 'gherkin/formatter/escaping'
4
+ require 'cucumber/core/ast/describes_itself'
5
+ require 'cucumber/core/ast/location'
6
+
7
+ module Cucumber
8
+ module Core
9
+ module Ast
10
+ # Step Definitions that match a plain text Step with a multiline argument table
11
+ # will receive it as an instance of DataTable. A DataTable object holds the data of a
12
+ # table parsed from a feature file and lets you access and manipulate the data
13
+ # in different ways.
14
+ #
15
+ # For example:
16
+ #
17
+ # Given I have:
18
+ # | a | b |
19
+ # | c | d |
20
+ #
21
+ # And a matching StepDefinition:
22
+ #
23
+ # Given /I have:/ do |table|
24
+ # data = table.raw
25
+ # end
26
+ #
27
+ # This will store <tt>[['a', 'b'], ['c', 'd']]</tt> in the <tt>data</tt> variable.
28
+ #
29
+ class DataTable
30
+ include DescribesItself
31
+ include HasLocation
32
+
33
+ class Builder
34
+ attr_reader :rows
35
+
36
+ def initialize
37
+ @rows = []
38
+ end
39
+
40
+ def row(row, line_number)
41
+ @rows << row
42
+ end
43
+
44
+ def eof
45
+ end
46
+ end
47
+
48
+ include ::Gherkin::Rubify
49
+
50
+ NULL_CONVERSIONS = Hash.new({ :strict => false, :proc => lambda{ |cell_value| cell_value } }).freeze
51
+
52
+ attr_accessor :file
53
+
54
+ def self.default_arg_name #:nodoc:
55
+ "table"
56
+ end
57
+
58
+ def self.parse(text, uri, location)
59
+ builder = Builder.new
60
+ lexer = ::Gherkin::Lexer::I18nLexer.new(builder)
61
+ lexer.scan(text)
62
+ new(builder.rows, location)
63
+ end
64
+
65
+ # Creates a new instance. +raw+ should be an Array of Array of String
66
+ # or an Array of Hash
67
+ # You don't typically create your own DataTable objects - Cucumber will do
68
+ # it internally and pass them to your Step Definitions.
69
+ #
70
+ def initialize(raw, location)
71
+ @cells_class = Cells
72
+ @cell_class = Cell
73
+ raw = ensure_array_of_array(rubify(raw))
74
+ # Verify that it's square
75
+ raw.transpose
76
+ create_cell_matrix(raw)
77
+ @location = location
78
+ end
79
+
80
+ def to_step_definition_arg
81
+ dup
82
+ end
83
+
84
+ # Creates a copy of this table
85
+ #
86
+ def dup
87
+ self.class.new(raw.dup, location)
88
+ end
89
+
90
+ # Returns a new, transposed table. Example:
91
+ #
92
+ # | a | 7 | 4 |
93
+ # | b | 9 | 2 |
94
+ #
95
+ # Gets converted into the following:
96
+ #
97
+ # | a | b |
98
+ # | 7 | 9 |
99
+ # | 4 | 2 |
100
+ #
101
+ def transpose
102
+ self.class.new(raw.transpose, location)
103
+ end
104
+
105
+ def map(&block)
106
+ new_raw = raw.map do |row|
107
+ row.map(&block)
108
+ end
109
+
110
+ self.class.new(new_raw, location)
111
+ end
112
+
113
+ # Converts this table into an Array of Hash where the keys of each
114
+ # Hash are the headers in the table. For example, a DataTable built from
115
+ # the following plain text:
116
+ #
117
+ # | a | b | sum |
118
+ # | 2 | 3 | 5 |
119
+ # | 7 | 9 | 16 |
120
+ #
121
+ # Gets converted into the following:
122
+ #
123
+ # [{'a' => '2', 'b' => '3', 'sum' => '5'}, {'a' => '7', 'b' => '9', 'sum' => '16'}]
124
+ #
125
+ def hashes
126
+ build_hashes
127
+ end
128
+
129
+ # Converts this table into a Hash where the first column is
130
+ # used as keys and the second column is used as values
131
+ #
132
+ # | a | 2 |
133
+ # | b | 3 |
134
+ #
135
+ # Gets converted into the following:
136
+ #
137
+ # {'a' => '2', 'b' => '3'}
138
+ #
139
+ # The table must be exactly two columns wide
140
+ #
141
+ def rows_hash
142
+ verify_table_width(2)
143
+ self.transpose.hashes[0]
144
+ end
145
+
146
+ # Gets the raw data of this table. For example, a DataTable built from
147
+ # the following plain text:
148
+ #
149
+ # | a | b |
150
+ # | c | d |
151
+ #
152
+ # gets converted into the following:
153
+ #
154
+ # [['a', 'b'], ['c', 'd']]
155
+ #
156
+ def raw
157
+ cell_matrix.map do |row|
158
+ row.map do |cell|
159
+ cell.value
160
+ end
161
+ end
162
+ end
163
+
164
+ def column_names #:nodoc:
165
+ cell_matrix[0].map { |cell| cell.value }
166
+ end
167
+
168
+ def rows
169
+ hashes.map do |hash|
170
+ hash.values_at(*headers)
171
+ end
172
+ end
173
+
174
+ # For testing only
175
+ def to_sexp #:nodoc:
176
+ [:table, *cells_rows.map{|row| row.to_sexp}]
177
+ end
178
+
179
+ def to_hash(cells) #:nodoc:
180
+ hash = Hash.new do |the_hash, key|
181
+ the_hash[key.to_s] if key.is_a?(Symbol)
182
+ end
183
+ column_names.each_with_index do |column_name, column_index|
184
+ hash[column_name] = cells.value(column_index)
185
+ end
186
+ hash
187
+ end
188
+
189
+ def verify_table_width(width) #:nodoc:
190
+ raise %{The table must have exactly #{width} columns} unless raw[0].size == width
191
+ end
192
+
193
+ def cells_rows #:nodoc:
194
+ cell_matrix.map do |cell_row|
195
+ @cells_class.new(self, cell_row)
196
+ end
197
+ end
198
+
199
+ def headers #:nodoc:
200
+ raw.first
201
+ end
202
+
203
+ def cell_matrix #:nodoc:
204
+ @cell_matrix
205
+ end
206
+
207
+ def col_width(col) #:nodoc:
208
+ columns[col].__send__(:width)
209
+ end
210
+
211
+ def ==(other)
212
+ other.class == self.class && raw == other.raw
213
+ end
214
+
215
+ def inspect
216
+ raw.inspect
217
+ end
218
+
219
+ private
220
+
221
+ TO_S_PREFIXES = Hash.new(' ')
222
+ TO_S_PREFIXES[:comment] = '(+) '
223
+ TO_S_PREFIXES[:undefined] = '(-) '
224
+
225
+ def build_hashes
226
+ cells_rows[1..-1].map do |row|
227
+ row.to_hash
228
+ end
229
+ end
230
+
231
+ def create_cell_matrix(raw) #:nodoc:
232
+ @cell_matrix = raw.map do |raw_row|
233
+ line = raw_row.line rescue -1
234
+ raw_row.map do |raw_cell|
235
+ new_cell(raw_cell, line)
236
+ end
237
+ end
238
+ end
239
+
240
+ def columns #:nodoc:
241
+ cell_matrix.transpose.map do |cell_row|
242
+ @cells_class.new(self, cell_row)
243
+ end
244
+ end
245
+
246
+ def new_cell(raw_cell, line) #:nodoc:
247
+ @cell_class.new(raw_cell, self, line)
248
+ end
249
+
250
+ def ensure_array_of_array(array)
251
+ Hash === array[0] ? hashes_to_array(array) : array
252
+ end
253
+
254
+ def hashes_to_array(hashes) #:nodoc:
255
+ header = hashes[0].keys.sort
256
+ [header] + hashes.map{|hash| header.map{|key| hash[key]}}
257
+ end
258
+
259
+ def description_for_visitors
260
+ :table
261
+ end
262
+
263
+ # Represents a row of cells or columns of cells
264
+ class Cells #:nodoc:
265
+ include Enumerable
266
+ include Gherkin::Formatter::Escaping
267
+
268
+ attr_reader :exception
269
+
270
+ def initialize(table, cells)
271
+ @table, @cells = table, cells
272
+ end
273
+
274
+ # For testing only
275
+ def to_sexp #:nodoc:
276
+ [:row, line, *@cells.map{|cell| cell.to_sexp}]
277
+ end
278
+
279
+ def to_hash #:nodoc:
280
+ @to_hash ||= @table.to_hash(self)
281
+ end
282
+
283
+ def value(n) #:nodoc:
284
+ self[n].value
285
+ end
286
+
287
+ def [](n)
288
+ @cells[n]
289
+ end
290
+
291
+ def line
292
+ @cells[0].line
293
+ end
294
+
295
+ private
296
+
297
+ def width
298
+ map{|cell| cell.value ? escape_cell(cell.value.to_s).unpack('U*').length : 0}.max
299
+ end
300
+
301
+ def each(&proc)
302
+ @cells.each(&proc)
303
+ end
304
+ end
305
+
306
+ class Cell #:nodoc:
307
+ attr_reader :line, :table
308
+ attr_accessor :status, :value
309
+
310
+ def initialize(value, table, line)
311
+ @value, @table, @line = value, table, line
312
+ end
313
+
314
+ def inspect!
315
+ @value = "(i) #{value.inspect}"
316
+ end
317
+
318
+ # For testing only
319
+ def to_sexp #:nodoc:
320
+ [:cell, @value]
321
+ end
322
+ end
323
+ end
324
+ end
325
+ end
326
+ end