cuke_modeler 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 +7 -0
- data/.gitignore +17 -0
- data/.simplecov +8 -0
- data/Gemfile +4 -0
- data/History.rdoc +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +73 -0
- data/Rakefile +38 -0
- data/cuke_modeler.gemspec +29 -0
- data/features/analysis/test_comparison.feature +123 -0
- data/features/analysis/test_manipulation.feature +37 -0
- data/features/modeling/background_modeling.feature +75 -0
- data/features/modeling/background_output.feature +130 -0
- data/features/modeling/directory_modeling.feature +120 -0
- data/features/modeling/directory_output.feature +13 -0
- data/features/modeling/doc_string_modeling.feature +63 -0
- data/features/modeling/doc_string_output.feature +71 -0
- data/features/modeling/example_modeling.feature +111 -0
- data/features/modeling/example_output.feature +192 -0
- data/features/modeling/feature_file_modeling.feature +64 -0
- data/features/modeling/feature_file_output.feature +13 -0
- data/features/modeling/feature_modeling.feature +164 -0
- data/features/modeling/feature_output.feature +244 -0
- data/features/modeling/outline_modeling.feature +100 -0
- data/features/modeling/outline_output.feature +197 -0
- data/features/modeling/row_modeling.feature +77 -0
- data/features/modeling/row_output.feature +27 -0
- data/features/modeling/scenario_modeling.feature +89 -0
- data/features/modeling/scenario_output.feature +147 -0
- data/features/modeling/step_modeling.feature +85 -0
- data/features/modeling/step_output.feature +52 -0
- data/features/modeling/table_modeling.feature +52 -0
- data/features/modeling/table_output.feature +42 -0
- data/features/modeling/table_row_modeling.feature +67 -0
- data/features/modeling/table_row_output.feature +27 -0
- data/features/modeling/tag_modeling.feature +58 -0
- data/features/modeling/tag_output.feature +16 -0
- data/features/step_definitions/action_steps.rb +3 -0
- data/features/step_definitions/background_steps.rb +81 -0
- data/features/step_definitions/directory_steps.rb +52 -0
- data/features/step_definitions/doc_string_steps.rb +63 -0
- data/features/step_definitions/feature_file_steps.rb +41 -0
- data/features/step_definitions/feature_steps.rb +96 -0
- data/features/step_definitions/outline_steps.rb +252 -0
- data/features/step_definitions/setup_steps.rb +50 -0
- data/features/step_definitions/spec_steps.rb +18 -0
- data/features/step_definitions/step_steps.rb +159 -0
- data/features/step_definitions/table_steps.rb +54 -0
- data/features/step_definitions/tag_steps.rb +61 -0
- data/features/step_definitions/test_steps.rb +114 -0
- data/features/step_definitions/verification_steps.rb +9 -0
- data/features/support/env.rb +27 -0
- data/features/support/transforms.rb +3 -0
- data/lib/cuke_modeler.rb +29 -0
- data/lib/cuke_modeler/background.rb +38 -0
- data/lib/cuke_modeler/containing.rb +18 -0
- data/lib/cuke_modeler/directory.rb +86 -0
- data/lib/cuke_modeler/doc_string.rb +87 -0
- data/lib/cuke_modeler/example.rb +184 -0
- data/lib/cuke_modeler/feature.rb +147 -0
- data/lib/cuke_modeler/feature_element.rb +73 -0
- data/lib/cuke_modeler/feature_file.rb +77 -0
- data/lib/cuke_modeler/nested.rb +34 -0
- data/lib/cuke_modeler/outline.rb +68 -0
- data/lib/cuke_modeler/parsing.rb +32 -0
- data/lib/cuke_modeler/raw.rb +20 -0
- data/lib/cuke_modeler/row.rb +64 -0
- data/lib/cuke_modeler/scenario.rb +45 -0
- data/lib/cuke_modeler/sourceable.rb +20 -0
- data/lib/cuke_modeler/step.rb +214 -0
- data/lib/cuke_modeler/table.rb +90 -0
- data/lib/cuke_modeler/table_row.rb +64 -0
- data/lib/cuke_modeler/tag.rb +62 -0
- data/lib/cuke_modeler/taggable.rb +54 -0
- data/lib/cuke_modeler/test_element.rb +77 -0
- data/lib/cuke_modeler/version.rb +3 -0
- data/lib/cuke_modeler/world.rb +113 -0
- data/spec/integration/background_integration_spec.rb +72 -0
- data/spec/integration/directory_integration_spec.rb +48 -0
- data/spec/integration/doc_string_integration_spec.rb +66 -0
- data/spec/integration/example_integration_spec.rb +94 -0
- data/spec/integration/feature_file_integration_spec.rb +44 -0
- data/spec/integration/feature_integration_spec.rb +152 -0
- data/spec/integration/outline_integration_spec.rb +92 -0
- data/spec/integration/scenario_integration_spec.rb +80 -0
- data/spec/integration/step_integration_spec.rb +184 -0
- data/spec/integration/table_integration_spec.rb +86 -0
- data/spec/integration/table_row_integration_spec.rb +68 -0
- data/spec/integration/tag_integration_spec.rb +67 -0
- data/spec/integration/world_integration_spec.rb +13 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/unit/background_unit_spec.rb +55 -0
- data/spec/unit/bare_bones_unit_specs.rb +13 -0
- data/spec/unit/containing_element_unit_specs.rb +17 -0
- data/spec/unit/directory_unit_spec.rb +103 -0
- data/spec/unit/doc_string_unit_spec.rb +109 -0
- data/spec/unit/example_unit_spec.rb +251 -0
- data/spec/unit/feature_element_unit_spec.rb +19 -0
- data/spec/unit/feature_element_unit_specs.rb +46 -0
- data/spec/unit/feature_file_unit_spec.rb +94 -0
- data/spec/unit/feature_unit_spec.rb +135 -0
- data/spec/unit/nested_element_unit_specs.rb +36 -0
- data/spec/unit/nested_unit_spec.rb +37 -0
- data/spec/unit/outline_unit_spec.rb +91 -0
- data/spec/unit/parsing_unit_spec.rb +21 -0
- data/spec/unit/prepopulated_unit_specs.rb +13 -0
- data/spec/unit/raw_element_unit_specs.rb +24 -0
- data/spec/unit/raw_unit_spec.rb +25 -0
- data/spec/unit/row_unit_spec.rb +55 -0
- data/spec/unit/scenario_unit_spec.rb +71 -0
- data/spec/unit/sourceable_unit_spec.rb +17 -0
- data/spec/unit/sourced_element_unit_specs.rb +18 -0
- data/spec/unit/step_unit_spec.rb +259 -0
- data/spec/unit/table_row_unit_spec.rb +55 -0
- data/spec/unit/table_unit_spec.rb +96 -0
- data/spec/unit/tag_unit_spec.rb +51 -0
- data/spec/unit/taggable_unit_spec.rb +78 -0
- data/spec/unit/tagged_element_unit_specs.rb +63 -0
- data/spec/unit/test_element_unit_spec.rb +40 -0
- data/spec/unit/test_element_unit_specs.rb +31 -0
- data/spec/unit/world_unit_spec.rb +130 -0
- metadata +364 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
module CukeModeler
|
|
2
|
+
|
|
3
|
+
# A class modeling a Cucumber .feature file.
|
|
4
|
+
|
|
5
|
+
class FeatureFile
|
|
6
|
+
|
|
7
|
+
include Containing
|
|
8
|
+
include Nested
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# The Feature objects contained by the FeatureFile
|
|
12
|
+
attr_accessor :features
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Creates a new FeatureFile object and, if *file_parsed* is provided,
|
|
16
|
+
# populates the object.
|
|
17
|
+
def initialize(file = nil)
|
|
18
|
+
@file = file
|
|
19
|
+
@features = []
|
|
20
|
+
|
|
21
|
+
if file
|
|
22
|
+
raise(ArgumentError, "Unknown file: #{file.inspect}") unless File.exists?(file)
|
|
23
|
+
|
|
24
|
+
parsed_file = parse_file(file)
|
|
25
|
+
|
|
26
|
+
build_file(parsed_file)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Returns the name of the file.
|
|
31
|
+
def name
|
|
32
|
+
File.basename(@file.gsub('\\', '/'))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Returns the path of the file.
|
|
36
|
+
def path
|
|
37
|
+
@file
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Returns the immediate child elements of the file(i.e. its Feature object).
|
|
41
|
+
def contains
|
|
42
|
+
@features
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Returns the number of features contained in the file.
|
|
46
|
+
def feature_count
|
|
47
|
+
@features.count
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Returns the Feature object contained by the FeatureFile.
|
|
51
|
+
def feature
|
|
52
|
+
@features.first
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Returns the path of the feature file.
|
|
56
|
+
def to_s
|
|
57
|
+
path.to_s
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def parse_file(file_to_parse)
|
|
65
|
+
source_text = IO.read(file_to_parse)
|
|
66
|
+
|
|
67
|
+
Parsing::parse_text(source_text)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def build_file(parsed_file)
|
|
71
|
+
unless parsed_file.empty?
|
|
72
|
+
@features << build_child_element(Feature, parsed_file.first)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module CukeModeler
|
|
2
|
+
|
|
3
|
+
# A mix-in module containing methods used by elements that are nested inside
|
|
4
|
+
# of other elements.
|
|
5
|
+
|
|
6
|
+
module Nested
|
|
7
|
+
|
|
8
|
+
# The parent object that contains *self*
|
|
9
|
+
attr_accessor :parent_element
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Returns the ancestor of *self* that matches the given type.
|
|
13
|
+
def get_ancestor(ancestor_type)
|
|
14
|
+
ancestor = self.parent_element
|
|
15
|
+
target_type = {:directory => Directory,
|
|
16
|
+
:feature_file => FeatureFile,
|
|
17
|
+
:feature => Feature,
|
|
18
|
+
:test => TestElement,
|
|
19
|
+
:step => Step,
|
|
20
|
+
:table => Table,
|
|
21
|
+
:example => Example
|
|
22
|
+
}[ancestor_type]
|
|
23
|
+
|
|
24
|
+
raise(ArgumentError, "Unknown ancestor type '#{ancestor_type}'.") if target_type.nil?
|
|
25
|
+
|
|
26
|
+
until ancestor.is_a?(target_type) || ancestor.nil?
|
|
27
|
+
ancestor = ancestor.parent_element
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
ancestor
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module CukeModeler
|
|
2
|
+
|
|
3
|
+
# A class modeling a Cucumber Scenario Outline.
|
|
4
|
+
|
|
5
|
+
class Outline < TestElement
|
|
6
|
+
|
|
7
|
+
include Taggable
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# The Example objects contained by the Outline
|
|
11
|
+
attr_accessor :examples
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Creates a new Outline object and, if *source* is provided, populates the
|
|
15
|
+
# object.
|
|
16
|
+
def initialize(source = nil)
|
|
17
|
+
parsed_outline = process_source(source)
|
|
18
|
+
|
|
19
|
+
super(parsed_outline)
|
|
20
|
+
|
|
21
|
+
@tags = []
|
|
22
|
+
@tag_elements = []
|
|
23
|
+
@examples = []
|
|
24
|
+
|
|
25
|
+
build_outline(parsed_outline) if parsed_outline
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Returns the immediate child elements of the outline (i.e. its Example
|
|
29
|
+
# objects.
|
|
30
|
+
def contains
|
|
31
|
+
@examples + @steps
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Returns a gherkin representation of the outline.
|
|
35
|
+
def to_s
|
|
36
|
+
text = ''
|
|
37
|
+
|
|
38
|
+
text << tag_output_string + "\n" unless tags.empty?
|
|
39
|
+
text << "Scenario Outline:#{name_output_string}"
|
|
40
|
+
text << "\n" + description_output_string unless description_text.empty?
|
|
41
|
+
text << "\n" unless steps.empty? || description_text.empty?
|
|
42
|
+
text << "\n" + steps_output_string unless steps.empty?
|
|
43
|
+
text << "\n\n" + examples_output_string unless examples.empty?
|
|
44
|
+
|
|
45
|
+
text
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def build_outline(parsed_outline)
|
|
53
|
+
populate_element_tags(parsed_outline)
|
|
54
|
+
populate_outline_examples(parsed_outline['examples']) if parsed_outline['examples']
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def populate_outline_examples(parsed_examples)
|
|
58
|
+
parsed_examples.each do |example|
|
|
59
|
+
@examples << build_child_element(Example, example)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def examples_output_string
|
|
64
|
+
examples.empty? ? '' : examples.collect { |example| example.to_s }.join("\n\n")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'stringio'
|
|
2
|
+
require 'gherkin/formatter/json_formatter'
|
|
3
|
+
require 'gherkin'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'multi_json'
|
|
6
|
+
|
|
7
|
+
module CukeModeler
|
|
8
|
+
|
|
9
|
+
# A module providing source text parsing functionality.
|
|
10
|
+
|
|
11
|
+
module Parsing
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
|
|
15
|
+
# Parses the Cucumber feature given in *source_text* and returns an array
|
|
16
|
+
# containing the hash representation of its logical structure.
|
|
17
|
+
def parse_text(source_text)
|
|
18
|
+
raise(ArgumentError, "Cannot parse #{source_text.class} objects. Strings only.") unless source_text.is_a?(String)
|
|
19
|
+
|
|
20
|
+
io = StringIO.new
|
|
21
|
+
formatter = Gherkin::Formatter::JSONFormatter.new(io)
|
|
22
|
+
parser = Gherkin::Parser::Parser.new(formatter)
|
|
23
|
+
parser.parse(source_text, 'fake_file.txt', 0)
|
|
24
|
+
formatter.done
|
|
25
|
+
|
|
26
|
+
MultiJson.load(io.string)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module CukeModeler
|
|
2
|
+
|
|
3
|
+
# A mix-in module containing methods used by elements that store their
|
|
4
|
+
# underlying implementation
|
|
5
|
+
|
|
6
|
+
module Raw
|
|
7
|
+
|
|
8
|
+
# The raw representation of the element (i.e. the output of the gherkin gem)
|
|
9
|
+
attr_accessor :raw_element
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def populate_raw_element(parsed_element)
|
|
16
|
+
@raw_element = parsed_element
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module CukeModeler
|
|
2
|
+
|
|
3
|
+
# A class modeling a Cucumber Examples table row.
|
|
4
|
+
|
|
5
|
+
class Row
|
|
6
|
+
|
|
7
|
+
include Sourceable
|
|
8
|
+
include Raw
|
|
9
|
+
include Nested
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# The cells that make up the row
|
|
13
|
+
attr_accessor :cells
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Creates a new Row object and, if *source* is provided, populates
|
|
17
|
+
# the object.
|
|
18
|
+
def initialize(source = nil)
|
|
19
|
+
parsed_row = process_source(source)
|
|
20
|
+
|
|
21
|
+
@cells = []
|
|
22
|
+
|
|
23
|
+
build_row(parsed_row) if parsed_row
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns a gherkin representation of the row.
|
|
27
|
+
def to_s
|
|
28
|
+
"| #{cells.join(' | ')} |"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def process_source(source)
|
|
36
|
+
case
|
|
37
|
+
when source.is_a?(String)
|
|
38
|
+
parse_row(source)
|
|
39
|
+
else
|
|
40
|
+
source
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def parse_row(source_text)
|
|
45
|
+
base_file_string = "Feature: Fake feature to parse\nScenario Outline:\n* fake step\nExamples: fake examples\n"
|
|
46
|
+
source_text = base_file_string + source_text
|
|
47
|
+
|
|
48
|
+
parsed_file = Parsing::parse_text(source_text)
|
|
49
|
+
|
|
50
|
+
parsed_file.first['elements'].first['examples'].first['rows'].first
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def build_row(parsed_row)
|
|
54
|
+
populate_element_source_line(parsed_row)
|
|
55
|
+
populate_row_cells(parsed_row)
|
|
56
|
+
populate_raw_element(parsed_row)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def populate_row_cells(parsed_row)
|
|
60
|
+
@cells = parsed_row['cells']
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module CukeModeler
|
|
2
|
+
|
|
3
|
+
# A class modeling a Cucumber Scenario.
|
|
4
|
+
|
|
5
|
+
class Scenario < TestElement
|
|
6
|
+
|
|
7
|
+
include Taggable
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# Creates a new Scenario object and, if *source* is provided, populates the
|
|
11
|
+
# object.
|
|
12
|
+
def initialize(source = nil)
|
|
13
|
+
parsed_scenario = process_source(source)
|
|
14
|
+
|
|
15
|
+
super(parsed_scenario)
|
|
16
|
+
|
|
17
|
+
@tags = []
|
|
18
|
+
@tag_elements = []
|
|
19
|
+
|
|
20
|
+
build_scenario(parsed_scenario) if parsed_scenario
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Returns gherkin representation of the scenario.
|
|
24
|
+
def to_s
|
|
25
|
+
text = ''
|
|
26
|
+
|
|
27
|
+
text << tag_output_string + "\n" unless tags.empty?
|
|
28
|
+
text << "Scenario:#{name_output_string}"
|
|
29
|
+
text << "\n" + description_output_string unless description_text.empty?
|
|
30
|
+
text << "\n" unless steps.empty? || description_text.empty?
|
|
31
|
+
text << "\n" + steps_output_string unless steps.empty?
|
|
32
|
+
|
|
33
|
+
text
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def build_scenario(scenario)
|
|
41
|
+
populate_element_tags(scenario)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module CukeModeler
|
|
2
|
+
|
|
3
|
+
# A mix-in module containing methods used by elements that know their
|
|
4
|
+
# source code line.
|
|
5
|
+
|
|
6
|
+
module Sourceable
|
|
7
|
+
|
|
8
|
+
# The line number where the element began in the source code
|
|
9
|
+
attr_reader :source_line
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def populate_element_source_line(parsed_element)
|
|
16
|
+
@source_line = parsed_element['line']
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
module CukeModeler
|
|
2
|
+
|
|
3
|
+
# A class modeling a Cucumber Feature.
|
|
4
|
+
|
|
5
|
+
class Step
|
|
6
|
+
|
|
7
|
+
include Containing
|
|
8
|
+
include Sourceable
|
|
9
|
+
include Raw
|
|
10
|
+
include Nested
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# The step's keyword
|
|
14
|
+
attr_accessor :keyword
|
|
15
|
+
|
|
16
|
+
# The base text of the step
|
|
17
|
+
attr_accessor :base
|
|
18
|
+
|
|
19
|
+
# The step's passed block
|
|
20
|
+
attr_accessor :block
|
|
21
|
+
|
|
22
|
+
# The step's arguments
|
|
23
|
+
attr_accessor :arguments
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# Creates a new Step object and, if *source* is provided, populates the
|
|
27
|
+
# object.
|
|
28
|
+
def initialize(source = nil)
|
|
29
|
+
@arguments = []
|
|
30
|
+
|
|
31
|
+
parsed_step = process_source(source)
|
|
32
|
+
|
|
33
|
+
build_step(parsed_step) if parsed_step
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Sets the delimiter that will be used by default when determining the
|
|
37
|
+
# boundaries of step arguments.
|
|
38
|
+
def delimiter=(new_delimiter)
|
|
39
|
+
self.left_delimiter = new_delimiter
|
|
40
|
+
self.right_delimiter = new_delimiter
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Returns the delimiter that is used to mark the beginning of a step
|
|
44
|
+
# argument.
|
|
45
|
+
def left_delimiter
|
|
46
|
+
@left_delimiter || World.left_delimiter
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Sets the left delimiter that will be used by default when determining
|
|
50
|
+
# step arguments.
|
|
51
|
+
def left_delimiter=(new_delimiter)
|
|
52
|
+
@left_delimiter = new_delimiter
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Returns the delimiter that is used to mark the end of a step
|
|
56
|
+
# argument.
|
|
57
|
+
def right_delimiter
|
|
58
|
+
@right_delimiter || World.right_delimiter
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Sets the right delimiter that will be used by default when determining
|
|
62
|
+
# step arguments.
|
|
63
|
+
def right_delimiter=(new_delimiter)
|
|
64
|
+
@right_delimiter = new_delimiter
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Returns true if the two steps have the same text, minus any keywords
|
|
68
|
+
# and arguments, and false otherwise.
|
|
69
|
+
def ==(other_step)
|
|
70
|
+
left_step = step_text(:with_keywords => false, :with_arguments => false)
|
|
71
|
+
right_step = other_step.step_text(:with_keywords => false, :with_arguments => false)
|
|
72
|
+
|
|
73
|
+
left_step == right_step
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Deprecated
|
|
77
|
+
#
|
|
78
|
+
# Returns the entire text of the step. Options can be set to selectively
|
|
79
|
+
# exclude certain portions of the text. *left_delimiter* and *right_delimiter*
|
|
80
|
+
# are used to determine which parts of the step are arguments.
|
|
81
|
+
#
|
|
82
|
+
# a_step = CukeModeler::Step.new("Given *some* step with a block:\n|block line 1|\n|block line 2|")
|
|
83
|
+
#
|
|
84
|
+
# a_step.step_text
|
|
85
|
+
# #=> ['Given *some* step with a block:', '|block line 1|', '|block line 2|']
|
|
86
|
+
# a_step.step_text(:with_keywords => false)
|
|
87
|
+
# #=> ['*some* step with a block:', '|block line 1|', '|block line 2|']
|
|
88
|
+
# a_step.step_text(:with_arguments => false, :left_delimiter => '*', :right_delimiter => '*')
|
|
89
|
+
# #=> ['Given ** step with a block:']
|
|
90
|
+
# a_step.step_text(:with_keywords => false, :with_arguments => false, :left_delimiter => '-', :right_delimiter => '-'))
|
|
91
|
+
# #=> ['*some* step with a block:']
|
|
92
|
+
#
|
|
93
|
+
def step_text(options = {})
|
|
94
|
+
options = {:with_keywords => true,
|
|
95
|
+
:with_arguments => true,
|
|
96
|
+
:left_delimiter => self.left_delimiter,
|
|
97
|
+
:right_delimiter => self.right_delimiter}.merge(options)
|
|
98
|
+
|
|
99
|
+
final_step = []
|
|
100
|
+
step_text = ''
|
|
101
|
+
|
|
102
|
+
step_text += "#{@keyword} " if options[:with_keywords]
|
|
103
|
+
|
|
104
|
+
if options[:with_arguments]
|
|
105
|
+
step_text += @base
|
|
106
|
+
final_step << step_text
|
|
107
|
+
final_step.concat(rebuild_block_text(@block)) if @block
|
|
108
|
+
else
|
|
109
|
+
step_text += stripped_step(@base, options[:left_delimiter], options[:right_delimiter])
|
|
110
|
+
final_step << step_text
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
final_step
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Populates the step's arguments based on the step's text and some method of
|
|
117
|
+
# determining which parts of the text are arguments. Methods include using
|
|
118
|
+
# a regular expression and using the step's delimiters.
|
|
119
|
+
def scan_arguments(*how)
|
|
120
|
+
if how.count == 1
|
|
121
|
+
pattern = how.first
|
|
122
|
+
else
|
|
123
|
+
left_delimiter = how[0] || self.left_delimiter
|
|
124
|
+
right_delimiter = how[1] || self.right_delimiter
|
|
125
|
+
|
|
126
|
+
return [] unless left_delimiter && right_delimiter
|
|
127
|
+
|
|
128
|
+
pattern = Regexp.new(Regexp.escape(left_delimiter) + '(.*?)' + Regexp.escape(right_delimiter))
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
@arguments = @base.scan(pattern).flatten
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Returns a gherkin representation of the step.
|
|
135
|
+
def to_s
|
|
136
|
+
text = "#{keyword} #{base}"
|
|
137
|
+
text << "\n" + block.to_s.split("\n").collect { |line| " #{line}" }.join("\n") if block
|
|
138
|
+
|
|
139
|
+
text
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
private
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def process_source(source)
|
|
147
|
+
case
|
|
148
|
+
when source.is_a?(String)
|
|
149
|
+
parse_step(source)
|
|
150
|
+
else
|
|
151
|
+
source
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def parse_step(source_text)
|
|
156
|
+
base_file_string = "Feature: Fake feature to parse\nScenario:\n"
|
|
157
|
+
source_text = base_file_string + source_text
|
|
158
|
+
|
|
159
|
+
parsed_file = Parsing::parse_text(source_text)
|
|
160
|
+
|
|
161
|
+
parsed_file.first['elements'].first['steps'].first
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def build_step(step)
|
|
165
|
+
populate_base(step)
|
|
166
|
+
populate_block(step)
|
|
167
|
+
populate_keyword(step)
|
|
168
|
+
populate_element_source_line(step)
|
|
169
|
+
populate_raw_element(step)
|
|
170
|
+
|
|
171
|
+
scan_arguments
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def populate_base(step)
|
|
175
|
+
@base = step['name']
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def populate_block(step)
|
|
179
|
+
@block = build_block(step)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def populate_keyword(step)
|
|
183
|
+
@keyword = step['keyword'].strip
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Returns the step string minus any arguments based on the given delimiters.
|
|
187
|
+
def stripped_step(step, left_delimiter, right_delimiter)
|
|
188
|
+
unless left_delimiter.nil? || right_delimiter.nil?
|
|
189
|
+
pattern = Regexp.new(Regexp.escape(left_delimiter) + '.*?' + Regexp.escape(right_delimiter))
|
|
190
|
+
step = step.gsub(pattern, left_delimiter + right_delimiter)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
step
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def build_block(step)
|
|
197
|
+
case
|
|
198
|
+
when step['rows']
|
|
199
|
+
@block = build_child_element(Table, step['rows'])
|
|
200
|
+
when step['doc_string']
|
|
201
|
+
@block = build_child_element(DocString, step['doc_string'])
|
|
202
|
+
else
|
|
203
|
+
@block = nil
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
@block
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def rebuild_block_text(blok)
|
|
210
|
+
blok.contents.collect { |row| "|#{row.join('|')}|" }
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
end
|
|
214
|
+
end
|