restspec 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +21 -0
  3. data/.gitignore +23 -0
  4. data/.rspec +4 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +6 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +188 -0
  9. data/ROADMAP.md +11 -0
  10. data/Rakefile +20 -0
  11. data/bin/restspec +54 -0
  12. data/bin/templates/Gemfile +3 -0
  13. data/bin/templates/custom_macros.rb +3 -0
  14. data/bin/templates/restspec_config.rb +10 -0
  15. data/bin/templates/spec_helper.rb +19 -0
  16. data/docs/endpoints.md +200 -0
  17. data/docs/helpers.md +40 -0
  18. data/docs/macros.md +140 -0
  19. data/docs/matchers.md +38 -0
  20. data/docs/schemas.md +28 -0
  21. data/docs/tutorial.md +477 -0
  22. data/docs/types.md +134 -0
  23. data/examples/store-api-tests/.rspec +3 -0
  24. data/examples/store-api-tests/Gemfile +4 -0
  25. data/examples/store-api-tests/Gemfile.lock +70 -0
  26. data/examples/store-api-tests/spec/api/category_spec.rb +23 -0
  27. data/examples/store-api-tests/spec/api/product_spec.rb +55 -0
  28. data/examples/store-api-tests/spec/api/restspec/endpoints.rb +39 -0
  29. data/examples/store-api-tests/spec/api/restspec/requirements.rb +0 -0
  30. data/examples/store-api-tests/spec/api/restspec/restspec_config.rb +6 -0
  31. data/examples/store-api-tests/spec/api/restspec/schemas.rb +11 -0
  32. data/examples/store-api-tests/spec/spec_helper.rb +19 -0
  33. data/examples/store-api-tests/spec/support/custom_macros.rb +3 -0
  34. data/examples/store-api-tests/spec/support/custom_matchers.rb +0 -0
  35. data/examples/store-api/.editorconfig +24 -0
  36. data/examples/store-api/.rbenv-vars.example +3 -0
  37. data/examples/store-api/.rspec +4 -0
  38. data/examples/store-api/.ruby-version +1 -0
  39. data/examples/store-api/Gemfile +58 -0
  40. data/examples/store-api/Gemfile.lock +216 -0
  41. data/examples/store-api/Guardfile +39 -0
  42. data/examples/store-api/README.md +1 -0
  43. data/examples/store-api/Rakefile +6 -0
  44. data/examples/store-api/app/assets/images/.keep +0 -0
  45. data/examples/store-api/app/assets/javascripts/application.js +16 -0
  46. data/examples/store-api/app/assets/javascripts/categories.js.coffee +3 -0
  47. data/examples/store-api/app/assets/javascripts/products.js.coffee +3 -0
  48. data/examples/store-api/app/assets/stylesheets/application.css +15 -0
  49. data/examples/store-api/app/assets/stylesheets/categories.css.scss +3 -0
  50. data/examples/store-api/app/assets/stylesheets/products.css.scss +3 -0
  51. data/examples/store-api/app/assets/stylesheets/scaffolds.css.scss +69 -0
  52. data/examples/store-api/app/controllers/application_controller.rb +5 -0
  53. data/examples/store-api/app/controllers/categories_controller.rb +74 -0
  54. data/examples/store-api/app/controllers/concerns/.keep +0 -0
  55. data/examples/store-api/app/controllers/products_controller.rb +74 -0
  56. data/examples/store-api/app/helpers/application_helper.rb +2 -0
  57. data/examples/store-api/app/helpers/categories_helper.rb +2 -0
  58. data/examples/store-api/app/helpers/products_helper.rb +2 -0
  59. data/examples/store-api/app/mailers/.keep +0 -0
  60. data/examples/store-api/app/models/.keep +0 -0
  61. data/examples/store-api/app/models/category.rb +2 -0
  62. data/examples/store-api/app/models/concerns/.keep +0 -0
  63. data/examples/store-api/app/models/product.rb +3 -0
  64. data/examples/store-api/app/views/categories/_form.html.erb +21 -0
  65. data/examples/store-api/app/views/categories/edit.html.erb +6 -0
  66. data/examples/store-api/app/views/categories/index.html.erb +25 -0
  67. data/examples/store-api/app/views/categories/index.json.jbuilder +4 -0
  68. data/examples/store-api/app/views/categories/new.html.erb +5 -0
  69. data/examples/store-api/app/views/categories/show.html.erb +9 -0
  70. data/examples/store-api/app/views/categories/show.json.jbuilder +1 -0
  71. data/examples/store-api/app/views/layouts/application.html.erb +14 -0
  72. data/examples/store-api/app/views/products/_form.html.erb +29 -0
  73. data/examples/store-api/app/views/products/edit.html.erb +6 -0
  74. data/examples/store-api/app/views/products/index.html.erb +29 -0
  75. data/examples/store-api/app/views/products/index.json.jbuilder +4 -0
  76. data/examples/store-api/app/views/products/new.html.erb +5 -0
  77. data/examples/store-api/app/views/products/show.html.erb +19 -0
  78. data/examples/store-api/app/views/products/show.json.jbuilder +6 -0
  79. data/examples/store-api/bin/bundle +3 -0
  80. data/examples/store-api/bin/guard +16 -0
  81. data/examples/store-api/bin/rails +8 -0
  82. data/examples/store-api/bin/rake +8 -0
  83. data/examples/store-api/bin/spring +18 -0
  84. data/examples/store-api/config.ru +4 -0
  85. data/examples/store-api/config/application.rb +30 -0
  86. data/examples/store-api/config/boot.rb +4 -0
  87. data/examples/store-api/config/database.yml +25 -0
  88. data/examples/store-api/config/environment.rb +5 -0
  89. data/examples/store-api/config/environments/development.rb +37 -0
  90. data/examples/store-api/config/environments/production.rb +78 -0
  91. data/examples/store-api/config/environments/test.rb +39 -0
  92. data/examples/store-api/config/initializers/assets.rb +8 -0
  93. data/examples/store-api/config/initializers/backtrace_silencers.rb +7 -0
  94. data/examples/store-api/config/initializers/cookies_serializer.rb +3 -0
  95. data/examples/store-api/config/initializers/filter_parameter_logging.rb +4 -0
  96. data/examples/store-api/config/initializers/inflections.rb +16 -0
  97. data/examples/store-api/config/initializers/mime_types.rb +4 -0
  98. data/examples/store-api/config/initializers/session_store.rb +3 -0
  99. data/examples/store-api/config/initializers/wrap_parameters.rb +14 -0
  100. data/examples/store-api/config/locales/en.yml +23 -0
  101. data/examples/store-api/config/routes.rb +59 -0
  102. data/examples/store-api/config/secrets.yml +22 -0
  103. data/examples/store-api/db/migrate/20141205154816_create_products.rb +11 -0
  104. data/examples/store-api/db/migrate/20141205171104_create_categories.rb +9 -0
  105. data/examples/store-api/db/migrate/20141205171140_add_category_id_to_products.rb +5 -0
  106. data/examples/store-api/db/schema.rb +31 -0
  107. data/examples/store-api/db/seeds.rb +7 -0
  108. data/examples/store-api/lib/assets/.keep +0 -0
  109. data/examples/store-api/lib/tasks/.keep +0 -0
  110. data/examples/store-api/log/.keep +0 -0
  111. data/examples/store-api/public/404.html +67 -0
  112. data/examples/store-api/public/422.html +67 -0
  113. data/examples/store-api/public/500.html +66 -0
  114. data/examples/store-api/public/favicon.ico +0 -0
  115. data/examples/store-api/public/robots.txt +5 -0
  116. data/examples/store-api/spec/controllers/categories_controller_spec.rb +159 -0
  117. data/examples/store-api/spec/controllers/products_controller_spec.rb +159 -0
  118. data/examples/store-api/spec/factories/categories.rb +6 -0
  119. data/examples/store-api/spec/factories/products.rb +8 -0
  120. data/examples/store-api/spec/helpers/categories_helper_spec.rb +15 -0
  121. data/examples/store-api/spec/helpers/products_helper_spec.rb +15 -0
  122. data/examples/store-api/spec/models/category_spec.rb +5 -0
  123. data/examples/store-api/spec/models/product_spec.rb +5 -0
  124. data/examples/store-api/spec/rails_helper.rb +50 -0
  125. data/examples/store-api/spec/requests/categories_spec.rb +10 -0
  126. data/examples/store-api/spec/requests/products_spec.rb +10 -0
  127. data/examples/store-api/spec/routing/categories_routing_spec.rb +35 -0
  128. data/examples/store-api/spec/routing/products_routing_spec.rb +35 -0
  129. data/examples/store-api/spec/spec_helper.rb +85 -0
  130. data/examples/store-api/spec/views/categories/edit.html.erb_spec.rb +18 -0
  131. data/examples/store-api/spec/views/categories/index.html.erb_spec.rb +19 -0
  132. data/examples/store-api/spec/views/categories/new.html.erb_spec.rb +18 -0
  133. data/examples/store-api/spec/views/categories/show.html.erb_spec.rb +14 -0
  134. data/examples/store-api/spec/views/products/edit.html.erb_spec.rb +24 -0
  135. data/examples/store-api/spec/views/products/index.html.erb_spec.rb +25 -0
  136. data/examples/store-api/spec/views/products/new.html.erb_spec.rb +24 -0
  137. data/examples/store-api/spec/views/products/show.html.erb_spec.rb +18 -0
  138. data/examples/store-api/vendor/assets/javascripts/.keep +0 -0
  139. data/examples/store-api/vendor/assets/stylesheets/.keep +0 -0
  140. data/lib/restspec.rb +38 -0
  141. data/lib/restspec/configuration.rb +43 -0
  142. data/lib/restspec/endpoints/dsl.rb +142 -0
  143. data/lib/restspec/endpoints/endpoint.rb +135 -0
  144. data/lib/restspec/endpoints/namespace.rb +89 -0
  145. data/lib/restspec/endpoints/network.rb +39 -0
  146. data/lib/restspec/endpoints/request.rb +11 -0
  147. data/lib/restspec/endpoints/response.rb +53 -0
  148. data/lib/restspec/requirements/dsl.rb +10 -0
  149. data/lib/restspec/requirements/requirement.rb +59 -0
  150. data/lib/restspec/rspec/api_helpers.rb +64 -0
  151. data/lib/restspec/rspec/api_macros.rb +126 -0
  152. data/lib/restspec/rspec/extras.rb +2 -0
  153. data/lib/restspec/rspec/matchers/api_matchers.rb +6 -0
  154. data/lib/restspec/rspec/matchers/be_like_schema.rb +18 -0
  155. data/lib/restspec/rspec/matchers/be_like_schema_array.rb +18 -0
  156. data/lib/restspec/rspec/matchers/have_header.rb +47 -0
  157. data/lib/restspec/rspec/matchers/have_status.rb +17 -0
  158. data/lib/restspec/rspec/matchers/include_where.rb +14 -0
  159. data/lib/restspec/rspec/shared_examples.rb +12 -0
  160. data/lib/restspec/schema/attribute.rb +31 -0
  161. data/lib/restspec/schema/attribute_example.rb +21 -0
  162. data/lib/restspec/schema/checker.rb +73 -0
  163. data/lib/restspec/schema/dsl.rb +36 -0
  164. data/lib/restspec/schema/schema.rb +21 -0
  165. data/lib/restspec/schema/schema_example.rb +28 -0
  166. data/lib/restspec/schema/types.rb +35 -0
  167. data/lib/restspec/schema/types/array_type.rb +34 -0
  168. data/lib/restspec/schema/types/basic_type.rb +35 -0
  169. data/lib/restspec/schema/types/boolean_type.rb +11 -0
  170. data/lib/restspec/schema/types/decimal_string_type.rb +32 -0
  171. data/lib/restspec/schema/types/decimal_type.rb +14 -0
  172. data/lib/restspec/schema/types/embedded_schema_type.rb +28 -0
  173. data/lib/restspec/schema/types/hash_type.rb +25 -0
  174. data/lib/restspec/schema/types/integer_type.rb +11 -0
  175. data/lib/restspec/schema/types/null_type.rb +11 -0
  176. data/lib/restspec/schema/types/one_of_type.rb +21 -0
  177. data/lib/restspec/schema/types/schema_id_type.rb +88 -0
  178. data/lib/restspec/schema/types/string_type.rb +11 -0
  179. data/lib/restspec/shortcuts.rb +8 -0
  180. data/lib/restspec/stores/endpoint_store.rb +25 -0
  181. data/lib/restspec/stores/namespace_store.rb +20 -0
  182. data/lib/restspec/stores/schema_store.rb +19 -0
  183. data/lib/restspec/values/status_code.rb +13 -0
  184. data/lib/restspec/values/super_hash.rb +12 -0
  185. data/lib/restspec/version.rb +3 -0
  186. data/restspec.gemspec +37 -0
  187. data/spec/restspec/endpoints/dsl_spec.rb +269 -0
  188. data/spec/restspec/endpoints/endpoint_spec.rb +146 -0
  189. data/spec/restspec/endpoints/namespace_spec.rb +143 -0
  190. data/spec/restspec/endpoints/response_spec.rb +49 -0
  191. data/spec/restspec/schema/attribute_example_spec.rb +35 -0
  192. data/spec/restspec/schema/dsl_spec.rb +78 -0
  193. data/spec/restspec/schema/schema_example_spec.rb +40 -0
  194. data/spec/restspec/schema/schema_spec.rb +11 -0
  195. data/spec/restspec/schema/types/array_type_spec.rb +56 -0
  196. data/spec/restspec/schema/types/basic_type_spec.rb +62 -0
  197. data/spec/restspec/schema/types/boolean_type_spec.rb +26 -0
  198. data/spec/restspec/schema/types/null_type_spec.rb +25 -0
  199. data/spec/restspec/schema/types/string_type_spec.rb +26 -0
  200. data/spec/restspec/values/status_code_spec.rb +13 -0
  201. data/spec/spec_helper.rb +23 -0
  202. metadata +484 -0
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+
3
+ include Restspec::Endpoints
4
+
5
+ describe Endpoint do
6
+ let(:endpoint) { Endpoint.new(:endpoint) }
7
+ subject { endpoint }
8
+
9
+ describe '#full_name' do
10
+ context 'standalone' do
11
+ its(:full_name) { should eq('endpoint') }
12
+ end
13
+
14
+ context 'inside a namespace' do
15
+ before { endpoint.namespace = Namespace.new(:namespace) }
16
+ its(:full_name) { should eq('namespace/endpoint') }
17
+ end
18
+ end
19
+
20
+ describe '#execute_once' do
21
+ before do
22
+ allow(endpoint).to receive(:execute).and_return(true)
23
+ end
24
+
25
+ let(:body) { double }
26
+ let(:url_params) { double }
27
+ let(:query_params) { double }
28
+
29
+ it 'just calls execute once' do
30
+ 4.times { endpoint.execute_once }
31
+ expect(endpoint).to have_received(:execute).once
32
+ end
33
+
34
+ it 'pass body, url_params and query_params to execute' do
35
+ endpoint.execute_once(body: body, url_params: url_params, query_params: query_params)
36
+ expect(endpoint).to have_received(:execute).with(
37
+ body: body, url_params: url_params, query_params: query_params
38
+ )
39
+ end
40
+
41
+ it 'executes :before param before executing' do
42
+ before_lambda = ->{ }
43
+ allow(before_lambda).to receive(:call)
44
+ endpoint.execute_once(before: before_lambda)
45
+
46
+ expect(before_lambda).to have_received(:call).ordered
47
+ expect(endpoint).to have_received(:execute).ordered
48
+ end
49
+ end
50
+
51
+ describe '#execute' do
52
+ let(:request) { OpenStruct.new }
53
+ let(:response) { OpenStruct.new }
54
+
55
+ before do
56
+ endpoint.method = :get
57
+ endpoint.path = '/home'
58
+
59
+ allow(Request).to receive(:new).and_return(request)
60
+ allow(Network).to receive(:request).and_return(response)
61
+ end
62
+
63
+ it 'tells the Network to request with a Request object containing everything' do
64
+ endpoint.execute
65
+ expect(Request).to have_received(:new).with(:get, '/home', {}, {})
66
+ end
67
+ end
68
+
69
+ describe '#schema_name' do
70
+ context 'stadalone' do
71
+ before { endpoint.schema_name = :schema_name }
72
+ its(:schema_name) { should eq(:schema_name) }
73
+ end
74
+
75
+ context 'inside a namespace' do
76
+ let(:namespace) do
77
+ Namespace.new(:namespace).tap do |ns|
78
+ ns.schema_name = :ns_schema_name
79
+ end
80
+ end
81
+
82
+ before { endpoint.namespace = namespace }
83
+
84
+ context 'without a single schema name' do
85
+ its(:schema_name) { should eq(:ns_schema_name) }
86
+ end
87
+
88
+ context 'with a single schema name' do
89
+ before { endpoint.schema_name = :single_schema_name }
90
+ its(:schema_name) { should eq(:single_schema_name) }
91
+ end
92
+ end
93
+ end
94
+
95
+ describe '#schema' do
96
+ let(:schema) { double }
97
+
98
+ before do
99
+ endpoint.schema_name = :single_schema_name
100
+ allow(Restspec::SchemaStore).to receive(:get).and_return(schema)
101
+ allow(schema).to receive(:extend_with) { schema }
102
+ end
103
+
104
+ it 'tells the Restspec::Schema::Finder to find a schema' do
105
+ found_schema = endpoint.schema
106
+ expect(Restspec::SchemaStore).to have_received(:get).with(:single_schema_name)
107
+ expect(found_schema).to eq(schema)
108
+ end
109
+ end
110
+
111
+ describe '#url_params' do
112
+ before do
113
+ endpoint.add_url_param_block(:mono) { 'mono' }
114
+ endpoint.add_url_param_block(:xyz) { 'xyz' }
115
+ end
116
+
117
+ it 'is the list of execute url param blocks in a hash with string keys' do
118
+ expect(endpoint.url_params).to eq({
119
+ 'mono' => 'mono',
120
+ 'xyz' => 'xyz'
121
+ })
122
+ end
123
+ end
124
+
125
+ describe '#full_path' do
126
+ before { endpoint.path = '/full_path' }
127
+
128
+ context 'standalone' do
129
+ its(:full_path) { should eq('/full_path') }
130
+ end
131
+
132
+ context 'inside an anonymous namespace (a member or collection block)' do
133
+ let(:member_namespace) { Namespace.create }
134
+ let(:top_level_namespace) { Namespace.create('top_level') }
135
+
136
+ before do
137
+ top_level_namespace.base_path = '/monkeys'
138
+ member_namespace.base_path = '/:id'
139
+ member_namespace.parent_namespace = top_level_namespace
140
+ endpoint.namespace = member_namespace
141
+ end
142
+
143
+ its(:full_path) { should eq('/monkeys/:id/full_path') }
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,143 @@
1
+ require 'spec_helper'
2
+
3
+ include Restspec::Endpoints
4
+
5
+ describe Namespace do
6
+ let(:namespace) { Namespace.new(:namespace) }
7
+
8
+ describe '.create (and #anonymous?)' do
9
+ it 'stores the namespace in Restspec::NamespaceStore' do
10
+ namespace = Namespace.create(:name)
11
+ expect(Restspec::NamespaceStore.get(:name)).to eq(namespace)
12
+ end
13
+
14
+ context 'without arguments' do
15
+ it 'creates an anonymous namespace' do
16
+ namespace = Namespace.create
17
+ expect(namespace).to be_anonymous
18
+ end
19
+ end
20
+ end
21
+
22
+ describe '#add_anonymous_children_namespace' do
23
+ it 'adds one object to #children_namespaces' do
24
+ expect { namespace.add_anonymous_children_namespace }.to change {
25
+ namespace.children_namespaces.size
26
+ }.by(1)
27
+ end
28
+ end
29
+
30
+ describe '#add_endpoint' do
31
+ let(:endpoint) { OpenStruct.new }
32
+
33
+ it 'adds the endpoint to #endpoints' do
34
+ expect { namespace.add_endpoint(endpoint) }.to change {
35
+ namespace.endpoints.size
36
+ }.by(1)
37
+ end
38
+
39
+ it 'sets the #namespace attribute of the endpoint to this namespace' do
40
+ expect { namespace.add_endpoint(endpoint) }.to change {
41
+ endpoint.namespace
42
+ }.from(nil).to(namespace)
43
+ end
44
+ end
45
+
46
+ describe '#get_endpoint' do
47
+ let(:endpoint_name) { 'name' }
48
+ let(:endpoint) { OpenStruct.new(name: endpoint_name) }
49
+
50
+ context 'when the endpoint was not inserted' do
51
+ it 'is nil' do
52
+ expect(namespace.get_endpoint(endpoint_name)).to be_nil
53
+ end
54
+ end
55
+
56
+ context 'when the endpoint is inside the namespace' do
57
+ before do
58
+ namespace.add_endpoint(endpoint)
59
+ end
60
+
61
+ it 'returns the endpoint' do
62
+ expect(namespace.get_endpoint(endpoint_name)).to eq(endpoint)
63
+ end
64
+ end
65
+
66
+ context 'when the endpoint is inside a child namespace' do
67
+ before do
68
+ child_namespace = namespace.add_anonymous_children_namespace
69
+ child_namespace.add_endpoint(endpoint)
70
+ end
71
+
72
+ it 'returns the endpoint' do
73
+ expect(namespace.get_endpoint(endpoint_name)).to eq(endpoint)
74
+ end
75
+ end
76
+ end
77
+
78
+ describe '#top_level_namespace?' do
79
+ subject { used_namespace.top_level_namespace? }
80
+
81
+ context 'with a child namespace' do
82
+ let(:used_namespace) { namespace.add_anonymous_children_namespace }
83
+ it { should eq(false) }
84
+ end
85
+
86
+ context 'with a normal namespace' do
87
+ let(:used_namespace) { namespace }
88
+ it { should eq(true) }
89
+ end
90
+ end
91
+
92
+ describe '#full_base_path' do
93
+ context 'for an anonymous namespace with parent' do
94
+ let(:grand_parent) { Namespace.create('ns') }
95
+ let(:parent) { grand_parent.add_anonymous_children_namespace }
96
+ let(:namespace) { parent.add_anonymous_children_namespace }
97
+
98
+ before do
99
+ grand_parent.base_path = '/monkeys'
100
+ parent.base_path = '/:id'
101
+ namespace.base_path = '/notifications'
102
+ end
103
+
104
+ it 'is equal to the base_path plus the full_base_path of the parent' do
105
+ expect(namespace.full_base_path).to eq('/monkeys/:id/notifications')
106
+ end
107
+ end
108
+
109
+ context 'for a named namespace without parent' do
110
+ let(:namespace) { Namespace.create('ns') }
111
+ before { namespace.base_path = '/ns' }
112
+ it 'is equal to the base_path' do
113
+ expect(namespace.full_base_path).to eq('/ns')
114
+ end
115
+ end
116
+ end
117
+
118
+ describe '#name' do
119
+ context 'for an anonymous namespace with parent' do
120
+ let(:grand_parent) { Namespace.create('ns') }
121
+ let(:parent) { Namespace.create('ns2').tap { |ns| ns.parent_namespace = grand_parent } }
122
+ let(:namespace) { parent.add_anonymous_children_namespace }
123
+
124
+ it 'is equal to the names joint by /' do
125
+ expect(namespace.name).to eq('ns/ns2')
126
+ end
127
+
128
+ context 'if the namespace has a name too' do
129
+ let(:namespace) { Namespace.create('ns3').tap { |ns| ns.parent_namespace = parent } }
130
+ it 'the name is put at the end' do
131
+ expect(namespace.name).to eq('ns/ns2/ns3')
132
+ end
133
+ end
134
+ end
135
+
136
+ context 'for a named namespace without parent' do
137
+ let(:namespace) { Namespace.create('ns') }
138
+ it 'is equal to the name alone' do
139
+ expect(namespace.name).to eq('ns')
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ include Restspec::Endpoints
4
+ SuperHash = Restspec::Values::SuperHash
5
+
6
+ describe Response do
7
+ let(:response) { Response.new(200, {}, body) }
8
+
9
+ describe '#read_body' do
10
+ subject { response.read_body }
11
+
12
+ context 'when the body is a scalar' do
13
+ let(:body) { 'Hello' }
14
+ it { should be_kind_of(String) }
15
+ it { should eq(body) }
16
+ end
17
+
18
+ context 'when the body is a hash of scalar values' do
19
+ let(:body) { { x: 1, y: 'string', z: true }.to_json }
20
+ it { should be_kind_of(SuperHash) }
21
+ end
22
+
23
+ context 'when the body is an array of scalar values' do
24
+ let(:info) { [1, 'string', true] }
25
+ let(:body) { info.to_json }
26
+ it { should be_kind_of(Array) }
27
+ it { should eq(info) }
28
+ end
29
+
30
+ context 'when the body is an array of hashes' do
31
+ let(:info) { [{x: 1}, {x: 2}, {x: 3}] }
32
+ let(:body) { info.to_json }
33
+ it { should be_kind_of(Array) }
34
+ it { should eq(info.as_json) }
35
+ end
36
+
37
+ context 'when the body is a hash of array elements' do
38
+ let(:body) { { animals: [ { name: 'Lion' }, { name: 'Elephant' } ], number_of_animals: 2 }.to_json }
39
+ it { should be_kind_of(SuperHash) }
40
+ it { should have_key(:animals) }
41
+
42
+ it 'includes an array of SuperHashes' do
43
+ subject.animals.each do |animal|
44
+ expect(animal).to be_kind_of(SuperHash)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ include Restspec::Schema
4
+
5
+ describe AttributeExample do
6
+ let(:type) { Types::StringType.new }
7
+ let(:attribute_options) { Hash.new }
8
+ let(:attribute) { Attribute.new(:name, type, attribute_options) }
9
+ let(:attribute_example) { AttributeExample.new(attribute) }
10
+
11
+ describe '#value' do
12
+ subject { attribute_example.value }
13
+
14
+ context 'when the attribute has an example value specified in him' do
15
+ let(:attribute_options) { { example: 'mono' } }
16
+ it { should eq('mono') }
17
+ end
18
+
19
+ context 'when the attribute has an example lambda specified in him' do
20
+ let(:attribute_options) { { example: ->{ 'mono' } } }
21
+ it { should eq('mono') }
22
+ end
23
+
24
+ context 'when attribute doesnt have an example option' do
25
+ before { allow(type).to receive(:example_for).and_return('type example') }
26
+
27
+ it { should eq('type example') }
28
+
29
+ it 'calls the example_for method of the type' do
30
+ subject
31
+ expect(type).to have_received(:example_for).with(attribute)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ include Restspec::Schema
4
+
5
+ describe DSL do
6
+ let(:dsl) { DSL.new }
7
+
8
+ describe '#schema' do
9
+ let(:single_dsl) { double }
10
+ let(:schema) { double(name: 'name') }
11
+
12
+ before do
13
+ allow(SingleSchemaDSL).to receive(:new).and_return(single_dsl)
14
+ allow(single_dsl).to receive(:instance_eval).and_return(single_dsl)
15
+ allow(single_dsl).to receive(:schema).and_return(schema)
16
+ end
17
+
18
+ it 'creates a SingleSchemaDSL with the given name' do
19
+ dsl.schema('name') { }
20
+ expect(SingleSchemaDSL).to have_received(:new)
21
+ end
22
+
23
+ it 'store the schema into the SchemaStore' do
24
+ dsl.schema('name') { }
25
+ expect(Restspec::SchemaStore.get('name')).to be_present
26
+ end
27
+ end
28
+ end
29
+
30
+ describe SingleSchemaDSL do
31
+ let(:dsl) { SingleSchemaDSL.new(name) }
32
+ let(:name) { 'name' }
33
+
34
+ describe '#initialize' do
35
+ it 'makes the dsl to return a schema with the given name' do
36
+ expect(dsl.schema.name).to eq(name)
37
+ end
38
+ end
39
+
40
+ describe '#attribute' do
41
+ let(:type_instance) { dsl.string }
42
+
43
+ it 'creates an attribute with name and type' do
44
+ dsl.attribute('attr_name', type_instance, {})
45
+
46
+ expect(dsl.schema.attributes.size).to eq(1)
47
+
48
+ attribute = dsl.schema.attributes.values.first
49
+
50
+ expect(attribute.name).to eq('attr_name')
51
+ expect(attribute.type).to eq(type_instance)
52
+ end
53
+
54
+ context 'when the :for option is just for checks' do
55
+ let(:attribute) { dsl.attribute('attr_name', type_instance, for: [:checks]) }
56
+
57
+ it 'is not allowed to generate examples' do
58
+ expect(attribute.can_generate_examples?).to eq(false)
59
+ end
60
+
61
+ it 'is allowed to run in validations' do
62
+ expect(attribute.can_be_checked?).to eq(true)
63
+ end
64
+ end
65
+
66
+ context 'when the :for option is just for examples' do
67
+ let(:attribute) { dsl.attribute('attr_name', type_instance, for: [:examples]) }
68
+
69
+ it 'is allowed to generate examples' do
70
+ expect(attribute.can_generate_examples?).to eq(true)
71
+ end
72
+
73
+ it 'is not allowed to run in validations' do
74
+ expect(attribute.can_be_checked?).to eq(false)
75
+ end
76
+ end
77
+ end
78
+ end