reqcord 0.1.1 → 0.1.2

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 (223) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/Gemfile +5 -0
  4. data/README.md +13 -0
  5. data/gemfiles/rails_7.1.gemfile +13 -0
  6. data/gemfiles/rails_7.2.gemfile +13 -0
  7. data/gemfiles/rails_8.0.gemfile +13 -0
  8. data/gemfiles/rails_8.1.gemfile +13 -0
  9. data/lib/reqcord/version.rb +1 -1
  10. data/reqcord.gemspec +18 -4
  11. metadata +65 -217
  12. data/.gitignore +0 -8
  13. data/Gemfile.lock +0 -171
  14. data/examples/complex-spec-app/.rspec +0 -1
  15. data/examples/complex-spec-app/README.md +0 -21
  16. data/examples/complex-spec-app/app.rb +0 -363
  17. data/examples/complex-spec-app/docs/api/README.md +0 -104
  18. data/examples/complex-spec-app/docs/api/api/v1/admin/products/create.md +0 -117
  19. data/examples/complex-spec-app/docs/api/api/v1/admin/products/destroy.md +0 -51
  20. data/examples/complex-spec-app/docs/api/api/v1/admin/products/index.md +0 -11
  21. data/examples/complex-spec-app/docs/api/api/v1/admin/products/list.md +0 -106
  22. data/examples/complex-spec-app/docs/api/api/v1/auth/index.md +0 -9
  23. data/examples/complex-spec-app/docs/api/api/v1/auth/login.md +0 -76
  24. data/examples/complex-spec-app/docs/api/api/v1/cart-items/create.md +0 -91
  25. data/examples/complex-spec-app/docs/api/api/v1/cart-items/destroy.md +0 -51
  26. data/examples/complex-spec-app/docs/api/api/v1/cart-items/index.md +0 -10
  27. data/examples/complex-spec-app/docs/api/api/v1/carts/checkout.md +0 -102
  28. data/examples/complex-spec-app/docs/api/api/v1/carts/index.md +0 -10
  29. data/examples/complex-spec-app/docs/api/api/v1/carts/show.md +0 -73
  30. data/examples/complex-spec-app/docs/api/api/v1/home/index.md +0 -9
  31. data/examples/complex-spec-app/docs/api/api/v1/home/list.md +0 -47
  32. data/examples/complex-spec-app/docs/api/api/v1/notes/create.md +0 -94
  33. data/examples/complex-spec-app/docs/api/api/v1/notes/index.md +0 -10
  34. data/examples/complex-spec-app/docs/api/api/v1/notes/list.md +0 -61
  35. data/examples/complex-spec-app/docs/api/api/v1/orders/cancel.md +0 -69
  36. data/examples/complex-spec-app/docs/api/api/v1/orders/create.md +0 -150
  37. data/examples/complex-spec-app/docs/api/api/v1/orders/destroy.md +0 -37
  38. data/examples/complex-spec-app/docs/api/api/v1/orders/index.md +0 -13
  39. data/examples/complex-spec-app/docs/api/api/v1/orders/list.md +0 -78
  40. data/examples/complex-spec-app/docs/api/api/v1/orders/show.md +0 -83
  41. data/examples/complex-spec-app/docs/api/api/v1/products/index.md +0 -11
  42. data/examples/complex-spec-app/docs/api/api/v1/products/list.md +0 -83
  43. data/examples/complex-spec-app/docs/api/api/v1/products/search.md +0 -88
  44. data/examples/complex-spec-app/docs/api/api/v1/products/show.md +0 -71
  45. data/examples/complex-spec-app/docs/api/api/v1/profiles/index.md +0 -10
  46. data/examples/complex-spec-app/docs/api/api/v1/profiles/show.md +0 -61
  47. data/examples/complex-spec-app/docs/api/api/v1/profiles/update.md +0 -91
  48. data/examples/complex-spec-app/docs/api/api/v2/products/index.md +0 -9
  49. data/examples/complex-spec-app/docs/api/api/v2/products/list.md +0 -77
  50. data/examples/complex-spec-app/docs/api/curl/api/v1/admin/products/create.sh +0 -18
  51. data/examples/complex-spec-app/docs/api/curl/api/v1/admin/products/destroy.sh +0 -9
  52. data/examples/complex-spec-app/docs/api/curl/api/v1/admin/products/list.sh +0 -9
  53. data/examples/complex-spec-app/docs/api/curl/api/v1/auth/login.sh +0 -9
  54. data/examples/complex-spec-app/docs/api/curl/api/v1/cart-items/create.sh +0 -16
  55. data/examples/complex-spec-app/docs/api/curl/api/v1/cart-items/destroy.sh +0 -9
  56. data/examples/complex-spec-app/docs/api/curl/api/v1/carts/checkout.sh +0 -13
  57. data/examples/complex-spec-app/docs/api/curl/api/v1/carts/show.sh +0 -9
  58. data/examples/complex-spec-app/docs/api/curl/api/v1/home/list.sh +0 -8
  59. data/examples/complex-spec-app/docs/api/curl/api/v1/notes/create.sh +0 -15
  60. data/examples/complex-spec-app/docs/api/curl/api/v1/notes/list.sh +0 -9
  61. data/examples/complex-spec-app/docs/api/curl/api/v1/orders/cancel.sh +0 -9
  62. data/examples/complex-spec-app/docs/api/curl/api/v1/orders/create.sh +0 -29
  63. data/examples/complex-spec-app/docs/api/curl/api/v1/orders/destroy.sh +0 -9
  64. data/examples/complex-spec-app/docs/api/curl/api/v1/orders/list.sh +0 -9
  65. data/examples/complex-spec-app/docs/api/curl/api/v1/orders/show.sh +0 -9
  66. data/examples/complex-spec-app/docs/api/curl/api/v1/products/list.sh +0 -8
  67. data/examples/complex-spec-app/docs/api/curl/api/v1/products/search.sh +0 -8
  68. data/examples/complex-spec-app/docs/api/curl/api/v1/products/show.sh +0 -8
  69. data/examples/complex-spec-app/docs/api/curl/api/v1/profiles/show.sh +0 -9
  70. data/examples/complex-spec-app/docs/api/curl/api/v1/profiles/update.sh +0 -16
  71. data/examples/complex-spec-app/docs/api/curl/api/v2/products/list.sh +0 -8
  72. data/examples/complex-spec-app/docs/api/dataset.json +0 -5116
  73. data/examples/complex-spec-app/docs/api/postman/collection.json +0 -2519
  74. data/examples/complex-spec-app/generate.rb +0 -14
  75. data/examples/complex-spec-app/reqcord.yml +0 -28
  76. data/examples/complex-spec-app/spec/requests/admin_spec.rb +0 -67
  77. data/examples/complex-spec-app/spec/requests/cart_spec.rb +0 -61
  78. data/examples/complex-spec-app/spec/requests/home_and_auth_spec.rb +0 -49
  79. data/examples/complex-spec-app/spec/requests/orders_spec.rb +0 -124
  80. data/examples/complex-spec-app/spec/requests/products_spec.rb +0 -65
  81. data/examples/complex-spec-app/spec/spec_helper.rb +0 -17
  82. data/examples/complex-test-app/README.md +0 -40
  83. data/examples/complex-test-app/app.rb +0 -384
  84. data/examples/complex-test-app/docs/api/README.md +0 -104
  85. data/examples/complex-test-app/docs/api/api/v1/admin/products/create.md +0 -117
  86. data/examples/complex-test-app/docs/api/api/v1/admin/products/destroy.md +0 -51
  87. data/examples/complex-test-app/docs/api/api/v1/admin/products/index.md +0 -11
  88. data/examples/complex-test-app/docs/api/api/v1/admin/products/list.md +0 -106
  89. data/examples/complex-test-app/docs/api/api/v1/auth/index.md +0 -9
  90. data/examples/complex-test-app/docs/api/api/v1/auth/login.md +0 -76
  91. data/examples/complex-test-app/docs/api/api/v1/cart-items/create.md +0 -91
  92. data/examples/complex-test-app/docs/api/api/v1/cart-items/destroy.md +0 -51
  93. data/examples/complex-test-app/docs/api/api/v1/cart-items/index.md +0 -10
  94. data/examples/complex-test-app/docs/api/api/v1/carts/checkout.md +0 -102
  95. data/examples/complex-test-app/docs/api/api/v1/carts/index.md +0 -10
  96. data/examples/complex-test-app/docs/api/api/v1/carts/show.md +0 -73
  97. data/examples/complex-test-app/docs/api/api/v1/home/index.md +0 -9
  98. data/examples/complex-test-app/docs/api/api/v1/home/list.md +0 -47
  99. data/examples/complex-test-app/docs/api/api/v1/notes/create.md +0 -94
  100. data/examples/complex-test-app/docs/api/api/v1/notes/index.md +0 -10
  101. data/examples/complex-test-app/docs/api/api/v1/notes/list.md +0 -61
  102. data/examples/complex-test-app/docs/api/api/v1/orders/cancel.md +0 -69
  103. data/examples/complex-test-app/docs/api/api/v1/orders/create.md +0 -150
  104. data/examples/complex-test-app/docs/api/api/v1/orders/destroy.md +0 -37
  105. data/examples/complex-test-app/docs/api/api/v1/orders/index.md +0 -13
  106. data/examples/complex-test-app/docs/api/api/v1/orders/list.md +0 -71
  107. data/examples/complex-test-app/docs/api/api/v1/orders/show.md +0 -83
  108. data/examples/complex-test-app/docs/api/api/v1/products/index.md +0 -11
  109. data/examples/complex-test-app/docs/api/api/v1/products/list.md +0 -83
  110. data/examples/complex-test-app/docs/api/api/v1/products/search.md +0 -88
  111. data/examples/complex-test-app/docs/api/api/v1/products/show.md +0 -71
  112. data/examples/complex-test-app/docs/api/api/v1/profiles/index.md +0 -10
  113. data/examples/complex-test-app/docs/api/api/v1/profiles/show.md +0 -61
  114. data/examples/complex-test-app/docs/api/api/v1/profiles/update.md +0 -91
  115. data/examples/complex-test-app/docs/api/api/v2/products/index.md +0 -9
  116. data/examples/complex-test-app/docs/api/api/v2/products/list.md +0 -77
  117. data/examples/complex-test-app/docs/api/curl/api/v1/admin/products/create.sh +0 -18
  118. data/examples/complex-test-app/docs/api/curl/api/v1/admin/products/destroy.sh +0 -9
  119. data/examples/complex-test-app/docs/api/curl/api/v1/admin/products/list.sh +0 -9
  120. data/examples/complex-test-app/docs/api/curl/api/v1/auth/login.sh +0 -9
  121. data/examples/complex-test-app/docs/api/curl/api/v1/cart-items/create.sh +0 -16
  122. data/examples/complex-test-app/docs/api/curl/api/v1/cart-items/destroy.sh +0 -9
  123. data/examples/complex-test-app/docs/api/curl/api/v1/carts/checkout.sh +0 -13
  124. data/examples/complex-test-app/docs/api/curl/api/v1/carts/show.sh +0 -9
  125. data/examples/complex-test-app/docs/api/curl/api/v1/home/list.sh +0 -8
  126. data/examples/complex-test-app/docs/api/curl/api/v1/notes/create.sh +0 -15
  127. data/examples/complex-test-app/docs/api/curl/api/v1/notes/list.sh +0 -9
  128. data/examples/complex-test-app/docs/api/curl/api/v1/orders/cancel.sh +0 -9
  129. data/examples/complex-test-app/docs/api/curl/api/v1/orders/create.sh +0 -29
  130. data/examples/complex-test-app/docs/api/curl/api/v1/orders/destroy.sh +0 -9
  131. data/examples/complex-test-app/docs/api/curl/api/v1/orders/list.sh +0 -9
  132. data/examples/complex-test-app/docs/api/curl/api/v1/orders/show.sh +0 -9
  133. data/examples/complex-test-app/docs/api/curl/api/v1/products/list.sh +0 -8
  134. data/examples/complex-test-app/docs/api/curl/api/v1/products/search.sh +0 -8
  135. data/examples/complex-test-app/docs/api/curl/api/v1/products/show.sh +0 -8
  136. data/examples/complex-test-app/docs/api/curl/api/v1/profiles/show.sh +0 -9
  137. data/examples/complex-test-app/docs/api/curl/api/v1/profiles/update.sh +0 -16
  138. data/examples/complex-test-app/docs/api/curl/api/v2/products/list.sh +0 -8
  139. data/examples/complex-test-app/docs/api/dataset.json +0 -5109
  140. data/examples/complex-test-app/docs/api/postman/collection.json +0 -2568
  141. data/examples/complex-test-app/generate.rb +0 -14
  142. data/examples/complex-test-app/reqcord.yml +0 -28
  143. data/examples/complex-test-app/test/integration/admin_test.rb +0 -70
  144. data/examples/complex-test-app/test/integration/cart_test.rb +0 -64
  145. data/examples/complex-test-app/test/integration/home_and_auth_test.rb +0 -53
  146. data/examples/complex-test-app/test/integration/orders_test.rb +0 -127
  147. data/examples/complex-test-app/test/integration/products_test.rb +0 -66
  148. data/examples/spec-app/.rspec +0 -1
  149. data/examples/spec-app/README.md +0 -36
  150. data/examples/spec-app/app.rb +0 -209
  151. data/examples/spec-app/docs/api/README.md +0 -45
  152. data/examples/spec-app/docs/api/api/v1/customers/create.md +0 -95
  153. data/examples/spec-app/docs/api/api/v1/customers/index.md +0 -11
  154. data/examples/spec-app/docs/api/api/v1/customers/list.md +0 -67
  155. data/examples/spec-app/docs/api/api/v1/customers/show.md +0 -65
  156. data/examples/spec-app/docs/api/api/v1/tasks/complete.md +0 -51
  157. data/examples/spec-app/docs/api/api/v1/tasks/create.md +0 -90
  158. data/examples/spec-app/docs/api/api/v1/tasks/destroy.md +0 -35
  159. data/examples/spec-app/docs/api/api/v1/tasks/index.md +0 -14
  160. data/examples/spec-app/docs/api/api/v1/tasks/list.md +0 -65
  161. data/examples/spec-app/docs/api/api/v1/tasks/show.md +0 -65
  162. data/examples/spec-app/docs/api/api/v1/tasks/update.md +0 -74
  163. data/examples/spec-app/docs/api/api/v1/users/create.md +0 -95
  164. data/examples/spec-app/docs/api/api/v1/users/index.md +0 -11
  165. data/examples/spec-app/docs/api/api/v1/users/list.md +0 -67
  166. data/examples/spec-app/docs/api/api/v1/users/show.md +0 -65
  167. data/examples/spec-app/docs/api/curl/api/v1/customers/create.sh +0 -17
  168. data/examples/spec-app/docs/api/curl/api/v1/customers/list.sh +0 -9
  169. data/examples/spec-app/docs/api/curl/api/v1/customers/show.sh +0 -9
  170. data/examples/spec-app/docs/api/curl/api/v1/tasks/complete.sh +0 -8
  171. data/examples/spec-app/docs/api/curl/api/v1/tasks/create.sh +0 -15
  172. data/examples/spec-app/docs/api/curl/api/v1/tasks/destroy.sh +0 -8
  173. data/examples/spec-app/docs/api/curl/api/v1/tasks/list.sh +0 -8
  174. data/examples/spec-app/docs/api/curl/api/v1/tasks/show.sh +0 -8
  175. data/examples/spec-app/docs/api/curl/api/v1/tasks/update.sh +0 -14
  176. data/examples/spec-app/docs/api/curl/api/v1/users/create.sh +0 -17
  177. data/examples/spec-app/docs/api/curl/api/v1/users/list.sh +0 -9
  178. data/examples/spec-app/docs/api/curl/api/v1/users/show.sh +0 -9
  179. data/examples/spec-app/docs/api/dataset.json +0 -2402
  180. data/examples/spec-app/docs/api/postman/collection.json +0 -1290
  181. data/examples/spec-app/generate.rb +0 -14
  182. data/examples/spec-app/reqcord.yml +0 -27
  183. data/examples/spec-app/spec/requests/customers_spec.rb +0 -71
  184. data/examples/spec-app/spec/requests/tasks_spec.rb +0 -78
  185. data/examples/spec-app/spec/requests/users_spec.rb +0 -68
  186. data/examples/spec-app/spec/spec_helper.rb +0 -17
  187. data/examples/test-app/README.md +0 -57
  188. data/examples/test-app/app.rb +0 -212
  189. data/examples/test-app/docs/api/README.md +0 -45
  190. data/examples/test-app/docs/api/api/v1/customers/create.md +0 -95
  191. data/examples/test-app/docs/api/api/v1/customers/index.md +0 -11
  192. data/examples/test-app/docs/api/api/v1/customers/list.md +0 -67
  193. data/examples/test-app/docs/api/api/v1/customers/show.md +0 -65
  194. data/examples/test-app/docs/api/api/v1/tasks/complete.md +0 -51
  195. data/examples/test-app/docs/api/api/v1/tasks/create.md +0 -90
  196. data/examples/test-app/docs/api/api/v1/tasks/destroy.md +0 -35
  197. data/examples/test-app/docs/api/api/v1/tasks/index.md +0 -14
  198. data/examples/test-app/docs/api/api/v1/tasks/list.md +0 -65
  199. data/examples/test-app/docs/api/api/v1/tasks/show.md +0 -65
  200. data/examples/test-app/docs/api/api/v1/tasks/update.md +0 -74
  201. data/examples/test-app/docs/api/api/v1/users/create.md +0 -95
  202. data/examples/test-app/docs/api/api/v1/users/index.md +0 -11
  203. data/examples/test-app/docs/api/api/v1/users/list.md +0 -67
  204. data/examples/test-app/docs/api/api/v1/users/show.md +0 -65
  205. data/examples/test-app/docs/api/curl/api/v1/customers/create.sh +0 -17
  206. data/examples/test-app/docs/api/curl/api/v1/customers/list.sh +0 -9
  207. data/examples/test-app/docs/api/curl/api/v1/customers/show.sh +0 -9
  208. data/examples/test-app/docs/api/curl/api/v1/tasks/complete.sh +0 -8
  209. data/examples/test-app/docs/api/curl/api/v1/tasks/create.sh +0 -15
  210. data/examples/test-app/docs/api/curl/api/v1/tasks/destroy.sh +0 -8
  211. data/examples/test-app/docs/api/curl/api/v1/tasks/list.sh +0 -8
  212. data/examples/test-app/docs/api/curl/api/v1/tasks/show.sh +0 -8
  213. data/examples/test-app/docs/api/curl/api/v1/tasks/update.sh +0 -14
  214. data/examples/test-app/docs/api/curl/api/v1/users/create.sh +0 -17
  215. data/examples/test-app/docs/api/curl/api/v1/users/list.sh +0 -9
  216. data/examples/test-app/docs/api/curl/api/v1/users/show.sh +0 -9
  217. data/examples/test-app/docs/api/dataset.json +0 -2402
  218. data/examples/test-app/docs/api/postman/collection.json +0 -1290
  219. data/examples/test-app/generate.rb +0 -14
  220. data/examples/test-app/reqcord.yml +0 -28
  221. data/examples/test-app/test/integration/customers_test.rb +0 -72
  222. data/examples/test-app/test/integration/tasks_test.rb +0 -80
  223. data/examples/test-app/test/integration/users_test.rb +0 -72
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Stands in for `bin/rails reqcord:generate`, which this single file example
4
- # has no `bin/rails` to run.
5
- require_relative "app"
6
-
7
- dataset = Reqcord::Generator.call(
8
- resources: ENV.fetch("RESOURCE", "").split(",").map(&:strip).reject(&:empty?),
9
- version: ENV["VERSION"]
10
- )
11
-
12
- puts
13
- puts "Endpoints: #{dataset.endpoints.size} (#{dataset.documented_endpoints.size} covered by tests)"
14
- puts "Output: #{Reqcord.configuration.output_directory}"
@@ -1,28 +0,0 @@
1
- version: 1
2
-
3
- test:
4
- framework: minitest
5
- paths:
6
- - test/integration
7
-
8
- routes:
9
- prefix: /api
10
-
11
- output:
12
- directory: docs/api
13
-
14
- exporters:
15
- - curl
16
- - markdown
17
- - postman
18
-
19
- variables:
20
- base_url: http://localhost:3000
21
-
22
- sanitize:
23
- headers:
24
- Authorization: "Bearer {{token}}"
25
- X-Api-Key: "{{api_key}}"
26
- body:
27
- password: "{{password}}"
28
- token: "{{token}}"
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../app"
4
- require "minitest/autorun"
5
-
6
- class AdminTest < ActionDispatch::IntegrationTest
7
- def api_key
8
- { "X-Api-Key" => "sk_live_super-secret-key" }
9
- end
10
-
11
- test "admin lists products with costs" do
12
- get "/api/v1/admin/products", headers: api_key, as: :json
13
-
14
- assert_response :ok
15
- end
16
-
17
- test "admin requires an api key" do
18
- get "/api/v1/admin/products", as: :json
19
-
20
- assert_response :unauthorized
21
- end
22
-
23
- test "admin creates a product" do
24
- post "/api/v1/admin/products",
25
- params: { product: { sku: "TEA-003", name: "Jasmine", category: "tea", price_cents: 1400 } },
26
- headers: api_key,
27
- as: :json
28
-
29
- assert_response :created
30
- end
31
-
32
- test "admin rejects a product without a sku" do
33
- post "/api/v1/admin/products", params: { product: { sku: "", name: "Nameless" } }, headers: api_key, as: :json
34
-
35
- assert_response :unprocessable_entity
36
- end
37
-
38
- test "admin rejects a duplicate sku" do
39
- post "/api/v1/admin/products",
40
- params: { product: { sku: "TEA-001", name: "Earl Grey again", category: "tea", price_cents: 1200 } },
41
- headers: api_key,
42
- as: :json
43
-
44
- assert_response :conflict
45
- end
46
-
47
- test "admin deletes a product" do
48
- delete "/api/v1/admin/products/4", headers: api_key, as: :json
49
-
50
- assert_response :no_content
51
- end
52
-
53
- test "admin cannot delete an unknown product" do
54
- delete "/api/v1/admin/products/999", headers: api_key, as: :json
55
-
56
- assert_response :not_found
57
- end
58
-
59
- test "v2 lists products" do
60
- get "/api/v2/products", as: :json
61
-
62
- assert_response :ok
63
- end
64
-
65
- test "v2 follows a cursor" do
66
- get "/api/v2/products", params: { cursor: "eyJpZCI6Mn0" }, as: :json
67
-
68
- assert_response :ok
69
- end
70
- end
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../app"
4
- require "minitest/autorun"
5
-
6
- class CartTest < ActionDispatch::IntegrationTest
7
- def auth
8
- { "Authorization" => "Bearer eyJhbGciOiJIUzI1NiJ9.super-secret" }
9
- end
10
-
11
- test "shows the cart" do
12
- get "/api/v1/cart", headers: auth, as: :json
13
-
14
- assert_response :ok
15
- end
16
-
17
- test "adds an item to the cart" do
18
- post "/api/v1/cart/items", params: { item: { sku: "TEA-002", quantity: 3 } }, headers: auth, as: :json
19
-
20
- assert_response :created
21
- end
22
-
23
- test "rejects an unknown sku" do
24
- post "/api/v1/cart/items", params: { item: { sku: "TEA-999", quantity: 1 } }, headers: auth, as: :json
25
-
26
- assert_response :unprocessable_entity
27
- end
28
-
29
- test "removes an item from the cart" do
30
- delete "/api/v1/cart/items/TEA-001", headers: auth, as: :json
31
-
32
- assert_response :no_content
33
- end
34
-
35
- test "cannot remove an item that is not in the cart" do
36
- delete "/api/v1/cart/items/MUG-002", headers: auth, as: :json
37
-
38
- assert_response :not_found
39
- end
40
-
41
- test "checks out with a card" do
42
- post "/api/v1/cart/checkout", params: { payment_method: "card" }, headers: auth, as: :json
43
-
44
- assert_response :created
45
- end
46
-
47
- test "checks out with a bank transfer" do
48
- post "/api/v1/cart/checkout", params: { payment_method: "bank_transfer" }, headers: auth, as: :json
49
-
50
- assert_response :created
51
- end
52
-
53
- test "rejects an unknown payment method" do
54
- post "/api/v1/cart/checkout", params: { payment_method: "cash" }, headers: auth, as: :json
55
-
56
- assert_response :unprocessable_entity
57
- end
58
-
59
- test "cart requires authentication" do
60
- get "/api/v1/cart", as: :json
61
-
62
- assert_response :unauthorized
63
- end
64
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../app"
4
- require "minitest/autorun"
5
-
6
- class HomeAndAuthTest < ActionDispatch::IntegrationTest
7
- def auth
8
- { "Authorization" => "Bearer eyJhbGciOiJIUzI1NiJ9.super-secret" }
9
- end
10
-
11
- test "root describes the api" do
12
- get "/api/v1", as: :json
13
-
14
- assert_response :ok
15
- end
16
-
17
- # A form post, not JSON: the documentation must keep it a form.
18
- test "logs in with a form" do
19
- post "/api/v1/auth/login", params: { email: "ada@example.com", password: "correct-horse-battery" }
20
-
21
- assert_response :ok
22
- end
23
-
24
- test "rejects a wrong password" do
25
- post "/api/v1/auth/login", params: { email: "ada@example.com", password: "wrong" }
26
-
27
- assert_response :unauthorized
28
- end
29
-
30
- test "shows the profile" do
31
- get "/api/v1/profile", headers: auth, as: :json
32
-
33
- assert_response :ok
34
- end
35
-
36
- test "updates the profile" do
37
- patch "/api/v1/profile", params: { profile: { name: "Ada L.", locale: "tr" } }, headers: auth, as: :json
38
-
39
- assert_response :ok
40
- end
41
-
42
- test "rejects an unknown locale" do
43
- patch "/api/v1/profile", params: { profile: { locale: "xx" } }, headers: auth, as: :json
44
-
45
- assert_response :unprocessable_entity
46
- end
47
-
48
- test "profile requires authentication" do
49
- get "/api/v1/profile", as: :json
50
-
51
- assert_response :unauthorized
52
- end
53
- end
@@ -1,127 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../app"
4
- require "minitest/autorun"
5
-
6
- class OrdersTest < ActionDispatch::IntegrationTest
7
- def auth
8
- { "Authorization" => "Bearer eyJhbGciOiJIUzI1NiJ9.super-secret" }
9
- end
10
-
11
- def order_payload
12
- {
13
- order: {
14
- line_items: [
15
- { sku: "TEA-001", quantity: 2 },
16
- { sku: "MUG-001", quantity: 1 }
17
- ],
18
- shipping_address: { line1: "1 Analytical Engine Way", city: "London", country: "GB" }
19
- }
20
- }
21
- end
22
-
23
- test "lists orders" do
24
- get "/api/v1/orders", headers: auth, as: :json
25
-
26
- assert_response :ok
27
- end
28
-
29
- test "lists pending orders" do
30
- get "/api/v1/orders", params: { status: "pending" }, headers: auth, as: :json
31
-
32
- assert_response :ok
33
- end
34
-
35
- test "lists shipped orders" do
36
- get "/api/v1/orders", params: { status: "shipped" }, headers: auth, as: :json
37
-
38
- assert_response :ok
39
- end
40
-
41
- test "shows an order" do
42
- get "/api/v1/orders/1", headers: auth, as: :json
43
-
44
- assert_response :ok
45
- end
46
-
47
- test "hides another customer's order" do
48
- get "/api/v1/orders/3", headers: auth, as: :json
49
-
50
- assert_response :forbidden
51
- end
52
-
53
- test "returns not found for an unknown order" do
54
- get "/api/v1/orders/999", headers: auth, as: :json
55
-
56
- assert_response :not_found
57
- end
58
-
59
- test "creates an order" do
60
- post "/api/v1/orders", params: order_payload, headers: auth, as: :json
61
-
62
- assert_response :created
63
- end
64
-
65
- test "creates a single item order" do
66
- post "/api/v1/orders",
67
- params: { order: { line_items: [{ sku: "MUG-002", quantity: 1 }], shipping_address: { line1: "Piazza", city: "Rome", country: "IT" } } },
68
- headers: auth,
69
- as: :json
70
-
71
- assert_response :created
72
- end
73
-
74
- test "rejects an order without line items" do
75
- post "/api/v1/orders", params: { order: { line_items: [] } }, headers: auth, as: :json
76
-
77
- assert_response :unprocessable_entity
78
- end
79
-
80
- test "rejects an unknown sku" do
81
- post "/api/v1/orders", params: { order: { line_items: [{ sku: "TEA-999", quantity: 1 }] } }, headers: auth, as: :json
82
-
83
- assert_response :unprocessable_entity
84
- end
85
-
86
- test "cancels a pending order" do
87
- post "/api/v1/orders/1/cancel", headers: auth, as: :json
88
-
89
- assert_response :ok
90
- end
91
-
92
- test "cannot cancel a shipped order" do
93
- post "/api/v1/orders/2/cancel", headers: auth, as: :json
94
-
95
- assert_response :conflict
96
- end
97
-
98
- test "deletes an order" do
99
- delete "/api/v1/orders/1", headers: auth, as: :json
100
-
101
- assert_response :no_content
102
- end
103
-
104
- test "orders require authentication" do
105
- get "/api/v1/orders", as: :json
106
-
107
- assert_response :unauthorized
108
- end
109
-
110
- test "lists the notes of an order" do
111
- get "/api/v1/orders/1/notes", headers: auth, as: :json
112
-
113
- assert_response :ok
114
- end
115
-
116
- test "adds a note to an order" do
117
- post "/api/v1/orders/1/notes", params: { note: { body: "Ring the bell twice" } }, headers: auth, as: :json
118
-
119
- assert_response :created
120
- end
121
-
122
- test "rejects an empty note" do
123
- post "/api/v1/orders/1/notes", params: { note: { body: "" } }, headers: auth, as: :json
124
-
125
- assert_response :unprocessable_entity
126
- end
127
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../app"
4
- require "minitest/autorun"
5
-
6
- class ProductsTest < ActionDispatch::IntegrationTest
7
- test "lists products" do
8
- get "/api/v1/products", as: :json
9
-
10
- assert_response :ok
11
- end
12
-
13
- test "filters products by category" do
14
- get "/api/v1/products", params: { filter: { category: "tea" } }, as: :json
15
-
16
- assert_response :ok
17
- end
18
-
19
- test "filters mugs" do
20
- get "/api/v1/products", params: { filter: { category: "mugs" } }, as: :json
21
-
22
- assert_response :ok
23
- end
24
-
25
- test "sorts by price ascending" do
26
- get "/api/v1/products", params: { sort: "price_asc" }, as: :json
27
-
28
- assert_response :ok
29
- end
30
-
31
- test "sorts by price descending" do
32
- get "/api/v1/products", params: { sort: "price_desc" }, as: :json
33
-
34
- assert_response :ok
35
- end
36
-
37
- test "paginates" do
38
- get "/api/v1/products", params: { page: 2, per_page: 2 }, as: :json
39
-
40
- assert_response :ok
41
- end
42
-
43
- test "shows a product" do
44
- get "/api/v1/products/3", as: :json
45
-
46
- assert_response :ok
47
- end
48
-
49
- test "returns not found for an unknown product" do
50
- get "/api/v1/products/999", as: :json
51
-
52
- assert_response :not_found
53
- end
54
-
55
- test "searches products" do
56
- get "/api/v1/products/search", params: { q: "mug" }, as: :json
57
-
58
- assert_response :ok
59
- end
60
-
61
- test "search needs a query" do
62
- get "/api/v1/products/search", as: :json
63
-
64
- assert_response :bad_request
65
- end
66
- end
@@ -1 +0,0 @@
1
- --require spec_helper
@@ -1,36 +0,0 @@
1
- # spec-app (RSpec)
2
-
3
- The same API as [test-app](../test-app), documented from RSpec request specs
4
- instead of Minitest. The generated dataset is identical in shape: the test
5
- framework only decides how examples are named.
6
-
7
- ```text
8
- app.rb the application (customers, users, tasks)
9
- spec/requests/*_spec.rb ordinary request specs
10
- spec/spec_helper.rb request helpers (see the note below)
11
- reqcord.yml `test.framework: rspec`
12
- docs/api/ generated Markdown, cURL scripts and Postman
13
- collection — the same files test-app gets
14
- ```
15
-
16
- ## Regenerate
17
-
18
- ```bash
19
- ruby generate.rb
20
- ```
21
-
22
- ## Notes
23
-
24
- This example runs on plain `rspec-core`, so `spec_helper.rb` includes the
25
- ActionDispatch request helpers itself and the specs assert
26
- `response.status`. An application using `rspec-rails` gets `type: :request`
27
- and `have_http_status` for free and needs none of that.
28
-
29
- The only Reqcord-facing difference from test-app is one line in `reqcord.yml`:
30
-
31
- ```yaml
32
- test:
33
- framework: rspec
34
- paths:
35
- - spec/requests
36
- ```
@@ -1,209 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # A tiny Rails API, in one file, so the example stays readable. In a real
4
- # application this is just your app; Reqcord does not care how it is built.
5
- #
6
- # The same three resources as test-app — customers, users, tasks — so the two
7
- # examples can be compared endpoint for endpoint.
8
- ENV["RAILS_ENV"] ||= "test"
9
-
10
- # Only needed because this example lives inside the Reqcord repository.
11
- # In your own application, `gem "reqcord"` in the Gemfile is enough.
12
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
13
-
14
- require "rails"
15
- require "action_controller/railtie"
16
- require "reqcord"
17
-
18
- class ExampleApp < Rails::Application
19
- config.root = __dir__
20
- config.eager_load = false
21
- config.logger = Logger.new(IO::NULL)
22
- config.secret_key_base = "a" * 64
23
- config.hosts.clear
24
- end
25
-
26
- Rails.application.initialize!
27
-
28
- module Api
29
- module V1
30
- class CustomersController < ActionController::API
31
- CUSTOMERS = [
32
- { id: 1, name: "John Doe", email: "john@example.com" },
33
- { id: 2, name: "Jane Roe", email: "jane@example.com" }
34
- ].freeze
35
-
36
- before_action :authenticate!
37
-
38
- def index
39
- render json: CUSTOMERS.first(params.fetch(:per_page, 25).to_i)
40
- end
41
-
42
- def show
43
- customer = CUSTOMERS.find { |record| record[:id] == params[:id].to_i }
44
-
45
- return render(json: { error: "Not Found" }, status: :not_found) unless customer
46
-
47
- render json: customer
48
- end
49
-
50
- STATUSES = %w[active passive].freeze
51
-
52
- def create
53
- if params.dig(:customer, :email).to_s.empty?
54
- return render(
55
- json: { errors: { email: ["can't be blank"] } },
56
- status: :unprocessable_entity
57
- )
58
- end
59
-
60
- unless STATUSES.include?(params.dig(:customer, :status).to_s)
61
- return render(
62
- json: { errors: { status: ["is not included in the list"] } },
63
- status: :unprocessable_entity
64
- )
65
- end
66
-
67
- render json: { id: 3, **customer_params }, status: :created
68
- end
69
-
70
- private
71
-
72
- def authenticate!
73
- return if request.headers["Authorization"].present?
74
-
75
- render json: { error: "Unauthorized" }, status: :unauthorized
76
- end
77
-
78
- def customer_params
79
- params.require(:customer).permit(:name, :email, :status).to_h.symbolize_keys
80
- end
81
- end
82
-
83
- class UsersController < ActionController::API
84
- USERS = [
85
- { id: 1, name: "John Doe", email: "john@example.com" },
86
- { id: 2, name: "Jane Roe", email: "jane@example.com" }
87
- ].freeze
88
-
89
- before_action :authenticate!
90
-
91
- def index
92
- render json: USERS.first(params.fetch(:per_page, 25).to_i)
93
- end
94
-
95
- def show
96
- user = USERS.find { |record| record[:id] == params[:id].to_i }
97
-
98
- return render(json: { error: "Not Found" }, status: :not_found) unless user
99
-
100
- render json: user
101
- end
102
-
103
- STATUSES = %w[active inactive].freeze
104
-
105
- def create
106
- if params.dig(:user, :email).to_s.empty?
107
- return render(
108
- json: { errors: { email: ["can't be blank"] } },
109
- status: :unprocessable_entity
110
- )
111
- end
112
-
113
- unless STATUSES.include?(params.dig(:user, :status).to_s)
114
- return render(
115
- json: { errors: { status: ["is not included in the list"] } },
116
- status: :unprocessable_entity
117
- )
118
- end
119
-
120
- render json: { id: 3, **user_params }, status: :created
121
- end
122
-
123
- private
124
-
125
- def authenticate!
126
- return if request.headers["Authorization"].present?
127
-
128
- render json: { error: "Unauthorized" }, status: :unauthorized
129
- end
130
-
131
- def user_params
132
- params.require(:user).permit(:name, :email, :status).to_h.symbolize_keys
133
- end
134
- end
135
-
136
- class TasksController < ActionController::API
137
- TASKS = [
138
- { id: 1, title: "Write the docs", status: "open", priority: "high" },
139
- { id: 2, title: "Ship 0.1.1", status: "done", priority: "high" },
140
- { id: 3, title: "Tidy the backlog", status: "open", priority: "low" }
141
- ].freeze
142
-
143
- STATUSES = %w[open done].freeze
144
- PRIORITIES = %w[low high].freeze
145
-
146
- def index
147
- tasks = TASKS
148
- tasks = tasks.select { |task| task[:status] == params[:status] } if params[:status].present?
149
-
150
- render json: tasks
151
- end
152
-
153
- before_action :find_task, only: %i[show update complete destroy]
154
-
155
- def show
156
- render json: @task
157
- end
158
-
159
- def create
160
- if params.dig(:task, :title).to_s.empty?
161
- return render(json: { errors: { title: ["can't be blank"] } }, status: :unprocessable_entity)
162
- end
163
-
164
- unless PRIORITIES.include?(params.dig(:task, :priority).to_s)
165
- return render(json: { errors: { priority: ["is not included in the list"] } }, status: :unprocessable_entity)
166
- end
167
-
168
- render json: { id: 4, status: "open", **task_params }, status: :created
169
- end
170
-
171
- def update
172
- render json: @task.merge(task_params)
173
- end
174
-
175
- def complete
176
- render json: @task.merge(status: "done")
177
- end
178
-
179
- def destroy
180
- head :no_content
181
- end
182
-
183
- private
184
-
185
- # Rendering in a before_action halts the chain, so the action never runs.
186
- def find_task
187
- @task = TASKS.find { |task| task[:id] == params[:id].to_i }
188
-
189
- render(json: { error: "Not Found" }, status: :not_found) unless @task
190
- end
191
-
192
- def task_params
193
- params.require(:task).permit(:title, :priority, :status).to_h.symbolize_keys
194
- end
195
- end
196
- end
197
- end
198
-
199
- Rails.application.routes.draw do
200
- namespace :api do
201
- namespace :v1 do
202
- resources :customers, only: %i[index show create]
203
- resources :users, only: %i[index show create]
204
- resources :tasks, except: %i[new edit] do
205
- post :complete, on: :member
206
- end
207
- end
208
- end
209
- end