cucumber-in-the-yard 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/History.txt +3 -0
  2. data/Manifest +51 -0
  3. data/README.txt +55 -0
  4. data/Rakefile +28 -0
  5. data/cucumber-in-the-yard.gemspec +42 -0
  6. data/example/example.feature +13 -0
  7. data/example/example.step.rb +48 -0
  8. data/example/example.third.feature +30 -0
  9. data/example/second_example.feature +36 -0
  10. data/lib/city.rb +23 -0
  11. data/lib/cucumber/city_builder.rb +130 -0
  12. data/lib/yard/code_objects/cucumber_location_helper.rb +15 -0
  13. data/lib/yard/code_objects/feature.rb +24 -0
  14. data/lib/yard/code_objects/scenario.rb +25 -0
  15. data/lib/yard/code_objects/step.rb +25 -0
  16. data/lib/yard/code_objects/tags.rb +63 -0
  17. data/lib/yard/extensions.rb +38 -0
  18. data/lib/yard/handlers/base.rb +21 -0
  19. data/lib/yard/handlers/feature_handler.rb +41 -0
  20. data/lib/yard/parser/feature.rb +46 -0
  21. data/lib/yard/rake/city_task.rb +12 -0
  22. data/lib/yard/rb_extensions.rb +152 -0
  23. data/lib/yard/templates/default/feature/html/feature.erb +243 -0
  24. data/lib/yard/templates/default/feature/setup.rb +5 -0
  25. data/lib/yard/templates/default/fulldoc/html/css/common.css +182 -0
  26. data/lib/yard/templates/default/fulldoc/html/full_list.erb +34 -0
  27. data/lib/yard/templates/default/fulldoc/html/full_list_features.erb +10 -0
  28. data/lib/yard/templates/default/fulldoc/html/full_list_scenarios.erb +10 -0
  29. data/lib/yard/templates/default/fulldoc/html/full_list_stepdefinitions.erb +11 -0
  30. data/lib/yard/templates/default/fulldoc/html/full_list_steps.erb +13 -0
  31. data/lib/yard/templates/default/fulldoc/html/full_list_tagusages.erb +10 -0
  32. data/lib/yard/templates/default/fulldoc/html/index.erb +24 -0
  33. data/lib/yard/templates/default/fulldoc/html/js/cucumber.js +13 -0
  34. data/lib/yard/templates/default/fulldoc/html/setup.rb +73 -0
  35. data/lib/yard/templates/default/layout/html/headers.erb +14 -0
  36. data/lib/yard/templates/default/layout/html/search.erb +8 -0
  37. data/lib/yard/templates/default/module/html/step_transforms.erb +23 -0
  38. data/lib/yard/templates/default/module/setup.rb +5 -0
  39. data/lib/yard/templates/default/scenario/html/scenario.erb +26 -0
  40. data/lib/yard/templates/default/scenario/setup.rb +5 -0
  41. data/lib/yard/templates/default/steptransformers/html/stepdefinition.erb +38 -0
  42. data/lib/yard/templates/default/steptransformers/setup.rb +5 -0
  43. data/lib/yard/templates/default/tagusage/html/tagusage.erb +65 -0
  44. data/lib/yard/templates/default/tagusage/setup.rb +5 -0
  45. data/spec/city/feature_parser_spec_examples.rb +153 -0
  46. data/spec/city/gherkin_loader_spec.rb +39 -0
  47. data/spec/city/test.feature +36 -0
  48. data/spec/city/yard_handlers_cucumber_spec.rb +24 -0
  49. data/spec/city/yard_namespace_object_spec.rb +8 -0
  50. data/spec/city/yard_parser_cucumber_spec.rb +215 -0
  51. data/spec/city/yard_rb_extensions_spec.rb +128 -0
  52. data/spec/spec_helper.rb +5 -0
  53. data.tar.gz.sig +0 -0
  54. metadata +201 -0
  55. metadata.gz.sig +0 -0
@@ -0,0 +1,153 @@
1
+
2
+ shared_examples_for "a feature file" do
3
+ it "should have a defined feature" do
4
+ @parser.features.first.should_not be_nil
5
+ end
6
+
7
+ it "the feature should have a unique name" do
8
+ @parser.features.first.name.should == @feature[:file].gsub('.','_').to_sym
9
+ end
10
+
11
+ it "the feature should have the specified title" do
12
+ @parser.features.first.value.should == @feature[:name]
13
+ end
14
+
15
+ it "the feature should have all specified tags" do
16
+ @feature[:tags].find do |expected_tag|
17
+ @parser.features.first.tags.find{|tag| tag.value == expected_tag }
18
+ end.should_not be_nil
19
+ end
20
+
21
+ it "the feature should have the correct number of tags" do
22
+ @feature[:tags].each do |expected_tag|
23
+ @parser.features.first.tags.find_all {|tag| tag.value == expected_tag }.count.should == 1
24
+ end
25
+ end
26
+
27
+ it "the feature's tags should have a file" do
28
+ @parser.features.first.tags.each do |tag|
29
+ tag.files.should_not be_nil
30
+ tag.files.should_not be_empty
31
+ tag.files.first.first.should == @feature[:file]
32
+ end
33
+ end
34
+
35
+ it "the feature should have a description" do
36
+ @parser.features.first.description.join("\n") == @feature[:description].join("\n")
37
+ end
38
+
39
+ it "the feature should have a file" do
40
+ @parser.features.first.files.first[0].should == @feature[:file]
41
+ end
42
+
43
+ it "the feature should have a line number" do
44
+ @parser.features.first.files.first[1].should_not be_nil
45
+ end
46
+
47
+ end
48
+
49
+ shared_examples_for "a feature file with a background" do
50
+
51
+ it "the feature should have a background" do
52
+ @parser.features.first.background.should_not be_nil
53
+ end
54
+
55
+ it "the background should have a unique scenario name" do
56
+ @parser.features.first.background.name.should == "#{@feature[:file]}.background".gsub('.','_').to_sym
57
+ end
58
+
59
+ it "the background should have the correct title" do
60
+ @parser.features.first.background.value.should == "Background"
61
+ end
62
+
63
+ it "the background should have a file" do
64
+ @parser.features.first.background.files.first[0].should == @feature[:file]
65
+ end
66
+
67
+ it "the background should have a line number" do
68
+ @parser.features.first.background.files.first[1].should_not be_nil
69
+ end
70
+
71
+ it "the background should have all their defined steps" do
72
+ @parser.features.first.scenarios.first.steps.should_not be_nil
73
+ if @background
74
+ @background.each_with_index do |step,index|
75
+ @parser.features.first.background.steps[index].value.should == step
76
+ end
77
+ end
78
+ end
79
+
80
+ it "the background steps should have files and line numbers" do
81
+ if @background
82
+ @background.each_with_index do |step,index|
83
+ @parser.features.first.background.steps[index].files.first[0].should == @feature[:file]
84
+ @parser.features.first.background.steps[index].files.first[1].should_not be_nil
85
+ end
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ shared_examples_for "a feature file with scenarios" do
92
+ it "should have all scenarios" do
93
+ @scenarios.each_with_index do |scenario,index|
94
+ @parser.features.first.scenarios[index].should_not be_nil
95
+ end
96
+ end
97
+
98
+ it "each scenario should have a unique scenario name" do
99
+ @parser.features.first.scenarios.first.name.should == "#{@feature[:file]}_scenario_0".gsub('.','_').to_sym
100
+ end
101
+
102
+ it "each scenario should have the correct title" do
103
+ @parser.features.first.scenarios.each_with_index do |scenario,index|
104
+ scenario.value.should == @scenarios[index][:title].join("\n")
105
+ end
106
+ end
107
+
108
+ it "each scenario should have the correct tags" do
109
+ @scenarios.each_with_index do |scenario,index|
110
+ scenario[:tags].each do |expeced_tag|
111
+ @parser.features.first.scenarios[index].tags.find {|tag| tag.value == expeced_tag}.should_not be_nil
112
+ end
113
+ end
114
+ end
115
+
116
+ it "each scenario should have the correct number of tags" do
117
+ @parser.features.first.scenarios.first.tags.find_all {|tag| tag.value == "@ninja" }.count.should == 1
118
+ end
119
+
120
+ it "each scenario should have a file" do
121
+ @parser.features.first.scenarios.first.files.first[0].should == @feature[:file]
122
+ end
123
+
124
+ it "each scenario should have a line number" do
125
+ @parser.features.first.scenarios.first.files.first[1].should_not be_nil
126
+ end
127
+
128
+ it "each scenario should have all their defined steps" do
129
+ @parser.features.first.scenarios.first.steps.should_not be_nil
130
+ if @scenarios
131
+ @scenarios.each_with_index do |scenario,scenario_index|
132
+ @parser.features.first.scenarios[scenario_index].should_not be_nil
133
+
134
+ scenario[:steps].each_with_index do |step,step_index|
135
+ @parser.features.first.scenarios[scenario_index].steps[step_index].name.should == "#{@feature[:file].gsub('.','_')}_scenario_#{scenario_index}_step_#{step_index}".to_sym
136
+ @parser.features.first.scenarios[scenario_index].steps[step_index].value.should == step
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ it "each scenario's steps should have files and line numbers" do
143
+ if @scenarios
144
+ @scenarios.each_with_index do |scenario,scenario_index|
145
+ scenario[:steps].each_with_index do |step,step_index|
146
+ @parser.features.first.scenarios[scenario_index].steps[step_index].files.first[0].should == @feature[:file]
147
+ @parser.features.first.scenarios[scenario_index].steps[step_index].files.first[1].should_not be_nil
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Gherkin" do
4
+
5
+
6
+ before(:all) do
7
+
8
+ @source = File.dirname(__FILE__) + '/test.feature'
9
+ File.should exist(@source)
10
+ @data = File.open(@source, 'r').read
11
+
12
+ @parser = YARD::Parser::Cucumber::FeatureParser.new(@data,@source)
13
+
14
+ end
15
+
16
+
17
+ it "should not be nil" do
18
+ @parser.should_not be_nil
19
+ end
20
+
21
+ it "should parse" do
22
+ @parser.parse
23
+ end
24
+
25
+ it "should tokenize" do
26
+ @parser.tokenize
27
+ end
28
+
29
+ it "should enumerator" do
30
+ @parser.enumerator
31
+ end
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+ end
@@ -0,0 +1,36 @@
1
+ @customer
2
+ Feature: Customer Logout Feature
3
+ As a customer of the product I am able to logout
4
+
5
+ Background:
6
+ Given this undefined step definition
7
+
8
+ @bvt
9
+ Scenario: Customer that is logged in is able to log out
10
+ Given that a customer is a valid customer
11
+ And a customer logs in as username 'frank' with password 'default'
12
+ And I expect them to have logged in successfully
13
+ When the customer logs out
14
+ Then I expect the customer to be shown the logout page
15
+
16
+ Scenario: Customers with a complete profile are allowed to post
17
+ Given that a customer is a valid customer
18
+ And the customer has the following details:
19
+ | Name | Email | Age |
20
+ | Frank | f@email.com | 22 |
21
+ When a customer logs in as username 'frank' with password 'default'
22
+ And visits the customer update page
23
+ Then I expect the customer is able able to post to their profile
24
+
25
+ @product
26
+ Scenario Outline: Customers that bought a product are included in their product groups
27
+ Given that <Customer> is a valid customer
28
+ And that the product, named '<Product>', is a valid product
29
+ When the customer has purchased the product
30
+ Then I expect the customer to be a member of the '<Product>' group
31
+
32
+ Examples:
33
+ | Customer | Product |
34
+ | Customer A | Product A |
35
+ | Customer A | Product B |
36
+ | Customer A | Product C |
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ module YARD::Handlers::Cucumber
4
+
5
+ describe Base do
6
+
7
+ it "should respond to method handles?" do
8
+ Base.should respond_to(:handles?)
9
+ end
10
+
11
+ end
12
+
13
+ describe FeatureHandler do
14
+
15
+ it "should respond to method process" do
16
+ FeatureHandler.should respond_to(:process)
17
+ end
18
+
19
+ end
20
+
21
+
22
+
23
+
24
+ end
@@ -0,0 +1,8 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ module YARD::CodeObjects
4
+
5
+ describe NamespaceObject do
6
+ end
7
+
8
+ end
@@ -0,0 +1,215 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.dirname(__FILE__) + '/feature_parser_spec_examples.rb'
3
+
4
+ module YARD::Parser::Cucumber
5
+
6
+ describe YARD::CodeObjects::Cucumber::Tag do
7
+
8
+ [:value].each do |attribute|
9
+ it "should respond to method #{attribute}" do
10
+ YARD::CodeObjects::Cucumber::Tag.new(:root,"tag_name").should respond_to(attribute)
11
+ end
12
+ end
13
+
14
+ end
15
+
16
+ describe YARD::CodeObjects::Cucumber::Step do
17
+
18
+ [:value, :definition].each do |attribute|
19
+ it "should respond to method #{attribute}" do
20
+ YARD::CodeObjects::Cucumber::Step.new(:root,"name").should respond_to(attribute)
21
+ end
22
+ end
23
+
24
+ it "should return the line prefix and the remainder" do
25
+ step = YARD::CodeObjects::Cucumber::Step.new(:root,"name") {|s| s.value = "Given something something" }
26
+ step.keyword.should == "Given"
27
+ step.line.should == "something something"
28
+ end
29
+
30
+ end
31
+
32
+ describe YARD::CodeObjects::Cucumber::Scenario do
33
+
34
+ [:value, :description, :steps, :tags ].each do |attribute|
35
+ it "should respond to method #{attribute}" do
36
+ YARD::CodeObjects::Cucumber::Scenario.new(:root,"name").should respond_to(attribute)
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ describe YARD::CodeObjects::Cucumber::Feature do
43
+
44
+ [:value, :description, :scenarios, :background, :tags ].each do |attribute|
45
+ it "should respond to method #{attribute}" do
46
+ YARD::CodeObjects::Cucumber::Feature.new(:root,"name").should respond_to(attribute)
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+
53
+ describe FeatureParser do
54
+
55
+
56
+ it "should accept source and a file when created" do
57
+ lambda { FeatureParser.new("source code","filename") }.should_not raise_exception(Exception)
58
+ end
59
+
60
+ [ "parse", "tokenize", "enumerator" ].each do |required_method|
61
+ it "should have a method named #{required_method}" do
62
+ FeatureParser.instance_methods.should include(required_method)
63
+ end
64
+ end
65
+
66
+ it "should return itself when parse is called" do
67
+ parser = FeatureParser.new("source","filename")
68
+ parser.parse.should == parser
69
+ end
70
+
71
+ context "feature file with tags, feature, and description" do
72
+
73
+ before(:all) do
74
+ @feature = { :file => 'new.exciting.feature',
75
+ :name => "New Exciting Feature",
76
+ :tags => [ "@bvt", "@build", "@wip" ],
77
+ :description => [ "This feature is going to save the company." ] }
78
+
79
+ @parser = FeatureParser.new(%{
80
+ #{@feature[:tags].join(" ")}
81
+ Feature: #{@feature[:name]}
82
+ #{@feature[:description].join("\n")}
83
+ },@feature[:file])
84
+
85
+ @parser = @parser.parse
86
+ end
87
+
88
+ after(:all) do
89
+ @parser = nil
90
+ end
91
+
92
+ it_should_behave_like "a feature file"
93
+
94
+ end
95
+
96
+ context "feature file with a description that uses step keywords" do
97
+
98
+ before(:all) do
99
+ @feature = { :file => 'description.with.keywords.feature',
100
+ :name => "Fully Described Feature",
101
+ :tags => [ "@bvt", "@build", "@wip" ],
102
+ :description => ["As a product owner",
103
+ "When I ask about the work done",
104
+ "Then I want to see what this cukes things is all about",
105
+ "And I really want a straight answer",
106
+ "Given that I can be provided with one"] }
107
+
108
+ @parser = FeatureParser.new(%{
109
+ #{@feature[:tags].join(" ")}
110
+ Feature: #{@feature[:name]}
111
+ #{@feature[:description].join("\n")}
112
+ },@feature[:file])
113
+
114
+ @parser = @parser.parse
115
+ end
116
+
117
+ after(:all) do
118
+ @parser = nil
119
+ end
120
+
121
+ it_should_behave_like "a feature file"
122
+
123
+ end
124
+
125
+
126
+ context "feature file with background and one scenario" do
127
+
128
+ before(:all) do
129
+
130
+ @feature = { :file => "ninja.exciting.feature",
131
+ :name => "Ninja Feature Set",
132
+ :tags => [ "@bvt", "@build", "@wip" ],
133
+ :description => ["This feature is going to save the company"] }
134
+
135
+ @background = [ "Given that I have taken a nap" ]
136
+
137
+ @scenarios = [ { :tags => ["@ninja"],
138
+ :title => ["Ninja striking an opponent in the morning"],
139
+ :steps => [ "Given that there is an opponent",
140
+ "And a reason to fight him",
141
+ "When I karate strike him",
142
+ "Then I expect him to fall" ] } ]
143
+
144
+ @parser = FeatureParser.new(%{
145
+ #{@feature[:tags].join(" ")}
146
+ Feature: #{@feature[:name]}
147
+ #{@feature[:description].join("\n")}
148
+ Background:
149
+ #{@background.join("\n")}
150
+ #{@scenarios.first[:tags].join(" ")}
151
+ Scenario: #{@scenarios.first[:title].join("\n")}
152
+ #{@scenarios.first[:steps].join("\n")}
153
+ },@feature[:file])
154
+ @parser = @parser.parse
155
+ end
156
+
157
+ after(:all) do
158
+ @parser = nil
159
+ end
160
+
161
+ it_should_behave_like "a feature file"
162
+ it_should_behave_like "a feature file with a background"
163
+ it_should_behave_like "a feature file with scenarios"
164
+
165
+ end
166
+
167
+ context "feature file no background and multiple scenarios" do
168
+
169
+ before(:all) do
170
+
171
+ @feature = { :file => "ninja.strike.feature",
172
+ :name => "Ninja Feature Set",
173
+ :tags => [ "@kill", "@silently", "@sneak" ],
174
+ :description => ["This feature is going to save the company"] }
175
+
176
+ @scenarios = [
177
+ { :tags => ["@ninja"],
178
+ :title => ["Killing Scenario"],
179
+ :steps => [ "Given that there is an opponent",
180
+ "And a reason to fight him",
181
+ "When I karate strike him",
182
+ "Then I expect him to fall" ] },
183
+ { :tags => [],
184
+ :title => ["Dissappearing Scenario"],
185
+ :steps => [ "Given that I have defeated an opponent",
186
+ "And there are no more opponents",
187
+ "When I stop to take a breath",
188
+ "Then I expect to dissapear" ] } ]
189
+
190
+ @parser = FeatureParser.new(%{
191
+ #{@feature[:tags].join(" ")}
192
+ Feature: #{@feature[:name]}
193
+ #{@feature[:description].join("\n")}
194
+ #{@scenarios.collect {|scenario|
195
+ scenario[:tags].join(" ") +
196
+ "\nScenario: " + scenario[:title].join("\n") + "\n" +
197
+ scenario[:steps].join("\n")
198
+ }.join("\n")}},@feature[:file])
199
+ @parser = @parser.parse
200
+ end
201
+
202
+ after(:all) do
203
+ @parser = nil
204
+ end
205
+
206
+ it_should_behave_like "a feature file"
207
+ it_should_behave_like "a feature file with scenarios"
208
+
209
+ end
210
+
211
+
212
+
213
+ end
214
+
215
+ end
@@ -0,0 +1,128 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ module YARD::CodeObjects
4
+
5
+ describe YARD::CodeObjects do
6
+
7
+ shared_examples_for "CodeObjects" do
8
+ it "should respond to all defined attributes" do
9
+ @attributes.each {|attribute| @object.should respond_to(attribute) }
10
+ end
11
+ end
12
+
13
+ describe StepDefinitionObject do
14
+
15
+ before(:each) do
16
+ @attributes = [ :value, :keyword, :constants, :compare_value ]
17
+ @object = StepDefinitionObject.new(:root,:unique_name)
18
+ end
19
+
20
+ class TestObject
21
+ attr_accessor :name, :value
22
+ def initialize ; yield self ; end
23
+ end
24
+
25
+ it_should_behave_like "CodeObjects"
26
+
27
+ describe "compare_value" do
28
+
29
+ [ { :value => "/THERE (?:IS|ARE) THREE \#\{ CONSTANTS \} IN HERE \#\{ FOR\} YOU TO \#\{FIND \}",
30
+ :results => [ 'CONSTANTS', 'FOR', 'FIND' ] } ].each do |data|
31
+
32
+ it "should find all the constants within the step definition" do
33
+
34
+ stepdef = StepDefinitionObject.new(:root,"name")
35
+ stepdef.value = data[:value]
36
+
37
+
38
+ data[:results].each do |result|
39
+ stepdef._value_constants(data[:value]).should include(result)
40
+ stepdef._value_constants.should include(result)
41
+ end
42
+
43
+ end
44
+ end
45
+
46
+
47
+ [ { :value => "/WHEN THE \#\{NOUN\} HITS THE FAN/",
48
+ :constants => [ TestObject.new{|c| c.name = "NOUN" ; c.value = "/SMURF/" } ], :result => "WHEN THE SMURF HITS THE FAN" },
49
+
50
+ { :value => "/\#\{ SUBJECT \} WALK INTO THE \#\{ PLACE\} AND ASK THE \#\{PERSON \}/",
51
+ :constants => [ TestObject.new{|c| c.name = "SUBJECT" ; c.value = "/1 PERSON/" },
52
+ TestObject.new{|c| c.name = "PLACE" ; c.value = "/BAR/" },
53
+ TestObject.new{|c| c.name = "PERSON" ; c.value = "/BARTENDER/" } ],
54
+ :result => "1 PERSON WALK INTO THE BAR AND ASK THE BARTENDER" },
55
+
56
+ ].each do |data|
57
+
58
+ it "should replace all constants found within (#{data[:value]}) the value" do
59
+
60
+ stepdef = StepDefinitionObject.new(:root,"name")
61
+ stepdef.value = data[:value]
62
+ stepdef.constants = data[:constants]
63
+
64
+ stepdef.compare_value.should == data[:result]
65
+
66
+ end
67
+
68
+ end
69
+
70
+
71
+ end
72
+
73
+
74
+
75
+ end
76
+
77
+ describe StepTransformObject do
78
+
79
+ before(:each) do
80
+ @attributes = [ :value ]
81
+ @object = StepTransformObject.new(:root,:unique_name)
82
+ end
83
+
84
+ it_should_behave_like "CodeObjects"
85
+
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+
92
+ module YARD::Handlers::Ruby::Legacy
93
+
94
+ describe YARD::Handlers::Ruby::Legacy do
95
+
96
+ shared_examples_for "Handlers" do
97
+ it "should match #{@match_criteria}" do
98
+ @handler::MATCH.should == @match_criteria
99
+ end
100
+
101
+ it "should respond to the method process" do
102
+ @handler.should respond_to(:process)
103
+ end
104
+
105
+ end
106
+
107
+ describe StepDefinitionHandler do
108
+ before(:each) do
109
+ @handler = StepDefinitionHandler
110
+ @match_criteria = /^((When|Given|And|Then)\s*(\/[^\/]+\/).+)$/
111
+ end
112
+
113
+ it_should_behave_like "Handlers"
114
+ end
115
+
116
+ describe StepTransformHandler do
117
+ before(:each) do
118
+ @handler = StepTransformHandler
119
+ @match_criteria = /^Transform\s*(\/[^\/]+\/).+$/
120
+ end
121
+
122
+ it_should_behave_like "Handlers"
123
+ end
124
+
125
+
126
+ end
127
+
128
+ end
@@ -0,0 +1,5 @@
1
+
2
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
3
+ $:.unshift(File.dirname(__FILE__))
4
+
5
+ require 'city'
data.tar.gz.sig ADDED
Binary file