cuke_modeler 0.1.0 → 0.2.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.
data/History.rdoc CHANGED
@@ -1,3 +1,8 @@
1
+ === Version 0.1.0 / 2016-02-21
2
+
3
+ * Better error feedback when parsing errors are encountered.
4
+
5
+
1
6
  === Version 0.1.0 / 2016-02-10
2
7
 
3
8
  * Support for version 3.0 of the 'gherkin' gem added.
@@ -7,7 +7,7 @@ module CukeModeler
7
7
  # Creates a new Background object and, if *source* is provided, populates
8
8
  # the object.
9
9
  def initialize(source = nil)
10
- parsed_background = process_source(source)
10
+ parsed_background = process_source(source, 'cuke_modeler_stand_alone_background.feature')
11
11
 
12
12
  super(parsed_background)
13
13
 
@@ -55,7 +55,7 @@ module CukeModeler
55
55
  base_file_string = "Feature:\nScenario:\n* step\n"
56
56
  source_text = base_file_string + source_text
57
57
 
58
- parsed_file = Parsing::parse_text(source_text)
58
+ parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_doc_string.feature')
59
59
 
60
60
  parsed_file.first['elements'].first['steps'].first['doc_string']
61
61
  end
@@ -110,7 +110,7 @@ module CukeModeler
110
110
  base_file_string = "Feature: Fake feature to parse\nScenario Outline:\n* fake step\n"
111
111
  source_text = base_file_string + source_text
112
112
 
113
- parsed_file = Parsing::parse_text(source_text)
113
+ parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_example.feature')
114
114
 
115
115
  parsed_file.first['elements'].first['examples'].first
116
116
  end
@@ -102,7 +102,7 @@ module CukeModeler
102
102
  end
103
103
 
104
104
  def parse_feature(source_text)
105
- parsed_file = Parsing::parse_text(source_text)
105
+ parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_feature.feature')
106
106
 
107
107
  parsed_file.first
108
108
  end
@@ -64,7 +64,7 @@ module CukeModeler
64
64
  def parse_file(file_to_parse)
65
65
  source_text = IO.read(file_to_parse)
66
66
 
67
- Parsing::parse_text(source_text)
67
+ Parsing::parse_text(source_text, file_to_parse)
68
68
  end
69
69
 
70
70
  def build_file(parsed_file)
@@ -14,7 +14,7 @@ module CukeModeler
14
14
  # Creates a new Outline object and, if *source* is provided, populates the
15
15
  # object.
16
16
  def initialize(source = nil)
17
- parsed_outline = process_source(source)
17
+ parsed_outline = process_source(source, 'cuke_modeler_stand_alone_outline.feature')
18
18
 
19
19
  super(parsed_outline)
20
20
 
@@ -17,10 +17,15 @@ if Gem.loaded_specs['gherkin'].version.version[/^3/]
17
17
  module Parsing
18
18
  class << self
19
19
 
20
- def parse_text(source_text)
20
+ def parse_text(source_text, filename = 'cuke_modeler_fake_file.feature')
21
21
  raise(ArgumentError, "Cannot parse #{source_text.class} objects. Strings only.") unless source_text.is_a?(String)
22
22
 
23
- parsed_result = Gherkin::Parser.new.parse(source_text)
23
+ begin
24
+ parsed_result = Gherkin::Parser.new.parse(source_text)
25
+ rescue => e
26
+ raise(ArgumentError, "Error encountered while parsing '#{filename}'\n#{e.class} - #{e.message}")
27
+ end
28
+
24
29
  adapted_result = CukeModeler::Gherkin3Adapter.new.adapt(parsed_result)
25
30
 
26
31
  adapted_result
@@ -49,13 +54,19 @@ else
49
54
 
50
55
  # Parses the Cucumber feature given in *source_text* and returns an array
51
56
  # containing the hash representation of its logical structure.
52
- def parse_text(source_text)
57
+ def parse_text(source_text, filename = 'cuke_modeler_fake_file.feature')
53
58
  raise(ArgumentError, "Cannot parse #{source_text.class} objects. Strings only.") unless source_text.is_a?(String)
54
59
 
55
60
  io = StringIO.new
56
61
  formatter = Gherkin::Formatter::JSONFormatter.new(io)
57
62
  parser = Gherkin::Parser::Parser.new(formatter)
58
- parser.parse(source_text, 'fake_file.txt', 0)
63
+
64
+ begin
65
+ parser.parse(source_text, filename, 0)
66
+ rescue => e
67
+ raise(ArgumentError, "Error encountered while parsing '#{filename}'\n#{e.class} - #{e.message}")
68
+ end
69
+
59
70
  formatter.done
60
71
 
61
72
 
@@ -45,7 +45,7 @@ module CukeModeler
45
45
  base_file_string = "Feature: Fake feature to parse\nScenario Outline:\n* fake step\nExamples: fake examples\n#{source_text}\n"
46
46
  source_text = base_file_string + source_text
47
47
 
48
- parsed_file = Parsing::parse_text(source_text)
48
+ parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_row.feature')
49
49
 
50
50
  parsed_file.first['elements'].first['examples'].first['rows'].last
51
51
  end
@@ -10,7 +10,7 @@ module CukeModeler
10
10
  # Creates a new Scenario object and, if *source* is provided, populates the
11
11
  # object.
12
12
  def initialize(source = nil)
13
- parsed_scenario = process_source(source)
13
+ parsed_scenario = process_source(source, 'cuke_modeler_stand_alone_scenario.feature')
14
14
 
15
15
  super(parsed_scenario)
16
16
 
@@ -158,7 +158,7 @@ module CukeModeler
158
158
  base_file_string = "Feature: Fake feature to parse\nScenario:\n"
159
159
  source_text = base_file_string + source_text
160
160
 
161
- parsed_file = Parsing::parse_text(source_text)
161
+ parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_step.feature')
162
162
 
163
163
  parsed_file.first['elements'].first['steps'].first
164
164
  end
@@ -51,7 +51,7 @@ module CukeModeler
51
51
  base_file_string = "Feature:\nScenario:\n* step\n"
52
52
  source_text = base_file_string + source_text
53
53
 
54
- parsed_file = Parsing::parse_text(source_text)
54
+ parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_table.feature')
55
55
 
56
56
  parsed_file.first['elements'].first['steps'].first['rows']
57
57
  end
@@ -45,7 +45,7 @@ module CukeModeler
45
45
  base_file_string = "Feature: Fake feature to parse\nScenario:\n* fake step\n"
46
46
  source_text = base_file_string + source_text
47
47
 
48
- parsed_file = Parsing::parse_text(source_text)
48
+ parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_table_row.feature')
49
49
 
50
50
  parsed_file.first['elements'].first['steps'].first['rows']['rows'].first
51
51
  end
@@ -43,7 +43,7 @@ module CukeModeler
43
43
  base_file_string = "\nFeature: Fake feature to parse"
44
44
  source_text = source_text + base_file_string
45
45
 
46
- parsed_file = Parsing::parse_text(source_text)
46
+ parsed_file = Parsing::parse_text(source_text, 'cuke_modeler_stand_alone_tag.feature')
47
47
 
48
48
  parsed_file.first['tags'].first
49
49
  end
@@ -37,20 +37,20 @@ module CukeModeler
37
37
  private
38
38
 
39
39
 
40
- def process_source(source)
40
+ def process_source(source, file_name = nil)
41
41
  case
42
42
  when source.is_a?(String)
43
- parse_test_element(source)
43
+ parse_test_element(source, file_name)
44
44
  else
45
45
  source
46
46
  end
47
47
  end
48
48
 
49
- def parse_test_element(source_text)
49
+ def parse_test_element(source_text, file_name = nil)
50
50
  base_file_string = "Feature: Fake feature to parse\n"
51
51
  source_text = base_file_string + source_text
52
52
 
53
- parsed_file = Parsing::parse_text(source_text)
53
+ parsed_file = Parsing::parse_text(source_text, file_name)
54
54
 
55
55
  parsed_file.first['elements'].first
56
56
  end
@@ -1,3 +1,3 @@
1
1
  module CukeModeler
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -26,6 +26,8 @@ RSpec.configure do |config|
26
26
  end
27
27
 
28
28
  config.before(:each) do
29
+ FileUtils.remove_dir(@default_file_directory, true) if File.exists?(@default_file_directory)
30
+
29
31
  FileUtils.mkdir(@default_file_directory)
30
32
  end
31
33
 
@@ -24,6 +24,12 @@ describe 'Background, Unit' do
24
24
  @element.name.should == 'test background'
25
25
  end
26
26
 
27
+ it 'provides a descriptive filename when being parsed from stand alone text' do
28
+ source = "bad background text \n Background:\n And a step\n @foo "
29
+
30
+ expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_background\.feature'/)
31
+ end
32
+
27
33
  it 'stores the original data generated by the parsing adapter', :gherkin3 => true do
28
34
  background = clazz.new('Background: test background')
29
35
  raw_data = background.raw_element
@@ -22,6 +22,12 @@ describe 'DocString, Unit' do
22
22
  @element.contents.should == ["some doc string"]
23
23
  end
24
24
 
25
+ it 'provides a descriptive filename when being parsed from stand alone text' do
26
+ source = 'bad doc string text'
27
+
28
+ expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_doc_string\.feature'/)
29
+ end
30
+
25
31
  it 'stores the original data generated by the parsing adapter', :gherkin3 => true do
26
32
  doc_string = clazz.new("\"\"\"\nsome doc string\n\"\"\"")
27
33
  raw_data = doc_string.raw_element
@@ -29,6 +29,12 @@ describe 'Example, Unit' do
29
29
  @element.name.should == 'test example'
30
30
  end
31
31
 
32
+ it 'provides a descriptive filename when being parsed from stand alone text' do
33
+ source = 'bad example text'
34
+
35
+ expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_example\.feature'/)
36
+ end
37
+
32
38
  it 'stores the original data generated by the parsing adapter', :gherkin3 => true do
33
39
  example = clazz.new("Examples: test example\n|param|\n|value|")
34
40
  raw_data = example.raw_element
@@ -16,12 +16,19 @@ describe 'FeatureFile, Unit' do
16
16
  @feature_file = clazz.new
17
17
  end
18
18
 
19
- it 'cannot model a non-existent directory' do
19
+ it 'cannot model a non-existent file' do
20
20
  path = "#{@default_file_directory}/missing_file.txt"
21
21
 
22
22
  expect { CukeModeler::FeatureFile.new(path) }.to raise_error(ArgumentError)
23
23
  end
24
24
 
25
+ it 'provides its own filename when being parsed' do
26
+ path = "#{@default_file_directory}/#{@default_feature_file_name}"
27
+ File.open(path, "w") { |file| file.puts 'bad feature text' }
28
+
29
+ expect { clazz.new(path) }.to raise_error(/'#{path}'/)
30
+ end
31
+
25
32
  it 'knows the name of the file that it is modeling' do
26
33
  path = "#{@default_file_directory}/#{@default_feature_file_name}"
27
34
  File.open(path, "w") { |file| file.puts "Feature:" }
@@ -35,9 +42,9 @@ describe 'FeatureFile, Unit' do
35
42
  path = "#{@default_file_directory}/#{@default_feature_file_name}"
36
43
  File.open(path, "w") { |file| file.puts "Feature:" }
37
44
 
38
- directory = CukeModeler::FeatureFile.new(path)
45
+ file = CukeModeler::FeatureFile.new(path)
39
46
 
40
- directory.path.should == path
47
+ file.path.should == path
41
48
  end
42
49
 
43
50
  it 'has features - #features' do
@@ -28,6 +28,12 @@ describe 'Feature, Unit' do
28
28
  @element.name.should == 'test feature'
29
29
  end
30
30
 
31
+ it 'provides a descriptive filename when being parsed from stand alone text' do
32
+ source = 'bad feature text'
33
+
34
+ expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_feature\.feature'/)
35
+ end
36
+
31
37
  it 'stores the original data generated by the parsing adapter', :gherkin3 => true do
32
38
  feature = clazz.new('Feature: test feature')
33
39
  raw_data = feature.raw_element
@@ -29,6 +29,12 @@ describe 'Outline, Unit' do
29
29
  @element.name.should == 'test outline'
30
30
  end
31
31
 
32
+ it 'provides a descriptive filename when being parsed from stand alone text' do
33
+ source = "bad outline text \n Scenario Outline:\n And a step\n @foo "
34
+
35
+ expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_outline\.feature'/)
36
+ end
37
+
32
38
  it 'stores the original data generated by the parsing adapter', :gherkin3 => true do
33
39
  outline = clazz.new("Scenario Outline: test outline\nExamples:\n|param|\n|value|")
34
40
  raw_data = outline.raw_element
@@ -4,18 +4,82 @@ SimpleCov.command_name('Parsing') unless RUBY_VERSION.to_s < '1.9.0'
4
4
 
5
5
  describe 'Parsing, Unit' do
6
6
 
7
+ let(:nodule) { CukeModeler::Parsing }
8
+
9
+
7
10
  it 'can parse text - #parse_text' do
8
- CukeModeler::Parsing.should respond_to(:parse_text)
11
+ nodule.should respond_to(:parse_text)
9
12
  end
10
13
 
11
14
  it 'can only parse strings' do
12
- expect{CukeModeler::Parsing.parse_text(5)}.to raise_error(ArgumentError)
13
- expect{CukeModeler::Parsing.parse_text('Feature:')}.to_not raise_error
15
+ expect { nodule.parse_text(5) }.to raise_error(ArgumentError)
16
+ expect { nodule.parse_text('Feature:') }.to_not raise_error
14
17
  end
15
18
 
16
19
  it 'returns an Array' do
17
- result = CukeModeler::Parsing.parse_text('Feature:')
20
+ result = nodule.parse_text('Feature:')
18
21
  result.is_a?(Array).should be_true
19
22
  end
20
23
 
24
+ it 'takes the text that is to be parsed and an optional file name' do
25
+ expect(nodule.method(:parse_text).arity).to eq(-2)
26
+ end
27
+
28
+ it 'raises and error if an error is encountered while parsing text' do
29
+ expect { nodule.parse_text('bad file') }.to raise_error(ArgumentError, /Error encountered while parsing '.*'/)
30
+ end
31
+
32
+ it 'includes the file parsed in the error that it raises' do
33
+ expect { nodule.parse_text('bad file', 'file foo.txt') }.to raise_error(/'file foo\.txt'/)
34
+ end
35
+
36
+ it 'includes the underlying error message in the error that it raises' do
37
+ begin
38
+ # Custom error type in order to ensure that we are throwing the correct thing
39
+ module CukeModeler
40
+ class TestError < StandardError
41
+ end
42
+ end
43
+
44
+ # Monkey patch Gherkin to throw the error that we need for testing
45
+ if Gem.loaded_specs['gherkin'].version.version[/^3/]
46
+ old_method = Gherkin::Parser.instance_method(:parse)
47
+
48
+ module Gherkin
49
+ class Parser
50
+ def parse(*args)
51
+ raise(CukeModeler::TestError, 'something went wrong')
52
+ end
53
+ end
54
+ end
55
+ else
56
+ old_method = Gherkin::Parser::Parser.instance_method(:parse)
57
+
58
+ module Gherkin
59
+ module Parser
60
+ class Parser
61
+ def parse(*args)
62
+ raise(CukeModeler::TestError, 'something went wrong')
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ expect { nodule.parse_text('bad file') }.to raise_error(/CukeModeler::TestError.*something went wrong/)
70
+ ensure
71
+ # Making sure that our changes don't escape a test and ruin the rest of the suite
72
+ if Gem.loaded_specs['gherkin'].version.version[/^3/]
73
+ Gherkin::Parser.send(:define_method, :parse, old_method)
74
+ else
75
+ Gherkin::Parser::Parser.send(:define_method, :parse, old_method)
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ it 'has a default file name if one is not provided' do
82
+ expect { nodule.parse_text('bad file') }.to raise_error(ArgumentError, /'cuke_modeler_fake_file\.feature'/)
83
+ end
84
+
21
85
  end
@@ -21,6 +21,12 @@ describe 'Row, Unit' do
21
21
  @element.cells.should == ['a', 'row']
22
22
  end
23
23
 
24
+ it 'provides a descriptive filename when being parsed from stand alone text' do
25
+ source = " |bad |row| text| \n @foo "
26
+
27
+ expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_row\.feature'/)
28
+ end
29
+
24
30
  it 'stores the original data generated by the parsing adapter', :gherkin3 => true do
25
31
  example_row = clazz.new("| a | row |")
26
32
  raw_data = example_row.raw_element
@@ -25,6 +25,12 @@ describe 'Scenario, Unit' do
25
25
  @element.name.should == 'test scenario'
26
26
  end
27
27
 
28
+ it 'provides a descriptive filename when being parsed from stand alone text' do
29
+ source = "bad scenario text \n Scenario:\n And a step\n @foo "
30
+
31
+ expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_scenario\.feature'/)
32
+ end
33
+
28
34
  it 'stores the original data generated by the parsing adapter', :gherkin3 => true do
29
35
  scenario = clazz.new("Scenario: test scenario")
30
36
  raw_data = scenario.raw_element
@@ -187,6 +187,12 @@ describe 'Step, Unit' do
187
187
  @element.base.should == 'test step'
188
188
  end
189
189
 
190
+ it 'provides a descriptive filename when being parsed from stand alone text' do
191
+ source = "bad step text\n And a step\n @foo"
192
+
193
+ expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_step\.feature'/)
194
+ end
195
+
190
196
  it 'stores the original data generated by the parsing adapter', :gherkin3 => true do
191
197
  step = clazz.new("* test step")
192
198
  raw_data = step.raw_element
@@ -21,6 +21,12 @@ describe 'TableRow, Unit' do
21
21
  @element.cells.should == ['a', 'row']
22
22
  end
23
23
 
24
+ it 'provides a descriptive filename when being parsed from stand alone text' do
25
+ source = 'bad table row text'
26
+
27
+ expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_table_row\.feature'/)
28
+ end
29
+
24
30
  it 'stores the original data generated by the parsing adapter', :gherkin3 => true do
25
31
  table_row = clazz.new("| a | row |")
26
32
  raw_data = table_row.raw_element
@@ -22,6 +22,12 @@ describe 'Table, Unit' do
22
22
  @element.contents.should == [['a table']]
23
23
  end
24
24
 
25
+ it 'provides a descriptive filename when being parsed from stand alone text' do
26
+ source = 'bad table text'
27
+
28
+ expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_table\.feature'/)
29
+ end
30
+
25
31
  it 'stores the original data generated by the parsing adapter', :gherkin3 => true do
26
32
  table = clazz.new("| a table |")
27
33
  raw_data = table.raw_element
@@ -20,6 +20,12 @@ describe 'Tag, Unit' do
20
20
  @element.name.should == '@a_tag'
21
21
  end
22
22
 
23
+ it 'provides a descriptive filename when being parsed from stand alone text' do
24
+ source = 'bad tag text'
25
+
26
+ expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_tag\.feature'/)
27
+ end
28
+
23
29
  it 'stores the original data generated by the parsing adapter', :gherkin3 => true do
24
30
  tag = clazz.new('@a_tag')
25
31
  raw_data = tag.raw_element
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cuke_modeler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-02-10 00:00:00.000000000 Z
12
+ date: 2016-02-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: gherkin