praxis 0.16.1 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (399) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +0 -1
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +2 -1
  5. data/CHANGELOG.md +41 -0
  6. data/CONTRIBUTING.md +3 -0
  7. data/lib/api_browser/Gruntfile.js +20 -4
  8. data/lib/api_browser/app/bower_components/angular-mocks/.bower.json +6 -6
  9. data/lib/api_browser/app/bower_components/angular-mocks/README.md +11 -5
  10. data/lib/api_browser/app/bower_components/angular-mocks/angular-mocks.js +475 -216
  11. data/lib/api_browser/app/bower_components/angular-mocks/bower.json +2 -2
  12. data/lib/api_browser/app/bower_components/angular-mocks/ngAnimateMock.js +2 -0
  13. data/lib/api_browser/app/bower_components/angular-mocks/ngMock.js +2 -0
  14. data/lib/api_browser/app/bower_components/angular-mocks/ngMockE2E.js +2 -0
  15. data/lib/api_browser/app/bower_components/angular-mocks/package.json +1 -1
  16. data/lib/api_browser/app/bower_components/angular-sanitize/.bower.json +8 -8
  17. data/lib/api_browser/app/bower_components/angular-sanitize/README.md +19 -5
  18. data/lib/api_browser/app/bower_components/angular-sanitize/angular-sanitize.js +186 -127
  19. data/lib/api_browser/app/bower_components/angular-sanitize/angular-sanitize.min.js +12 -10
  20. data/lib/api_browser/app/bower_components/angular-sanitize/angular-sanitize.min.js.map +3 -3
  21. data/lib/api_browser/app/bower_components/angular-sanitize/bower.json +3 -2
  22. data/lib/api_browser/app/bower_components/angular-sanitize/index.js +2 -0
  23. data/lib/api_browser/app/bower_components/angular-sanitize/package.json +26 -0
  24. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/.bower.json +15 -8
  25. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/bower.json +11 -3
  26. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-csp.css +6 -0
  27. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.js +1177 -453
  28. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.min.js +4 -4
  29. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap.js +1066 -404
  30. data/lib/api_browser/app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap.min.js +3 -3
  31. data/lib/api_browser/app/bower_components/angular-ui-router/.bower.json +5 -6
  32. data/lib/api_browser/app/bower_components/angular-ui-router/CHANGELOG.md +208 -3
  33. data/lib/api_browser/app/bower_components/angular-ui-router/CONTRIBUTING.md +65 -0
  34. data/lib/api_browser/app/bower_components/angular-ui-router/LICENSE +1 -1
  35. data/lib/api_browser/app/bower_components/angular-ui-router/README.md +36 -71
  36. data/lib/api_browser/app/bower_components/angular-ui-router/api/angular-ui-router.d.ts +126 -0
  37. data/lib/api_browser/app/bower_components/angular-ui-router/bower.json +1 -1
  38. data/lib/api_browser/app/bower_components/angular-ui-router/release/angular-ui-router.js +1902 -755
  39. data/lib/api_browser/app/bower_components/angular-ui-router/release/angular-ui-router.min.js +2 -2
  40. data/lib/api_browser/app/bower_components/angular-ui-router/src/common.js +69 -23
  41. data/lib/api_browser/app/bower_components/angular-ui-router/src/resolve.js +15 -5
  42. data/lib/api_browser/app/bower_components/angular-ui-router/src/state.js +556 -295
  43. data/lib/api_browser/app/bower_components/angular-ui-router/src/stateDirectives.js +101 -42
  44. data/lib/api_browser/app/bower_components/angular-ui-router/src/stateFilters.js +6 -2
  45. data/lib/api_browser/app/bower_components/angular-ui-router/src/templateFactory.js +2 -2
  46. data/lib/api_browser/app/bower_components/angular-ui-router/src/urlMatcherFactory.js +822 -97
  47. data/lib/api_browser/app/bower_components/angular-ui-router/src/urlRouter.js +274 -120
  48. data/lib/api_browser/app/bower_components/angular-ui-router/src/viewDirective.js +33 -20
  49. data/lib/api_browser/app/bower_components/angular-ui-router/src/viewScroll.js +1 -1
  50. data/lib/api_browser/app/bower_components/angular/.bower.json +5 -5
  51. data/lib/api_browser/app/bower_components/angular/README.md +2 -5
  52. data/lib/api_browser/app/bower_components/angular/angular-csp.css +5 -8
  53. data/lib/api_browser/app/bower_components/angular/angular.js +12975 -6996
  54. data/lib/api_browser/app/bower_components/angular/angular.min.js +285 -213
  55. data/lib/api_browser/app/bower_components/angular/angular.min.js.gzip +0 -0
  56. data/lib/api_browser/app/bower_components/angular/angular.min.js.map +3 -3
  57. data/lib/api_browser/app/bower_components/angular/bower.json +1 -1
  58. data/lib/api_browser/app/bower_components/angular/index.js +2 -0
  59. data/lib/api_browser/app/bower_components/angular/package.json +2 -2
  60. data/lib/api_browser/app/bower_components/bootstrap-sass/.bower.json +31 -16
  61. data/lib/api_browser/app/bower_components/bootstrap-sass/CHANGELOG.md +108 -0
  62. data/lib/api_browser/app/bower_components/bootstrap-sass/CONTRIBUTING.md +55 -37
  63. data/lib/api_browser/app/bower_components/bootstrap-sass/README.md +147 -206
  64. data/lib/api_browser/app/bower_components/bootstrap-sass/bower.json +19 -8
  65. data/lib/api_browser/app/bower_components/bootstrap-sass/{dist/fonts → vendor/assets/fonts/bootstrap}/glyphicons-halflings-regular.eot +0 -0
  66. data/lib/api_browser/app/bower_components/bootstrap-sass/{dist/fonts → vendor/assets/fonts/bootstrap}/glyphicons-halflings-regular.svg +0 -0
  67. data/lib/api_browser/app/bower_components/bootstrap-sass/{dist/fonts → vendor/assets/fonts/bootstrap}/glyphicons-halflings-regular.ttf +0 -0
  68. data/lib/api_browser/app/bower_components/bootstrap-sass/{dist/fonts → vendor/assets/fonts/bootstrap}/glyphicons-halflings-regular.woff +0 -0
  69. data/lib/api_browser/app/bower_components/bootstrap-sass/vendor/assets/javascripts/bootstrap.js +12 -0
  70. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/affix.js +1 -1
  71. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/alert.js +1 -1
  72. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/button.js +11 -5
  73. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/carousel.js +5 -5
  74. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/collapse.js +1 -1
  75. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/dropdown.js +5 -5
  76. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/modal.js +1 -1
  77. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/popover.js +1 -1
  78. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/scrollspy.js +2 -2
  79. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/tab.js +1 -1
  80. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/tooltip.js +1 -1
  81. data/lib/api_browser/app/bower_components/bootstrap-sass/{js → vendor/assets/javascripts/bootstrap}/transition.js +1 -1
  82. data/lib/api_browser/app/bower_components/bootstrap-sass/vendor/assets/stylesheets/bootstrap.scss +1 -0
  83. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_alerts.scss +0 -0
  84. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_badges.scss +6 -6
  85. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_breadcrumbs.scss +0 -0
  86. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_button-groups.scss +7 -33
  87. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_buttons.scss +2 -5
  88. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_carousel.scss +1 -0
  89. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_close.scss +0 -0
  90. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_code.scss +0 -0
  91. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_component-animations.scss +0 -0
  92. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_dropdowns.scss +3 -8
  93. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_forms.scss +11 -0
  94. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_glyphicons.scss +5 -5
  95. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_grid.scss +12 -26
  96. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_input-groups.scss +1 -1
  97. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_jumbotron.scss +8 -2
  98. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_labels.scss +6 -0
  99. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_list-group.scss +0 -0
  100. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_media.scss +0 -0
  101. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_mixins.scss +38 -51
  102. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_modals.scss +2 -5
  103. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_navbar.scss +41 -53
  104. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_navs.scss +0 -20
  105. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_normalize.scss +0 -0
  106. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_pager.scss +0 -0
  107. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_pagination.scss +0 -0
  108. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_panels.scss +11 -1
  109. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_popovers.scss +0 -0
  110. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_print.scss +0 -0
  111. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_progress-bars.scss +0 -12
  112. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_responsive-utilities.scss +0 -0
  113. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_scaffolding.scss +0 -0
  114. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_tables.scss +5 -18
  115. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_theme.scss +2 -2
  116. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_thumbnails.scss +9 -3
  117. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_tooltip.scss +0 -0
  118. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_type.scss +54 -52
  119. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_utilities.scss +0 -0
  120. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_variables.scss +20 -11
  121. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/_wells.scss +0 -0
  122. data/lib/api_browser/app/bower_components/bootstrap-sass/{lib → vendor/assets/stylesheets/bootstrap}/bootstrap.scss +0 -0
  123. data/lib/api_browser/app/bower_components/lodash/.bower.json +9 -13
  124. data/lib/api_browser/app/bower_components/lodash/LICENSE.txt +3 -3
  125. data/lib/api_browser/app/bower_components/lodash/bower.json +4 -7
  126. data/lib/api_browser/app/bower_components/lodash/lodash.js +12235 -0
  127. data/lib/api_browser/app/bower_components/lodash/lodash.min.js +98 -0
  128. data/lib/api_browser/app/index.html +0 -1
  129. data/lib/api_browser/app/js/app.js +2 -5
  130. data/lib/api_browser/app/js/controllers/action.js +21 -37
  131. data/lib/api_browser/app/js/controllers/controller.js +23 -1
  132. data/lib/api_browser/app/js/controllers/menu.js +46 -14
  133. data/lib/api_browser/app/js/controllers/type.js +2 -9
  134. data/lib/api_browser/app/js/directives/attribute_description.js +15 -5
  135. data/lib/api_browser/app/js/directives/attribute_table.js +6 -6
  136. data/lib/api_browser/app/js/directives/fixed_if_fits.js +20 -0
  137. data/lib/api_browser/app/js/directives/no_container.js +6 -6
  138. data/lib/api_browser/app/js/directives/type_placeholder.js +21 -0
  139. data/lib/api_browser/app/js/factories/Configuration.js +13 -0
  140. data/lib/api_browser/app/js/factories/Documentation.js +0 -3
  141. data/lib/api_browser/app/js/factories/normalize_attributes.js +19 -0
  142. data/lib/api_browser/app/js/factories/template_for.js +113 -0
  143. data/lib/api_browser/app/sass/modules/_body.scss +26 -4
  144. data/lib/api_browser/app/sass/modules/_sidebar.scss +68 -1
  145. data/lib/api_browser/app/sass/praxis.scss +1 -5
  146. data/lib/api_browser/app/sass/variables/_bootstrap-variables.scss +13 -4
  147. data/lib/api_browser/app/views/action.html +13 -17
  148. data/lib/api_browser/app/views/controller.html +32 -4
  149. data/lib/api_browser/app/views/directives/attribute_description.html +1 -1
  150. data/lib/api_browser/app/views/directives/attribute_description/{_default.html → default.html} +0 -0
  151. data/lib/api_browser/app/views/directives/attribute_description/example.html +13 -0
  152. data/lib/api_browser/app/views/directives/attribute_description/headers.html +8 -0
  153. data/lib/api_browser/app/views/directives/attribute_description/member_options.html +4 -0
  154. data/lib/api_browser/app/views/directives/attribute_description/values.html +14 -0
  155. data/lib/api_browser/app/views/directives/attribute_table.html +2 -2
  156. data/lib/api_browser/app/views/home.html +1 -3
  157. data/lib/api_browser/app/views/layout.html +3 -36
  158. data/lib/api_browser/app/views/menu.html +45 -0
  159. data/lib/api_browser/app/views/navbar.html +1 -1
  160. data/lib/api_browser/app/views/type.html +2 -2
  161. data/lib/api_browser/app/views/type/{_details.html → details.html} +6 -6
  162. data/lib/api_browser/app/views/types/embedded/default.html +10 -0
  163. data/lib/api_browser/app/views/types/embedded/links.html +11 -0
  164. data/lib/api_browser/app/views/types/embedded/struct.html +2 -0
  165. data/lib/api_browser/app/views/types/label/link.html +1 -0
  166. data/lib/api_browser/app/views/types/label/primitive.html +1 -0
  167. data/lib/api_browser/app/views/types/label/primitive_collection.html +1 -0
  168. data/lib/api_browser/app/views/types/label/type.html +1 -0
  169. data/lib/api_browser/app/views/types/label/type_collection.html +1 -0
  170. data/lib/api_browser/app/views/{directives/request_body/_default.html → types/standalone/default.html} +1 -1
  171. data/lib/api_browser/app/views/types/standalone/struct.html +1 -0
  172. data/lib/api_browser/bower.json +9 -9
  173. data/lib/api_browser/package.json +1 -1
  174. data/lib/praxis.rb +10 -4
  175. data/lib/praxis/action_definition.rb +16 -4
  176. data/lib/praxis/action_definition/headers_dsl_compiler.rb +5 -2
  177. data/lib/praxis/api_definition.rb +3 -1
  178. data/lib/praxis/api_general_info.rb +49 -5
  179. data/lib/praxis/application.rb +12 -4
  180. data/lib/praxis/bootloader.rb +1 -0
  181. data/lib/praxis/bootloader_stages/environment.rb +2 -0
  182. data/lib/praxis/bootloader_stages/routing.rb +1 -1
  183. data/lib/praxis/bootloader_stages/subgroup_loader.rb +1 -0
  184. data/lib/praxis/exceptions/validation.rb +7 -0
  185. data/lib/praxis/handlers/plain.rb +16 -0
  186. data/lib/praxis/handlers/xml.rb +4 -4
  187. data/lib/praxis/links.rb +13 -3
  188. data/lib/praxis/media_type_identifier.rb +3 -0
  189. data/lib/praxis/multipart/parser.rb +41 -48
  190. data/lib/praxis/multipart/part.rb +196 -3
  191. data/lib/praxis/request.rb +14 -11
  192. data/lib/praxis/request_stages/request_stage.rb +4 -0
  193. data/lib/praxis/request_stages/response.rb +10 -9
  194. data/lib/praxis/request_stages/validate.rb +1 -7
  195. data/lib/praxis/request_stages/validate_params_and_headers.rb +30 -5
  196. data/lib/praxis/request_stages/validate_payload.rb +14 -5
  197. data/lib/praxis/resource_definition.rb +117 -15
  198. data/lib/praxis/response.rb +6 -5
  199. data/lib/praxis/response_definition.rb +51 -5
  200. data/lib/praxis/responses/http.rb +5 -0
  201. data/lib/praxis/responses/multipart_ok.rb +51 -0
  202. data/lib/praxis/responses/validation_error.rb +7 -7
  203. data/lib/praxis/restful_doc_generator.rb +9 -4
  204. data/lib/praxis/route.rb +3 -2
  205. data/lib/praxis/router.rb +26 -16
  206. data/lib/praxis/router/rack.rb +51 -0
  207. data/lib/praxis/router/simple.rb +146 -0
  208. data/lib/praxis/routing_config.rb +2 -2
  209. data/lib/praxis/trait.rb +1 -1
  210. data/lib/praxis/types/fuzzy_hash.rb +49 -0
  211. data/lib/praxis/types/media_type_common.rb +1 -1
  212. data/lib/praxis/types/multipart.rb +47 -12
  213. data/lib/praxis/types/multipart_array.rb +320 -0
  214. data/lib/praxis/types/multipart_array/part_definition.rb +52 -0
  215. data/lib/praxis/validation_handler.rb +10 -0
  216. data/lib/praxis/version.rb +2 -2
  217. data/praxis.gemspec +3 -3
  218. data/spec/api_browser/directives/type_placeholder_spec.js +134 -0
  219. data/spec/api_browser/factories/normalize_attributes_spec.js +97 -0
  220. data/spec/api_browser/factories/template_for_spec.js +67 -0
  221. data/spec/functional_spec.rb +111 -45
  222. data/spec/praxis/action_definition_spec.rb +31 -7
  223. data/spec/praxis/api_definition_spec.rb +2 -2
  224. data/spec/praxis/api_general_info_spec.rb +25 -0
  225. data/spec/praxis/application_spec.rb +24 -11
  226. data/spec/praxis/handlers/xml_spec.rb +55 -33
  227. data/spec/praxis/links_spec.rb +18 -1
  228. data/spec/praxis/media_type_collection_spec.rb +1 -1
  229. data/spec/praxis/media_type_spec.rb +2 -2
  230. data/spec/praxis/multipart/parser_spec.rb +21 -13
  231. data/spec/praxis/plugins/praxis_mapper_plugin_spec.rb +1 -1
  232. data/spec/praxis/request_spec.rb +52 -24
  233. data/spec/praxis/{request_stages_action_spec.rb → request_stages/action_spec.rb} +1 -1
  234. data/spec/praxis/{request_stage_spec.rb → request_stages/request_stage_spec.rb} +0 -0
  235. data/spec/praxis/{request_stages_validate_spec.rb → request_stages/validate_spec.rb} +1 -1
  236. data/spec/praxis/resource_definition_spec.rb +30 -4
  237. data/spec/praxis/response_definition_spec.rb +60 -19
  238. data/spec/praxis/response_spec.rb +2 -2
  239. data/spec/praxis/responses/validation_error_spec.rb +33 -16
  240. data/spec/praxis/route_spec.rb +4 -2
  241. data/spec/praxis/router_spec.rb +28 -12
  242. data/spec/praxis/routing_config_spec.rb +11 -5
  243. data/spec/praxis/types/collection_spec.rb +1 -1
  244. data/spec/praxis/types/fuzzy_hash_spec.rb +20 -0
  245. data/spec/praxis/types/multipart_array/part_definition_spec.rb +5 -0
  246. data/spec/praxis/types/multipart_array_spec.rb +334 -0
  247. data/spec/praxis/types/multipart_spec.rb +14 -5
  248. data/spec/spec_app/app/controllers/instances.rb +20 -10
  249. data/spec/spec_app/app/controllers/volumes.rb +8 -4
  250. data/spec/spec_app/app/responses/bulk_response.rb +0 -6
  251. data/spec/spec_app/config/environment.rb +13 -0
  252. data/spec/spec_app/design/api.rb +7 -10
  253. data/spec/spec_app/design/media_types/instance.rb +3 -1
  254. data/spec/spec_app/design/resources/instances.rb +50 -41
  255. data/spec/spec_app/design/resources/volume_snapshots.rb +39 -0
  256. data/spec/spec_app/design/resources/volumes.rb +11 -6
  257. data/spec/spec_helper.rb +3 -1
  258. metadata +125 -218
  259. data/lib/api_browser/app/bower_components/angular-ui-router/src/compat.js +0 -146
  260. data/lib/api_browser/app/bower_components/bootstrap-sass/CNAME +0 -1
  261. data/lib/api_browser/app/bower_components/bootstrap-sass/DOCS-LICENSE +0 -319
  262. data/lib/api_browser/app/bower_components/bootstrap-sass/Gemfile +0 -5
  263. data/lib/api_browser/app/bower_components/bootstrap-sass/Gemfile.lock +0 -14
  264. data/lib/api_browser/app/bower_components/bootstrap-sass/Gruntfile.js +0 -244
  265. data/lib/api_browser/app/bower_components/bootstrap-sass/LICENSE +0 -176
  266. data/lib/api_browser/app/bower_components/bootstrap-sass/LICENSE-MIT +0 -21
  267. data/lib/api_browser/app/bower_components/bootstrap-sass/Rakefile +0 -44
  268. data/lib/api_browser/app/bower_components/bootstrap-sass/_config.yml +0 -25
  269. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/ads.html +0 -1
  270. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/footer.html +0 -34
  271. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/header.html +0 -42
  272. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-about.html +0 -12
  273. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-components.html +0 -137
  274. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-css.html +0 -99
  275. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-customize.html +0 -40
  276. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-getting-started.html +0 -44
  277. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-javascript.html +0 -88
  278. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/nav-main.html +0 -37
  279. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/old-bs-docs.html +0 -8
  280. data/lib/api_browser/app/bower_components/bootstrap-sass/_includes/social-buttons.html +0 -16
  281. data/lib/api_browser/app/bower_components/bootstrap-sass/_layouts/default.html +0 -79
  282. data/lib/api_browser/app/bower_components/bootstrap-sass/_layouts/home.html +0 -47
  283. data/lib/api_browser/app/bower_components/bootstrap-sass/about.html +0 -93
  284. data/lib/api_browser/app/bower_components/bootstrap-sass/browserstack.json +0 -37
  285. data/lib/api_browser/app/bower_components/bootstrap-sass/components.html +0 -3689
  286. data/lib/api_browser/app/bower_components/bootstrap-sass/composer.json +0 -28
  287. data/lib/api_browser/app/bower_components/bootstrap-sass/css.html +0 -2674
  288. data/lib/api_browser/app/bower_components/bootstrap-sass/customize.html +0 -1715
  289. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/css/bootstrap-theme.css +0 -427
  290. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/css/bootstrap-theme.min.css +0 -1
  291. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/css/bootstrap.css +0 -6350
  292. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/css/bootstrap.min.css +0 -1
  293. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/js/bootstrap.js +0 -2002
  294. data/lib/api_browser/app/bower_components/bootstrap-sass/dist/js/bootstrap.min.js +0 -9
  295. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/css/docs.css +0 -1195
  296. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/css/pygments-manni.css +0 -66
  297. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/ico/apple-touch-icon-144-precomposed.png +0 -0
  298. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/ico/favicon.png +0 -0
  299. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/application.js +0 -103
  300. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/customizer.js +0 -332
  301. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/filesaver.js +0 -169
  302. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/holder.js +0 -404
  303. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/ie8-responsive-file-warning.js +0 -12
  304. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/jszip.js +0 -1467
  305. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/less.js +0 -9
  306. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/raw-files.js +0 -3
  307. data/lib/api_browser/app/bower_components/bootstrap-sass/docs-assets/js/uglify.js +0 -14
  308. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/carousel/carousel.css +0 -148
  309. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/carousel/index.html +0 -206
  310. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/grid/grid.css +0 -28
  311. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/grid/index.html +0 -148
  312. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/jumbotron-narrow/index.html +0 -82
  313. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/jumbotron-narrow/jumbotron-narrow.css +0 -79
  314. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/jumbotron/index.html +0 -99
  315. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/jumbotron/jumbotron.css +0 -5
  316. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/justified-nav/index.html +0 -83
  317. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/justified-nav/justified-nav.css +0 -88
  318. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar-fixed-top/index.html +0 -91
  319. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar-fixed-top/navbar-fixed-top.css +0 -4
  320. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar-static-top/index.html +0 -92
  321. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar-static-top/navbar-static-top.css +0 -7
  322. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar/index.html +0 -88
  323. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/navbar/navbar.css +0 -8
  324. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/non-responsive/index.html +0 -101
  325. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/non-responsive/non-responsive.css +0 -116
  326. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/offcanvas/index.html +0 -130
  327. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/offcanvas/offcanvas.css +0 -50
  328. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/offcanvas/offcanvas.js +0 -5
  329. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/carousel.jpg +0 -0
  330. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/grid.jpg +0 -0
  331. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/jumbotron-narrow.jpg +0 -0
  332. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/jumbotron.jpg +0 -0
  333. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/justified-nav.jpg +0 -0
  334. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/navbar-fixed.jpg +0 -0
  335. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/navbar-static.jpg +0 -0
  336. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/navbar.jpg +0 -0
  337. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/non-responsive.jpg +0 -0
  338. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/offcanvas.jpg +0 -0
  339. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/sign-in.jpg +0 -0
  340. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/starter-template.jpg +0 -0
  341. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/sticky-footer-navbar.jpg +0 -0
  342. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/sticky-footer.jpg +0 -0
  343. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/screenshots/theme.jpg +0 -0
  344. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/signin/index.html +0 -50
  345. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/signin/signin.css +0 -40
  346. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/starter-template/index.html +0 -68
  347. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/starter-template/starter-template.css +0 -7
  348. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/sticky-footer-navbar/index.html +0 -91
  349. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/sticky-footer-navbar/sticky-footer-navbar.css +0 -45
  350. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/sticky-footer/index.html +0 -55
  351. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/sticky-footer/sticky-footer.css +0 -38
  352. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/theme/index.html +0 -384
  353. data/lib/api_browser/app/bower_components/bootstrap-sass/examples/theme/theme.css +0 -14
  354. data/lib/api_browser/app/bower_components/bootstrap-sass/fonts/glyphicons-halflings-regular.eot +0 -0
  355. data/lib/api_browser/app/bower_components/bootstrap-sass/fonts/glyphicons-halflings-regular.svg +0 -229
  356. data/lib/api_browser/app/bower_components/bootstrap-sass/fonts/glyphicons-halflings-regular.ttf +0 -0
  357. data/lib/api_browser/app/bower_components/bootstrap-sass/fonts/glyphicons-halflings-regular.woff +0 -0
  358. data/lib/api_browser/app/bower_components/bootstrap-sass/getting-started.html +0 -1021
  359. data/lib/api_browser/app/bower_components/bootstrap-sass/index.html +0 -16
  360. data/lib/api_browser/app/bower_components/bootstrap-sass/javascript.html +0 -1983
  361. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/index.html +0 -52
  362. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/affix.js +0 -25
  363. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/alert.js +0 -62
  364. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/button.js +0 -116
  365. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/carousel.js +0 -87
  366. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/collapse.js +0 -164
  367. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/dropdown.js +0 -219
  368. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/modal.js +0 -196
  369. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/phantom.js +0 -69
  370. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/popover.js +0 -133
  371. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/scrollspy.js +0 -37
  372. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/tab.js +0 -86
  373. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/tooltip.js +0 -437
  374. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/unit/transition.js +0 -13
  375. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/vendor/jquery.js +0 -6
  376. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/vendor/qunit.css +0 -232
  377. data/lib/api_browser/app/bower_components/bootstrap-sass/js/tests/vendor/qunit.js +0 -1510
  378. data/lib/api_browser/app/bower_components/bootstrap-sass/package.json +0 -40
  379. data/lib/api_browser/app/bower_components/lodash/dist/lodash.compat.js +0 -7157
  380. data/lib/api_browser/app/bower_components/lodash/dist/lodash.compat.min.js +0 -61
  381. data/lib/api_browser/app/bower_components/lodash/dist/lodash.js +0 -6785
  382. data/lib/api_browser/app/bower_components/lodash/dist/lodash.min.js +0 -56
  383. data/lib/api_browser/app/bower_components/lodash/dist/lodash.underscore.js +0 -4979
  384. data/lib/api_browser/app/bower_components/lodash/dist/lodash.underscore.min.js +0 -39
  385. data/lib/api_browser/app/js/directives/attribute_table_row.js +0 -17
  386. data/lib/api_browser/app/js/directives/request_body.js +0 -25
  387. data/lib/api_browser/app/js/directives/request_headers.js +0 -17
  388. data/lib/api_browser/app/js/directives/request_parameters.js +0 -17
  389. data/lib/api_browser/app/js/directives/type_label.js +0 -52
  390. data/lib/api_browser/app/js/factories/PayloadTemplates.js +0 -10
  391. data/lib/api_browser/app/js/factories/TemplateProvider.js +0 -45
  392. data/lib/api_browser/app/js/factories/TypeTemplates.js +0 -11
  393. data/lib/api_browser/app/views/directives/attribute_description/_example.html +0 -13
  394. data/lib/api_browser/app/views/directives/attribute_description/_headers.html +0 -8
  395. data/lib/api_browser/app/views/directives/attribute_table_row/_default.html +0 -10
  396. data/lib/api_browser/app/views/directives/attribute_table_row/_links.html +0 -11
  397. data/lib/api_browser/app/views/directives/attribute_table_row/_struct.html +0 -2
  398. data/lib/api_browser/app/views/directives/request_body/_struct.html +0 -1
  399. data/lib/api_browser/app/views/resource/_actions.html +0 -27
@@ -3,17 +3,19 @@ require 'spec_helper'
3
3
  describe Praxis::Route do
4
4
 
5
5
  let(:verb) { 'GET' }
6
- let(:path) { '/stuff' }
6
+ let(:path) { '/base/stuff' }
7
+ let(:prefixed_path) { '/stuff' }
7
8
  let(:name) { nil }
8
9
  let(:version) { '1.0' }
9
10
  let(:options) { {} }
10
11
 
11
- subject(:route) { Praxis::Route.new(verb, path, version, name: name, **options) }
12
+ subject(:route) { Praxis::Route.new(verb, path, version, name: name, prefixed_path: prefixed_path, **options) }
12
13
 
13
14
  its(:verb) { should be(verb) }
14
15
  its(:path) { should be(path) }
15
16
  its(:name) { should be(name) }
16
17
  its(:version) { should be(version) }
18
+ its(:prefixed_path) { should eq(prefixed_path) }
17
19
  its(:options) { should eq(options) }
18
20
 
19
21
  it 'defaults version to "n/a"' do
@@ -19,14 +19,14 @@ describe Praxis::Router do
19
19
  let(:env){ {"HTTP_X_API_VERSION" => request_version } }
20
20
  let(:request) {Praxis::Request.new(env)}
21
21
 
22
- #let(:request){ double("request", version: request_version, env: env ) }
23
22
  context 'with matching versions' do
24
23
  let(:request_version) { "1.0" }
25
24
  it 'calls the target' do
26
- expect( target ).to receive(:call).with(request)
25
+ expect(target).to receive(:call).with(request)
27
26
  matcher.call(request)
28
27
  end
29
28
  end
29
+
30
30
  context 'with non-matching versions' do
31
31
  let(:request_version) { "4.0" }
32
32
  before do
@@ -80,14 +80,21 @@ describe Praxis::Router do
80
80
  let(:target){ double('target') }
81
81
  let(:verb_router){ double('verb_router') }
82
82
 
83
- it 'wraps the target with a VersionMatcher' do
84
- router.instance_variable_set( :@routes, {'verb'=>verb_router} ) # Ugly, but no need to have a reader
85
- expect(verb_router).to receive(:on) do|path, args|# .with(route.path, call: "foo")
86
- expect(path).to eq(route.path)
87
- expect(args).to be_kind_of(Hash)
88
- expect(args[:call]).to be_kind_of(Praxis::Router::VersionMatcher)
83
+ let(:resource_definition) { double('resource_definition', version_options: {using: [:header, :params]} ) }
84
+ let(:action) { double('action', resource_definition: resource_definition) }
85
+ let(:target) { double('target', action: action) }
86
+
87
+
88
+ context 'with params or header versioning' do
89
+ it 'wraps the target with a VersionMatcher' do
90
+ router.instance_variable_set( :@routes, {'verb'=>verb_router} ) # Ugly, but no need to have a reader
91
+ expect(verb_router).to receive(:on) do|path, args|# .with(route.path, call: "foo")
92
+ expect(path).to eq(route.path)
93
+ expect(args).to be_kind_of(Hash)
94
+ expect(args[:call]).to be_kind_of(Praxis::Router::VersionMatcher)
95
+ end
96
+ router.add_route(target, route)
89
97
  end
90
- router.add_route(target ,route)
91
98
  end
92
99
 
93
100
  end
@@ -103,13 +110,18 @@ describe Praxis::Router do
103
110
  let(:router_response_for_wildcard){ "* result" }
104
111
  let(:post_target_router){ double("POST target", call: router_response_for_post) }
105
112
  let(:any_target_router){ double("ANY target", call: router_response_for_wildcard) }
113
+
114
+ let(:resource_definition) { double('resource_definition', version_options: {using: [:header, :params]} ) }
115
+ let(:action) { double('action', resource_definition: resource_definition) }
116
+ let(:target) { double('target', action: action) }
117
+
106
118
  before do
107
119
  env['HTTP_X_API_VERSION'] = request_version if request_version
108
120
  allow_any_instance_of(Praxis::Router::RequestRouter).
109
121
  to receive(:call).with(request).and_return(router_response)
110
- router.add_route(double("P"),double("route1", verb: 'POST', path: '/', options: {} , version: request_version))
122
+ router.add_route(target,double("route1", verb: 'POST', path: '/', options: {} , version: request_version))
111
123
  # Hijack the callable block in the routes (since there's no way to point back to the registered route object)
112
- router.instance_variable_get( :@routes )['POST'] = post_target_router
124
+ router.instance_variable_get(:@routes)['POST'] = post_target_router
113
125
 
114
126
  end
115
127
 
@@ -130,8 +142,12 @@ describe Praxis::Router do
130
142
  end
131
143
 
132
144
  context 'for routes with wildcards (a POST and a * route)' do
145
+ let(:resource_definition) { double('resource_definition', version_options: {using: [:header, :params]} ) }
146
+ let(:action) { double('action', resource_definition: resource_definition) }
147
+ let(:target) { double('target', action: action) }
148
+
133
149
  before do
134
- router.add_route(double("*"),double("route2", verb: 'ANY', path: '/*', options: {} , version: request_version))
150
+ router.add_route(target,double("route2", verb: 'ANY', path: '/*', options: {} , version: request_version))
135
151
  # Hijack the callable block in the routes (since there's no way to point back to the registered route object)
136
152
  router.instance_variable_get( :@routes )['ANY'] = any_target_router
137
153
  end
@@ -10,9 +10,10 @@ describe Praxis::RoutingConfig do
10
10
  end
11
11
 
12
12
  let(:routing_block) { Proc.new{} }
13
+ let(:base_path){ '' }
13
14
  let(:default_route_prefix) { "/" + resource_definition.name.split("::").last.underscore }
14
15
 
15
- subject(:routing_config){ Praxis::RoutingConfig.new(&routing_block) }
16
+ subject(:routing_config){ Praxis::RoutingConfig.new(base: base_path, &routing_block) }
16
17
 
17
18
  its(:version) { should eq('n/a') }
18
19
  its(:prefix ) { should eq('') }
@@ -40,6 +41,7 @@ describe Praxis::RoutingConfig do
40
41
  context '#add_route' do
41
42
  let(:path) { '/people' }
42
43
  let(:options) { {} }
44
+ let(:base_path){ '/api' }
43
45
  let(:route) { routing_config.add_route 'GET', path, **options}
44
46
 
45
47
  it 'returns a corresponding Praxis::Route' do
@@ -58,12 +60,12 @@ describe Praxis::RoutingConfig do
58
60
  end
59
61
 
60
62
  it 'does NOT pass the name option down to mustermann' do
61
- expect(Mustermann).to receive(:new).with(path, hash_excluding({name: 'alternative'}))
63
+ expect(Mustermann).to receive(:new).with(base_path + path, hash_excluding({name: 'alternative'}))
62
64
  expect(route.name).to eq('alternative')
63
65
  end
64
66
 
65
67
  it 'passes them through the underlying mustermann object (telling it to ignore unknown ones)' do
66
- expect(Mustermann).to receive(:new).with(path, hash_including(ignore_unknown_options: true, except: '/special'))
68
+ expect(Mustermann).to receive(:new).with(base_path + path, hash_including(ignore_unknown_options: true, except: '/special'))
67
69
  expect(route.options).to eq( { except: '/special' })
68
70
  end
69
71
  end
@@ -74,13 +76,17 @@ describe Praxis::RoutingConfig do
74
76
  end
75
77
 
76
78
  it 'includes the prefix in the route path' do
77
- expect(route.path.to_s).to eq '/parents/:parent_id/people'
79
+ expect(route.path.to_s).to eq '/api/parents/:parent_id/people'
80
+ end
81
+
82
+ it 'has the right prefixed_path' do
83
+ expect(route.prefixed_path).to eq '/parents/:parent_id/people'
78
84
  end
79
85
 
80
86
  context 'for paths beginning with //' do
81
87
  let(:path) { '//people' }
82
88
  it 'does not include the prefix in the route path' do
83
- expect(route.path.to_s).to eq '/people'
89
+ expect(route.path.to_s).to eq '/api/people'
84
90
  end
85
91
  end
86
92
  end
@@ -90,7 +90,7 @@ describe Praxis::Collection do
90
90
 
91
91
 
92
92
  context 'for members' do
93
- let(:volume_output) { example.render(:default) }
93
+ let(:volume_output) { example.render(view: :default) }
94
94
 
95
95
  subject(:output) { volume_output[:snapshots] }
96
96
 
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ describe Praxis::Types::FuzzyHash do
4
+
5
+ let(:initial_value) {{
6
+ 'key' => 'value',
7
+ /bob/ => 'rob',
8
+ /\d+/ => 'one'
9
+ }}
10
+
11
+ subject(:hash) { Praxis::Types::FuzzyHash.new(initial_value) }
12
+
13
+ its(['key']) { should eq 'value' }
14
+ its([/bob/]) { should eq 'rob' }
15
+ its(['bobby']) { should eq 'rob' }
16
+
17
+ its([1]) { should eq 'one' }
18
+ its(['1']) { should eq 'one' }
19
+ end
20
+
@@ -0,0 +1,5 @@
1
+ require "spec_helper"
2
+
3
+ describe Praxis::Types::MultipartArray::PartDefinition do
4
+ end
5
+
@@ -0,0 +1,334 @@
1
+ require "spec_helper"
2
+
3
+ describe Praxis::Types::MultipartArray do
4
+
5
+ let(:type) do
6
+ Class.new(Praxis::Types::MultipartArray) do
7
+ self.options[:case_insensitive_load] = true
8
+
9
+ part 'title', String, required: true
10
+ part(/nam/, String, regexp: /Bob/i)
11
+
12
+ part /stuff/ do
13
+ payload Hash
14
+ end
15
+
16
+ file 'files', multiple: true do
17
+ header 'Content-Type', 'application/octet-stream'
18
+ filename String, regexp: /file/
19
+ payload Attributor::Tempfile
20
+ end
21
+
22
+ part 'image', Attributor::Tempfile, filename: true
23
+
24
+ end
25
+ end
26
+
27
+
28
+ let(:form) do
29
+ form_data = MIME::Multipart::FormData.new
30
+ entity = MIME::Text.new('Bob')
31
+ form_data.add entity,'name'
32
+
33
+ entity = MIME::Text.new('Captain')
34
+ form_data.add entity,'title'
35
+
36
+ entity = MIME::Application.new('file1')
37
+ form_data.add entity,'files', 'file1'
38
+
39
+ entity = MIME::Application.new('file2')
40
+ form_data.add entity,'files', 'file2'
41
+
42
+ entity = MIME::Application.new('
43
+ <?xml version="1.0" encoding="UTF-8"?>
44
+ <hash>
45
+ <first_name>James</first_name>
46
+ </hash>
47
+ ', 'xml')
48
+ form_data.add entity,'stuff1'
49
+
50
+ entity = MIME::Application.new('{"first_name": "Frank"}', 'json')
51
+ form_data.add entity,'stuff2'
52
+
53
+ entity = MIME::Application.new('', 'jpg')
54
+ form_data.add entity,'image', 'image.jpg'
55
+
56
+ form_data
57
+ end
58
+
59
+ let(:content_type) { form.headers.get('Content-Type') }
60
+ let(:body) { form.body.to_s }
61
+
62
+ subject(:payload) { type.load(body, content_type: content_type) }
63
+
64
+ it 'validates' do
65
+ part = payload.part('files').first
66
+ expect(payload.validate).to be_empty
67
+ end
68
+
69
+ it 'loads parts correctly' do
70
+ expect(payload.part('name')).to be_kind_of(Praxis::MultipartPart)
71
+ expect(payload.part('name').payload).to eq 'Bob'
72
+
73
+ title = payload.part('title')
74
+ expect(title.payload).to eq 'Captain'
75
+
76
+ files = payload.part('files')
77
+ expect(files).to have(2).items
78
+
79
+ stuff1 = payload.part('stuff1')
80
+ expect(stuff1.payload['first_name']).to eq 'James'
81
+
82
+ stuff2 = payload.part('stuff2')
83
+ expect(stuff2.payload['first_name']).to eq 'Frank'
84
+
85
+ image = payload.part('image')
86
+ expect(image.filename).to eq 'image.jpg'
87
+ end
88
+
89
+ context 'with only payload_type defined' do
90
+ let(:type) do
91
+ Class.new(Praxis::Types::MultipartArray) do
92
+ name_type String
93
+ payload_type Hash do
94
+ key 'sub_hash', Hash
95
+ end
96
+ end
97
+ end
98
+
99
+ let(:json_payload) { {sub_hash: {key:'value'}}.to_json }
100
+ let(:body) { StringIO.new("--boundary\r\nContent-Disposition: form-data; name=blah\r\n\r\n#{json_payload}\r\n--boundary--") }
101
+ let(:content_type) { "multipart/form-data; boundary=boundary" }
102
+
103
+ it do
104
+ expect(payload.part('blah').payload['sub_hash']).to eq('key' => 'value')
105
+ end
106
+ end
107
+
108
+ context '.describe' do
109
+ subject(:description) { type.describe(false) }
110
+
111
+ its([:name]) { should eq 'Praxis::Types::MultipartArray' }
112
+
113
+ it { should have_key :part_name }
114
+ it { should have_key :attributes }
115
+ it { should have_key :pattern_attributes }
116
+
117
+ context 'attributes' do
118
+ subject(:attributes) { description[:attributes] }
119
+ its(:keys) { should match_array ['title', 'files', 'image']}
120
+
121
+ context 'the "title" part' do
122
+ subject(:title_description) { attributes['title'] }
123
+
124
+ it 'describes the options' do
125
+ expect(title_description[:options][:required]).to be true
126
+ end
127
+
128
+ it 'describes the payload' do
129
+ expect(title_description[:type][:payload][:type]).to eq Attributor::String.describe
130
+ end
131
+ end
132
+
133
+ context 'the "files" part' do
134
+ subject(:files_description) { attributes['files'] }
135
+
136
+ it 'describes the options' do
137
+ expect(files_description[:options][:multiple]).to be true
138
+ end
139
+
140
+ it 'describes the payload' do
141
+ expect(files_description[:type][:payload][:type]).to eq Attributor::Tempfile.describe
142
+ end
143
+
144
+ it 'describes the filename' do
145
+ filename = files_description[:type][:filename]
146
+ expect(filename[:options]).to eq(regexp: /file/)
147
+ expect(filename[:type]).to eq Attributor::String.describe
148
+ end
149
+
150
+ end
151
+ end
152
+
153
+ context 'pattern attributes' do
154
+ subject(:pattern_attributes) { description[:pattern_attributes] }
155
+ its(:keys) { should match_array ['nam', 'stuff']}
156
+ end
157
+
158
+ context 'with no parts defined' do
159
+ let(:type) do
160
+ Class.new(Praxis::Types::MultipartArray) do
161
+ name_type DateTime
162
+ payload_type Hash
163
+ end
164
+ end
165
+ its([:name]) { should eq 'Praxis::Types::MultipartArray' }
166
+
167
+ it { should_not have_key :attributes }
168
+ it { should_not have_key :pattern_attributes }
169
+
170
+ it { should have_key :part_name }
171
+ it { should have_key :part_payload }
172
+ end
173
+
174
+ context 'with an example passed in' do
175
+ let(:example) { type.example }
176
+ subject(:description) { type.describe(false, example: example) }
177
+
178
+ it 'uses the example values' do
179
+ expect(
180
+ description[:attributes]['title'][:type][:payload][:example]
181
+ ).to eq example.part('title').payload
182
+
183
+ file_example = example.part('files').first.payload
184
+ file_example.rewind
185
+ expect(
186
+ description[:attributes]['files'][:type][:payload][:example]
187
+ ).to eq file_example.read
188
+
189
+ image_example = example.part('image').payload
190
+ image_example.rewind
191
+ expect(
192
+ description[:attributes]['image'][:type][:payload][:example]
193
+ ).to eq image_example.read
194
+ end
195
+ end
196
+ end
197
+
198
+ context 'dumping' do
199
+ subject(:dumped) { payload.dump }
200
+
201
+ it 'dumps' do
202
+ loaded = type.load(dumped, content_type: payload.content_type)
203
+ end
204
+ context 'an example' do
205
+ let(:payload) { type.example }
206
+
207
+ it 'dumps' do
208
+ loaded = type.load(dumped, content_type: payload.content_type)
209
+ end
210
+ end
211
+ end
212
+
213
+ context 'with errors' do
214
+ let(:form) do
215
+ form_data = MIME::Multipart::FormData.new
216
+
217
+ entity = MIME::Text.new('James')
218
+ form_data.add entity,'name'
219
+
220
+
221
+ entity = MIME::Text.new('file1')
222
+ form_data.add entity,'files', 'file1'
223
+
224
+ form_data
225
+ end
226
+
227
+ subject(:errors) { payload.validate }
228
+
229
+ it 'validates part headers' do
230
+ expect(errors).to have(3).items
231
+ expect(errors).to match_array([
232
+ %r|\.name\.payload value .* does not match regexp|,
233
+ %r|\.files\.headers.* is not within the allowed values|,
234
+ %r|\.title is required|
235
+ ])
236
+ end
237
+ end
238
+
239
+ context '.example' do
240
+ subject(:payload) { type.example }
241
+
242
+ it 'generates parts' do
243
+ title = payload.part('title')
244
+ expect(title).to_not be_nil
245
+ expect(title.payload).to match /\w+/
246
+
247
+ files = payload.part('files')
248
+ expect(files).to have(2).items
249
+
250
+ files.each do |file|
251
+ expect(file.payload).to be_kind_of(Tempfile)
252
+ expect(file.filename).to match /\w+/
253
+
254
+ expect(file.headers['Content-Type']).to eq 'application/octet-stream'
255
+ end
256
+ end
257
+
258
+ it 'is valid' do
259
+ expect(payload.validate).to have(0).items
260
+ end
261
+
262
+ end
263
+
264
+ context 'with a hackish default part definition' do
265
+ let(:type) do
266
+ Class.new(Praxis::Types::MultipartArray) do
267
+ self.options[:case_insensitive_load] = true
268
+
269
+ part /\d+/, Instance
270
+ end
271
+ end
272
+
273
+ let(:form) do
274
+ form_data = MIME::Multipart::FormData.new
275
+
276
+ (1..5).each do |i|
277
+ instance = Instance.example("instance-#{i}")
278
+ body = JSON.pretty_generate(instance.render)
279
+ entity = MIME::Text.new(body)
280
+ form_data.add entity,i.to_s
281
+ end
282
+
283
+ form_data
284
+ end
285
+
286
+ it 'loads the parts as the proper type' do
287
+ payload.each do |part|
288
+ expect(part.payload).to be_kind_of(Instance)
289
+ end
290
+ end
291
+
292
+ end
293
+
294
+
295
+ context 'anonymous generation' do
296
+ let(:definition_block) do
297
+ proc do
298
+ name_type Integer
299
+ payload_type Instance
300
+ end
301
+ end
302
+
303
+ let(:attribute) do
304
+ Attributor::Attribute.new(Praxis::Types::MultipartArray, &definition_block)
305
+ end
306
+
307
+ let(:form) do
308
+ form_data = MIME::Multipart::FormData.new
309
+
310
+ (1..5).each do |i|
311
+ instance = Instance.example("instance-#{i}")
312
+ body = JSON.pretty_generate(instance.render)
313
+ entity = MIME::Text.new(body)
314
+ form_data.add entity,i.to_s
315
+ end
316
+
317
+ form_data
318
+ end
319
+
320
+ let(:payload) { attribute.load(body, content_type: content_type) }
321
+
322
+ it 'loads the parts as the proper type' do
323
+ expect(payload).to have(5).items
324
+ payload.each do |part|
325
+ expect(part.name).to be_kind_of(Integer)
326
+ expect(part.payload).to be_kind_of(Instance)
327
+ end
328
+ end
329
+
330
+
331
+ end
332
+
333
+
334
+ end