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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c5592e4df1c096fb27aa06c022cb950183635504
4
- data.tar.gz: 681b9a079009dfe1b818018ed8c540722cfda404
3
+ metadata.gz: 4b0b0ef00becfafd5985cca205bc28dc4b40e03d
4
+ data.tar.gz: b9ca759b19c08d11b3cff9b0ef57266b8dcdd79d
5
5
  SHA512:
6
- metadata.gz: ed883f867ad4143adfa89ce11404feb45ef00505470529f5cdb95bad7dd40a38f307c339505f8973d5e0a75c0053267be3e3dd48b627051caf2878e0f4d0b72f
7
- data.tar.gz: 28d76baeba6a3b7fd66fe82f2d16dcd997d9b9c87c5a0320201f716cb91a00c2aee14c9a5fe94dab46264cc14b5b2eec2cad95a509d4a224d7fe2262078562c3
6
+ metadata.gz: 5be12fcd7c6953e2efe8ad8e43c6fdb89042e0888dcd4f58d4c9d4c27e254e2a55cb0ec208dcd1ecb299cb3573cae74673e2c605428a68a1e5b7f88e6c937bfd
7
+ data.tar.gz: ac3a95e8de02cff3e6d8fc0a0f6c2384d1b56e0011ad516db8264056fd144df6d49b6693cd7dae3e3d247fc1262da915f190d107b6b8c034b34471117b4602ba
data/.rspec CHANGED
@@ -1,3 +1,2 @@
1
1
  --colour
2
2
  --format=Fuubar
3
- --backtrace
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.1.5
1
+ 2.2.2
data/.travis.yml CHANGED
@@ -1,7 +1,8 @@
1
1
  language: ruby
2
2
  cache: bundler
3
3
  rvm:
4
- - "2.1.5"
4
+ - 2.1.5
5
+ - 2.2.2
5
6
  node_js:
6
7
  - "0.10"
7
8
  branches:
data/CHANGELOG.md CHANGED
@@ -2,6 +2,47 @@
2
2
 
3
3
  ## next
4
4
 
5
+
6
+ ## 0.17.0
7
+
8
+ * Merges action details pages into one long page in doc browser
9
+ * Refined path-based versioning:
10
+ * Added `ApiGeneralInfo#version_with`, which defaults to `[:header, :params`] and may be set to `:path` to use path-based versioning.
11
+ * Added support for specifying an `:api_version` placeholder to the global version's `ApiGeneralInfo#base_path`.
12
+ * Deprecated `ResourceDefinition.version using: :path` option, use `ApiGeneralInfo#version_with` instead.
13
+ * Fix bug where before/after hooks set on sub-stages of `:app` would not be triggered
14
+ * Refactors the api browser to allow registering custom type templates.
15
+ * This also removes an undocumented feature that did something similar.
16
+ * Fixes an issue where Struct properties wouldn't be displayed.
17
+ * Added `endpoint` directive to global API info, only used for documentation purposes.
18
+ * Added `ResourceDefinition.parent` directive to define a parent resource.
19
+ * The parent's `canonical_path` is used as the base of the child's routes.
20
+ * Any parameters in the parent's route will also be applied as defaults in the child. The last route parameter is assumed to be an 'id'-type parameter, and is prefixed with the parent's snake-cased singular name. I.e., `id` from a `Volume` parent will be renamed to `volume_id`. Any other parameters are copied unchanged.
21
+ * This behavior can be overridden by providing a mapping hash of the form `{parent_name => child_name}` to the `parent` directive. See [VolumeSnapshots](spec/spec_app/design/resources/volume_snapshots.rb) for an example.
22
+ * Backwards incompatible Change: Refactored `ValidationError` to be more consistent with the reported fields
23
+ * Changed `message` for `summary`. Always present, and should provide a quick description of the type of error encountered. For example: "Error loading payload data"
24
+ * Semantically changed `errors` to always have the details of one or many errors that have occurred. For example: "Unknown key received: :foobar while loading $.payload.user"
25
+ * Note: if you are an application that used and tested against the previous `message` field you will need to adjust your tests to check for the values in the `summary` field and or the `errors` contents. But it will now be a much more consistent experience that will allow API clients to notify of the exact errors and details to their clients.
26
+ * Added `Application.validation_handler` to customize response generation for validation errors. See [validation_handler.rb](lib/praxis/validation_handler.rb) for default version.
27
+ * Copied mustermann's routers to praxis repo in anticipation of their removal from mustermann itself.
28
+ * Added response body validation.
29
+ * Validation is controlled by the `praxis.validate_response_bodies` boolean
30
+ config option, and uses the `media_type` defined for the response definition.
31
+ * Added `location:` option to `Responses::Created.new`.
32
+ * `ResourceDefinition.parse_href` now accepts any instance of `URI::Generic` in addition to a string.
33
+ * Fixed path generation for nested ResourceDefinitions
34
+ * Substantial changes and improvements to multipart request and response handling:
35
+ * Added `Praxis::Types::MultipartArray`, a type of `Attributor::Collection` with `Praxis::MultipartPart` members that allows the handling of duplicate named parts and unnamed ones. The new type supports defining many details about the expected structure of the parts, including headers, payloads, names and filename information. In addition, this type is able to load and validate full multipart bodies into the expected type structure, generate example objects as well as dump them into a full multipart body including boundaries and properly encoded parts following their content-types. See documentation for details and more features.
36
+ * Made `Praxis::MultipartPart` a proper `Attributor::Type`.
37
+ * Added `Praxis::Responses:MultipartOk` properly returning `MultipartArray` responses.
38
+ * Deprecated `Praxis::Multipart`. A replacement for true hash-like behavior will be added before their removal in 1.0.
39
+ * `ActionDefinition#response` now accepts an optional second `type` parameter, and optional block to further define that type. The `type` provided will be used to specify the `media_type` option to pass to the corresponding `ResponseDefinition`.
40
+ * The `header` directive inside `ActionDefinition#headers` now accepts an optional second `type` parameter that may be used to override the default `String` type that would be used.
41
+ * Added `Praxis::Handlers::Plain` encoder for 'text/plain'.
42
+ * Fixed `Praxis::Handlers::XML ` handler to transform dashes to underscores and treat empty hashes like ActiveSupport does.
43
+ * Adds hierarchival navigation to the doc browser.
44
+ * Adds a ConfigurationProvider allowing for easy doc customization.
45
+
5
46
  ## 0.16.1
6
47
 
7
48
  * Fixed a bug where documentation generation would fail if an application had headers in a Trait using the simplified `header` DSL.
data/CONTRIBUTING.md CHANGED
@@ -45,6 +45,9 @@ everything for everybody. This means that we might decide against incorporating
45
45
  a new feature. However, there might be a way to implement that feature *on top
46
46
  of* Praxis.
47
47
 
48
+ If you want to work on something that we have already reviewed and prepared,
49
+ checkout the *Ready* column on our [Waffle board](https://waffle.io/rightscale/praxis).
50
+
48
51
  ### Discuss your design on the mailing list
49
52
 
50
53
  We recommend discussing your plans on the
@@ -140,7 +140,22 @@ module.exports = function(grunt) {
140
140
  }
141
141
  },
142
142
 
143
- ngmin: {
143
+ ngAnnotate: {
144
+ options: {
145
+ add: true,
146
+ singleQuotes: true,
147
+ ngAnnotateOptions: {
148
+ plugin: [{init: function() {},
149
+ match: function(node) {
150
+ if (node.callee && node.callee.object) {
151
+ var object = node.callee.object;
152
+ if (object && object.type === 'Identifier' && object.name === 'templateForProvider' && node.callee.property.name === 'register') {
153
+ return node.arguments[0];
154
+ }
155
+ }
156
+ }}]
157
+ }
158
+ },
144
159
  dist: {
145
160
  files: [{
146
161
  expand: true,
@@ -256,11 +271,12 @@ module.exports = function(grunt) {
256
271
  'node_modules/quick_check/dist/jasmine-quick-check.js',
257
272
  'app/bower_components/jquery/dist/jquery.js',
258
273
  'app/bower_components/angular/angular.js',
259
- 'app/bower_components/lodash/dist/lodash.compat.js',
274
+ 'app/bower_components/lodash/lodash.js',
260
275
  'app/bower_components/angular-ui-router/release/angular-ui-router.js',
261
276
  'app/bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.js',
262
277
  'app/bower_components/angular-sanitize/angular-sanitize.js',
263
278
  'app/bower_components/angular-mocks/angular-mocks.js',
279
+ 'app/bower_components/showdown/compressed/Showdown.min.js',
264
280
  'app/js/app.js', 'app/js/**/*.js', '.tmp/templates.js', '../../spec/api_browser/**/*.js'
265
281
  ],
266
282
  frameworks: ['jasmine'],
@@ -324,7 +340,7 @@ module.exports = function(grunt) {
324
340
  // Updates index.html for any file added or removed
325
341
  scripts: {
326
342
  files: ['app/js/**/*.js', userDocsPath + '/**/*.js'],
327
- tasks: 'fileblocks:serve',
343
+ tasks: ['fileblocks:serve', 'wiredep'],
328
344
  options: { livereload: 9091 }
329
345
  },
330
346
 
@@ -388,7 +404,7 @@ module.exports = function(grunt) {
388
404
  'useminPrepare',
389
405
  'ngtemplates',
390
406
  'concat',
391
- 'ngmin',
407
+ 'ngAnnotate',
392
408
  'copy:dist',
393
409
  'cssmin',
394
410
  'uglify',
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "angular-mocks",
3
- "version": "1.2.28",
3
+ "version": "1.4.0",
4
4
  "main": "./angular-mocks.js",
5
5
  "ignore": [],
6
6
  "dependencies": {
7
- "angular": "1.2.28"
7
+ "angular": "1.4.0"
8
8
  },
9
9
  "homepage": "https://github.com/angular/bower-angular-mocks",
10
- "_release": "1.2.28",
10
+ "_release": "1.4.0",
11
11
  "_resolution": {
12
12
  "type": "version",
13
- "tag": "v1.2.28",
14
- "commit": "6bb9b6fd3fdb2eba0f64dc615fa55c5f0050af75"
13
+ "tag": "v1.4.0",
14
+ "commit": "5a7f9f0bad5da4314df7f638fcaf330ff864cae2"
15
15
  },
16
16
  "_source": "git://github.com/angular/bower-angular-mocks.git",
17
- "_target": "~1.2.6",
17
+ "_target": "~1.4.0",
18
18
  "_originalSource": "angular-mocks"
19
19
  }
@@ -14,10 +14,16 @@ You can install this package either with `npm` or with `bower`.
14
14
  npm install angular-mocks
15
15
  ```
16
16
 
17
- The mocks are then available at `node_modules/angular-mocks/angular-mocks.js`.
18
-
19
- Note that this package is not in CommonJS format, so doing `require('angular-mocks')` will
20
- return `undefined`.
17
+ You can `require` ngMock modules:
18
+
19
+ ```js
20
+ var angular = require('angular');
21
+ angular.module('myMod', [
22
+ require('angular-animate'),
23
+ require('angular-mocks/ngMock')
24
+ require('angular-mocks/ngAnimateMock')
25
+ ]);
26
+ ```
21
27
 
22
28
  ### bower
23
29
 
@@ -36,7 +42,7 @@ Documentation is available on the
36
42
 
37
43
  The MIT License
38
44
 
39
- Copyright (c) 2010-2012 Google, Inc. http://angularjs.org
45
+ Copyright (c) 2010-2015 Google, Inc. http://angularjs.org
40
46
 
41
47
  Permission is hereby granted, free of charge, to any person obtaining a copy
42
48
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  /**
2
- * @license AngularJS v1.2.28
3
- * (c) 2010-2014 Google, Inc. http://angularjs.org
2
+ * @license AngularJS v1.4.0
3
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
6
6
  (function(window, angular, undefined) {
@@ -53,9 +53,10 @@ angular.mock.$Browser = function() {
53
53
  self.onUrlChange = function(listener) {
54
54
  self.pollFns.push(
55
55
  function() {
56
- if (self.$$lastUrl != self.$$url) {
56
+ if (self.$$lastUrl !== self.$$url || self.$$state !== self.$$lastState) {
57
57
  self.$$lastUrl = self.$$url;
58
- listener(self.$$url);
58
+ self.$$lastState = self.$$state;
59
+ listener(self.$$url, self.$$state);
59
60
  }
60
61
  }
61
62
  );
@@ -63,17 +64,16 @@ angular.mock.$Browser = function() {
63
64
  return listener;
64
65
  };
65
66
 
67
+ self.$$applicationDestroyed = angular.noop;
66
68
  self.$$checkUrlChange = angular.noop;
67
69
 
68
- self.cookieHash = {};
69
- self.lastCookieHash = {};
70
70
  self.deferredFns = [];
71
71
  self.deferredNextId = 0;
72
72
 
73
73
  self.defer = function(fn, delay) {
74
74
  delay = delay || 0;
75
75
  self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});
76
- self.deferredFns.sort(function(a,b){ return a.time - b.time;});
76
+ self.deferredFns.sort(function(a, b) { return a.time - b.time;});
77
77
  return self.deferredNextId++;
78
78
  };
79
79
 
@@ -116,7 +116,7 @@ angular.mock.$Browser = function() {
116
116
  self.defer.now += delay;
117
117
  } else {
118
118
  if (self.deferredFns.length) {
119
- self.defer.now = self.deferredFns[self.deferredFns.length-1].time;
119
+ self.defer.now = self.deferredFns[self.deferredFns.length - 1].time;
120
120
  } else {
121
121
  throw new Error('No deferred tasks to be flushed');
122
122
  }
@@ -127,7 +127,7 @@ angular.mock.$Browser = function() {
127
127
  }
128
128
  };
129
129
 
130
- self.$$baseHref = '';
130
+ self.$$baseHref = '/';
131
131
  self.baseHref = function() {
132
132
  return this.$$baseHref;
133
133
  };
@@ -141,42 +141,27 @@ angular.mock.$Browser.prototype = {
141
141
  * run all fns in pollFns
142
142
  */
143
143
  poll: function poll() {
144
- angular.forEach(this.pollFns, function(pollFn){
144
+ angular.forEach(this.pollFns, function(pollFn) {
145
145
  pollFn();
146
146
  });
147
147
  },
148
148
 
149
- addPollFn: function(pollFn) {
150
- this.pollFns.push(pollFn);
151
- return pollFn;
152
- },
153
-
154
- url: function(url, replace) {
149
+ url: function(url, replace, state) {
150
+ if (angular.isUndefined(state)) {
151
+ state = null;
152
+ }
155
153
  if (url) {
156
154
  this.$$url = url;
155
+ // Native pushState serializes & copies the object; simulate it.
156
+ this.$$state = angular.copy(state);
157
157
  return this;
158
158
  }
159
159
 
160
160
  return this.$$url;
161
161
  },
162
162
 
163
- cookies: function(name, value) {
164
- if (name) {
165
- if (angular.isUndefined(value)) {
166
- delete this.cookieHash[name];
167
- } else {
168
- if (angular.isString(value) && //strings only
169
- value.length <= 4096) { //strict cookie storage limits
170
- this.cookieHash[name] = value;
171
- }
172
- }
173
- } else {
174
- if (!angular.equals(this.cookieHash, this.lastCookieHash)) {
175
- this.lastCookieHash = angular.copy(this.cookieHash);
176
- this.cookieHash = angular.copy(this.cookieHash);
177
- }
178
- return this.cookieHash;
179
- }
163
+ state: function() {
164
+ return this.$$state;
180
165
  },
181
166
 
182
167
  notifyWhenNoOutstandingRequests: function(fn) {
@@ -191,7 +176,7 @@ angular.mock.$Browser.prototype = {
191
176
  *
192
177
  * @description
193
178
  * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors
194
- * passed into the `$exceptionHandler`.
179
+ * passed to the `$exceptionHandler`.
195
180
  */
196
181
 
197
182
  /**
@@ -200,7 +185,7 @@ angular.mock.$Browser.prototype = {
200
185
  *
201
186
  * @description
202
187
  * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed
203
- * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration
188
+ * to it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration
204
189
  * information.
205
190
  *
206
191
  *
@@ -240,32 +225,31 @@ angular.mock.$ExceptionHandlerProvider = function() {
240
225
  *
241
226
  * @param {string} mode Mode of operation, defaults to `rethrow`.
242
227
  *
243
- * - `rethrow`: If any errors are passed into the handler in tests, it typically
244
- * means that there is a bug in the application or test, so this mock will
245
- * make these tests fail.
246
228
  * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log`
247
229
  * mode stores an array of errors in `$exceptionHandler.errors`, to allow later
248
230
  * assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and
249
231
  * {@link ngMock.$log#reset reset()}
232
+ * - `rethrow`: If any errors are passed to the handler in tests, it typically means that there
233
+ * is a bug in the application or test, so this mock will make these tests fail.
234
+ * For any implementations that expect exceptions to be thrown, the `rethrow` mode
235
+ * will also maintain a log of thrown errors.
250
236
  */
251
237
  this.mode = function(mode) {
252
- switch(mode) {
253
- case 'rethrow':
254
- handler = function(e) {
255
- throw e;
256
- };
257
- break;
238
+
239
+ switch (mode) {
258
240
  case 'log':
241
+ case 'rethrow':
259
242
  var errors = [];
260
-
261
243
  handler = function(e) {
262
244
  if (arguments.length == 1) {
263
245
  errors.push(e);
264
246
  } else {
265
247
  errors.push([].slice.call(arguments, 0));
266
248
  }
249
+ if (mode === "rethrow") {
250
+ throw e;
251
+ }
267
252
  };
268
-
269
253
  handler.errors = errors;
270
254
  break;
271
255
  default:
@@ -307,7 +291,7 @@ angular.mock.$LogProvider = function() {
307
291
  }
308
292
  };
309
293
 
310
- this.$get = function () {
294
+ this.$get = function() {
311
295
  var $log = {
312
296
  log: function() { $log.log.logs.push(concat([], arguments, 0)); },
313
297
  warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
@@ -327,13 +311,13 @@ angular.mock.$LogProvider = function() {
327
311
  * @description
328
312
  * Reset all of the logging arrays to empty.
329
313
  */
330
- $log.reset = function () {
314
+ $log.reset = function() {
331
315
  /**
332
316
  * @ngdoc property
333
317
  * @name $log#log.logs
334
318
  *
335
319
  * @description
336
- * Array of messages logged using {@link ngMock.$log#log}.
320
+ * Array of messages logged using {@link ng.$log#log `log()`}.
337
321
  *
338
322
  * @example
339
323
  * ```js
@@ -347,7 +331,7 @@ angular.mock.$LogProvider = function() {
347
331
  * @name $log#info.logs
348
332
  *
349
333
  * @description
350
- * Array of messages logged using {@link ngMock.$log#info}.
334
+ * Array of messages logged using {@link ng.$log#info `info()`}.
351
335
  *
352
336
  * @example
353
337
  * ```js
@@ -361,7 +345,7 @@ angular.mock.$LogProvider = function() {
361
345
  * @name $log#warn.logs
362
346
  *
363
347
  * @description
364
- * Array of messages logged using {@link ngMock.$log#warn}.
348
+ * Array of messages logged using {@link ng.$log#warn `warn()`}.
365
349
  *
366
350
  * @example
367
351
  * ```js
@@ -375,7 +359,7 @@ angular.mock.$LogProvider = function() {
375
359
  * @name $log#error.logs
376
360
  *
377
361
  * @description
378
- * Array of messages logged using {@link ngMock.$log#error}.
362
+ * Array of messages logged using {@link ng.$log#error `error()`}.
379
363
  *
380
364
  * @example
381
365
  * ```js
@@ -389,7 +373,7 @@ angular.mock.$LogProvider = function() {
389
373
  * @name $log#debug.logs
390
374
  *
391
375
  * @description
392
- * Array of messages logged using {@link ngMock.$log#debug}.
376
+ * Array of messages logged using {@link ng.$log#debug `debug()`}.
393
377
  *
394
378
  * @example
395
379
  * ```js
@@ -405,21 +389,21 @@ angular.mock.$LogProvider = function() {
405
389
  * @name $log#assertEmpty
406
390
  *
407
391
  * @description
408
- * Assert that the all of the logging methods have no logged messages. If messages present, an
409
- * exception is thrown.
392
+ * Assert that all of the logging methods have no logged messages. If any messages are present,
393
+ * an exception is thrown.
410
394
  */
411
395
  $log.assertEmpty = function() {
412
396
  var errors = [];
413
397
  angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {
414
398
  angular.forEach($log[logLevel].logs, function(log) {
415
- angular.forEach(log, function (logItem) {
399
+ angular.forEach(log, function(logItem) {
416
400
  errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' +
417
401
  (logItem.stack || ''));
418
402
  });
419
403
  });
420
404
  });
421
405
  if (errors.length) {
422
- errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or "+
406
+ errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or " +
423
407
  "an expected log message was not checked and removed:");
424
408
  errors.push('');
425
409
  throw new Error(errors.join('\n---------\n'));
@@ -449,23 +433,28 @@ angular.mock.$LogProvider = function() {
449
433
  * indefinitely.
450
434
  * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
451
435
  * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
436
+ * @param {...*=} Pass additional parameters to the executed function.
452
437
  * @returns {promise} A promise which will be notified on each iteration.
453
438
  */
454
439
  angular.mock.$IntervalProvider = function() {
455
- this.$get = ['$rootScope', '$q',
456
- function($rootScope, $q) {
440
+ this.$get = ['$browser', '$rootScope', '$q', '$$q',
441
+ function($browser, $rootScope, $q, $$q) {
457
442
  var repeatFns = [],
458
443
  nextRepeatId = 0,
459
444
  now = 0;
460
445
 
461
446
  var $interval = function(fn, delay, count, invokeApply) {
462
- var deferred = $q.defer(),
463
- promise = deferred.promise,
447
+ var hasParams = arguments.length > 4,
448
+ args = hasParams ? Array.prototype.slice.call(arguments, 4) : [],
464
449
  iteration = 0,
465
- skipApply = (angular.isDefined(invokeApply) && !invokeApply);
450
+ skipApply = (angular.isDefined(invokeApply) && !invokeApply),
451
+ deferred = (skipApply ? $$q : $q).defer(),
452
+ promise = deferred.promise;
466
453
 
467
454
  count = (angular.isDefined(count)) ? count : 0;
468
- promise.then(null, null, fn);
455
+ promise.then(null, null, (!hasParams) ? fn : function() {
456
+ fn.apply(null, args);
457
+ });
469
458
 
470
459
  promise.$$intervalId = nextRepeatId;
471
460
 
@@ -485,7 +474,11 @@ angular.mock.$IntervalProvider = function() {
485
474
  }
486
475
  }
487
476
 
488
- if (!skipApply) $rootScope.$apply();
477
+ if (skipApply) {
478
+ $browser.defer.flush();
479
+ } else {
480
+ $rootScope.$apply();
481
+ }
489
482
  }
490
483
 
491
484
  repeatFns.push({
@@ -495,7 +488,7 @@ angular.mock.$IntervalProvider = function() {
495
488
  id: nextRepeatId,
496
489
  deferred: deferred
497
490
  });
498
- repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});
491
+ repeatFns.sort(function(a, b) { return a.nextTime - b.nextTime;});
499
492
 
500
493
  nextRepeatId++;
501
494
  return promise;
@@ -511,7 +504,7 @@ angular.mock.$IntervalProvider = function() {
511
504
  * @returns {boolean} Returns `true` if the task was successfully cancelled.
512
505
  */
513
506
  $interval.cancel = function(promise) {
514
- if(!promise) return false;
507
+ if (!promise) return false;
515
508
  var fnIndex;
516
509
 
517
510
  angular.forEach(repeatFns, function(fn, index) {
@@ -544,7 +537,7 @@ angular.mock.$IntervalProvider = function() {
544
537
  var task = repeatFns[0];
545
538
  task.fn();
546
539
  task.nextTime += task.delay;
547
- repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;});
540
+ repeatFns.sort(function(a, b) { return a.nextTime - b.nextTime;});
548
541
  }
549
542
  return millis;
550
543
  };
@@ -568,20 +561,20 @@ function jsonStringToDate(string) {
568
561
  tzHour = 0,
569
562
  tzMin = 0;
570
563
  if (match[9]) {
571
- tzHour = int(match[9] + match[10]);
572
- tzMin = int(match[9] + match[11]);
564
+ tzHour = toInt(match[9] + match[10]);
565
+ tzMin = toInt(match[9] + match[11]);
573
566
  }
574
- date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
575
- date.setUTCHours(int(match[4]||0) - tzHour,
576
- int(match[5]||0) - tzMin,
577
- int(match[6]||0),
578
- int(match[7]||0));
567
+ date.setUTCFullYear(toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));
568
+ date.setUTCHours(toInt(match[4] || 0) - tzHour,
569
+ toInt(match[5] || 0) - tzMin,
570
+ toInt(match[6] || 0),
571
+ toInt(match[7] || 0));
579
572
  return date;
580
573
  }
581
574
  return string;
582
575
  }
583
576
 
584
- function int(str) {
577
+ function toInt(str) {
585
578
  return parseInt(str, 10);
586
579
  }
587
580
 
@@ -592,9 +585,10 @@ function padNumber(num, digits, trim) {
592
585
  num = -num;
593
586
  }
594
587
  num = '' + num;
595
- while(num.length < digits) num = '0' + num;
596
- if (trim)
588
+ while (num.length < digits) num = '0' + num;
589
+ if (trim) {
597
590
  num = num.substr(num.length - digits);
591
+ }
598
592
  return neg + num;
599
593
  }
600
594
 
@@ -636,7 +630,7 @@ function padNumber(num, digits, trim) {
636
630
  * ```
637
631
  *
638
632
  */
639
- angular.mock.TzDate = function (offset, timestamp) {
633
+ angular.mock.TzDate = function(offset, timestamp) {
640
634
  var self = new Date(0);
641
635
  if (angular.isString(timestamp)) {
642
636
  var tsStr = timestamp;
@@ -644,17 +638,18 @@ angular.mock.TzDate = function (offset, timestamp) {
644
638
  self.origDate = jsonStringToDate(timestamp);
645
639
 
646
640
  timestamp = self.origDate.getTime();
647
- if (isNaN(timestamp))
641
+ if (isNaN(timestamp)) {
648
642
  throw {
649
643
  name: "Illegal Argument",
650
644
  message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
651
645
  };
646
+ }
652
647
  } else {
653
648
  self.origDate = new Date(timestamp);
654
649
  }
655
650
 
656
651
  var localOffset = new Date(timestamp).getTimezoneOffset();
657
- self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;
652
+ self.offsetDiff = localOffset * 60 * 1000 - offset * 1000 * 60 * 60;
658
653
  self.date = new Date(timestamp + self.offsetDiff);
659
654
 
660
655
  self.getTime = function() {
@@ -776,14 +771,24 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
776
771
  };
777
772
  });
778
773
 
779
- $provide.decorator('$animate', function($delegate, $$asyncCallback) {
774
+ $provide.decorator('$animate', ['$delegate', '$$asyncCallback', '$timeout', '$browser', '$$rAF',
775
+ function($delegate, $$asyncCallback, $timeout, $browser, $$rAF) {
780
776
  var animate = {
781
- queue : [],
782
- enabled : $delegate.enabled,
783
- triggerCallbacks : function() {
777
+ queue: [],
778
+ cancel: $delegate.cancel,
779
+ enabled: $delegate.enabled,
780
+ triggerCallbackEvents: function() {
781
+ $$rAF.flush();
784
782
  $$asyncCallback.flush();
785
783
  },
786
- triggerReflow : function() {
784
+ triggerCallbackPromise: function() {
785
+ $timeout.flush(0);
786
+ },
787
+ triggerCallbacks: function() {
788
+ this.triggerCallbackEvents();
789
+ this.triggerCallbackPromise();
790
+ },
791
+ triggerReflow: function() {
787
792
  angular.forEach(reflowQueue, function(fn) {
788
793
  fn();
789
794
  });
@@ -792,19 +797,20 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
792
797
  };
793
798
 
794
799
  angular.forEach(
795
- ['enter','leave','move','addClass','removeClass','setClass'], function(method) {
800
+ ['animate','enter','leave','move','addClass','removeClass','setClass'], function(method) {
796
801
  animate[method] = function() {
797
802
  animate.queue.push({
798
- event : method,
799
- element : arguments[0],
800
- args : arguments
803
+ event: method,
804
+ element: arguments[0],
805
+ options: arguments[arguments.length - 1],
806
+ args: arguments
801
807
  });
802
- $delegate[method].apply($delegate, arguments);
808
+ return $delegate[method].apply($delegate, arguments);
803
809
  };
804
810
  });
805
811
 
806
812
  return animate;
807
- });
813
+ }]);
808
814
 
809
815
  }]);
810
816
 
@@ -864,13 +870,13 @@ angular.mock.dump = function(object) {
864
870
  function serializeScope(scope, offset) {
865
871
  offset = offset || ' ';
866
872
  var log = [offset + 'Scope(' + scope.$id + '): {'];
867
- for ( var key in scope ) {
873
+ for (var key in scope) {
868
874
  if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) {
869
875
  log.push(' ' + key + ': ' + angular.toJson(scope[key]));
870
876
  }
871
877
  }
872
878
  var child = scope.$$childHead;
873
- while(child) {
879
+ while (child) {
874
880
  log.push(serializeScope(child, offset + ' '));
875
881
  child = child.$$nextSibling;
876
882
  }
@@ -982,6 +988,11 @@ angular.mock.dump = function(object) {
982
988
  * First we create the controller under test:
983
989
  *
984
990
  ```js
991
+ // The module code
992
+ angular
993
+ .module('MyApp', [])
994
+ .controller('MyController', MyController);
995
+
985
996
  // The controller code
986
997
  function MyController($scope, $http) {
987
998
  var authToken;
@@ -1009,13 +1020,17 @@ angular.mock.dump = function(object) {
1009
1020
  ```js
1010
1021
  // testing controller
1011
1022
  describe('MyController', function() {
1012
- var $httpBackend, $rootScope, createController;
1023
+ var $httpBackend, $rootScope, createController, authRequestHandler;
1024
+
1025
+ // Set up the module
1026
+ beforeEach(module('MyApp'));
1013
1027
 
1014
1028
  beforeEach(inject(function($injector) {
1015
1029
  // Set up the mock http service responses
1016
1030
  $httpBackend = $injector.get('$httpBackend');
1017
1031
  // backend definition common for all tests
1018
- $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
1032
+ authRequestHandler = $httpBackend.when('GET', '/auth.py')
1033
+ .respond({userId: 'userX'}, {'A-Token': 'xxx'});
1019
1034
 
1020
1035
  // Get hold of a scope (i.e. the root scope)
1021
1036
  $rootScope = $injector.get('$rootScope');
@@ -1041,6 +1056,18 @@ angular.mock.dump = function(object) {
1041
1056
  });
1042
1057
 
1043
1058
 
1059
+ it('should fail authentication', function() {
1060
+
1061
+ // Notice how you can change the response even after it was set
1062
+ authRequestHandler.respond(401, '');
1063
+
1064
+ $httpBackend.expectGET('/auth.py');
1065
+ var controller = createController();
1066
+ $httpBackend.flush();
1067
+ expect($rootScope.status).toBe('Failed...');
1068
+ });
1069
+
1070
+
1044
1071
  it('should send msg to server', function() {
1045
1072
  var controller = createController();
1046
1073
  $httpBackend.flush();
@@ -1075,7 +1102,7 @@ angular.mock.dump = function(object) {
1075
1102
  ```
1076
1103
  */
1077
1104
  angular.mock.$HttpBackendProvider = function() {
1078
- this.$get = ['$rootScope', createHttpBackendMock];
1105
+ this.$get = ['$rootScope', '$timeout', createHttpBackendMock];
1079
1106
  };
1080
1107
 
1081
1108
  /**
@@ -1092,7 +1119,7 @@ angular.mock.$HttpBackendProvider = function() {
1092
1119
  * @param {Object=} $browser Auto-flushing enabled if specified
1093
1120
  * @return {Object} Instance of $httpBackend mock
1094
1121
  */
1095
- function createHttpBackendMock($rootScope, $delegate, $browser) {
1122
+ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1096
1123
  var definitions = [],
1097
1124
  expectations = [],
1098
1125
  responses = [],
@@ -1105,7 +1132,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1105
1132
  return function() {
1106
1133
  return angular.isNumber(status)
1107
1134
  ? [status, data, headers, statusText]
1108
- : [200, status, data];
1135
+ : [200, status, data, headers];
1109
1136
  };
1110
1137
  }
1111
1138
 
@@ -1122,7 +1149,9 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1122
1149
  }
1123
1150
 
1124
1151
  function wrapResponse(wrapped) {
1125
- if (!$browser && timeout && timeout.then) timeout.then(handleTimeout);
1152
+ if (!$browser && timeout) {
1153
+ timeout.then ? timeout.then(handleTimeout) : $timeout(handleTimeout, timeout);
1154
+ }
1126
1155
 
1127
1156
  return handleResponse;
1128
1157
 
@@ -1145,14 +1174,16 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1145
1174
  }
1146
1175
 
1147
1176
  if (expectation && expectation.match(method, url)) {
1148
- if (!expectation.matchData(data))
1177
+ if (!expectation.matchData(data)) {
1149
1178
  throw new Error('Expected ' + expectation + ' with different data\n' +
1150
1179
  'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
1180
+ }
1151
1181
 
1152
- if (!expectation.matchHeaders(headers))
1182
+ if (!expectation.matchHeaders(headers)) {
1153
1183
  throw new Error('Expected ' + expectation + ' with different headers\n' +
1154
1184
  'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
1155
1185
  prettyPrint(headers));
1186
+ }
1156
1187
 
1157
1188
  expectations.shift();
1158
1189
 
@@ -1188,32 +1219,39 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1188
1219
  * Creates a new backend definition.
1189
1220
  *
1190
1221
  * @param {string} method HTTP method.
1191
- * @param {string|RegExp} url HTTP url.
1222
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1223
+ * and returns true if the url matches the current definition.
1192
1224
  * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1193
1225
  * data string and returns true if the data is as expected.
1194
1226
  * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1195
1227
  * object and returns true if the headers match the current definition.
1196
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1197
- * request is handled.
1228
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1229
+ * request is handled. You can save this object for later use and invoke `respond` again in
1230
+ * order to change how a matched request is handled.
1198
1231
  *
1199
1232
  * - respond –
1200
1233
  * `{function([status,] data[, headers, statusText])
1201
1234
  * | function(function(method, url, data, headers)}`
1202
1235
  * – The respond method takes a set of static data to be returned or a function that can
1203
1236
  * return an array containing response status (number), response data (string), response
1204
- * headers (Object), and the text for the status (string).
1237
+ * headers (Object), and the text for the status (string). The respond method returns the
1238
+ * `requestHandler` object for possible overrides.
1205
1239
  */
1206
1240
  $httpBackend.when = function(method, url, data, headers) {
1207
1241
  var definition = new MockHttpExpectation(method, url, data, headers),
1208
1242
  chain = {
1209
1243
  respond: function(status, data, headers, statusText) {
1244
+ definition.passThrough = undefined;
1210
1245
  definition.response = createResponse(status, data, headers, statusText);
1246
+ return chain;
1211
1247
  }
1212
1248
  };
1213
1249
 
1214
1250
  if ($browser) {
1215
1251
  chain.passThrough = function() {
1252
+ definition.response = undefined;
1216
1253
  definition.passThrough = true;
1254
+ return chain;
1217
1255
  };
1218
1256
  }
1219
1257
 
@@ -1227,10 +1265,12 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1227
1265
  * @description
1228
1266
  * Creates a new backend definition for GET requests. For more info see `when()`.
1229
1267
  *
1230
- * @param {string|RegExp} url HTTP url.
1268
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1269
+ * and returns true if the url matches the current definition.
1231
1270
  * @param {(Object|function(Object))=} headers HTTP headers.
1232
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1233
- * request is handled.
1271
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1272
+ * request is handled. You can save this object for later use and invoke `respond` again in
1273
+ * order to change how a matched request is handled.
1234
1274
  */
1235
1275
 
1236
1276
  /**
@@ -1239,10 +1279,12 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1239
1279
  * @description
1240
1280
  * Creates a new backend definition for HEAD requests. For more info see `when()`.
1241
1281
  *
1242
- * @param {string|RegExp} url HTTP url.
1282
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1283
+ * and returns true if the url matches the current definition.
1243
1284
  * @param {(Object|function(Object))=} headers HTTP headers.
1244
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1245
- * request is handled.
1285
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1286
+ * request is handled. You can save this object for later use and invoke `respond` again in
1287
+ * order to change how a matched request is handled.
1246
1288
  */
1247
1289
 
1248
1290
  /**
@@ -1251,10 +1293,12 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1251
1293
  * @description
1252
1294
  * Creates a new backend definition for DELETE requests. For more info see `when()`.
1253
1295
  *
1254
- * @param {string|RegExp} url HTTP url.
1296
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1297
+ * and returns true if the url matches the current definition.
1255
1298
  * @param {(Object|function(Object))=} headers HTTP headers.
1256
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1257
- * request is handled.
1299
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1300
+ * request is handled. You can save this object for later use and invoke `respond` again in
1301
+ * order to change how a matched request is handled.
1258
1302
  */
1259
1303
 
1260
1304
  /**
@@ -1263,12 +1307,14 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1263
1307
  * @description
1264
1308
  * Creates a new backend definition for POST requests. For more info see `when()`.
1265
1309
  *
1266
- * @param {string|RegExp} url HTTP url.
1310
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1311
+ * and returns true if the url matches the current definition.
1267
1312
  * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1268
1313
  * data string and returns true if the data is as expected.
1269
1314
  * @param {(Object|function(Object))=} headers HTTP headers.
1270
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1271
- * request is handled.
1315
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1316
+ * request is handled. You can save this object for later use and invoke `respond` again in
1317
+ * order to change how a matched request is handled.
1272
1318
  */
1273
1319
 
1274
1320
  /**
@@ -1277,26 +1323,14 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1277
1323
  * @description
1278
1324
  * Creates a new backend definition for PUT requests. For more info see `when()`.
1279
1325
  *
1280
- * @param {string|RegExp} url HTTP url.
1326
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1327
+ * and returns true if the url matches the current definition.
1281
1328
  * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1282
1329
  * data string and returns true if the data is as expected.
1283
1330
  * @param {(Object|function(Object))=} headers HTTP headers.
1284
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1285
- * request is handled.
1286
- */
1287
-
1288
- /**
1289
- * @ngdoc method
1290
- * @name $httpBackend#whenPATCH
1291
- * @description
1292
- * Creates a new backend definition for PATCH requests. For more info see `when()`.
1293
- *
1294
- * @param {string|RegExp} url HTTP url.
1295
- * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1296
- * data string and returns true if the data is as expected.
1297
- * @param {(Object|function(Object))=} headers HTTP headers.
1298
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1299
- * request is handled.
1331
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1332
+ * request is handled. You can save this object for later use and invoke `respond` again in
1333
+ * order to change how a matched request is handled.
1300
1334
  */
1301
1335
 
1302
1336
  /**
@@ -1305,9 +1339,11 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1305
1339
  * @description
1306
1340
  * Creates a new backend definition for JSONP requests. For more info see `when()`.
1307
1341
  *
1308
- * @param {string|RegExp} url HTTP url.
1309
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1310
- * request is handled.
1342
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1343
+ * and returns true if the url matches the current definition.
1344
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1345
+ * request is handled. You can save this object for later use and invoke `respond` again in
1346
+ * order to change how a matched request is handled.
1311
1347
  */
1312
1348
  createShortMethods('when');
1313
1349
 
@@ -1319,30 +1355,36 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1319
1355
  * Creates a new request expectation.
1320
1356
  *
1321
1357
  * @param {string} method HTTP method.
1322
- * @param {string|RegExp} url HTTP url.
1358
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1359
+ * and returns true if the url matches the current definition.
1323
1360
  * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1324
1361
  * receives data string and returns true if the data is as expected, or Object if request body
1325
1362
  * is in JSON format.
1326
1363
  * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1327
1364
  * object and returns true if the headers match the current expectation.
1328
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1329
- * request is handled.
1365
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1366
+ * request is handled. You can save this object for later use and invoke `respond` again in
1367
+ * order to change how a matched request is handled.
1330
1368
  *
1331
1369
  * - respond –
1332
1370
  * `{function([status,] data[, headers, statusText])
1333
1371
  * | function(function(method, url, data, headers)}`
1334
1372
  * – The respond method takes a set of static data to be returned or a function that can
1335
1373
  * return an array containing response status (number), response data (string), response
1336
- * headers (Object), and the text for the status (string).
1374
+ * headers (Object), and the text for the status (string). The respond method returns the
1375
+ * `requestHandler` object for possible overrides.
1337
1376
  */
1338
1377
  $httpBackend.expect = function(method, url, data, headers) {
1339
- var expectation = new MockHttpExpectation(method, url, data, headers);
1378
+ var expectation = new MockHttpExpectation(method, url, data, headers),
1379
+ chain = {
1380
+ respond: function(status, data, headers, statusText) {
1381
+ expectation.response = createResponse(status, data, headers, statusText);
1382
+ return chain;
1383
+ }
1384
+ };
1385
+
1340
1386
  expectations.push(expectation);
1341
- return {
1342
- respond: function (status, data, headers, statusText) {
1343
- expectation.response = createResponse(status, data, headers, statusText);
1344
- }
1345
- };
1387
+ return chain;
1346
1388
  };
1347
1389
 
1348
1390
 
@@ -1352,10 +1394,12 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1352
1394
  * @description
1353
1395
  * Creates a new request expectation for GET requests. For more info see `expect()`.
1354
1396
  *
1355
- * @param {string|RegExp} url HTTP url.
1397
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1398
+ * and returns true if the url matches the current definition.
1356
1399
  * @param {Object=} headers HTTP headers.
1357
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1358
- * request is handled. See #expect for more info.
1400
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1401
+ * request is handled. You can save this object for later use and invoke `respond` again in
1402
+ * order to change how a matched request is handled. See #expect for more info.
1359
1403
  */
1360
1404
 
1361
1405
  /**
@@ -1364,10 +1408,12 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1364
1408
  * @description
1365
1409
  * Creates a new request expectation for HEAD requests. For more info see `expect()`.
1366
1410
  *
1367
- * @param {string|RegExp} url HTTP url.
1411
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1412
+ * and returns true if the url matches the current definition.
1368
1413
  * @param {Object=} headers HTTP headers.
1369
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1370
- * request is handled.
1414
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1415
+ * request is handled. You can save this object for later use and invoke `respond` again in
1416
+ * order to change how a matched request is handled.
1371
1417
  */
1372
1418
 
1373
1419
  /**
@@ -1376,10 +1422,12 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1376
1422
  * @description
1377
1423
  * Creates a new request expectation for DELETE requests. For more info see `expect()`.
1378
1424
  *
1379
- * @param {string|RegExp} url HTTP url.
1425
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1426
+ * and returns true if the url matches the current definition.
1380
1427
  * @param {Object=} headers HTTP headers.
1381
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1382
- * request is handled.
1428
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1429
+ * request is handled. You can save this object for later use and invoke `respond` again in
1430
+ * order to change how a matched request is handled.
1383
1431
  */
1384
1432
 
1385
1433
  /**
@@ -1388,13 +1436,15 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1388
1436
  * @description
1389
1437
  * Creates a new request expectation for POST requests. For more info see `expect()`.
1390
1438
  *
1391
- * @param {string|RegExp} url HTTP url.
1439
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1440
+ * and returns true if the url matches the current definition.
1392
1441
  * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1393
1442
  * receives data string and returns true if the data is as expected, or Object if request body
1394
1443
  * is in JSON format.
1395
1444
  * @param {Object=} headers HTTP headers.
1396
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1397
- * request is handled.
1445
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1446
+ * request is handled. You can save this object for later use and invoke `respond` again in
1447
+ * order to change how a matched request is handled.
1398
1448
  */
1399
1449
 
1400
1450
  /**
@@ -1403,13 +1453,15 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1403
1453
  * @description
1404
1454
  * Creates a new request expectation for PUT requests. For more info see `expect()`.
1405
1455
  *
1406
- * @param {string|RegExp} url HTTP url.
1456
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1457
+ * and returns true if the url matches the current definition.
1407
1458
  * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1408
1459
  * receives data string and returns true if the data is as expected, or Object if request body
1409
1460
  * is in JSON format.
1410
1461
  * @param {Object=} headers HTTP headers.
1411
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1412
- * request is handled.
1462
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1463
+ * request is handled. You can save this object for later use and invoke `respond` again in
1464
+ * order to change how a matched request is handled.
1413
1465
  */
1414
1466
 
1415
1467
  /**
@@ -1418,13 +1470,15 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1418
1470
  * @description
1419
1471
  * Creates a new request expectation for PATCH requests. For more info see `expect()`.
1420
1472
  *
1421
- * @param {string|RegExp} url HTTP url.
1473
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1474
+ * and returns true if the url matches the current definition.
1422
1475
  * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1423
1476
  * receives data string and returns true if the data is as expected, or Object if request body
1424
1477
  * is in JSON format.
1425
1478
  * @param {Object=} headers HTTP headers.
1426
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1427
- * request is handled.
1479
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1480
+ * request is handled. You can save this object for later use and invoke `respond` again in
1481
+ * order to change how a matched request is handled.
1428
1482
  */
1429
1483
 
1430
1484
  /**
@@ -1433,9 +1487,11 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1433
1487
  * @description
1434
1488
  * Creates a new request expectation for JSONP requests. For more info see `expect()`.
1435
1489
  *
1436
- * @param {string|RegExp} url HTTP url.
1437
- * @returns {requestHandler} Returns an object with a `respond` method that controls how a matched
1438
- * request is handled.
1490
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives an url
1491
+ * and returns true if the url matches the current definition.
1492
+ * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1493
+ * request is handled. You can save this object for later use and invoke `respond` again in
1494
+ * order to change how a matched request is handled.
1439
1495
  */
1440
1496
  createShortMethods('expect');
1441
1497
 
@@ -1450,11 +1506,11 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1450
1506
  * all pending requests will be flushed. If there are no pending requests when the flush method
1451
1507
  * is called an exception is thrown (as this typically a sign of programming error).
1452
1508
  */
1453
- $httpBackend.flush = function(count) {
1454
- $rootScope.$digest();
1509
+ $httpBackend.flush = function(count, digest) {
1510
+ if (digest !== false) $rootScope.$digest();
1455
1511
  if (!responses.length) throw new Error('No pending request to flush !');
1456
1512
 
1457
- if (angular.isDefined(count)) {
1513
+ if (angular.isDefined(count) && count !== null) {
1458
1514
  while (count--) {
1459
1515
  if (!responses.length) throw new Error('No more pending request to flush !');
1460
1516
  responses.shift()();
@@ -1464,7 +1520,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1464
1520
  responses.shift()();
1465
1521
  }
1466
1522
  }
1467
- $httpBackend.verifyNoOutstandingExpectation();
1523
+ $httpBackend.verifyNoOutstandingExpectation(digest);
1468
1524
  };
1469
1525
 
1470
1526
 
@@ -1482,8 +1538,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
1482
1538
  * afterEach($httpBackend.verifyNoOutstandingExpectation);
1483
1539
  * ```
1484
1540
  */
1485
- $httpBackend.verifyNoOutstandingExpectation = function() {
1486
- $rootScope.$digest();
1541
+ $httpBackend.verifyNoOutstandingExpectation = function(digest) {
1542
+ if (digest !== false) $rootScope.$digest();
1487
1543
  if (expectations.length) {
1488
1544
  throw new Error('Unsatisfied requests: ' + expectations.join(', '));
1489
1545
  }
@@ -1557,6 +1613,7 @@ function MockHttpExpectation(method, url, data, headers) {
1557
1613
  this.matchUrl = function(u) {
1558
1614
  if (!url) return true;
1559
1615
  if (angular.isFunction(url.test)) return url.test(u);
1616
+ if (angular.isFunction(url)) return url(u);
1560
1617
  return url == u;
1561
1618
  };
1562
1619
 
@@ -1645,7 +1702,7 @@ function MockXhr() {
1645
1702
  * that adds a "flush" and "verifyNoPendingTasks" methods.
1646
1703
  */
1647
1704
 
1648
- angular.mock.$TimeoutDecorator = function($delegate, $browser) {
1705
+ angular.mock.$TimeoutDecorator = ['$delegate', '$browser', function($delegate, $browser) {
1649
1706
 
1650
1707
  /**
1651
1708
  * @ngdoc method
@@ -1684,9 +1741,9 @@ angular.mock.$TimeoutDecorator = function($delegate, $browser) {
1684
1741
  }
1685
1742
 
1686
1743
  return $delegate;
1687
- };
1744
+ }];
1688
1745
 
1689
- angular.mock.$RAFDecorator = function($delegate) {
1746
+ angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
1690
1747
  var queue = [];
1691
1748
  var rafFn = function(fn) {
1692
1749
  var index = queue.length;
@@ -1699,22 +1756,22 @@ angular.mock.$RAFDecorator = function($delegate) {
1699
1756
  rafFn.supported = $delegate.supported;
1700
1757
 
1701
1758
  rafFn.flush = function() {
1702
- if(queue.length === 0) {
1759
+ if (queue.length === 0) {
1703
1760
  throw new Error('No rAF callbacks present');
1704
1761
  }
1705
1762
 
1706
1763
  var length = queue.length;
1707
- for(var i=0;i<length;i++) {
1764
+ for (var i = 0; i < length; i++) {
1708
1765
  queue[i]();
1709
1766
  }
1710
1767
 
1711
- queue = [];
1768
+ queue = queue.slice(i);
1712
1769
  };
1713
1770
 
1714
1771
  return rafFn;
1715
- };
1772
+ }];
1716
1773
 
1717
- angular.mock.$AsyncCallbackDecorator = function($delegate) {
1774
+ angular.mock.$AsyncCallbackDecorator = ['$delegate', function($delegate) {
1718
1775
  var callbacks = [];
1719
1776
  var addFn = function(fn) {
1720
1777
  callbacks.push(fn);
@@ -1726,7 +1783,7 @@ angular.mock.$AsyncCallbackDecorator = function($delegate) {
1726
1783
  callbacks = [];
1727
1784
  };
1728
1785
  return addFn;
1729
- };
1786
+ }];
1730
1787
 
1731
1788
  /**
1732
1789
  *
@@ -1737,6 +1794,77 @@ angular.mock.$RootElementProvider = function() {
1737
1794
  };
1738
1795
  };
1739
1796
 
1797
+ /**
1798
+ * @ngdoc service
1799
+ * @name $controller
1800
+ * @description
1801
+ * A decorator for {@link ng.$controller} with additional `bindings` parameter, useful when testing
1802
+ * controllers of directives that use {@link $compile#-bindtocontroller- `bindToController`}.
1803
+ *
1804
+ *
1805
+ * ## Example
1806
+ *
1807
+ * ```js
1808
+ *
1809
+ * // Directive definition ...
1810
+ *
1811
+ * myMod.directive('myDirective', {
1812
+ * controller: 'MyDirectiveController',
1813
+ * bindToController: {
1814
+ * name: '@'
1815
+ * }
1816
+ * });
1817
+ *
1818
+ *
1819
+ * // Controller definition ...
1820
+ *
1821
+ * myMod.controller('MyDirectiveController', ['log', function($log) {
1822
+ * $log.info(this.name);
1823
+ * })];
1824
+ *
1825
+ *
1826
+ * // In a test ...
1827
+ *
1828
+ * describe('myDirectiveController', function() {
1829
+ * it('should write the bound name to the log', inject(function($controller, $log) {
1830
+ * var ctrl = $controller('MyDirective', { /* no locals &#42;/ }, { name: 'Clark Kent' });
1831
+ * expect(ctrl.name).toEqual('Clark Kent');
1832
+ * expect($log.info.logs).toEqual(['Clark Kent']);
1833
+ * });
1834
+ * });
1835
+ *
1836
+ * ```
1837
+ *
1838
+ * @param {Function|string} constructor If called with a function then it's considered to be the
1839
+ * controller constructor function. Otherwise it's considered to be a string which is used
1840
+ * to retrieve the controller constructor using the following steps:
1841
+ *
1842
+ * * check if a controller with given name is registered via `$controllerProvider`
1843
+ * * check if evaluating the string on the current scope returns a constructor
1844
+ * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
1845
+ * `window` object (not recommended)
1846
+ *
1847
+ * The string can use the `controller as property` syntax, where the controller instance is published
1848
+ * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
1849
+ * to work correctly.
1850
+ *
1851
+ * @param {Object} locals Injection locals for Controller.
1852
+ * @param {Object=} bindings Properties to add to the controller before invoking the constructor. This is used
1853
+ * to simulate the `bindToController` feature and simplify certain kinds of tests.
1854
+ * @return {Object} Instance of given controller.
1855
+ */
1856
+ angular.mock.$ControllerDecorator = ['$delegate', function($delegate) {
1857
+ return function(expression, locals, later, ident) {
1858
+ if (later && typeof later === 'object') {
1859
+ var create = $delegate(expression, locals, true, ident);
1860
+ angular.extend(create.instance, later);
1861
+ return create();
1862
+ }
1863
+ return $delegate(expression, locals, later, ident);
1864
+ };
1865
+ }];
1866
+
1867
+
1740
1868
  /**
1741
1869
  * @ngdoc module
1742
1870
  * @name ngMock
@@ -1764,6 +1892,8 @@ angular.module('ngMock', ['ng']).provider({
1764
1892
  $provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
1765
1893
  $provide.decorator('$$rAF', angular.mock.$RAFDecorator);
1766
1894
  $provide.decorator('$$asyncCallback', angular.mock.$AsyncCallbackDecorator);
1895
+ $provide.decorator('$rootScope', angular.mock.$RootScopeDecorator);
1896
+ $provide.decorator('$controller', angular.mock.$ControllerDecorator);
1767
1897
  }]);
1768
1898
 
1769
1899
  /**
@@ -1840,12 +1970,14 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1840
1970
  * Creates a new backend definition.
1841
1971
  *
1842
1972
  * @param {string} method HTTP method.
1843
- * @param {string|RegExp} url HTTP url.
1973
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1974
+ * and returns true if the url matches the current definition.
1844
1975
  * @param {(string|RegExp)=} data HTTP request body.
1845
1976
  * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1846
1977
  * object and returns true if the headers match the current definition.
1847
1978
  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1848
- * control how a matched request is handled.
1979
+ * control how a matched request is handled. You can save this object for later use and invoke
1980
+ * `respond` or `passThrough` again in order to change how a matched request is handled.
1849
1981
  *
1850
1982
  * - respond –
1851
1983
  * `{function([status,] data[, headers, statusText])
@@ -1856,6 +1988,7 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1856
1988
  * - passThrough – `{function()}` – Any request matching a backend definition with
1857
1989
  * `passThrough` handler will be passed through to the real backend (an XHR request will be made
1858
1990
  * to the server.)
1991
+ * - Both methods return the `requestHandler` object for possible overrides.
1859
1992
  */
1860
1993
 
1861
1994
  /**
@@ -1865,10 +1998,12 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1865
1998
  * @description
1866
1999
  * Creates a new backend definition for GET requests. For more info see `when()`.
1867
2000
  *
1868
- * @param {string|RegExp} url HTTP url.
2001
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2002
+ * and returns true if the url matches the current definition.
1869
2003
  * @param {(Object|function(Object))=} headers HTTP headers.
1870
2004
  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1871
- * control how a matched request is handled.
2005
+ * control how a matched request is handled. You can save this object for later use and invoke
2006
+ * `respond` or `passThrough` again in order to change how a matched request is handled.
1872
2007
  */
1873
2008
 
1874
2009
  /**
@@ -1878,10 +2013,12 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1878
2013
  * @description
1879
2014
  * Creates a new backend definition for HEAD requests. For more info see `when()`.
1880
2015
  *
1881
- * @param {string|RegExp} url HTTP url.
2016
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2017
+ * and returns true if the url matches the current definition.
1882
2018
  * @param {(Object|function(Object))=} headers HTTP headers.
1883
2019
  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1884
- * control how a matched request is handled.
2020
+ * control how a matched request is handled. You can save this object for later use and invoke
2021
+ * `respond` or `passThrough` again in order to change how a matched request is handled.
1885
2022
  */
1886
2023
 
1887
2024
  /**
@@ -1891,10 +2028,12 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1891
2028
  * @description
1892
2029
  * Creates a new backend definition for DELETE requests. For more info see `when()`.
1893
2030
  *
1894
- * @param {string|RegExp} url HTTP url.
2031
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2032
+ * and returns true if the url matches the current definition.
1895
2033
  * @param {(Object|function(Object))=} headers HTTP headers.
1896
2034
  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1897
- * control how a matched request is handled.
2035
+ * control how a matched request is handled. You can save this object for later use and invoke
2036
+ * `respond` or `passThrough` again in order to change how a matched request is handled.
1898
2037
  */
1899
2038
 
1900
2039
  /**
@@ -1904,11 +2043,13 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1904
2043
  * @description
1905
2044
  * Creates a new backend definition for POST requests. For more info see `when()`.
1906
2045
  *
1907
- * @param {string|RegExp} url HTTP url.
2046
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2047
+ * and returns true if the url matches the current definition.
1908
2048
  * @param {(string|RegExp)=} data HTTP request body.
1909
2049
  * @param {(Object|function(Object))=} headers HTTP headers.
1910
2050
  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1911
- * control how a matched request is handled.
2051
+ * control how a matched request is handled. You can save this object for later use and invoke
2052
+ * `respond` or `passThrough` again in order to change how a matched request is handled.
1912
2053
  */
1913
2054
 
1914
2055
  /**
@@ -1918,11 +2059,13 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1918
2059
  * @description
1919
2060
  * Creates a new backend definition for PUT requests. For more info see `when()`.
1920
2061
  *
1921
- * @param {string|RegExp} url HTTP url.
2062
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2063
+ * and returns true if the url matches the current definition.
1922
2064
  * @param {(string|RegExp)=} data HTTP request body.
1923
2065
  * @param {(Object|function(Object))=} headers HTTP headers.
1924
2066
  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1925
- * control how a matched request is handled.
2067
+ * control how a matched request is handled. You can save this object for later use and invoke
2068
+ * `respond` or `passThrough` again in order to change how a matched request is handled.
1926
2069
  */
1927
2070
 
1928
2071
  /**
@@ -1932,11 +2075,13 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1932
2075
  * @description
1933
2076
  * Creates a new backend definition for PATCH requests. For more info see `when()`.
1934
2077
  *
1935
- * @param {string|RegExp} url HTTP url.
2078
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2079
+ * and returns true if the url matches the current definition.
1936
2080
  * @param {(string|RegExp)=} data HTTP request body.
1937
2081
  * @param {(Object|function(Object))=} headers HTTP headers.
1938
2082
  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1939
- * control how a matched request is handled.
2083
+ * control how a matched request is handled. You can save this object for later use and invoke
2084
+ * `respond` or `passThrough` again in order to change how a matched request is handled.
1940
2085
  */
1941
2086
 
1942
2087
  /**
@@ -1946,45 +2091,132 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1946
2091
  * @description
1947
2092
  * Creates a new backend definition for JSONP requests. For more info see `when()`.
1948
2093
  *
1949
- * @param {string|RegExp} url HTTP url.
2094
+ * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2095
+ * and returns true if the url matches the current definition.
1950
2096
  * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1951
- * control how a matched request is handled.
2097
+ * control how a matched request is handled. You can save this object for later use and invoke
2098
+ * `respond` or `passThrough` again in order to change how a matched request is handled.
1952
2099
  */
1953
2100
  angular.mock.e2e = {};
1954
2101
  angular.mock.e2e.$httpBackendDecorator =
1955
- ['$rootScope', '$delegate', '$browser', createHttpBackendMock];
2102
+ ['$rootScope', '$timeout', '$delegate', '$browser', createHttpBackendMock];
2103
+
2104
+
2105
+ /**
2106
+ * @ngdoc type
2107
+ * @name $rootScope.Scope
2108
+ * @module ngMock
2109
+ * @description
2110
+ * {@link ng.$rootScope.Scope Scope} type decorated with helper methods useful for testing. These
2111
+ * methods are automatically available on any {@link ng.$rootScope.Scope Scope} instance when
2112
+ * `ngMock` module is loaded.
2113
+ *
2114
+ * In addition to all the regular `Scope` methods, the following helper methods are available:
2115
+ */
2116
+ angular.mock.$RootScopeDecorator = ['$delegate', function($delegate) {
1956
2117
 
2118
+ var $rootScopePrototype = Object.getPrototypeOf($delegate);
2119
+
2120
+ $rootScopePrototype.$countChildScopes = countChildScopes;
2121
+ $rootScopePrototype.$countWatchers = countWatchers;
2122
+
2123
+ return $delegate;
2124
+
2125
+ // ------------------------------------------------------------------------------------------ //
2126
+
2127
+ /**
2128
+ * @ngdoc method
2129
+ * @name $rootScope.Scope#$countChildScopes
2130
+ * @module ngMock
2131
+ * @description
2132
+ * Counts all the direct and indirect child scopes of the current scope.
2133
+ *
2134
+ * The current scope is excluded from the count. The count includes all isolate child scopes.
2135
+ *
2136
+ * @returns {number} Total number of child scopes.
2137
+ */
2138
+ function countChildScopes() {
2139
+ // jshint validthis: true
2140
+ var count = 0; // exclude the current scope
2141
+ var pendingChildHeads = [this.$$childHead];
2142
+ var currentScope;
2143
+
2144
+ while (pendingChildHeads.length) {
2145
+ currentScope = pendingChildHeads.shift();
2146
+
2147
+ while (currentScope) {
2148
+ count += 1;
2149
+ pendingChildHeads.push(currentScope.$$childHead);
2150
+ currentScope = currentScope.$$nextSibling;
2151
+ }
2152
+ }
1957
2153
 
1958
- angular.mock.clearDataCache = function() {
1959
- var key,
1960
- cache = angular.element.cache;
2154
+ return count;
2155
+ }
1961
2156
 
1962
- for(key in cache) {
1963
- if (Object.prototype.hasOwnProperty.call(cache,key)) {
1964
- var handle = cache[key].handle;
1965
2157
 
1966
- handle && angular.element(handle.elem).off();
1967
- delete cache[key];
2158
+ /**
2159
+ * @ngdoc method
2160
+ * @name $rootScope.Scope#$countWatchers
2161
+ * @module ngMock
2162
+ * @description
2163
+ * Counts all the watchers of direct and indirect child scopes of the current scope.
2164
+ *
2165
+ * The watchers of the current scope are included in the count and so are all the watchers of
2166
+ * isolate child scopes.
2167
+ *
2168
+ * @returns {number} Total number of watchers.
2169
+ */
2170
+ function countWatchers() {
2171
+ // jshint validthis: true
2172
+ var count = this.$$watchers ? this.$$watchers.length : 0; // include the current scope
2173
+ var pendingChildHeads = [this.$$childHead];
2174
+ var currentScope;
2175
+
2176
+ while (pendingChildHeads.length) {
2177
+ currentScope = pendingChildHeads.shift();
2178
+
2179
+ while (currentScope) {
2180
+ count += currentScope.$$watchers ? currentScope.$$watchers.length : 0;
2181
+ pendingChildHeads.push(currentScope.$$childHead);
2182
+ currentScope = currentScope.$$nextSibling;
2183
+ }
1968
2184
  }
2185
+
2186
+ return count;
1969
2187
  }
1970
- };
2188
+ }];
1971
2189
 
1972
2190
 
1973
- if(window.jasmine || window.mocha) {
2191
+ if (window.jasmine || window.mocha) {
1974
2192
 
1975
2193
  var currentSpec = null,
2194
+ annotatedFunctions = [],
1976
2195
  isSpecRunning = function() {
1977
2196
  return !!currentSpec;
1978
2197
  };
1979
2198
 
2199
+ angular.mock.$$annotate = angular.injector.$$annotate;
2200
+ angular.injector.$$annotate = function(fn) {
2201
+ if (typeof fn === 'function' && !fn.$inject) {
2202
+ annotatedFunctions.push(fn);
2203
+ }
2204
+ return angular.mock.$$annotate.apply(this, arguments);
2205
+ };
2206
+
1980
2207
 
1981
2208
  (window.beforeEach || window.setup)(function() {
2209
+ annotatedFunctions = [];
1982
2210
  currentSpec = this;
1983
2211
  });
1984
2212
 
1985
2213
  (window.afterEach || window.teardown)(function() {
1986
2214
  var injector = currentSpec.$injector;
1987
2215
 
2216
+ annotatedFunctions.forEach(function(fn) {
2217
+ delete fn.$inject;
2218
+ });
2219
+
1988
2220
  angular.forEach(currentSpec.$modules, function(module) {
1989
2221
  if (module && module.$$hashKey) {
1990
2222
  module.$$hashKey = undefined;
@@ -1997,11 +2229,8 @@ if(window.jasmine || window.mocha) {
1997
2229
 
1998
2230
  if (injector) {
1999
2231
  injector.get('$rootElement').off();
2000
- injector.get('$browser').pollFns.length = 0;
2001
2232
  }
2002
2233
 
2003
- angular.mock.clearDataCache();
2004
-
2005
2234
  // clean up jquery's fragment cache
2006
2235
  angular.forEach(angular.element.fragments, function(val, key) {
2007
2236
  delete angular.element.fragments[key];
@@ -2164,14 +2393,28 @@ if(window.jasmine || window.mocha) {
2164
2393
  /////////////////////
2165
2394
  function workFn() {
2166
2395
  var modules = currentSpec.$modules || [];
2167
-
2396
+ var strictDi = !!currentSpec.$injectorStrict;
2168
2397
  modules.unshift('ngMock');
2169
2398
  modules.unshift('ng');
2170
2399
  var injector = currentSpec.$injector;
2171
2400
  if (!injector) {
2172
- injector = currentSpec.$injector = angular.injector(modules);
2401
+ if (strictDi) {
2402
+ // If strictDi is enabled, annotate the providerInjector blocks
2403
+ angular.forEach(modules, function(moduleFn) {
2404
+ if (typeof moduleFn === "function") {
2405
+ angular.injector.$$annotate(moduleFn);
2406
+ }
2407
+ });
2408
+ }
2409
+ injector = currentSpec.$injector = angular.injector(modules, strictDi);
2410
+ currentSpec.$injectorStrict = strictDi;
2173
2411
  }
2174
- for(var i = 0, ii = blockFns.length; i < ii; i++) {
2412
+ for (var i = 0, ii = blockFns.length; i < ii; i++) {
2413
+ if (currentSpec.$injectorStrict) {
2414
+ // If the injector is strict / strictDi, and the spec wants to inject using automatic
2415
+ // annotation, then annotate the function here.
2416
+ injector.annotate(blockFns[i]);
2417
+ }
2175
2418
  try {
2176
2419
  /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */
2177
2420
  injector.invoke(blockFns[i] || angular.noop, this);
@@ -2187,6 +2430,22 @@ if(window.jasmine || window.mocha) {
2187
2430
  }
2188
2431
  }
2189
2432
  };
2433
+
2434
+
2435
+ angular.mock.inject.strictDi = function(value) {
2436
+ value = arguments.length ? !!value : true;
2437
+ return isSpecRunning() ? workFn() : workFn;
2438
+
2439
+ function workFn() {
2440
+ if (value !== currentSpec.$injectorStrict) {
2441
+ if (currentSpec.$injector) {
2442
+ throw new Error('Injector already created, can not modify strict annotations');
2443
+ } else {
2444
+ currentSpec.$injectorStrict = value;
2445
+ }
2446
+ }
2447
+ }
2448
+ };
2190
2449
  }
2191
2450
 
2192
2451