cucumber_converter 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e724f4801bff3904058cfe06e7422f9f08fce8ad
4
+ data.tar.gz: b1f1c3ed1ec67fb7d6b0ffcc2134c0d34581bb8c
5
+ SHA512:
6
+ metadata.gz: 70173f93eb47117f642d25e41d05a3d73ffa9fa873776a07d7103f0517ca9800bee3a270e263a2504cc0989e043067266a0712c85f396f4f271a25b2a6fc9cf7
7
+ data.tar.gz: 66d9aad618734b1925cc531a19e120a5a02178c2bad27425f3e0499bda012be656a613a739dcc61d382fa8e378ecdb21cd3f8aace34ca4fc09250d2d46139e09
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ load File.expand_path('../../lib/cucumber_converter.rb', __FILE__)
data/lib/background.rb ADDED
@@ -0,0 +1,12 @@
1
+ class Background
2
+ include StepContainer
3
+
4
+ def initialize(gherkin, step_data)
5
+ @steps = gherkin[:steps] || []
6
+ @step_data = step_data
7
+ end
8
+
9
+ def template_path
10
+ File.expand_path('./templates/background.erb', GEM_PATH)
11
+ end
12
+ end
data/lib/config.rb ADDED
@@ -0,0 +1,17 @@
1
+ module Configuration
2
+ class << self
3
+ def default_config
4
+ {
5
+ step_path_base: File.expand_path("features/step_definitions", WD),
6
+ feature_path_base: File.expand_path("features", WD),
7
+ tags: { "@javascript" => "js: true" }
8
+ }
9
+ end
10
+
11
+ def config(config_file)
12
+ OpenStruct.new(default_config.merge(
13
+ File.exists?(config_file) ? YAML.load_file(config_file) : {}
14
+ ))
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ require 'setup'
2
+
3
+ # load all step definitions to be captured
4
+ # having redifined 'Given' in the main object, loading these files in the main scope
5
+ # should call our definition, which has a reference to our step capturer to capture these calls.
6
+ Dir.glob("#{Config.step_path_base}/**/*.rb").each(&method(:load))
7
+
8
+ # Beep Boop Beep -- now we have code for step definitions
9
+ steps = step_capturer.post_process!
10
+
11
+ # Write those files!
12
+ step_definitions = StepDefinition.parse_steps(steps, Config.step_path_base)
13
+ FileWriter.write_files(step_definitions)
14
+
15
+ # convert feature files
16
+ # use gherkin parser to get an object representation of a feature file,
17
+ # and write it in rspec syntax
18
+ feature_files = Dir.glob("#{Config.feature_path_base}/**/*.feature")
19
+ features = Feature.parse_features(feature_files, Gherkin::Parser.new, steps)
20
+ FileWriter.write_files(features)
data/lib/feature.rb ADDED
@@ -0,0 +1,51 @@
1
+ class Feature
2
+ include StepContainer
3
+
4
+ attr_accessor :gherkin
5
+
6
+ class << self
7
+ def parse_features(feature_files, parser, steps)
8
+ feature_files.each_with_object({}) do |filename, memo|
9
+ gherkin_document = parser.parse(File.read(filename))
10
+ memo[new_filename(filename)] = new(gherkin_document, steps)
11
+ end
12
+ end
13
+
14
+ def new_filename(filename)
15
+ FileWriter
16
+ .write_path(Config.feature_path_base, "cucumber_to_rspec/features/", WD, filename)
17
+ .gsub('.feature', '.rb')
18
+ end
19
+ end
20
+
21
+ def initialize(gherkin, step_data)
22
+ @gherkin = gherkin
23
+ @step_data = step_data
24
+ end
25
+
26
+ private
27
+
28
+ def feature_name
29
+ @feature_name ||= gherkin[:feature][:name]
30
+ end
31
+
32
+ def feature_tags
33
+ tag_parser.format_tags(gherkin[:feature][:tags])
34
+ end
35
+
36
+ def scenarios
37
+ @scenarios ||= gherkin[:feature][:children].select { |child|
38
+ child[:type] == :Scenario
39
+ }.map{ |child| Scenario.new(child, step_data) }
40
+ end
41
+
42
+ def background
43
+ @background ||= gherkin[:feature][:children].select { |child|
44
+ child[:type] == :Background
45
+ }.map{ |child| Background.new(child, step_data) }.first
46
+ end
47
+
48
+ def template_path
49
+ File.expand_path('./templates/feature.erb', GEM_PATH)
50
+ end
51
+ end
@@ -0,0 +1,16 @@
1
+ module FileWriter
2
+ class << self
3
+ def write_path(base_path, write_path, wd, filename)
4
+ File.expand_path(filename.gsub(base_path, File.expand_path(write_path, wd)))
5
+ end
6
+
7
+ def write_file(file_path, file_contents)
8
+ response = FileUtils.mkdir_p(File.dirname(file_path))
9
+ File.open(file_path, 'w+') { |f| f.write(file_contents) }
10
+ end
11
+
12
+ def write_files(files)
13
+ files.each(&method(:write_file))
14
+ end
15
+ end
16
+ end
data/lib/given.rb ADDED
@@ -0,0 +1,17 @@
1
+ module GivenDefinition
2
+ # Define Given, Then, When, And to record all step definitions.
3
+
4
+ attr_reader :step_capturer
5
+
6
+ def set_step_capturer(step_capturer)
7
+ @step_capturer = step_capturer
8
+ end
9
+
10
+ def Given(regex, &block)
11
+ step_capturer.capture!(regex, &block)
12
+ end
13
+
14
+ alias Then Given
15
+ alias And Given
16
+ alias When Given
17
+ end
data/lib/scenario.rb ADDED
@@ -0,0 +1,22 @@
1
+ class Scenario
2
+ include StepContainer
3
+
4
+ attr_accessor :name
5
+
6
+ def initialize(gherkin, step_data)
7
+ @name = gherkin[:name]
8
+ @steps = gherkin[:steps] || []
9
+ @tags = gherkin[:tags]
10
+ @step_data = step_data
11
+ end
12
+
13
+ private
14
+
15
+ def scenario_tags
16
+ tag_parser.format_tags(@tags)
17
+ end
18
+
19
+ def template_path
20
+ File.expand_path('./templates/scenario.erb', GEM_PATH)
21
+ end
22
+ end
data/lib/setup.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'fileutils'
2
+ require "ostruct"
3
+ require 'yaml'
4
+ require 'erb'
5
+ require 'gherkin/parser'
6
+ require 'gherkin/pickles/compiler'
7
+ require_relative 'config'
8
+ require_relative 'step_capture'
9
+ require_relative 'file_writer'
10
+ require_relative 'step_container'
11
+ require_relative 'step_definition'
12
+ require_relative 'step_converter'
13
+ require_relative 'feature'
14
+ require_relative 'background'
15
+ require_relative 'scenario'
16
+ require_relative 'tag_parser'
17
+ require 'given'
18
+
19
+ WD = `pwd`.chomp
20
+ GEM_PATH = File.dirname(File.expand_path(__FILE__))
21
+ Config = Configuration.config(File.expand_path('.cucumber_converter.yml', WD))
22
+
23
+ include GivenDefinition
24
+ set_step_capturer(StepCapturer.new)
@@ -0,0 +1,17 @@
1
+ class StepCapturer
2
+ attr_accessor :step_definitions
3
+
4
+ def initialize
5
+ @step_definitions = []
6
+ end
7
+
8
+ def capture!(regex, &block)
9
+ step_definitions << StepDefinition.new(regex, &block)
10
+ end
11
+
12
+ def post_process!
13
+ @step_definitions = step_definitions.map do |step|
14
+ step.process!(step_definitions)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ module StepContainer
2
+ attr_accessor :steps, :step_data
3
+
4
+ def to_s
5
+ template.result(binding)
6
+ end
7
+
8
+ private
9
+
10
+ def tag_parser
11
+ @tag_parser ||= TagParser.new
12
+ end
13
+
14
+ def step_converter
15
+ @step_converter ||= StepConverter.new
16
+ end
17
+
18
+ def parse_step(step)
19
+ step_converter.convert(step[:text], step_data)
20
+ end
21
+
22
+ def parsed_steps
23
+ steps.map(&method(:parse_step))
24
+ end
25
+
26
+ def template
27
+ ERB.new(File.read(template_path), nil, '->')
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ class StepConverter
2
+ def convert(step_line, step_definitions)
3
+ matched = matched_step(step_line, step_definitions)
4
+ if matched
5
+ arguments = matched.regex.match(step_line)[1..-1]
6
+ "#{matched.method_name}(#{arguments.map(&:inspect).join(", ")})"
7
+ else
8
+ "# #{step_line} -- no method matched"
9
+ end
10
+ end
11
+
12
+ def matched_step(step_line, step_definitions)
13
+ step_definitions.find do |step_definition|
14
+ step_definition.regex.match(step_line)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,96 @@
1
+ require 'method_source'
2
+
3
+ class StepDefinition
4
+ WRITE_PATH = "cucumber_to_rspec/step_definitions/"
5
+
6
+ class << self
7
+ def parse_steps(steps, base_path)
8
+ self.steps_by_file(steps).each_with_object({}) do |(filename, file_steps), memo|
9
+ memo[self.new_file_path(filename, base_path)] = self.render_template(file_steps)
10
+ end
11
+ end
12
+
13
+ def steps_by_file(steps)
14
+ steps.group_by(&:location)
15
+ end
16
+
17
+ def new_file_path(filename, base_path)
18
+ FileWriter.write_path(base_path, WRITE_PATH, WD, filename)
19
+ end
20
+
21
+ def render_template(file_steps)
22
+ self.template.result(binding)
23
+ end
24
+
25
+ def template
26
+ ERB.new(File.read(self.template_path), nil, '->')
27
+ end
28
+
29
+ def template_path
30
+ File.expand_path('./templates/step_definitions_file.erb', GEM_PATH)
31
+ end
32
+ end
33
+
34
+ attr_accessor :regex, :block, :location, :method_name, :processed_code
35
+
36
+ def step_converter
37
+ @step_converter ||= StepConverter.new
38
+ end
39
+
40
+ def initialize(regex, &block)
41
+ @regex = regex
42
+ @method_name = method_name_from_regex(regex)
43
+ @block = block
44
+ @location = block.source_location.first
45
+ end
46
+
47
+ def method_name_from_regex(regex)
48
+ regex
49
+ .inspect[1..-2]
50
+ .gsub(/\s/,"_")
51
+ .gsub(/\W|\d/,"")
52
+ .gsub(/_$/,"")
53
+ .gsub(/_+/,"_")
54
+ .downcase
55
+ end
56
+
57
+ def to_s
58
+ template.result(binding)
59
+ end
60
+
61
+ def template_path
62
+ File.expand_path('./templates/step_definition.erb', GEM_PATH)
63
+ end
64
+
65
+ def template
66
+ ERB.new(File.read(template_path), nil, '->')
67
+ end
68
+
69
+ def block_source
70
+ @block_source ||= block.source
71
+ end
72
+
73
+ def method_definition
74
+ return @method_definition if @method_definition
75
+ match = block_source.split("\n").first.match(/(?:And|When|Then|Given)\(.*\)[\s]do[\s]?(?:\|(.*)\|)?/)
76
+ @method_definition = match ? method_name + ('(%s)' % match[1]) : method_name
77
+ end
78
+
79
+ def method_body
80
+ @method_body || raise("Method not processed")
81
+ end
82
+
83
+ # this is specifically looking to references to other steps, by way of the 'step' call. If it finds these lines
84
+ # it will substitute a direct method call, like we do with the features
85
+ def process!(step_definitions)
86
+ @method_body = block_source.split("\n")[1..-2].map do |line|
87
+ step_method_call_match = line.match(/^(\s*)step "(.*)"/)
88
+ if step_method_call_match
89
+ step_method_call_match[1] + step_converter.convert(step_method_call_match[2], step_definitions)
90
+ else
91
+ line
92
+ end
93
+ end
94
+ return self
95
+ end
96
+ end
data/lib/tag_parser.rb ADDED
@@ -0,0 +1,6 @@
1
+ class TagParser
2
+ def format_tags(tags)
3
+ return nil if tags.empty?
4
+ ", #{tags.map{ |tag| Config.tags[tag[:name]] || tag[:name].tr('@',':') }.join(", ")}"
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ before(:each) do
2
+ <% parsed_steps.each do |step| -%>
3
+ <%= step %>
4
+ <% end -%>
5
+ end
@@ -0,0 +1,6 @@
1
+ feature "<%= feature_name %>"<%= feature_tags %> do
2
+ <%= background -%>
3
+ <% scenarios.each do |scenario| %>
4
+ <%= scenario -%>
5
+ <% end -%>
6
+ end
@@ -0,0 +1,5 @@
1
+ scenario "<%= name %>"<%= scenario_tags %> do
2
+ <% parsed_steps.each do |step| -%>
3
+ <%= step %>
4
+ <% end -%>
5
+ end
@@ -0,0 +1,5 @@
1
+ def <%= method_definition %>
2
+ <% method_body.each do |line| -%>
3
+ <%= line %>
4
+ <% end -%>
5
+ end
@@ -0,0 +1,5 @@
1
+ module StepDefinitions
2
+ <% file_steps.each do |step| -%>
3
+ <%= step %>
4
+ <% end -%>
5
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cucumber_converter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tracy Meade
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-28 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Converts cucumber tests to Rspec Features
14
+ email: meade.tracy@gmail.com
15
+ executables:
16
+ - cucumber_convert
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/cucumber_convert
21
+ - lib/background.rb
22
+ - lib/config.rb
23
+ - lib/cucumber_converter.rb
24
+ - lib/feature.rb
25
+ - lib/file_writer.rb
26
+ - lib/given.rb
27
+ - lib/scenario.rb
28
+ - lib/setup.rb
29
+ - lib/step_capture.rb
30
+ - lib/step_container.rb
31
+ - lib/step_converter.rb
32
+ - lib/step_definition.rb
33
+ - lib/tag_parser.rb
34
+ - lib/templates/background.erb
35
+ - lib/templates/feature.erb
36
+ - lib/templates/scenario.erb
37
+ - lib/templates/step_definition.erb
38
+ - lib/templates/step_definitions_file.erb
39
+ homepage:
40
+ licenses: []
41
+ metadata: {}
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 2.4.5.1
59
+ signing_key:
60
+ specification_version: 4
61
+ summary: Converts cucumber tests to Rspec Features
62
+ test_files: []