peppers-ghost 0.0.0 → 0.0.1.alpha.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c4990710319dbcc755fa8e9651b277ea26c94db
4
- data.tar.gz: a39e7dca88220240fdd6be33c1210fc2baac987b
3
+ metadata.gz: fb4767e7fefac57d01e5c9e1bbde36cf7fb59870
4
+ data.tar.gz: badd39258d23e417c1f1a133d4056287b4f383e3
5
5
  SHA512:
6
- metadata.gz: c2fda7ce252b9959861633268deb497e3b47c86efb73c93b796ee51eea3add569f0c2f17efb94e7e90c786bf7ac81697c52cc7d872f92be0291046e3ae2886db
7
- data.tar.gz: 78a728fe87cd8f04015531f33343d6d0486e26dccecb1b617ac5385584d392b6cd818a87d110e7ad95e6c3a008fbb46987f071ea4d0f2520176b717e0c83d71e
6
+ metadata.gz: ee1667f92c9415f36181d25b8a6f1cc46ce9e472a51be55699e205f38caa1f0d241db565681facf3c27baea4fe0e5370a3610fb386a4cdf75f58c1cd340db99e
7
+ data.tar.gz: 2a61937f5bb389aa2a3ddc43cd5316c673834bcd6a36bff1f11ae447ab2019995ffd91af236a3567e45c7f0534027b166834b3166301f27f9088b28ad12435e4
@@ -1,21 +1,21 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- peppers-ghost (0.0.0)
4
+ peppers-ghost (0.0.1)
5
5
  rspec
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
9
9
  specs:
10
10
  diff-lcs (1.2.4)
11
- rspec (2.14.1)
12
- rspec-core (~> 2.14.0)
13
- rspec-expectations (~> 2.14.0)
14
- rspec-mocks (~> 2.14.0)
15
- rspec-core (2.14.4)
16
- rspec-expectations (2.14.0)
11
+ rspec (2.13.0)
12
+ rspec-core (~> 2.13.0)
13
+ rspec-expectations (~> 2.13.0)
14
+ rspec-mocks (~> 2.13.0)
15
+ rspec-core (2.13.1)
16
+ rspec-expectations (2.13.0)
17
17
  diff-lcs (>= 1.1.3, < 2.0)
18
- rspec-mocks (2.14.2)
18
+ rspec-mocks (2.13.1)
19
19
 
20
20
  PLATFORMS
21
21
  ruby
@@ -1,25 +1,14 @@
1
+ require 'time'
2
+
3
+ require 'uuidtools'
1
4
  require 'rspec'
2
5
 
3
6
  module PeppersGhost
4
7
  end
5
8
 
6
- require_relative 'peppers-ghost/core'
7
-
8
- require_relative 'peppers-ghost/ghost'
9
9
  require_relative 'peppers-ghost/ghost_factory'
10
-
11
- require_relative 'peppers-ghost/shared/json_context'
12
- require_relative 'peppers-ghost/shared/list_example'
13
-
14
10
  require_relative 'peppers-ghost/matchers'
15
- require_relative 'peppers-ghost/matchers/match_structure_of'
16
- require_relative 'peppers-ghost/matchers/match_resource'
17
-
18
- module PeppersGhost
19
- extend PeppersGhost::GhostFactory
20
- end
21
11
 
22
12
  RSpec.configure do |config|
23
- config.include PeppersGhost::Core
24
- config.include PeppersGhost::Matchers
13
+ config.include PeppersGhost::Matchers, :json => true
25
14
  end
@@ -1,21 +1,125 @@
1
1
  module PeppersGhost::GhostFactory
2
- def define(&block)
2
+ def self.registry
3
+ @registry ||= Registry.new
4
+ end
5
+
6
+ class << self
7
+ delegate :find, to: :registry
8
+ end
9
+
10
+ def self.define(&block)
3
11
  instance_eval &block
4
12
  end
5
13
 
6
- def ghost_for(resource)
7
- ghosts[resource]
14
+ def self.reload
15
+ Dir[File.join(File.expand_path('spec/ghosts'), '**', '*.rb')].sort.each do |file|
16
+ load file
17
+ end
18
+ end
19
+
20
+ def self.resource(name, &block)
21
+ resource = Resource.new
22
+ resource.instance_eval(&block) if block_given?
23
+
24
+ registry.add_resource name, resource
25
+ end
26
+
27
+ class Registry
28
+ def initialize
29
+ @resources = {}
30
+ end
31
+
32
+ def add_resource(name, resource)
33
+ @resources[name] = resource
34
+ end
35
+
36
+ def find(name)
37
+ @resources[name]
38
+ end
39
+ end
40
+
41
+ class Resource
42
+ def initialize
43
+ @attributes = {}
44
+ end
45
+
46
+ def attribute_names
47
+ @attributes.keys
48
+ end
49
+
50
+ def attribute_definition_for(name)
51
+ @attributes[name]
52
+ end
53
+
54
+ def attribute(name, options={}, &block)
55
+ if block_given?
56
+ add_dynamic_attribute(name, options, &block)
57
+ else
58
+ add_implicit_attribute(name, options)
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def add_dynamic_attribute(name, options={}, &block)
65
+ @attributes[name] = DynamicAttributeDefinition.new(name, options, block)
66
+ end
67
+
68
+ def add_implicit_attribute(name, options={})
69
+ @attributes[name] = ImplicitAttributeDefinition.new(name, options)
70
+ end
71
+
72
+ def method_missing(name, *args, &block)
73
+ attribute(name, *args, &block)
74
+ end
75
+ end
76
+
77
+ class AttributeDefinition
78
+ attr_reader :name, :resource
79
+
80
+ def initialize(name, options={})
81
+ @name = name
82
+ @resource = options[:resource]
83
+ end
84
+
85
+ private
86
+
87
+ def transform(value)
88
+ case value
89
+ when UUIDTools::UUID
90
+ value.to_s
91
+ when Date, Time
92
+ value.iso8601
93
+ else
94
+ value
95
+ end
96
+ end
8
97
  end
9
98
 
10
- def ghost(name, &block)
11
- ghost = PeppersGhost::Ghost.new
12
- ghost.instance_eval &block
13
- ghosts[name] = ghost
99
+ class ImplicitAttributeDefinition < AttributeDefinition
100
+ def evaluate(object)
101
+ if object.respond_to?(name)
102
+ transform object.send(name)
103
+ elsif object.is_a?(Hash)
104
+ transform(object[name.to_s] || object[name.to_sym])
105
+ end
106
+ end
14
107
  end
15
108
 
16
- private
109
+ class DynamicAttributeDefinition < AttributeDefinition
110
+ def initialize(name, options={}, block)
111
+ super name, options
112
+ @block = block
113
+ end
17
114
 
18
- def ghosts
19
- @ghosts ||= {}
115
+ def evaluate(object)
116
+ transform object.instance_eval(&block)
117
+ end
118
+
119
+ private
120
+
121
+ attr_reader :block
20
122
  end
21
123
  end
124
+
125
+ PeppersGhost::GhostFactory.reload
@@ -1,5 +1,160 @@
1
- module PeppersGhost
2
- module Matchers
3
- extend RSpec::Matchers::DSL
1
+ module PeppersGhost::Matchers
2
+ def mirrors_ghost(json_resource, resource, type, strict = false)
3
+ mirrors_structure json_resource, type, 1
4
+ match_values json_resource, resource, type, strict
5
+ end
6
+
7
+ def mirrors_structure(json_resource, type, count = nil)
8
+ expect(json_resource).to_not eq(nil),
9
+ "Expected the #{type} to not be nil"
10
+
11
+ if json_resource.is_a?(Array)
12
+ match_array_structures json_resource, type, count
13
+ elsif !count.nil? and count != 1
14
+ expect(count).to eq(1),
15
+ "Got a singular resource, expected #{count} #{type.to_s.pluralize}"
16
+ else
17
+ match_individual_structure json_resource, type
18
+ end
19
+ end
20
+
21
+ def mirrors_many(json_resources, resources, type, strict = false)
22
+ check_resource_count json_resources, resources, type
23
+ json_resources.each_with_index do |json_resource, i|
24
+ mirrors_ghost json_resource, resources[i], type, strict
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def match_values(json_resource, resource, type, strict = false)
31
+ attributes = attributes_for_resource(type)
32
+ json_resource = json_resource.first if json_resource.is_a?(Array)
33
+ match_attributes json_resource, resource, type, attributes, strict
34
+ end
35
+
36
+ def match_individual_structure(json_resource, type)
37
+ attributes = attributes_for_resource(type)
38
+ expect(json_resource.keys).to match_array attributes.map(&:to_s)
39
+ deep_structure json_resource, type
40
+ end
41
+
42
+ def match_array_structures(json_resources, type, count)
43
+ if count
44
+ expected_resource_count json_resources, count, type
45
+ end
46
+
47
+ json_resources.each do |json_resource|
48
+ mirrors_structure json_resource, type
49
+ end
50
+ end
51
+
52
+ def match_attributes(json_resource, resource, type, attributes, strict = false)
53
+ attributes.each do |attribute|
54
+ resource_doc = resource_doc_for(type)
55
+ definition = resource_doc.attribute_definition_for(attribute)
56
+
57
+ value = definition.evaluate(resource)
58
+ json_value = json_resource[attribute.to_s]
59
+
60
+ if definition.resource
61
+ deep_match json_value, value, definition
62
+ else
63
+ match_attribute json_value, value, type, attribute, strict
64
+ end
65
+ end
66
+ end
67
+
68
+ def deep_match(json_value, value, definition)
69
+ valid = false
70
+ if array?(definition)
71
+ valid = true if json_value.count > 0
72
+ mirrors_many json_value, value, definition.resource
73
+ else
74
+ expect(json_value).to_not be_an Array
75
+ if json_value or value
76
+ valid = true
77
+ mirrors_ghost json_value, value, definition.resource
78
+ end
79
+ end
80
+ Frogger.log_resource(definition.resource, valid)
81
+ end
82
+
83
+ def check_resource_count(json_resources, resources, type)
84
+ expect(json_resources).to be_an Array
85
+ expected_resource_count json_resources, resources.count, type
86
+ end
87
+
88
+ def expected_resource_count(json_resources, count, type)
89
+ structure = type.to_s.pluralize(count)
90
+ expect(json_resources).to have(count).send(structure)
91
+ end
92
+
93
+ def deep_structure(json_resource, type)
94
+ resource_doc = resource_doc_for(type)
95
+ resource_doc.attribute_names.each do |attribute_name|
96
+ definition = resource_doc.attribute_definition_for(attribute_name)
97
+ json_value = json_resource[attribute_name.to_s]
98
+ if definition.resource && json_value
99
+ check_structure json_value, definition
100
+ end
101
+ end
102
+ end
103
+
104
+ def check_structure(json_value, definition)
105
+ check_array_for json_value, definition
106
+ mirrors_structure json_value, definition.resource
107
+ end
108
+
109
+ def check_array_for(json_value, definition)
110
+ if array?(definition)
111
+ expect(json_value).to be_an Array
112
+ else
113
+ expect(json_value).to_not be_an Array
114
+ end
115
+ end
116
+
117
+ def match_attribute(json_value, value, type, attribute, strict = false)
118
+ if strict
119
+ expect(json_value).to_not eq(nil),
120
+ "#{type}.#{attribute} is nil.\n" +
121
+ "Turn off strict mode for this test if a nil value is expected."
122
+ end
123
+
124
+ expect(json_value).to eq(value),
125
+ mismatch_message(type, attribute, json_value, value)
126
+ end
127
+
128
+ def mismatch_message(type, attribute, json_value, value)
129
+ mask = "%s.%s does not match.\n\n" +
130
+ "expected: %s\n" +
131
+ " got: %s"
132
+
133
+ mask % [
134
+ type,
135
+ attribute,
136
+ stringify_value(value),
137
+ stringify_value(json_value),
138
+ ]
139
+ end
140
+
141
+ def stringify_value(value)
142
+ "#{value.class}:#{value}"
143
+ end
144
+
145
+ def resource_doc_for(type)
146
+ type = type.to_s.singularize.to_sym
147
+ resource_doc = PeppersGhost::GhostFactory.find(type)
148
+ expect(resource_doc).to be_a(PeppersGhost::GhostFactory::Resource),
149
+ "Resource specification could not be found for #{type}."
150
+ resource_doc
151
+ end
152
+
153
+ def attributes_for_resource(type)
154
+ resource_doc_for(type).attribute_names
155
+ end
156
+
157
+ def array?(definition)
158
+ definition.resource.to_s.pluralize == definition.resource.to_s
4
159
  end
5
160
  end
@@ -1,13 +1,14 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'peppers-ghost'
3
- s.version = '0.0.0'
3
+ s.version = '0.0.1.alpha.1'
4
4
 
5
5
  s.summary = 'Adds some helpers for testing api resources'
6
- s.description = %Q{}.strip
6
+ s.description = %Q{
7
+ }.strip
7
8
 
8
9
  s.author = 'Travis Herrick'
9
10
  s.email = 'tthetoad@gmail.com'
10
- s.homepage = 'http://www.bitbucket.org/ToadJamb/peppers-ghost'
11
+ s.homepage = 'http://www.bitbucket.org/ToadJamb/gems-peppers-ghost'
11
12
 
12
13
  s.license = 'LGPLv3'
13
14
 
@@ -18,6 +19,7 @@ Gem::Specification.new do |s|
18
19
  s.test_files = Dir['spec/**/*.rb']
19
20
 
20
21
  s.add_dependency 'rspec'
22
+ s.add_dependency 'uuidtools'
21
23
 
22
24
  s.has_rdoc = false
23
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: peppers-ghost
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1.alpha.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Travis Herrick
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-01 00:00:00.000000000 Z
11
+ date: 2014-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: uuidtools
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  description: ''
28
42
  email: tthetoad@gmail.com
29
43
  executables: []
@@ -33,16 +47,10 @@ files:
33
47
  - Gemfile
34
48
  - Gemfile.lock
35
49
  - peppers-ghost.gemspec
36
- - lib/peppers-ghost/core.rb
37
- - lib/peppers-ghost/ghost.rb
50
+ - lib/peppers-ghost.rb
38
51
  - lib/peppers-ghost/ghost_factory.rb
39
- - lib/peppers-ghost/matchers/match_resource.rb
40
- - lib/peppers-ghost/matchers/match_structure_of.rb
41
52
  - lib/peppers-ghost/matchers.rb
42
- - lib/peppers-ghost/shared/json_context.rb
43
- - lib/peppers-ghost/shared/list_example.rb
44
- - lib/peppers-ghost.rb
45
- homepage: http://www.bitbucket.org/ToadJamb/peppers-ghost
53
+ homepage: http://www.bitbucket.org/ToadJamb/gems-peppers-ghost
46
54
  licenses:
47
55
  - LGPLv3
48
56
  metadata: {}
@@ -57,12 +65,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
57
65
  version: '0'
58
66
  required_rubygems_version: !ruby/object:Gem::Requirement
59
67
  requirements:
60
- - - '>='
68
+ - - '>'
61
69
  - !ruby/object:Gem::Version
62
- version: '0'
70
+ version: 1.3.1
63
71
  requirements: []
64
72
  rubyforge_project:
65
- rubygems_version: 2.0.3
73
+ rubygems_version: 2.1.11
66
74
  signing_key:
67
75
  specification_version: 4
68
76
  summary: Adds some helpers for testing api resources
@@ -1,58 +0,0 @@
1
- module PeppersGhost::Core
2
- def match_resource_type(json_resource, resource, attributes, strict = false)
3
- match_structure json_resource, attributes
4
- match_values json_resource, resource, attributes, strict
5
- end
6
-
7
- def match_structure(json_resource, attributes, count = nil, method = nil)
8
- method ||= :resource
9
- expect(json_resource).to_not be_nil
10
-
11
- if json_resource.is_a?(Array)
12
- expect(json_resource).to have(count).method_missing(method) if count
13
- match_single_structure json_resource, attributes, count
14
- else
15
- expect(json_resource.keys).to match_array attributes.map(&:to_s)
16
- end
17
- end
18
-
19
- def match_values(json_resource, resource, attributes, strict = false)
20
- if json_resource.is_a?(Array)
21
- expect(json_resource).to have(1).resource
22
- json_resource = json_resource.first
23
- end
24
- match_attributes json_resource, resource, attributes, strict
25
- end
26
-
27
- private
28
-
29
- def match_single_structure(json_resources, attributes, count)
30
- json_resources.each do |json_resource|
31
- match_structure json_resource, attributes
32
- end
33
- end
34
-
35
- def match_attributes(json_resource, resource, attributes, strict = false)
36
- attributes.each do |attribute|
37
- next unless resource.respond_to?(attribute) or
38
- (resource.is_a?(Hash) and
39
- (resource.has_key?(attribute.to_s) or resource.has_key?(attribute.to_sym)))
40
-
41
- value =
42
- if resource.respond_to?(attribute)
43
- resource.send attribute
44
- elsif resource.is_a? Hash
45
- resource[attribute.to_s] || resource[attribute.to_sym]
46
- end
47
-
48
- json_value = json_resource[attribute.to_s]
49
-
50
- match_attribute json_value, value, strict
51
- end
52
- end
53
-
54
- def match_attribute(json_value, value, strict = false)
55
- expect(value).to_not be_nil if strict
56
- expect(json_value).to eq value
57
- end
58
- end
@@ -1,9 +0,0 @@
1
- class PeppersGhost::Ghost
2
- def attributes
3
- @attributes ||= []
4
- end
5
-
6
- def method_missing(method, *args, &block)
7
- attributes << method
8
- end
9
- end
@@ -1,21 +0,0 @@
1
- module PeppersGhost::Matchers
2
- matcher :match_resource do |expected, type|
3
- chain :strictly do
4
- @strict = true
5
- end
6
-
7
- match do |actual|
8
- begin
9
- resource = PeppersGhost.ghost_for(type)
10
- match_resource_type actual, expected, resource.attributes, @strict
11
- rescue RSpec::Expectations::ExpectationNotMetError => e
12
- @error = e.message
13
- false
14
- end
15
- end
16
-
17
- failure_message_for_should do
18
- @error
19
- end
20
- end
21
- end
@@ -1,30 +0,0 @@
1
- module PeppersGhost::Matchers
2
- matcher :match_structure_of do |expected|
3
- chain :with do |count|
4
- @count = count
5
- end
6
-
7
- match do |actual|
8
- begin
9
- resource = PeppersGhost.ghost_for(expected)
10
- match_structure actual, resource.attributes, @count, @method
11
- rescue RSpec::Expectations::ExpectationNotMetError => e
12
- @error = e.message
13
- false
14
- end
15
- end
16
-
17
- failure_message_for_should do
18
- @error
19
- end
20
-
21
- def method_missing(method, *args, &block)
22
- if defined?(@method)
23
- super
24
- else
25
- @method = method
26
- end
27
- self
28
- end
29
- end
30
- end
@@ -1,5 +0,0 @@
1
- shared_context 'json' do
2
- let(:json) { JSON last_response.body }
3
- let(:root_key) { json.keys.reject { |k| k == 'meta' }.first }
4
- let(:json_root) { json[root_key] }
5
- end
@@ -1,7 +0,0 @@
1
- shared_examples_for 'a list of' do |type, count|
2
- include_context 'json'
3
-
4
- it "returns a list of #{type}" do
5
- expect(json_root).to match_structure_of(type).with(count).method_missing(type)
6
- end
7
- end