hash_dealer 1.2.6 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Guardfile +1 -1
- data/README.rdoc +86 -4
- data/VERSION +1 -1
- data/hash_dealer.gemspec +3 -2
- data/lib/core_extensions.rb +28 -9
- data/lib/hash_dealer.rb +3 -1
- data/lib/path_string.rb +1 -1
- data/lib/variable_array.rb +11 -0
- data/spec/lib/hash_dealer_spec.rb +11 -0
- data/spec/lib/matcher_spec.rb +5 -0
- metadata +4 -3
data/Guardfile
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
guard 'rspec', :version => 2, :cli => "--color --format nested" do
|
5
5
|
watch(%r{^spec/.+_spec\.rb$})
|
6
|
-
watch(%r{^lib/(.+)\.rb$}) { |m| "spec
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec" }
|
7
7
|
watch('spec/spec_helper.rb') { "spec" }
|
8
8
|
|
9
9
|
# Rails example
|
data/README.rdoc
CHANGED
@@ -1,8 +1,90 @@
|
|
1
|
-
=
|
1
|
+
= hash_dealer
|
2
2
|
|
3
|
-
|
3
|
+
== A library for creating reusable, extendable Hash-like objects for testing
|
4
4
|
|
5
|
-
==
|
5
|
+
== Defining HashDealers
|
6
|
+
|
7
|
+
Everyone has a favorite Hash Dealer - here is how you create your template. Note that any method can be used in your definition
|
8
|
+
|
9
|
+
HashDealer.define(:variable) do
|
10
|
+
a("test_a")
|
11
|
+
b("test_b")
|
12
|
+
end
|
13
|
+
|
14
|
+
Once you have your HashDealer - ask him to roll one up for you
|
15
|
+
|
16
|
+
HashDealer.roll(:variable) => {:a => "test_a", :b => "test_b"}
|
17
|
+
|
18
|
+
If you'd like to customize your Hash - just pass in some options
|
19
|
+
|
20
|
+
HashDealer.roll(:variable, :a => "My own Kief") => {:a => "My own Kief", :b => "test_b"}
|
21
|
+
|
22
|
+
=== Dynamic Hashes
|
23
|
+
|
24
|
+
Sometimes you'd like dynamic values for your Hash - or to use another HashDealer that you want to be dynamic - to do so, use a block inside your HashDealer definition
|
25
|
+
|
26
|
+
HashDealer.define(:dynamic) do
|
27
|
+
abc {Kernel.rand(100)}
|
28
|
+
end
|
29
|
+
|
30
|
+
HashDealer.roll(:dynamic) => {:abc => 12}
|
31
|
+
HashDealer.roll(:dynamic) => {:abc => 32}
|
32
|
+
|
33
|
+
=== Nested Hashes
|
34
|
+
HashDealer does not evaluate your defined Hashes until they are called - so you can use other HashDealers that are not yet loaded in your HashDealer definitions
|
35
|
+
|
36
|
+
HashDealer.define(:b) do
|
37
|
+
hash_a(HashDealer.roll(:a))
|
38
|
+
end
|
39
|
+
|
40
|
+
HashDealer.define(:a) do
|
41
|
+
a("123")
|
42
|
+
end
|
43
|
+
|
44
|
+
HashDealer.roll(:b) => {:hash_a => {:a => "123"}}
|
45
|
+
|
46
|
+
=== Inheritance
|
47
|
+
|
48
|
+
HashDealers can inherit from one another using the :parent option in their definitions
|
49
|
+
|
50
|
+
HashDealer.define(:variable_2, :parent => :variable) do
|
51
|
+
a("variable_2")
|
52
|
+
my_var("abc")
|
53
|
+
end
|
54
|
+
|
55
|
+
HashDealer.roll(:variable_2) => {:a => "variable_2", :b => "test_b", :my_var => "abc"}
|
56
|
+
|
57
|
+
=== Elements other than Hashes
|
58
|
+
Sometimes you need to ask your dealer for something other than Hash - just define a root element
|
59
|
+
|
60
|
+
HashDealer.define(:crack) do
|
61
|
+
root([1,2,3])
|
62
|
+
end
|
63
|
+
|
64
|
+
HashDealer.roll(:crack) => [1,2,3]
|
65
|
+
|
66
|
+
== Rspec Matchers
|
67
|
+
|
68
|
+
One goal of HashDealer is to allow you to define dynamic matchers to ensure that JSON responses from interfacing APIs follow a consistent format
|
69
|
+
|
70
|
+
E.g.
|
71
|
+
|
72
|
+
response = {:id => 1, :name => "My Name", :email => "dan.langevin@lifebooker.com"}
|
73
|
+
{:id => 1, :name => ":name", :email => ":email"}.matcher.should match_response(response)
|
74
|
+
|
75
|
+
We don't care about the actual content of the fields, just that they are of the same type (generally) and that the hashes have the same fields
|
76
|
+
|
77
|
+
Similarly
|
78
|
+
|
79
|
+
response = [{:id => 1, :name => "My Name", :email => "dan.langevin@lifebooker.com"}, {:id => 2, :name => "Another Developer", :email => "wbartosch@lifebooker.com"}]
|
80
|
+
[{:id => 1, :name => ":name", :email => ":email"}].matcher.should match_response(response)
|
81
|
+
|
82
|
+
We don't care how many elements there are in the array (we might get back 100 records from our test), just that they have the correct format
|
83
|
+
|
84
|
+
=== The matcher method
|
85
|
+
To achieve this, we use the .matcher method, which is defined on a Hash, String, Numeric and Array and should match_response(x) as an Rspec Matcher
|
86
|
+
|
87
|
+
== Contributing to hash_dealer
|
6
88
|
|
7
89
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
90
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
@@ -14,6 +96,6 @@ Description goes here.
|
|
14
96
|
|
15
97
|
== Copyright
|
16
98
|
|
17
|
-
Copyright (c) 2011
|
99
|
+
Copyright (c) 2011 Lifebooker, Inc. See LICENSE.txt for
|
18
100
|
further details.
|
19
101
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.3.0
|
data/hash_dealer.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{hash_dealer}
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Dan Langevin"]
|
12
|
-
s.date = %q{2011-08-
|
12
|
+
s.date = %q{2011-08-26}
|
13
13
|
s.description = %q{Like Factory Girl but for Hashes only}
|
14
14
|
s.email = %q{dan.langevin@lifebooker.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -30,6 +30,7 @@ Gem::Specification.new do |s|
|
|
30
30
|
"lib/hash_dealer.rb",
|
31
31
|
"lib/matcher.rb",
|
32
32
|
"lib/path_string.rb",
|
33
|
+
"lib/variable_array.rb",
|
33
34
|
"spec/lib/hash_dealer_spec.rb",
|
34
35
|
"spec/lib/matcher_spec.rb",
|
35
36
|
"spec/lib/path_string_spec.rb",
|
data/lib/core_extensions.rb
CHANGED
@@ -25,14 +25,15 @@ class String
|
|
25
25
|
end
|
26
26
|
|
27
27
|
class Hash
|
28
|
-
def pathify_strings
|
28
|
+
def pathify_strings
|
29
29
|
self.each_pair do |k,v|
|
30
30
|
if v.is_a?(Array) || v.is_a?(Hash)
|
31
|
-
v.pathify_strings
|
31
|
+
self[k] = v.pathify_strings
|
32
32
|
elsif v.instance_of?(String) || v.is_a?(Numeric)
|
33
33
|
self[k] = PathString.new(URI.decode(v.to_s))
|
34
34
|
end
|
35
35
|
end
|
36
|
+
self
|
36
37
|
end
|
37
38
|
# recursively get a matcher for each value
|
38
39
|
def matcher(opts = {})
|
@@ -52,17 +53,35 @@ class Hash
|
|
52
53
|
end
|
53
54
|
end
|
54
55
|
class Array
|
55
|
-
def pathify_strings
|
56
|
-
self.
|
57
|
-
|
58
|
-
|
56
|
+
def pathify_strings
|
57
|
+
if self.first == ":matcher"
|
58
|
+
val = VariableArray.new(self)
|
59
|
+
else
|
60
|
+
val = self
|
61
|
+
end
|
62
|
+
val.each_with_index do |v,k|
|
63
|
+
if v.is_a?(Array) || v.is_a?(Hash)
|
64
|
+
val[k] = v.pathify_strings
|
59
65
|
elsif v.instance_of?(String) || v.is_a?(Numeric)
|
60
|
-
|
66
|
+
val[k] = PathString.new(URI.decode(v.to_s))
|
61
67
|
end
|
62
68
|
end
|
69
|
+
val
|
63
70
|
end
|
64
71
|
# call matcher on all of the elements
|
65
72
|
def matcher(opts = {})
|
66
|
-
self.
|
73
|
+
self.unshift(":matcher")
|
74
|
+
VariableArray.new(self.collect(&:matcher))
|
67
75
|
end
|
68
|
-
|
76
|
+
# we want this to apply to both :eql? and ==
|
77
|
+
alias_method :eql?, :==
|
78
|
+
# we want this to add decorator behavior to ==, proxying to VariableArray if possible
|
79
|
+
define_method "==_with_variable_array" do |other|
|
80
|
+
return other == self if other.is_a?(VariableArray)
|
81
|
+
self.send("==_without_variable_array",other)
|
82
|
+
end
|
83
|
+
# Equivalent to:
|
84
|
+
# alias_method_chain "==", "variable_array"
|
85
|
+
alias_method "==_without_variable_array", :==
|
86
|
+
alias_method :==, "==_with_variable_array"
|
87
|
+
end
|
data/lib/hash_dealer.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.expand_path('../path_string', __FILE__)
|
2
|
+
require File.expand_path('../variable_array', __FILE__)
|
2
3
|
require File.expand_path('../core_extensions', __FILE__)
|
3
4
|
require File.expand_path('../matcher', __FILE__)
|
4
5
|
|
@@ -13,11 +14,12 @@ class HashDealer
|
|
13
14
|
|
14
15
|
# define a method of the request factory
|
15
16
|
def self.define(name, opts = {}, &block)
|
16
|
-
self.hashes[name] =
|
17
|
+
self.hashes[name] = [opts, block]
|
17
18
|
end
|
18
19
|
|
19
20
|
def self.roll(name, *args)
|
20
21
|
raise Exception.new("No HashDealer called #{name}") unless self.hashes[name]
|
22
|
+
self.hashes[name] = self.new(self.hashes[name][0], &self.hashes[name][1]) unless self.hashes[name].is_a?(HashDealer)
|
21
23
|
self.hashes[name]._attributes(*args)
|
22
24
|
end
|
23
25
|
|
data/lib/path_string.rb
CHANGED
@@ -130,4 +130,15 @@ describe HashDealer do
|
|
130
130
|
HashDealer.roll(:test)[:attributes].should eql("test")
|
131
131
|
HashDealer.roll(:test).matcher[:attributes].should eql(":test")
|
132
132
|
end
|
133
|
+
|
134
|
+
it "should allow the use of a HashDealer in the definition of another before the first is defined" do
|
135
|
+
HashDealer.define(:b) do
|
136
|
+
hash_a(HashDealer.roll(:a))
|
137
|
+
end
|
138
|
+
HashDealer.define(:a) do
|
139
|
+
a("123")
|
140
|
+
end
|
141
|
+
HashDealer.roll(:b).should eql({:hash_a => {:a => "123"}})
|
142
|
+
end
|
143
|
+
|
133
144
|
end
|
data/spec/lib/matcher_spec.rb
CHANGED
@@ -14,4 +14,9 @@ describe "match_resonse Matcher" do
|
|
14
14
|
{"a" => ":b"}.should match_list([{"a" => "test"}, {"a" => "test2"}])
|
15
15
|
end
|
16
16
|
|
17
|
+
it "should match using wildcards for variable length arrays" do
|
18
|
+
{"a" => ["a"]}.matcher.should match_response({"a" => ["a", "b", "c", "d"]})
|
19
|
+
{"a" => [{"a" => "b"}]}.matcher.should match_response({"a" => [{"a" => "c"},{"a" => "x"},{"a" => "y"}]})
|
20
|
+
end
|
21
|
+
|
17
22
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: hash_dealer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.
|
5
|
+
version: 1.3.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Dan Langevin
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-08-
|
13
|
+
date: 2011-08-26 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -112,6 +112,7 @@ files:
|
|
112
112
|
- lib/hash_dealer.rb
|
113
113
|
- lib/matcher.rb
|
114
114
|
- lib/path_string.rb
|
115
|
+
- lib/variable_array.rb
|
115
116
|
- spec/lib/hash_dealer_spec.rb
|
116
117
|
- spec/lib/matcher_spec.rb
|
117
118
|
- spec/lib/path_string_spec.rb
|
@@ -129,7 +130,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
129
130
|
requirements:
|
130
131
|
- - ">="
|
131
132
|
- !ruby/object:Gem::Version
|
132
|
-
hash: -
|
133
|
+
hash: -979585820027461548
|
133
134
|
segments:
|
134
135
|
- 0
|
135
136
|
version: "0"
|