data_spec 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41b97a4b8d4e7d9ba659c756dd00132cb8fc8865
4
- data.tar.gz: 6991ac05e24b5c297ebabfb3d8795669b6681f6a
3
+ metadata.gz: 38a6a7c19a43116b793ccc2565beba91ec40ad58
4
+ data.tar.gz: 78178e54b3ad7afc932a487ca8ce453104e95a52
5
5
  SHA512:
6
- metadata.gz: 4428020420b3c23d340b4893a6bc6882014bf78c860cac3b5540099ec333bf195518c9cfa230cb624ffcc419258ba809129687d190b9cd8b7cc9547f379f38d6
7
- data.tar.gz: 7d963c06e3a45144c6b5e05d540ea80a277b90de236cc05170f932b210d4180f0cf7fd6ebe9f09476d5c3077a8c8c9b9819cc4752a6c333e80e199d13e6f9abb
6
+ metadata.gz: ebd55fded46197f459fd651d339bcef2798f36681a8a0c5d27e96087f13dd92c3cd61d3788fdb90f840cabe2e24337409f40449921b87d503b8718bb0b915fc2
7
+ data.tar.gz: 23239a0654bdd2c85c817fcb00ff8b810a63c5f4d0eb77bf39fedd0b0d6495357858128c443416c15bff0bed87e67e6b50bdcd5a130f5900d52ed9b71298f449
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ bundler_args: --without development
3
+ rvm:
4
+ - 2.0.0
data/Gemfile CHANGED
@@ -4,4 +4,11 @@ ruby '2.0.0'
4
4
  # Specify your gem's dependencies in data_spec.gemspec
5
5
  gemspec
6
6
 
7
- gem 'debugger'
7
+ group :test do
8
+ gem 'rake'
9
+ end
10
+
11
+ group :development do
12
+ gem 'debugger'
13
+ gem 'bundler'
14
+ end
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  data_spec
2
2
  ========
3
3
 
4
+ [![Build Status](https://secure.travis-ci.org/narfanator/data_spec.png)](http://travis-ci.org/narfanator/data_spec) [![Dependency Status](https://gemnasium.com/narfanator/data_spec.png)](https://gemnasium.com/narfanator/data_spec) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/narfanator/data_spec)
5
+
4
6
  Easily compare hashes and arrays in RSpec and Cucumber
5
7
 
6
8
  Originally inspired by collectiveidea's json_spec gem
@@ -9,29 +11,29 @@ Installation
9
11
  ------------
10
12
 
11
13
  gem 'data_spec'
12
- {cucumber}
13
- {rspec}
14
14
 
15
- Cucumber
16
- ------------
15
+ # Cucumber
17
16
 
18
- # Setup:
17
+ Setup:
18
+ ------------
19
19
 
20
- Include `data_spec/cucumber` and define `data` in your Cucumber environment:
20
+ Include `data_spec` and define `data` in your Cucumber environment:
21
21
  ```ruby
22
22
  # features/support/env.rb
23
- require "data_spec/cucumber"
23
+ require "data_spec"
24
24
 
25
25
  def data
26
26
  #...
27
27
  end
28
28
  ```
29
29
 
30
- # Usage:
30
+ Usage:
31
+ ------------
32
+ **The step `Given the data is:` is not supplied by this gem**
31
33
 
32
34
  Use either YAML or JSON:
33
35
  ````ruby
34
- Given the data is: # You define this one
36
+ Given the data is:
35
37
  """
36
38
  chunky: bacon
37
39
  """
@@ -75,7 +77,7 @@ Then the data includes:
75
77
  - 1
76
78
  - 2
77
79
  """
78
- And the data at "even" includes "'in a': hash"
80
+ And the data at "3/even" includes "'in a': hash"
79
81
  ```
80
82
 
81
83
  Check types:
@@ -86,9 +88,9 @@ Given the data is:
86
88
  - 1
87
89
  - 2013-07-06 20:09:32.824102000 -07:00
88
90
  """
89
- Then the data at "0" is of type String
90
- Then the data at "1" is of type Fixnum
91
- Then the data at "2" is of type Time
91
+ Then the data at "0" should be of type String
92
+ Then the data at "1" should be of type Fixnum
93
+ Then the data at "2" should be of type Time
92
94
  ```
93
95
 
94
96
  Use embedded code:
@@ -97,80 +99,158 @@ Given the data is:
97
99
  """
98
100
  - `1+1`
99
101
  - '$1e2$'
100
- - `"bacon".class`
102
+ - `'bacon'.class`
101
103
  """
102
104
  Then the data at "0" should be 2
103
105
  Then the data at "1" should be 100
104
- Then the data at "2" should be `String.class`
106
+ Then the data at "2" should be `"chunky".class`
105
107
  ```
106
108
  (Among other things, this lets you work around Ruby YAML's lack of support for scientific notation)
109
+
107
110
  **Note: This is done via a raw `eval`, so it's dangerous**
108
111
 
109
- #Steps
112
+ Store data for later use:
113
+ ```ruby
114
+ Given `@samples` is:
115
+ """
116
+ where: "http://google.com"
117
+ when: `Time.now`
118
+ """
119
+ And `@samples` includes:
120
+ """
121
+ what: {}
122
+ """
123
+ And `@samples['what']` is:
124
+ """
125
+ - chunky
126
+ - bacon
127
+ """
128
+ And the data is:
129
+ """
130
+ meal:
131
+ main_course: `@samples['what'][1]`
132
+ style: `@samples['what'][0]`
133
+ ordered: `@samples['when']`
134
+ """
135
+ Then the data should be:
136
+ """
137
+ meal:
138
+ main_course: bacon
139
+ style: chunky
140
+ ordered: `@samples['when']`
141
+ """
142
+ ```
143
+
144
+ Again, this is done by raw eval, so it's dangerous, and it's definitely enough to shoot your foot off with.
145
+
146
+ If you're using this in anything like a complex sense, look up the "evaluation" and "remember" helpers, below
147
+
110
148
 
149
+ Steps
150
+ ----------
151
+
152
+ Matching:
111
153
  * `Then the data should be:`
112
154
  * `Then the data should be "..."`
113
155
  * `Then the data at "..." should be:`
114
156
  * `Then the data at "..." should be "..."`
115
157
 
158
+ Inclusion:
116
159
  * `Then the data includes:`
117
160
  * `Then the data includes "..."`
118
161
  * `Then the data at "..." includes:`
119
162
  * `Then the data at "..." includes "..."`
120
163
 
164
+ Type checking:
121
165
  * `Then the data is of type ...`
122
166
  * `Then the data at "..." if of type ...`
123
167
 
124
168
  Pathing is done like so: `data[:chunky]['Bacon'][0]` would be "chunky/bacon/0". Each element (when looking in a hash) is first tried as a symbol, then as a string.
125
169
 
126
- When checking inclusion against an array, you need to supply an array: `[1,2,3]` includes `[2]`, or `[1, [2,3], 4]` includes `[[2,3]]`
170
+ When checking inclusion against an array, you need to supply an array: `[1,2,3]` includes `[2]`, or `[1, [2,3], 4]` includes `[[2,3]]`.
127
171
 
128
172
  When checking inclusion against a hash, you need to supply a hash: `{one: :two, three: four}` includes `{one: :two}`
129
173
 
130
- RSpec
174
+ You don't see this quite the same in the Cucumber steps because YAML parsing from a string does this inherently: `"one: two"` becomes `{'one' => 'two'}` and
175
+ `"[one, two]"` or `"- one\n- two"` becomes `['one', 'two']`
176
+
177
+ # RSpec
178
+
179
+ Setup
131
180
  --------
181
+ ```ruby
182
+ #in spec/spec_helper.rb
183
+ require 'data_spec'
184
+ ```
132
185
 
186
+ Matchers
187
+ --------
188
+ Three matchers:
133
189
  * `match_data(...).at(...)`
134
190
  * `includes_data(...).at(...)`
135
191
  * `match_block(lambda{...}).at(...)`
136
192
 
137
- Exact matching is (as it turns out!) handled by `==`, while partial matching is handled by http://stackoverflow.com/questions/3826969/ruby-hash-include-another-hash-deep-check
138
- Note that pathing is applied to the object being checked: in `hash1.should match_data(hash2).at("path/0")`, `hash1[:path][0]` would be compared to `hash2`.
193
+ Exact matching is handled by `==`, while partial matching is handled by
194
+ [`deep_include?`](http://stackoverflow.com/questions/3826969/ruby-hash-include-another-hash-deep-check)
195
+
196
+ Note that pathing is applied to the object being checked:
197
+
198
+ hash1.should match_data(hash2).at("path/0")
199
+
200
+ results in:
201
+
202
+ hash1[:path][0].should match_data(hash2)
203
+
204
+ # Library
139
205
 
140
206
  Helpers
141
207
  --------
142
- * DataSpec::Helpers.at_path(data, path)
143
- * DataSpec.parse
208
+ * `DataSpec::Helpers.at_path(data, path)`
209
+ * `DataSpec.parse`
144
210
 
145
- `at_path` is what provides the "pathing" functionality, while `parse` provides interpreting embedded code.
211
+ `at_path` is what provides the "pathing" functionality, while `parse` provides the interpreting of embedded code.
146
212
 
147
213
  As seen in the examples, you can use $ at the beginning and end, or backticks instead of quotes.
148
- The backticks will actually be converted to dollar signs, but they're prettier and easier to read.
214
+ The backticks will actually be converted to dollar signs (YAML parsers choke on backticks),
215
+ but they're prettier and easier to read.
149
216
 
150
- Refinements
151
- -------
152
- `DataSpec::Refinements` adds `tree_walk_with_self` to both `Hash` and `Array`.
153
- It allows you to apply a block to every key/value pair in the hash or array, traversing recursively.
154
- Supply a block accepting `(key, value), hash`, where `hash` is the current node; `hash[key] == value`; this allows you to alter the values.
217
+ * `DataSpec::Helpers.evaluate(string)`
155
218
 
156
- Issues
157
- -------
158
- * The YAML/JSON equivelance check is failing.
159
- * The error messages suck. Plan is to provide them as a diff'd YAML, although I'm not sure what to do for blocks
160
- * No table syntax as in json_spec
161
- * No explicit testing of `tree_walks_with_self`
162
- * No support for XML
219
+ This simply does an `eval` on the string; however, _because it also used when parsing YAML/JSON_, you can add variables
220
+ in which it is run, and use those variables in your YAML and JSON.
163
221
 
164
- Contributing
165
- -----------
166
- Go for it! Accepted code will have Cucumber and RSpec testing and be minimalist; if you spot a bug, try to provide a failing test in the report.
222
+ * `DataSpec::Helpers.remember(string, data)
167
223
 
168
- "Minimalist" doesn't mean fewest lines of code (although that's usually the case); it generally means "fewest new functions and objects"
224
+ This is another way to add data to the evaulation scope; pass in the complete variable name (such as `@sample_data`) and the data to be stored.
225
+
226
+ Refinements
227
+ -------
228
+ Defined in `DataSpec::Refinements`; to use, `using DataSpec::Refinements`
169
229
 
230
+ * `Array.tree_walk_with_self{|(key, value), array| ... }`
231
+ * `Array.deep_include? sub_array`
232
+ * `Hash.tree_walk_with_self{|(key, value), hash| ... }`
233
+ * `Hash.deep_include? sub_hash`
170
234
 
235
+ `tree_walk_with_self` allows you to apply a block to every key/value pair in the hash or array, traversing recursively.
236
+ The third yielded value is the current node: `hash[key] == value` - this allows you to alter the values of the hash during traversal.
171
237
 
238
+ `Array.deep_include? sub_array` simply does `(sub_array - self).empty?`, which is true when all elements of the sub-array
239
+ are present in `self`
172
240
 
241
+ `Hash.deep_include? sub_hash` is used to detect if every key/value pair in the `sub_hash` is present in `self`
173
242
 
243
+ #Contributing
174
244
 
245
+ Remaining Issues
246
+ -------
247
+ * The error messages suck. Plan is to provide them as a diff'd YAML, although I'm not sure what to do for blocks
248
+ * No table syntax as in `json_spec`
249
+ * No explicit testing of `tree_walks_with_self`
250
+ * No support for XML
175
251
 
252
+ Pull Requests
253
+ -----------
254
+ Go for it! Accepted code will have Cucumber and RSpec testing and be minimalist; if you spot a bug, try to provide a failing test in the report.
176
255
 
256
+ "Minimalist" doesn't mean fewest lines of code (although that's usually the case); it means "fewest new functions and objects"
data/Rakefile CHANGED
@@ -1 +1,11 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require "cucumber/rake/task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ Cucumber::Rake::Task.new(:cucumber) do |t|
7
+ t.cucumber_opts = "--tags ~@fail"
8
+ end
9
+
10
+ task :test => [:spec, :cucumber]
11
+ task :default => :test
data/data_spec.gemspec CHANGED
@@ -14,11 +14,9 @@ Gem::Specification.new do |spec|
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.test_files = spec.files.grep(%r{^(spec|features)/})
19
18
  spec.require_paths = ["lib"]
20
19
 
21
- spec.add_development_dependency "bundler", "~> 1.3"
22
20
  spec.add_development_dependency "rake"
23
21
  spec.add_dependency "cucumber"
24
22
  spec.add_dependency "rspec"
@@ -3,33 +3,33 @@ Feature: Core Steps
3
3
  Scenario: JSON / YAML Equality
4
4
  Given the data is:
5
5
  """
6
- - chunky: bacon
7
- ordered_by:
8
- - person: joe
9
- wants:
10
- pieces: `1+1`
11
- - person: josephina
12
- wants:
13
- pieces: `1e2`
6
+ chunky: bacon
7
+ ordered_by:
8
+ - person: joe
9
+ wants:
10
+ pieces: `1+1`
11
+ - person: josephina
12
+ wants:
13
+ pieces: `1e2`
14
14
  """
15
15
  Then the data should be:
16
16
  """
17
17
  {
18
- "chunky": "bacon",
19
18
  "ordered_by": [
20
19
  {
21
- "person": "joe",
22
20
  "wants": {
23
21
  "pieces": "`1+1`"
24
- }
22
+ },
23
+ "person": "joe"
25
24
  },
26
25
  {
27
- "person": "josephina",
28
26
  "wants": {
29
27
  "pieces": "`1e2`"
30
- }
28
+ },
29
+ "person": "josephina"
31
30
  }
32
- ]
31
+ ],
32
+ "chunky": "bacon"
33
33
  }
34
34
  """
35
35
 
@@ -110,9 +110,9 @@ Feature: Core Steps
110
110
  hash: {}
111
111
  array: []
112
112
  """
113
- Then the data at "date" is of type Time
114
- And the data at "fixnum" is of type Fixnum
115
- And the data at "float" is of type Float
116
- And the data at "string" is of type String
117
- And the data at "hash" is of type Hash
118
- And the data at "array" is of type Array
113
+ Then the data at "date" should be of type Time
114
+ And the data at "fixnum" should be of type Fixnum
115
+ And the data at "float" should be of type Float
116
+ And the data at "string" should be of type String
117
+ And the data at "hash" should be of type Hash
118
+ And the data at "array" should be of type Array
@@ -0,0 +1,126 @@
1
+ Feature: Storage of local information
2
+
3
+ Scenario: Variable Assignment
4
+ Given `@var` is "chunky"
5
+ And the data is:
6
+ """
7
+ `@var`
8
+ """
9
+ Then the data should be:
10
+ """
11
+ chunky
12
+ """
13
+
14
+ Scenario: Array Assignment
15
+ Given `@var` is:
16
+ """
17
+ - chunky
18
+ - bacon
19
+ """
20
+ And the data is:
21
+ """
22
+ - `@var[0]`
23
+ - `@var[1]`
24
+ """
25
+ Then the data at "0" should be "`@var[0]`"
26
+ And the data should be:
27
+ """
28
+ `@var`
29
+ """
30
+
31
+ Scenario: Array Appending
32
+ Given `@var` is:
33
+ """
34
+ - chunky
35
+ - bacon
36
+ """
37
+ And `@var` includes:
38
+ """
39
+ - two
40
+ - three
41
+ """
42
+ And the data is:
43
+ """
44
+ `@var`
45
+ """
46
+ Then the data should include "`@var[2,3]`"
47
+
48
+ Scenario: Hash Assignment
49
+ Given `@var` is:
50
+ """
51
+ chunky: bacon
52
+ bacon: chunky
53
+ """
54
+ And the data is:
55
+ """
56
+ `@var`
57
+ """
58
+ Then the data at "chunky" should be "bacon"
59
+ And the data should be:
60
+ """
61
+ bacon: chunky
62
+ chunky: bacon
63
+ """
64
+
65
+ Scenario: Hash Appending
66
+ Given `@var` is:
67
+ """
68
+ chunky: bacon
69
+ bacon: chunky
70
+ """
71
+ And `@var` includes:
72
+ """
73
+ bacon: bacon
74
+ one: two
75
+ """
76
+ And the data is:
77
+ """
78
+ `@var`
79
+ """
80
+ Then the data at "bacon" should be "bacon"
81
+ And the data at "one" should be "two"
82
+
83
+ Scenario: Nesting:
84
+ Given `@var` is:
85
+ """
86
+ nested:
87
+ hash:
88
+ chunky: bacon
89
+ """
90
+ And `@var['nested']` includes:
91
+ """
92
+ array:
93
+ - 1
94
+ - 2
95
+ """
96
+ And the data is:
97
+ """
98
+ - `@var['nested']['hash']['chunky']`
99
+ - `@var['nested']['array']`
100
+ """
101
+ Then the data should be:
102
+ """
103
+ - bacon
104
+ - - 1
105
+ - 2
106
+ """
107
+
108
+ Scenario: Multiple Variables
109
+ Given `@one` is:
110
+ """
111
+ one: two
112
+ """
113
+ And `@two` is:
114
+ """
115
+ two: three
116
+ """
117
+ And the data is:
118
+ """
119
+ - `@one`
120
+ - `@two`
121
+ """
122
+ Then the data is:
123
+ """
124
+ - one: two
125
+ - two: three
126
+ """
@@ -0,0 +1,95 @@
1
+ Feature: Readme Examples
2
+
3
+ Scenario: Matching
4
+ Given the data is:
5
+ """
6
+ chunky: bacon
7
+ """
8
+ Then the data should be:
9
+ """
10
+ {
11
+ "chunky": "bacon"
12
+ }
13
+ """
14
+ Scenario: Path Selection
15
+ Given the data is:
16
+ """
17
+ interleaved:
18
+ - hashes:
19
+ and:
20
+ - arrays
21
+ """
22
+ Then the data at "interleaved/0/hashes" should be:
23
+ """
24
+ and:
25
+ - arrays
26
+ """
27
+
28
+ Scenario: Inclusion
29
+ Given the data is:
30
+ """
31
+ - 1
32
+ - 2
33
+ - 3
34
+ - even:
35
+ 'in a': hash
36
+ 'with only': some keys
37
+ """
38
+ Then the data should include:
39
+ """
40
+ - 1
41
+ - 2
42
+ """
43
+ And the data at "3/even" should include "'in a': hash"
44
+
45
+ Scenario: Type Checking
46
+ Given the data is:
47
+ """
48
+ - bacon
49
+ - 1
50
+ - 2013-07-06 20:09:32.824102000 -07:00
51
+ """
52
+ Then the data at "0" should be of type String
53
+ Then the data at "1" should be of type Fixnum
54
+ Then the data at "2" should be of type Time
55
+
56
+ Scenario: Embedded Code
57
+ Given the data is:
58
+ """
59
+ - `1+1`
60
+ - '$1e2$'
61
+ - `"bacon".class`
62
+ """
63
+ Then the data at "0" should be "2"
64
+ Then the data at "1" should be "100"
65
+ Then the data at "2" should be "`"chunky".class`"
66
+
67
+ Scenario: Memory
68
+ Given `@samples` is:
69
+ """
70
+ where: "http://google.com"
71
+ when: `Time.now`
72
+ """
73
+ And `@samples` includes:
74
+ """
75
+ what: {}
76
+ """
77
+ And `@samples['what']` is:
78
+ """
79
+ - chunky
80
+ - bacon
81
+ """
82
+ And the data is:
83
+ """
84
+ meal:
85
+ main_course: `@samples['what'][1]`
86
+ style: `@samples['what'][0]`
87
+ ordered: `@samples['when']`
88
+ """
89
+ Then the data should be:
90
+ """
91
+ meal:
92
+ main_course: bacon
93
+ style: chunky
94
+ ordered: `@samples['when']`
95
+ """
@@ -1,5 +1,5 @@
1
1
  require "data_spec/cucumber"
2
- require 'debugger'
2
+ #require 'debugger'
3
3
 
4
4
  def data
5
5
  @data
@@ -1,6 +1,20 @@
1
+ require File.expand_path("../../data_spec", __FILE__)
1
2
  require 'data_spec'
3
+ require 'time'
2
4
 
3
- World(DataSpec::Helpers, DataSpec::Matchers, DataSpec::Inclusion, DataSpec::Block)
5
+ World(DataSpec::Helpers, DataSpec::Matchers)
6
+
7
+ Given(/^`(.*?)` is:?(?: "(.*?)")?$/) do |var, inline, *block|
8
+ DataSpec::Helpers.evaluate("#{var} = DataSpec.parse(%##{(inline || block.first)}#)")
9
+ end
10
+
11
+ Given(/^`(.*?)` includes:?(?: "(.*?)")?$/) do |var, inline, *block|
12
+ if DataSpec.parse("`#{var}`").is_a? Hash
13
+ DataSpec::Helpers.evaluate("#{var}.merge! DataSpec.parse(%##{(inline || block.first)}#)")
14
+ elsif DataSpec.parse("`#{var}`").is_a? Array
15
+ DataSpec::Helpers.evaluate("#{var} += DataSpec.parse(%##{(inline || block.first)}#)")
16
+ end
17
+ end
4
18
 
5
19
  # Then the data at "path" should be "data"
6
20
  # Then the data should be: (...)
@@ -12,6 +26,12 @@ Then(/^the data(?: at "(.*?)")? should include:?(?: "(.*?)")?$/) do |path, inlin
12
26
  data.should include_data(DataSpec.parse(inline || block.first)).at(path)
13
27
  end
14
28
 
15
- Then(/^the data at "(.*?)" is of type ([A-Z][a-z]+)$/) do |path, type|
16
- data.should match_block(lambda{|item| item.is_a? Object.const_get(type)}).at(path)
29
+ Then(/^the data at "(.*?)" should be of type ([A-Z][a-z]+)$/) do |path, type|
30
+ if type == "Time"
31
+ #JSON doesn't actually interpret a time string into a Time,
32
+ # YAML will, but Time doesn't parse a Time object
33
+ data.should match_block(lambda{|item| Time.parse(item.to_s).is_a? Time}).at(path)
34
+ else
35
+ data.should match_block(lambda{|item| item.is_a? Object.const_get(type)}).at(path)
36
+ end
17
37
  end
@@ -1,11 +1,10 @@
1
+ require 'yaml'
1
2
  module DataSpec
2
3
  module Refinements
3
4
  refine Array do
4
5
  def tree_walk_with_self &block
5
6
  self.each_with_index do |element, index|
6
- if element.is_a? Hash
7
- element.tree_walk_with_self &block
8
- elsif element.is_a? Array
7
+ if element.is_a?(Hash) || element.is_a?(Array)
9
8
  element.tree_walk_with_self &block
10
9
  else
11
10
  yield [index, element], self
@@ -20,17 +19,16 @@ module DataSpec
20
19
 
21
20
  refine Hash do
22
21
  def tree_walk_with_self &block
23
- self.each do |key,value|
24
- if value.is_a? Hash
25
- value.tree_walk_with_self &block
26
- elsif value.is_a? Array
22
+ self.each do |key, value|
23
+ if value.is_a?(Hash) || value.is_a?(Array)
27
24
  value.tree_walk_with_self &block
28
25
  else
29
- yield [key,value], self
26
+ yield [key, value], self
30
27
  end
31
28
  end
32
29
  end
33
30
 
31
+ #TODO: Can I replace this with a block passed to Tree Walker?
34
32
  def deep_include?(sub_hash)
35
33
  sub_hash.keys.all? do |key|
36
34
  self.has_key?(key) && if sub_hash[key].is_a?(Hash)
@@ -47,17 +45,28 @@ end
47
45
  using DataSpec::Refinements
48
46
  module DataSpec
49
47
  module Helpers
48
+ def self.evaluate string
49
+ eval(string)
50
+ end
51
+ def self.remember varname, data
52
+ instance_variable_set(varname, data)
53
+ end
50
54
  def self.parse yaml
51
55
  # `code` is more readable, but not parsable, for our purposes we're converting it to $
52
56
  unrendered = YAML.load(yaml.gsub("`", "$"))
53
57
 
54
- return unrendered unless unrendered.is_a?(Array) || unrendered.is_a?(Hash)
55
-
56
- unrendered.tree_walk_with_self do |(k, v), h|
57
- if v =~ /^\$(.+)\$$/
58
- h[k] = eval($1)
58
+ if unrendered.is_a?(Array) || unrendered.is_a?(Hash)
59
+ rendered = unrendered.tree_walk_with_self do |(k, v), h|
60
+ if v =~ /^\$(.+)\$$/
61
+ h[k] = self.evaluate($1)
62
+ end
59
63
  end
64
+ elsif unrendered.is_a?(String) && unrendered =~ /^\$(.+)\$$/
65
+ rendered = self.evaluate($1)
66
+ else
67
+ rendered = unrendered
60
68
  end
69
+ rendered
61
70
  end
62
71
  def self.at_path data, path
63
72
  return data if path.nil? || path.empty?
@@ -15,12 +15,10 @@ module DataSpec
15
15
  @path = path
16
16
  end
17
17
 
18
- diffable
18
+ failure_message_for_should do |actual|
19
+ "Got:\n#{actual.to_yaml}\nExpected:\n#{expected.to_yaml}"
20
+ end
19
21
  end
20
- end
21
-
22
- module Inclusion
23
- extend RSpec::Matchers::DSL
24
22
 
25
23
  matcher :include_data do |expected|
26
24
  match do |actual|
@@ -31,12 +29,10 @@ module DataSpec
31
29
  @path = path
32
30
  end
33
31
 
34
- diffable
32
+ failure_message_for_should do |actual|
33
+ "Got:\n#{actual.to_yaml}\nExpected:\n#{expected.to_yaml}"
34
+ end
35
35
  end
36
- end
37
-
38
- module Block
39
- extend RSpec::Matchers::DSL
40
36
 
41
37
  matcher :match_block do |block|
42
38
  match do |actual|
@@ -48,7 +44,4 @@ module DataSpec
48
44
  end
49
45
  end
50
46
  end
51
-
52
- module Interpolation
53
- end
54
47
  end
@@ -1,3 +1,3 @@
1
1
  module DataSpec
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/data_spec.rb CHANGED
@@ -5,7 +5,10 @@ require 'data_spec/matchers'
5
5
  if RSpec && RSpec.respond_to?(:configure)
6
6
  RSpec.configure do |config|
7
7
  config.include DataSpec::Matchers
8
- config.include DataSpec::Inclusion
9
- config.include DataSpec::Block
8
+ config.include DataSpec::Helpers
10
9
  end
11
10
  end
11
+
12
+ if defined?(World)
13
+ require 'data_spec/cucumber'
14
+ end
@@ -1,8 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe DataSpec::Block do
3
+ describe DataSpec::Matchers do
4
4
  it "can check versus a block" do
5
5
  "chunky".should match_block(lambda{|got| got.is_a? String})
6
+
6
7
  "chunky".should_not match_block(lambda{|got| got.is_a? Integer})
7
8
  end
8
9
 
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataSpec do
4
+ it "can remember things for use in evaluation" do
5
+ time = Time.now
6
+ DataSpec::Helpers.remember("@var", time)
7
+ DataSpec::Helpers.evaluate("@var.day").should be(time.day)
8
+ end
9
+ end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe DataSpec::Inclusion do
3
+ describe DataSpec::Matchers do
4
4
 
5
5
  it "can check array inclusion" do
6
6
  [1,2,3].should include_data([2])
@@ -46,9 +46,9 @@ describe DataSpec::Inclusion do
46
46
  end
47
47
 
48
48
  it "can check at a path" do
49
- [1, {array: [2, {chunky: :bacon, bacon: :chunky} ] } ].should include_data({chunky: :bacon}).at("1/array/1")
50
- [1, {array: [2, {chunky: :bacon, bacon: :chunky} ] } ].should include_data({chunky: :bacon}).at("1/array/1")
49
+ [1, {breakfast: [2, {chunky: :bacon, bacon: :chunky} ] } ].should include_data({chunky: :bacon}).at("1/breakfast/1")
50
+ [1, {breakfast: [2, {chunky: :bacon, bacon: :chunky} ] } ].should include_data({chunky: :bacon}).at("1/breakfast/1")
51
51
 
52
- [1, {array: [2, {chunky: :bacon, bacon: :chunky} ] } ].should_not include_data({chunky: :nocab}).at("1/array/1")
52
+ [1, {breakfast: [2, {chunky: :bacon, bacon: :chunky} ] } ].should_not include_data({chunky: :nocab}).at("1/breakfast/1")
53
53
  end
54
54
  end
@@ -6,30 +6,37 @@ describe DataSpec::Matchers do
6
6
  {}.should match_data({})
7
7
  {}.should_not match_data([])
8
8
  end
9
+
9
10
  it "should match empty arrays" do
10
11
  [].should match_data([])
11
12
  [].should_not match_data({})
12
13
  end
14
+
13
15
  it "should match strings" do
14
16
  "Bacon".should match_data("Bacon")
15
17
  "Bacon".should_not match_data("Chunky")
16
18
  end
19
+
17
20
  it "should match integers" do
18
21
  1.should match_data(1)
19
22
  2.should_not match_data(1)
20
23
  end
24
+
21
25
  it "should match floats" do
22
26
  1.1.should match_data(1.1)
23
27
  2.1.should_not match_data(1.1)
24
28
  end
29
+
25
30
  it "should match true" do
26
31
  true.should match_data(true)
27
32
  true.should_not match_data(false)
28
33
  end
34
+
29
35
  it "should match false" do
30
36
  false.should match_data(false)
31
37
  false.should_not match_data(true)
32
38
  end
39
+
33
40
  it "should match nil" do
34
41
  nil.should match_data(nil)
35
42
  nil.should_not match_data("something")
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
- require 'debugger'
3
+ #require 'debugger'
4
4
 
5
5
  require 'data_spec' # and any other gems you need
6
6
 
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data_spec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - narfanator
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-07 00:00:00.000000000 Z
11
+ date: 2013-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ~>
18
- - !ruby/object:Gem::Version
19
- version: '1.3'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ~>
25
- - !ruby/object:Gem::Version
26
- version: '1.3'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: rake
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -75,12 +61,15 @@ extra_rdoc_files: []
75
61
  files:
76
62
  - .gitignore
77
63
  - .rspec
64
+ - .travis.yml
78
65
  - Gemfile
79
66
  - LICENSE.txt
80
67
  - README.md
81
68
  - Rakefile
82
69
  - data_spec.gemspec
83
70
  - features/core.feature
71
+ - features/memory.feature
72
+ - features/readme.feature
84
73
  - features/step_definitions/steps.rb
85
74
  - features/support/env.rb
86
75
  - lib/data_spec.rb
@@ -89,6 +78,7 @@ files:
89
78
  - lib/data_spec/matchers.rb
90
79
  - lib/data_spec/version.rb
91
80
  - spec/data_spec/block_spec.rb
81
+ - spec/data_spec/helpers_spec.rb
92
82
  - spec/data_spec/inclusion_spec.rb
93
83
  - spec/data_spec/interpolation_spec.rb
94
84
  - spec/data_spec/matchers_spec.rb
@@ -120,9 +110,12 @@ summary: RSpec matchers and Cucumber steps for describing hash and array structu
120
110
  including deep nesting
121
111
  test_files:
122
112
  - features/core.feature
113
+ - features/memory.feature
114
+ - features/readme.feature
123
115
  - features/step_definitions/steps.rb
124
116
  - features/support/env.rb
125
117
  - spec/data_spec/block_spec.rb
118
+ - spec/data_spec/helpers_spec.rb
126
119
  - spec/data_spec/inclusion_spec.rb
127
120
  - spec/data_spec/interpolation_spec.rb
128
121
  - spec/data_spec/matchers_spec.rb