restspec 0.0.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.
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