nucleus 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (224) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +1 -0
  3. data/.gitignore +19 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +44 -0
  6. data/.travis.yml +21 -0
  7. data/CHANGELOG.md +19 -0
  8. data/CONTRIBUTING.md +13 -0
  9. data/Gemfile +16 -0
  10. data/Guardfile +22 -0
  11. data/LICENSE +21 -0
  12. data/README.md +675 -0
  13. data/Rakefile +137 -0
  14. data/bin/nucleus +91 -0
  15. data/bin/nucleus.bat +1 -0
  16. data/config.ru +18 -0
  17. data/config/adapters/cloud_control.yml +32 -0
  18. data/config/adapters/cloud_foundry_v2.yml +61 -0
  19. data/config/adapters/heroku.yml +13 -0
  20. data/config/adapters/openshift_v2.yml +20 -0
  21. data/config/nucleus_config.rb +47 -0
  22. data/lib/nucleus.rb +13 -0
  23. data/lib/nucleus/adapter_resolver.rb +115 -0
  24. data/lib/nucleus/adapters/base_adapter.rb +109 -0
  25. data/lib/nucleus/adapters/buildpack_translator.rb +79 -0
  26. data/lib/nucleus/adapters/v1/cloud_control/application.rb +108 -0
  27. data/lib/nucleus/adapters/v1/cloud_control/authentication.rb +27 -0
  28. data/lib/nucleus/adapters/v1/cloud_control/buildpacks.rb +23 -0
  29. data/lib/nucleus/adapters/v1/cloud_control/cloud_control.rb +153 -0
  30. data/lib/nucleus/adapters/v1/cloud_control/data.rb +76 -0
  31. data/lib/nucleus/adapters/v1/cloud_control/domains.rb +68 -0
  32. data/lib/nucleus/adapters/v1/cloud_control/lifecycle.rb +27 -0
  33. data/lib/nucleus/adapters/v1/cloud_control/log_poller.rb +71 -0
  34. data/lib/nucleus/adapters/v1/cloud_control/logs.rb +103 -0
  35. data/lib/nucleus/adapters/v1/cloud_control/regions.rb +32 -0
  36. data/lib/nucleus/adapters/v1/cloud_control/scaling.rb +17 -0
  37. data/lib/nucleus/adapters/v1/cloud_control/semantic_errors.rb +31 -0
  38. data/lib/nucleus/adapters/v1/cloud_control/services.rb +162 -0
  39. data/lib/nucleus/adapters/v1/cloud_control/token.rb +17 -0
  40. data/lib/nucleus/adapters/v1/cloud_control/vars.rb +88 -0
  41. data/lib/nucleus/adapters/v1/cloud_foundry_v2/app_states.rb +28 -0
  42. data/lib/nucleus/adapters/v1/cloud_foundry_v2/application.rb +111 -0
  43. data/lib/nucleus/adapters/v1/cloud_foundry_v2/authentication.rb +17 -0
  44. data/lib/nucleus/adapters/v1/cloud_foundry_v2/buildpacks.rb +23 -0
  45. data/lib/nucleus/adapters/v1/cloud_foundry_v2/cloud_foundry_v2.rb +141 -0
  46. data/lib/nucleus/adapters/v1/cloud_foundry_v2/data.rb +97 -0
  47. data/lib/nucleus/adapters/v1/cloud_foundry_v2/domains.rb +149 -0
  48. data/lib/nucleus/adapters/v1/cloud_foundry_v2/lifecycle.rb +41 -0
  49. data/lib/nucleus/adapters/v1/cloud_foundry_v2/logs.rb +303 -0
  50. data/lib/nucleus/adapters/v1/cloud_foundry_v2/regions.rb +33 -0
  51. data/lib/nucleus/adapters/v1/cloud_foundry_v2/scaling.rb +15 -0
  52. data/lib/nucleus/adapters/v1/cloud_foundry_v2/semantic_errors.rb +27 -0
  53. data/lib/nucleus/adapters/v1/cloud_foundry_v2/services.rb +286 -0
  54. data/lib/nucleus/adapters/v1/cloud_foundry_v2/vars.rb +80 -0
  55. data/lib/nucleus/adapters/v1/heroku/app_states.rb +57 -0
  56. data/lib/nucleus/adapters/v1/heroku/application.rb +93 -0
  57. data/lib/nucleus/adapters/v1/heroku/authentication.rb +27 -0
  58. data/lib/nucleus/adapters/v1/heroku/buildpacks.rb +27 -0
  59. data/lib/nucleus/adapters/v1/heroku/data.rb +78 -0
  60. data/lib/nucleus/adapters/v1/heroku/domains.rb +43 -0
  61. data/lib/nucleus/adapters/v1/heroku/heroku.rb +146 -0
  62. data/lib/nucleus/adapters/v1/heroku/lifecycle.rb +51 -0
  63. data/lib/nucleus/adapters/v1/heroku/logs.rb +108 -0
  64. data/lib/nucleus/adapters/v1/heroku/regions.rb +42 -0
  65. data/lib/nucleus/adapters/v1/heroku/scaling.rb +28 -0
  66. data/lib/nucleus/adapters/v1/heroku/semantic_errors.rb +23 -0
  67. data/lib/nucleus/adapters/v1/heroku/services.rb +168 -0
  68. data/lib/nucleus/adapters/v1/heroku/vars.rb +65 -0
  69. data/lib/nucleus/adapters/v1/openshift_v2/app_states.rb +68 -0
  70. data/lib/nucleus/adapters/v1/openshift_v2/application.rb +108 -0
  71. data/lib/nucleus/adapters/v1/openshift_v2/authentication.rb +21 -0
  72. data/lib/nucleus/adapters/v1/openshift_v2/data.rb +96 -0
  73. data/lib/nucleus/adapters/v1/openshift_v2/domains.rb +37 -0
  74. data/lib/nucleus/adapters/v1/openshift_v2/lifecycle.rb +60 -0
  75. data/lib/nucleus/adapters/v1/openshift_v2/logs.rb +106 -0
  76. data/lib/nucleus/adapters/v1/openshift_v2/openshift_v2.rb +125 -0
  77. data/lib/nucleus/adapters/v1/openshift_v2/regions.rb +58 -0
  78. data/lib/nucleus/adapters/v1/openshift_v2/scaling.rb +39 -0
  79. data/lib/nucleus/adapters/v1/openshift_v2/semantic_errors.rb +40 -0
  80. data/lib/nucleus/adapters/v1/openshift_v2/services.rb +173 -0
  81. data/lib/nucleus/adapters/v1/openshift_v2/vars.rb +49 -0
  82. data/lib/nucleus/adapters/v1/stub_adapter.rb +464 -0
  83. data/lib/nucleus/core/adapter_authentication_inductor.rb +62 -0
  84. data/lib/nucleus/core/adapter_extensions/auth/auth_client.rb +44 -0
  85. data/lib/nucleus/core/adapter_extensions/auth/authentication_retry_wrapper.rb +79 -0
  86. data/lib/nucleus/core/adapter_extensions/auth/expiring_token_auth_client.rb +53 -0
  87. data/lib/nucleus/core/adapter_extensions/auth/http_basic_auth_client.rb +37 -0
  88. data/lib/nucleus/core/adapter_extensions/auth/o_auth2_auth_client.rb +95 -0
  89. data/lib/nucleus/core/adapter_extensions/auth/token_auth_client.rb +36 -0
  90. data/lib/nucleus/core/adapter_extensions/http_client.rb +177 -0
  91. data/lib/nucleus/core/adapter_extensions/http_tail_client.rb +26 -0
  92. data/lib/nucleus/core/adapter_extensions/tail_stopper.rb +25 -0
  93. data/lib/nucleus/core/common/errors/ambiguous_adapter_error.rb +7 -0
  94. data/lib/nucleus/core/common/errors/file_existence_error.rb +7 -0
  95. data/lib/nucleus/core/common/errors/startup_error.rb +12 -0
  96. data/lib/nucleus/core/common/exit_codes.rb +25 -0
  97. data/lib/nucleus/core/common/files/application_repo_sanitizer.rb +52 -0
  98. data/lib/nucleus/core/common/files/archive_extractor.rb +112 -0
  99. data/lib/nucleus/core/common/files/archiver.rb +91 -0
  100. data/lib/nucleus/core/common/link_generator.rb +46 -0
  101. data/lib/nucleus/core/common/logging/logging.rb +52 -0
  102. data/lib/nucleus/core/common/logging/multi_logger.rb +59 -0
  103. data/lib/nucleus/core/common/logging/request_log_formatter.rb +48 -0
  104. data/lib/nucleus/core/common/ssh_handler.rb +108 -0
  105. data/lib/nucleus/core/common/stream_callback.rb +27 -0
  106. data/lib/nucleus/core/common/thread_config_accessor.rb +85 -0
  107. data/lib/nucleus/core/common/url_converter.rb +28 -0
  108. data/lib/nucleus/core/enums/application_states.rb +26 -0
  109. data/lib/nucleus/core/enums/logfile_types.rb +28 -0
  110. data/lib/nucleus/core/error_messages.rb +127 -0
  111. data/lib/nucleus/core/errors/adapter_error.rb +13 -0
  112. data/lib/nucleus/core/errors/adapter_missing_implementation_error.rb +12 -0
  113. data/lib/nucleus/core/errors/adapter_request_error.rb +10 -0
  114. data/lib/nucleus/core/errors/adapter_resource_not_found_error.rb +10 -0
  115. data/lib/nucleus/core/errors/endpoint_authentication_error.rb +10 -0
  116. data/lib/nucleus/core/errors/platform_specific_semantic_error.rb +12 -0
  117. data/lib/nucleus/core/errors/platform_timeout_error.rb +10 -0
  118. data/lib/nucleus/core/errors/platform_unavailable_error.rb +10 -0
  119. data/lib/nucleus/core/errors/semantic_adapter_request_error.rb +19 -0
  120. data/lib/nucleus/core/errors/unknown_adapter_call_error.rb +10 -0
  121. data/lib/nucleus/core/file_handling/archive_converter.rb +29 -0
  122. data/lib/nucleus/core/file_handling/file_manager.rb +64 -0
  123. data/lib/nucleus/core/file_handling/git_deployer.rb +133 -0
  124. data/lib/nucleus/core/file_handling/git_repo_analyzer.rb +23 -0
  125. data/lib/nucleus/core/import/adapter_configuration.rb +53 -0
  126. data/lib/nucleus/core/import/vendor_parser.rb +28 -0
  127. data/lib/nucleus/core/import/version_detector.rb +18 -0
  128. data/lib/nucleus/core/models/abstract_model.rb +29 -0
  129. data/lib/nucleus/core/models/endpoint.rb +30 -0
  130. data/lib/nucleus/core/models/provider.rb +26 -0
  131. data/lib/nucleus/core/models/vendor.rb +22 -0
  132. data/lib/nucleus/ext/kernel.rb +5 -0
  133. data/lib/nucleus/ext/regexp.rb +49 -0
  134. data/lib/nucleus/os.rb +15 -0
  135. data/lib/nucleus/root_dir.rb +13 -0
  136. data/lib/nucleus/scripts/finalize.rb +8 -0
  137. data/lib/nucleus/scripts/initialize.rb +9 -0
  138. data/lib/nucleus/scripts/initialize_config_defaults.rb +26 -0
  139. data/lib/nucleus/scripts/load.rb +17 -0
  140. data/lib/nucleus/scripts/load_dependencies.rb +43 -0
  141. data/lib/nucleus/scripts/setup_config.rb +28 -0
  142. data/lib/nucleus/scripts/shutdown.rb +11 -0
  143. data/lib/nucleus/version.rb +3 -0
  144. data/nucleus.gemspec +88 -0
  145. data/public/robots.txt +2 -0
  146. data/public/swagger-ui/css/reset.css +125 -0
  147. data/public/swagger-ui/css/screen.css +1224 -0
  148. data/public/swagger-ui/images/apple-touch-icon-114x114.png +0 -0
  149. data/public/swagger-ui/images/apple-touch-icon-120x120.png +0 -0
  150. data/public/swagger-ui/images/apple-touch-icon-144x144.png +0 -0
  151. data/public/swagger-ui/images/apple-touch-icon-152x152.png +0 -0
  152. data/public/swagger-ui/images/apple-touch-icon-57x57.png +0 -0
  153. data/public/swagger-ui/images/apple-touch-icon-60x60.png +0 -0
  154. data/public/swagger-ui/images/apple-touch-icon-72x72.png +0 -0
  155. data/public/swagger-ui/images/apple-touch-icon-76x76.png +0 -0
  156. data/public/swagger-ui/images/explorer_icons.png +0 -0
  157. data/public/swagger-ui/images/favicon-128.png +0 -0
  158. data/public/swagger-ui/images/favicon-16x16.png +0 -0
  159. data/public/swagger-ui/images/favicon-196x196.png +0 -0
  160. data/public/swagger-ui/images/favicon-32x32.png +0 -0
  161. data/public/swagger-ui/images/favicon-96x96.png +0 -0
  162. data/public/swagger-ui/images/favicon.ico +0 -0
  163. data/public/swagger-ui/images/logo_small.png +0 -0
  164. data/public/swagger-ui/images/mstile-144x144.png +0 -0
  165. data/public/swagger-ui/images/mstile-150x150.png +0 -0
  166. data/public/swagger-ui/images/mstile-310x150.png +0 -0
  167. data/public/swagger-ui/images/mstile-310x310.png +0 -0
  168. data/public/swagger-ui/images/mstile-70x70.png +0 -0
  169. data/public/swagger-ui/images/pet_store_api.png +0 -0
  170. data/public/swagger-ui/images/throbber.gif +0 -0
  171. data/public/swagger-ui/images/wordnik_api.png +0 -0
  172. data/public/swagger-ui/index.html +107 -0
  173. data/public/swagger-ui/lib/backbone-min.js +38 -0
  174. data/public/swagger-ui/lib/handlebars-1.0.0.js +2278 -0
  175. data/public/swagger-ui/lib/highlight.7.3.pack.js +1 -0
  176. data/public/swagger-ui/lib/jquery-1.8.0.min.js +2 -0
  177. data/public/swagger-ui/lib/jquery.ba-bbq.min.js +18 -0
  178. data/public/swagger-ui/lib/jquery.slideto.min.js +1 -0
  179. data/public/swagger-ui/lib/jquery.wiggle.min.js +8 -0
  180. data/public/swagger-ui/lib/shred.bundle.js +2765 -0
  181. data/public/swagger-ui/lib/shred/content.js +193 -0
  182. data/public/swagger-ui/lib/swagger-oauth.js +211 -0
  183. data/public/swagger-ui/lib/swagger.js +1653 -0
  184. data/public/swagger-ui/lib/underscore-min.js +32 -0
  185. data/public/swagger-ui/o2c.html +15 -0
  186. data/public/swagger-ui/redirect.html +14 -0
  187. data/public/swagger-ui/swagger-ui.js +2324 -0
  188. data/public/swagger-ui/swagger-ui.min.js +1 -0
  189. data/schemas/api.adapter.schema.yml +31 -0
  190. data/schemas/api.requirements.schema.yml +17 -0
  191. data/spec/factories/models.rb +61 -0
  192. data/spec/integration/api/auth_spec.rb +58 -0
  193. data/spec/integration/api/endpoints_spec.rb +167 -0
  194. data/spec/integration/api/errors_spec.rb +47 -0
  195. data/spec/integration/api/providers_spec.rb +157 -0
  196. data/spec/integration/api/swagger_schema_spec.rb +64 -0
  197. data/spec/integration/api/vendors_spec.rb +45 -0
  198. data/spec/integration/integration_spec_helper.rb +27 -0
  199. data/spec/integration/test_data_generator.rb +55 -0
  200. data/spec/nucleus_git_key.pem +51 -0
  201. data/spec/spec_helper.rb +98 -0
  202. data/spec/support/shared_example_request_types.rb +99 -0
  203. data/spec/test_suites.rake +31 -0
  204. data/spec/unit/adapters/archive_converter_spec.rb +25 -0
  205. data/spec/unit/adapters/file_manager_spec.rb +93 -0
  206. data/spec/unit/adapters/git_deployer_spec.rb +262 -0
  207. data/spec/unit/adapters/v1/stub_spec.rb +14 -0
  208. data/spec/unit/common/helpers/auth_helper_spec.rb +73 -0
  209. data/spec/unit/common/oauth2_auth_client_spec.rb +108 -0
  210. data/spec/unit/common/regexp_spec.rb +33 -0
  211. data/spec/unit/common/request_log_formatter_spec.rb +108 -0
  212. data/spec/unit/common/thread_config_accessor_spec.rb +97 -0
  213. data/spec/unit/models/endpoint_spec.rb +83 -0
  214. data/spec/unit/models/provider_spec.rb +102 -0
  215. data/spec/unit/models/vendor_spec.rb +100 -0
  216. data/spec/unit/schemas/adapter_schema_spec.rb +16 -0
  217. data/spec/unit/schemas/adapter_validation_spec.rb +56 -0
  218. data/spec/unit/schemas/requirements_schema_spec.rb +16 -0
  219. data/spec/unit/unit_spec_helper.rb +11 -0
  220. data/tasks/compatibility.rake +113 -0
  221. data/tasks/evaluation.rake +162 -0
  222. data/wiki/adapter_tests.md +99 -0
  223. data/wiki/implement_new_adapter.md +155 -0
  224. metadata +836 -0
@@ -0,0 +1 @@
1
+ $(function(){$.fn.vAlign=function(){return this.each(function(c){var a=$(this).height();var d=$(this).parent().height();var b=(d-a)/2;$(this).css("margin-top",b)})};$.fn.stretchFormtasticInputWidthToParent=function(){return this.each(function(b){var d=$(this).closest("form").innerWidth();var c=parseInt($(this).closest("form").css("padding-left"),10)+parseInt($(this).closest("form").css("padding-right"),10);var a=parseInt($(this).css("padding-left"),10)+parseInt($(this).css("padding-right"),10);$(this).css("width",d-c-a)})};$("form.formtastic li.string input, form.formtastic textarea").stretchFormtasticInputWidthToParent();$("ul.downplayed li div.content p").vAlign();$("form.sandbox").submit(function(){var a=true;$(this).find("input.required").each(function(){$(this).removeClass("error");if($(this).val()==""){$(this).addClass("error");$(this).wiggle();a=false}});return a})});function clippyCopiedCallback(b){$("#api_key_copied").fadeIn().delay(1000).fadeOut()}log=function(){log.history=log.history||[];log.history.push(arguments);if(this.console){console.log(Array.prototype.slice.call(arguments)[0])}};if(Function.prototype.bind&&console&&typeof console.log=="object"){["log","info","warn","error","assert","dir","clear","profile","profileEnd"].forEach(function(a){console[a]=this.bind(console[a],console)},Function.prototype.call)}var Docs={shebang:function(){var b=$.param.fragment().split("/");b.shift();switch(b.length){case 1:log("shebang resource:"+b[0]);var d="resource_"+b[0];Docs.expandEndpointListForResource(b[0]);$("#"+d).slideto({highlight:false});break;case 2:log("shebang endpoint: "+b.join("_"));Docs.expandEndpointListForResource(b[0]);$("#"+d).slideto({highlight:false});var c=b.join("_");var a=c+"_content";log("li_dom_id "+c);log("li_content_dom_id "+a);Docs.expandOperation($("#"+a));$("#"+c).slideto({highlight:false});break}},toggleEndpointListForResource:function(b){var a=$("li#resource_"+Docs.escapeResourceName(b)+" ul.endpoints");if(a.is(":visible")){Docs.collapseEndpointListForResource(b)}else{Docs.expandEndpointListForResource(b)}},expandEndpointListForResource:function(b){var b=Docs.escapeResourceName(b);if(b==""){$(".resource ul.endpoints").slideDown();return}$("li#resource_"+b).addClass("active");var a=$("li#resource_"+b+" ul.endpoints");a.slideDown()},collapseEndpointListForResource:function(b){var b=Docs.escapeResourceName(b);$("li#resource_"+b).removeClass("active");var a=$("li#resource_"+b+" ul.endpoints");a.slideUp()},expandOperationsForResource:function(a){Docs.expandEndpointListForResource(a);if(a==""){$(".resource ul.endpoints li.operation div.content").slideDown();return}$("li#resource_"+Docs.escapeResourceName(a)+" li.operation div.content").each(function(){Docs.expandOperation($(this))})},collapseOperationsForResource:function(a){Docs.expandEndpointListForResource(a);$("li#resource_"+Docs.escapeResourceName(a)+" li.operation div.content").each(function(){Docs.collapseOperation($(this))})},escapeResourceName:function(a){return a.replace(/[!"#$%&'()*+,.\/:;<=>?@\[\\\]\^`{|}~]/g,"\\$&")},expandOperation:function(a){a.slideDown()},collapseOperation:function(a){a.slideUp()}};(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.content_type=b(function(g,l,f,k,j){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);j=j||{};var i="",c,h="function",m=this;function e(r,q){var o="",p;o+="\n ";p=f.each.call(r,r.produces,{hash:{},inverse:m.noop,fn:m.program(2,d,q),data:q});if(p||p===0){o+=p}o+="\n";return o}function d(r,q){var o="",p;o+='\n <option value="';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+='">';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+="</option>\n ";return o}function n(p,o){return'\n <option value="application/json">application/json</option>\n'}i+='<label for="contentType"></label>\n<select name="contentType">\n';c=f["if"].call(l,l.produces,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j),data:j});if(c||c===0){i+=c}i+="\n</select>\n";return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.main=b(function(g,m,f,l,k){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);k=k||{};var i="",c,h="function",j=this.escapeExpression,p=this;function e(v,u){var r="",t,s;r+='\n <div class="info_title">'+j(((t=((t=v.info),t==null||t===false?t:t.title)),typeof t===h?t.apply(v):t))+'</div>\n <div class="info_description">';s=((t=((t=v.info),t==null||t===false?t:t.description)),typeof t===h?t.apply(v):t);if(s||s===0){r+=s}r+="</div>\n ";s=f["if"].call(v,((t=v.info),t==null||t===false?t:t.termsOfServiceUrl),{hash:{},inverse:p.noop,fn:p.program(2,d,u),data:u});if(s||s===0){r+=s}r+="\n ";s=f["if"].call(v,((t=v.info),t==null||t===false?t:t.contact),{hash:{},inverse:p.noop,fn:p.program(4,q,u),data:u});if(s||s===0){r+=s}r+="\n ";s=f["if"].call(v,((t=v.info),t==null||t===false?t:t.license),{hash:{},inverse:p.noop,fn:p.program(6,o,u),data:u});if(s||s===0){r+=s}r+="\n ";return r}function d(u,t){var r="",s;r+='<div class="info_tos"><a href="'+j(((s=((s=u.info),s==null||s===false?s:s.termsOfServiceUrl)),typeof s===h?s.apply(u):s))+'">Terms of service</a></div>';return r}function q(u,t){var r="",s;r+="<div class='info_contact'><a href=\"mailto:"+j(((s=((s=u.info),s==null||s===false?s:s.contact)),typeof s===h?s.apply(u):s))+'">Contact the developer</a></div>';return r}function o(u,t){var r="",s;r+="<div class='info_license'><a href='"+j(((s=((s=u.info),s==null||s===false?s:s.licenseUrl)),typeof s===h?s.apply(u):s))+"'>"+j(((s=((s=u.info),s==null||s===false?s:s.license)),typeof s===h?s.apply(u):s))+"</a></div>";return r}function n(u,t){var r="",s;r+='\n , <span style="font-variant: small-caps">api version</span>: ';if(s=f.apiVersion){s=s.call(u,{hash:{},data:t})}else{s=u.apiVersion;s=typeof s===h?s.apply(u):s}r+=j(s)+"\n ";return r}i+="<div class='info' id='api_info'>\n ";c=f["if"].call(m,m.info,{hash:{},inverse:p.noop,fn:p.program(1,e,k),data:k});if(c||c===0){i+=c}i+="\n</div>\n<div class='container' id='resources_container'>\n <ul id='resources'>\n </ul>\n\n <div class=\"footer\">\n <br>\n <br>\n <h4 style=\"color: #999\">[ <span style=\"font-variant: small-caps\">base url</span>: ";if(c=f.basePath){c=c.call(m,{hash:{},data:k})}else{c=m.basePath;c=typeof c===h?c.apply(m):c}i+=j(c)+"\n ";c=f["if"].call(m,m.apiVersion,{hash:{},inverse:p.noop,fn:p.program(8,n,k),data:k});if(c||c===0){i+=c}i+="]</h4>\n </div>\n</div>\n";return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.operation=b(function(g,s,q,m,y){this.compilerInfo=[4,">= 1.0.0"];q=this.merge(q,g.helpers);y=y||{};var r="",i,f,e="function",d=this.escapeExpression,p=this,c=q.blockHelperMissing;function o(C,B){var z="",A;z+="\n <h4>Implementation Notes</h4>\n <p>";if(A=q.notes){A=A.call(C,{hash:{},data:B})}else{A=C.notes;A=typeof A===e?A.apply(C):A}if(A||A===0){z+=A}z+="</p>\n ";return z}function n(A,z){return'\n <div class="auth">\n <span class="api-ic ic-error"></span>'}function l(C,B){var z="",A;z+='\n <div id="api_information_panel" style="top: 526px; left: 776px; display: none;">\n ';A=q.each.call(C,C,{hash:{},inverse:p.noop,fn:p.program(6,k,B),data:B});if(A||A===0){z+=A}z+="\n </div>\n ";return z}function k(D,C){var z="",B,A;z+="\n <div title='";A=((B=D.description),typeof B===e?B.apply(D):B);if(A||A===0){z+=A}z+="'>"+d(((B=D.scope),typeof B===e?B.apply(D):B))+"</div>\n ";return z}function h(A,z){return"</div>"}function x(A,z){return'\n <div class=\'access\'>\n <span class="api-ic ic-off" title="click to authenticate"></span>\n </div>\n '}function w(A,z){return'\n <h4>Response Class</h4>\n <p><span class="model-signature" /></p>\n <br/>\n <div class="response-content-type" />\n '}function v(A,z){return'\n <h4>Parameters</h4>\n <table class=\'fullwidth\'>\n <thead>\n <tr>\n <th style="width: 100px; max-width: 100px">Parameter</th>\n <th style="width: 310px; max-width: 310px">Value</th>\n <th style="width: 200px; max-width: 200px">Description</th>\n <th style="width: 100px; max-width: 100px">Parameter Type</th>\n <th style="width: 220px; max-width: 230px">Data Type</th>\n </tr>\n </thead>\n <tbody class="operation-params">\n\n </tbody>\n </table>\n '}function u(A,z){return"\n <div style='margin:0;padding:0;display:inline'></div>\n <h4>Response Messages</h4>\n <table class='fullwidth'>\n <thead>\n <tr>\n <th>HTTP Status Code</th>\n <th>Reason</th>\n <th>Response Model</th>\n </tr>\n </thead>\n <tbody class=\"operation-status\">\n \n </tbody>\n </table>\n "}function t(A,z){return"\n "}function j(A,z){return"\n <div class='sandbox_header'>\n <input class='submit' name='commit' type='button' value='Try it out!' />\n <a href='#' class='response_hider' style='display:none'>Hide Response</a>\n <span class='response_throbber' style='display:none'></span>\n </div>\n "}r+="\n <ul class='operations' >\n <li class='";if(i=q.method){i=i.call(s,{hash:{},data:y})}else{i=s.method;i=typeof i===e?i.apply(s):i}r+=d(i)+" operation' id='";if(i=q.parentId){i=i.call(s,{hash:{},data:y})}else{i=s.parentId;i=typeof i===e?i.apply(s):i}r+=d(i)+"_";if(i=q.nickname){i=i.call(s,{hash:{},data:y})}else{i=s.nickname;i=typeof i===e?i.apply(s):i}r+=d(i)+"'>\n <div class='heading'>\n <h3>\n <span class='http_method'>\n <a href='#!/";if(i=q.parentId){i=i.call(s,{hash:{},data:y})}else{i=s.parentId;i=typeof i===e?i.apply(s):i}r+=d(i)+"/";if(i=q.nickname){i=i.call(s,{hash:{},data:y})}else{i=s.nickname;i=typeof i===e?i.apply(s):i}r+=d(i)+'\' class="toggleOperation">';if(i=q.method){i=i.call(s,{hash:{},data:y})}else{i=s.method;i=typeof i===e?i.apply(s):i}r+=d(i)+"</a>\n </span>\n <span class='path'>\n <a href='#!/";if(i=q.parentId){i=i.call(s,{hash:{},data:y})}else{i=s.parentId;i=typeof i===e?i.apply(s):i}r+=d(i)+"/";if(i=q.nickname){i=i.call(s,{hash:{},data:y})}else{i=s.nickname;i=typeof i===e?i.apply(s):i}r+=d(i)+'\' class="toggleOperation">';if(i=q.path){i=i.call(s,{hash:{},data:y})}else{i=s.path;i=typeof i===e?i.apply(s):i}r+=d(i)+"</a>\n </span>\n </h3>\n <ul class='options'>\n <li>\n <a href='#!/";if(i=q.parentId){i=i.call(s,{hash:{},data:y})}else{i=s.parentId;i=typeof i===e?i.apply(s):i}r+=d(i)+"/";if(i=q.nickname){i=i.call(s,{hash:{},data:y})}else{i=s.nickname;i=typeof i===e?i.apply(s):i}r+=d(i)+'\' class="toggleOperation">';if(i=q.summary){i=i.call(s,{hash:{},data:y})}else{i=s.summary;i=typeof i===e?i.apply(s):i}if(i||i===0){r+=i}r+="</a>\n </li>\n </ul>\n </div>\n <div class='content' id='";if(i=q.parentId){i=i.call(s,{hash:{},data:y})}else{i=s.parentId;i=typeof i===e?i.apply(s):i}r+=d(i)+"_";if(i=q.nickname){i=i.call(s,{hash:{},data:y})}else{i=s.nickname;i=typeof i===e?i.apply(s):i}r+=d(i)+"_content' style='display:none'>\n ";i=q["if"].call(s,s.notes,{hash:{},inverse:p.noop,fn:p.program(1,o,y),data:y});if(i||i===0){r+=i}r+="\n ";f={hash:{},inverse:p.noop,fn:p.program(3,n,y),data:y};if(i=q.oauth){i=i.call(s,f)}else{i=s.oauth;i=typeof i===e?i.apply(s):i}if(!q.oauth){i=c.call(s,i,f)}if(i||i===0){r+=i}r+="\n ";i=q.each.call(s,s.oauth,{hash:{},inverse:p.noop,fn:p.program(5,l,y),data:y});if(i||i===0){r+=i}r+="\n ";f={hash:{},inverse:p.noop,fn:p.program(8,h,y),data:y};if(i=q.oauth){i=i.call(s,f)}else{i=s.oauth;i=typeof i===e?i.apply(s):i}if(!q.oauth){i=c.call(s,i,f)}if(i||i===0){r+=i}r+="\n ";f={hash:{},inverse:p.noop,fn:p.program(10,x,y),data:y};if(i=q.oauth){i=i.call(s,f)}else{i=s.oauth;i=typeof i===e?i.apply(s):i}if(!q.oauth){i=c.call(s,i,f)}if(i||i===0){r+=i}r+="\n ";i=q["if"].call(s,s.type,{hash:{},inverse:p.noop,fn:p.program(12,w,y),data:y});if(i||i===0){r+=i}r+="\n <form accept-charset='UTF-8' class='sandbox'>\n <div style='margin:0;padding:0;display:inline'></div>\n ";i=q["if"].call(s,s.parameters,{hash:{},inverse:p.noop,fn:p.program(14,v,y),data:y});if(i||i===0){r+=i}r+="\n ";i=q["if"].call(s,s.responseMessages,{hash:{},inverse:p.noop,fn:p.program(16,u,y),data:y});if(i||i===0){r+=i}r+="\n ";i=q["if"].call(s,s.isReadOnly,{hash:{},inverse:p.program(20,j,y),fn:p.program(18,t,y),data:y});if(i||i===0){r+=i}r+="\n </form>\n <div class='response' style='display:none'>\n <h4>Request URL</h4>\n <div class='block request_url'></div>\n <h4>Response Body</h4>\n <div class='block response_body'></div>\n <h4>Response Code</h4>\n <div class='block response_code'></div>\n <h4>Response Headers</h4>\n <div class='block response_headers'></div>\n </div>\n </div>\n </li>\n </ul>\n";return r})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param=b(function(f,q,o,j,t){this.compilerInfo=[4,">= 1.0.0"];o=this.merge(o,f.helpers);t=t||{};var p="",g,d="function",c=this.escapeExpression,n=this;function m(y,x){var v="",w;v+="\n ";w=o["if"].call(y,y.isFile,{hash:{},inverse:n.program(4,k,x),fn:n.program(2,l,x),data:x});if(w||w===0){v+=w}v+="\n ";return v}function l(y,x){var v="",w;v+='\n <input type="file" name=\'';if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+'\'/>\n <div class="parameter-content-type" />\n ';return v}function k(y,x){var v="",w;v+="\n ";w=o["if"].call(y,y.defaultValue,{hash:{},inverse:n.program(7,h,x),fn:n.program(5,i,x),data:x});if(w||w===0){v+=w}v+="\n ";return v}function i(y,x){var v="",w;v+="\n <textarea class='body-textarea' name='";if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+"'>";if(w=o.defaultValue){w=w.call(y,{hash:{},data:x})}else{w=y.defaultValue;w=typeof w===d?w.apply(y):w}v+=c(w)+"</textarea>\n ";return v}function h(y,x){var v="",w;v+="\n <textarea class='body-textarea' name='";if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+'\'></textarea>\n <br />\n <div class="parameter-content-type" />\n ';return v}function e(y,x){var v="",w;v+="\n ";w=o["if"].call(y,y.isFile,{hash:{},inverse:n.program(10,u,x),fn:n.program(2,l,x),data:x});if(w||w===0){v+=w}v+="\n ";return v}function u(y,x){var v="",w;v+="\n ";w=o["if"].call(y,y.defaultValue,{hash:{},inverse:n.program(13,r,x),fn:n.program(11,s,x),data:x});if(w||w===0){v+=w}v+="\n ";return v}function s(y,x){var v="",w;v+="\n <input class='parameter' minlength='0' name='";if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+"' placeholder='' type='text' value='";if(w=o.defaultValue){w=w.call(y,{hash:{},data:x})}else{w=y.defaultValue;w=typeof w===d?w.apply(y):w}v+=c(w)+"'/>\n ";return v}function r(y,x){var v="",w;v+="\n <input class='parameter' minlength='0' name='";if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+"' placeholder='' type='text' value=''/>\n ";return v}p+="<td class='code'>";if(g=o.name){g=g.call(q,{hash:{},data:t})}else{g=q.name;g=typeof g===d?g.apply(q):g}p+=c(g)+"</td>\n<td>\n\n ";g=o["if"].call(q,q.isBody,{hash:{},inverse:n.program(9,e,t),fn:n.program(1,m,t),data:t});if(g||g===0){p+=g}p+="\n\n</td>\n<td>";if(g=o.description){g=g.call(q,{hash:{},data:t})}else{g=q.description;g=typeof g===d?g.apply(q):g}if(g||g===0){p+=g}p+="</td>\n<td>";if(g=o.paramType){g=g.call(q,{hash:{},data:t})}else{g=q.paramType;g=typeof g===d?g.apply(q):g}if(g||g===0){p+=g}p+='</td>\n<td>\n <span class="model-signature"></span>\n</td>\n';return p})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param_list=b(function(h,t,r,m,y){this.compilerInfo=[4,">= 1.0.0"];r=this.merge(r,h.helpers);y=y||{};var s="",j,g,e,p=this,q=r.helperMissing,d="function",c=this.escapeExpression;function o(A,z){return" multiple='multiple'"}function n(A,z){return"\n "}function l(C,B){var z="",A;z+="\n ";A=r["if"].call(C,C.defaultValue,{hash:{},inverse:p.program(8,i,B),fn:p.program(6,k,B),data:B});if(A||A===0){z+=A}z+="\n ";return z}function k(A,z){return"\n "}function i(E,D){var z="",C,B,A;z+="\n ";A={hash:{},inverse:p.program(11,x,D),fn:p.program(9,f,D),data:D};B=((C=r.isArray||E.isArray),C?C.call(E,E,A):q.call(E,"isArray",E,A));if(B||B===0){z+=B}z+="\n ";return z}function f(A,z){return"\n "}function x(A,z){return"\n <option selected=\"\" value=''></option>\n "}function w(C,B){var z="",A;z+="\n ";A=r["if"].call(C,C.isDefault,{hash:{},inverse:p.program(16,u,B),fn:p.program(14,v,B),data:B});if(A||A===0){z+=A}z+="\n ";return z}function v(C,B){var z="",A;z+='\n <option selected="" value=\'';if(A=r.value){A=A.call(C,{hash:{},data:B})}else{A=C.value;A=typeof A===d?A.apply(C):A}z+=c(A)+"'>";if(A=r.value){A=A.call(C,{hash:{},data:B})}else{A=C.value;A=typeof A===d?A.apply(C):A}z+=c(A)+" (default)</option>\n ";return z}function u(C,B){var z="",A;z+="\n <option value='";if(A=r.value){A=A.call(C,{hash:{},data:B})}else{A=C.value;A=typeof A===d?A.apply(C):A}z+=c(A)+"'>";if(A=r.value){A=A.call(C,{hash:{},data:B})}else{A=C.value;A=typeof A===d?A.apply(C):A}z+=c(A)+"</option>\n ";return z}s+="<td class='code'>";if(j=r.name){j=j.call(t,{hash:{},data:y})}else{j=t.name;j=typeof j===d?j.apply(t):j}s+=c(j)+"</td>\n<td>\n <select ";e={hash:{},inverse:p.noop,fn:p.program(1,o,y),data:y};g=((j=r.isArray||t.isArray),j?j.call(t,t,e):q.call(t,"isArray",t,e));if(g||g===0){s+=g}s+=" class='parameter' name='";if(g=r.name){g=g.call(t,{hash:{},data:y})}else{g=t.name;g=typeof g===d?g.apply(t):g}s+=c(g)+"'>\n ";g=r["if"].call(t,t.required,{hash:{},inverse:p.program(5,l,y),fn:p.program(3,n,y),data:y});if(g||g===0){s+=g}s+="\n ";g=r.each.call(t,((j=t.allowableValues),j==null||j===false?j:j.descriptiveValues),{hash:{},inverse:p.noop,fn:p.program(13,w,y),data:y});if(g||g===0){s+=g}s+="\n </select>\n</td>\n<td>";if(g=r.description){g=g.call(t,{hash:{},data:y})}else{g=t.description;g=typeof g===d?g.apply(t):g}if(g||g===0){s+=g}s+="</td>\n<td>";if(g=r.paramType){g=g.call(t,{hash:{},data:y})}else{g=t.paramType;g=typeof g===d?g.apply(t):g}if(g||g===0){s+=g}s+='</td>\n<td><span class="model-signature"></span></td>';return s})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param_readonly=b(function(g,m,f,l,k){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);k=k||{};var i="",d,h="function",j=this.escapeExpression,o=this;function e(t,s){var q="",r;q+="\n <textarea class='body-textarea' readonly='readonly' name='";if(r=f.name){r=r.call(t,{hash:{},data:s})}else{r=t.name;r=typeof r===h?r.apply(t):r}q+=j(r)+"'>";if(r=f.defaultValue){r=r.call(t,{hash:{},data:s})}else{r=t.defaultValue;r=typeof r===h?r.apply(t):r}q+=j(r)+"</textarea>\n ";return q}function c(t,s){var q="",r;q+="\n ";r=f["if"].call(t,t.defaultValue,{hash:{},inverse:o.program(6,n,s),fn:o.program(4,p,s),data:s});if(r||r===0){q+=r}q+="\n ";return q}function p(t,s){var q="",r;q+="\n ";if(r=f.defaultValue){r=r.call(t,{hash:{},data:s})}else{r=t.defaultValue;r=typeof r===h?r.apply(t):r}q+=j(r)+"\n ";return q}function n(r,q){return"\n (empty)\n "}i+="<td class='code'>";if(d=f.name){d=d.call(m,{hash:{},data:k})}else{d=m.name;d=typeof d===h?d.apply(m):d}i+=j(d)+"</td>\n<td>\n ";d=f["if"].call(m,m.isBody,{hash:{},inverse:o.program(3,c,k),fn:o.program(1,e,k),data:k});if(d||d===0){i+=d}i+="\n</td>\n<td>";if(d=f.description){d=d.call(m,{hash:{},data:k})}else{d=m.description;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+="</td>\n<td>";if(d=f.paramType){d=d.call(m,{hash:{},data:k})}else{d=m.paramType;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+='</td>\n<td><span class="model-signature"></span></td>\n';return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param_readonly_required=b(function(g,m,f,l,k){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);k=k||{};var i="",d,h="function",j=this.escapeExpression,o=this;function e(t,s){var q="",r;q+="\n <textarea class='body-textarea' readonly='readonly' placeholder='(required)' name='";if(r=f.name){r=r.call(t,{hash:{},data:s})}else{r=t.name;r=typeof r===h?r.apply(t):r}q+=j(r)+"'>";if(r=f.defaultValue){r=r.call(t,{hash:{},data:s})}else{r=t.defaultValue;r=typeof r===h?r.apply(t):r}q+=j(r)+"</textarea>\n ";return q}function c(t,s){var q="",r;q+="\n ";r=f["if"].call(t,t.defaultValue,{hash:{},inverse:o.program(6,n,s),fn:o.program(4,p,s),data:s});if(r||r===0){q+=r}q+="\n ";return q}function p(t,s){var q="",r;q+="\n ";if(r=f.defaultValue){r=r.call(t,{hash:{},data:s})}else{r=t.defaultValue;r=typeof r===h?r.apply(t):r}q+=j(r)+"\n ";return q}function n(r,q){return"\n (empty)\n "}i+="<td class='code required'>";if(d=f.name){d=d.call(m,{hash:{},data:k})}else{d=m.name;d=typeof d===h?d.apply(m):d}i+=j(d)+"</td>\n<td>\n ";d=f["if"].call(m,m.isBody,{hash:{},inverse:o.program(3,c,k),fn:o.program(1,e,k),data:k});if(d||d===0){i+=d}i+="\n</td>\n<td>";if(d=f.description){d=d.call(m,{hash:{},data:k})}else{d=m.description;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+="</td>\n<td>";if(d=f.paramType){d=d.call(m,{hash:{},data:k})}else{d=m.paramType;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+='</td>\n<td><span class="model-signature"></span></td>\n';return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param_required=b(function(f,q,o,j,u){this.compilerInfo=[4,">= 1.0.0"];o=this.merge(o,f.helpers);u=u||{};var p="",g,d="function",c=this.escapeExpression,n=this;function m(z,y){var w="",x;w+="\n ";x=o["if"].call(z,z.isFile,{hash:{},inverse:n.program(4,k,y),fn:n.program(2,l,y),data:y});if(x||x===0){w+=x}w+="\n ";return w}function l(z,y){var w="",x;w+='\n <input type="file" name=\'';if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"'/>\n ";return w}function k(z,y){var w="",x;w+="\n ";x=o["if"].call(z,z.defaultValue,{hash:{},inverse:n.program(7,h,y),fn:n.program(5,i,y),data:y});if(x||x===0){w+=x}w+="\n ";return w}function i(z,y){var w="",x;w+="\n <textarea class='body-textarea' placeholder='(required)' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"'>";if(x=o.defaultValue){x=x.call(z,{hash:{},data:y})}else{x=z.defaultValue;x=typeof x===d?x.apply(z):x}w+=c(x)+"</textarea>\n ";return w}function h(z,y){var w="",x;w+="\n <textarea class='body-textarea' placeholder='(required)' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+'\'></textarea>\n <br />\n <div class="parameter-content-type" />\n ';return w}function e(z,y){var w="",x;w+="\n ";x=o["if"].call(z,z.isFile,{hash:{},inverse:n.program(12,t,y),fn:n.program(10,v,y),data:y});if(x||x===0){w+=x}w+="\n ";return w}function v(z,y){var w="",x;w+="\n <input class='parameter' class='required' type='file' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"'/>\n ";return w}function t(z,y){var w="",x;w+="\n ";x=o["if"].call(z,z.defaultValue,{hash:{},inverse:n.program(15,r,y),fn:n.program(13,s,y),data:y});if(x||x===0){w+=x}w+="\n ";return w}function s(z,y){var w="",x;w+="\n <input class='parameter required' minlength='1' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"' placeholder='(required)' type='text' value='";if(x=o.defaultValue){x=x.call(z,{hash:{},data:y})}else{x=z.defaultValue;x=typeof x===d?x.apply(z):x}w+=c(x)+"'/>\n ";return w}function r(z,y){var w="",x;w+="\n <input class='parameter required' minlength='1' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"' placeholder='(required)' type='text' value=''/>\n ";return w}p+="<td class='code required'>";if(g=o.name){g=g.call(q,{hash:{},data:u})}else{g=q.name;g=typeof g===d?g.apply(q):g}p+=c(g)+"</td>\n<td>\n ";g=o["if"].call(q,q.isBody,{hash:{},inverse:n.program(9,e,u),fn:n.program(1,m,u),data:u});if(g||g===0){p+=g}p+="\n</td>\n<td>\n <strong>";if(g=o.description){g=g.call(q,{hash:{},data:u})}else{g=q.description;g=typeof g===d?g.apply(q):g}if(g||g===0){p+=g}p+="</strong>\n</td>\n<td>";if(g=o.paramType){g=g.call(q,{hash:{},data:u})}else{g=q.paramType;g=typeof g===d?g.apply(q):g}if(g||g===0){p+=g}p+='</td>\n<td><span class="model-signature"></span></td>\n';return p})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.parameter_content_type=b(function(g,l,f,k,j){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);j=j||{};var i="",c,h="function",m=this;function e(r,q){var o="",p;o+="\n ";p=f.each.call(r,r.consumes,{hash:{},inverse:m.noop,fn:m.program(2,d,q),data:q});if(p||p===0){o+=p}o+="\n";return o}function d(r,q){var o="",p;o+='\n <option value="';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+='">';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+="</option>\n ";return o}function n(p,o){return'\n <option value="application/json">application/json</option>\n'}i+='<label for="parameterContentType"></label>\n<select name="parameterContentType">\n';c=f["if"].call(l,l.consumes,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j),data:j});if(c||c===0){i+=c}i+="\n</select>\n";return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.resource=b(function(f,l,e,k,j){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,f.helpers);j=j||{};var h="",c,o,g="function",i=this.escapeExpression,n=this,m=e.blockHelperMissing;function d(q,p){return" : "}h+="<div class='heading'>\n <h2>\n <a href='#!/";if(c=e.id){c=c.call(l,{hash:{},data:j})}else{c=l.id;c=typeof c===g?c.apply(l):c}h+=i(c)+'\' class="toggleEndpointList" data-id="';if(c=e.id){c=c.call(l,{hash:{},data:j})}else{c=l.id;c=typeof c===g?c.apply(l):c}h+=i(c)+'">';if(c=e.name){c=c.call(l,{hash:{},data:j})}else{c=l.name;c=typeof c===g?c.apply(l):c}h+=i(c)+"</a> ";o={hash:{},inverse:n.noop,fn:n.program(1,d,j),data:j};if(c=e.description){c=c.call(l,o)}else{c=l.description;c=typeof c===g?c.apply(l):c}if(!e.description){c=m.call(l,c,o)}if(c||c===0){h+=c}if(c=e.description){c=c.call(l,{hash:{},data:j})}else{c=l.description;c=typeof c===g?c.apply(l):c}if(c||c===0){h+=c}h+="\n </h2>\n <ul class='options'>\n <li>\n <a href='#!/";if(c=e.id){c=c.call(l,{hash:{},data:j})}else{c=l.id;c=typeof c===g?c.apply(l):c}h+=i(c)+"' id='endpointListTogger_";if(c=e.id){c=c.call(l,{hash:{},data:j})}else{c=l.id;c=typeof c===g?c.apply(l):c}h+=i(c)+'\' class="toggleEndpointList" data-id="';if(c=e.id){c=c.call(l,{hash:{},data:j})}else{c=l.id;c=typeof c===g?c.apply(l):c}h+=i(c)+'">Show/Hide</a>\n </li>\n <li>\n <a href=\'#\' class="collapseResource" data-id="';if(c=e.id){c=c.call(l,{hash:{},data:j})}else{c=l.id;c=typeof c===g?c.apply(l):c}h+=i(c)+'">\n List Operations\n </a>\n </li>\n <li>\n <a href=\'#\' class="expandResource" data-id=';if(c=e.id){c=c.call(l,{hash:{},data:j})}else{c=l.id;c=typeof c===g?c.apply(l):c}h+=i(c)+">\n Expand Operations\n </a>\n </li>\n <li>\n <a href='";if(c=e.url){c=c.call(l,{hash:{},data:j})}else{c=l.url;c=typeof c===g?c.apply(l):c}h+=i(c)+"'>Raw</a>\n </li>\n </ul>\n</div>\n<ul class='endpoints' id='";if(c=e.id){c=c.call(l,{hash:{},data:j})}else{c=l.id;c=typeof c===g?c.apply(l):c}h+=i(c)+"_endpoint_list' style='display:none'>\n\n</ul>\n";return h})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.response_content_type=b(function(g,l,f,k,j){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);j=j||{};var i="",c,h="function",m=this;function e(r,q){var o="",p;o+="\n ";p=f.each.call(r,r.produces,{hash:{},inverse:m.noop,fn:m.program(2,d,q),data:q});if(p||p===0){o+=p}o+="\n";return o}function d(r,q){var o="",p;o+='\n <option value="';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+='">';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+="</option>\n ";return o}function n(p,o){return'\n <option value="application/json">application/json</option>\n'}i+='<label for="responseContentType"></label>\n<select name="responseContentType">\n';c=f["if"].call(l,l.produces,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j),data:j});if(c||c===0){i+=c}i+="\n</select>\n";return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.signature=b(function(e,k,d,j,i){this.compilerInfo=[4,">= 1.0.0"];d=this.merge(d,e.helpers);i=i||{};var g="",c,f="function",h=this.escapeExpression;g+='<div>\n<ul class="signature-nav">\n <li><a class="description-link" href="#">Model</a></li>\n <li><a class="snippet-link" href="#">Model Schema</a></li>\n</ul>\n<div>\n\n<div class="signature-container">\n <div class="description">\n ';if(c=d.signature){c=c.call(k,{hash:{},data:i})}else{c=k.signature;c=typeof c===f?c.apply(k):c}if(c||c===0){g+=c}g+='\n </div>\n\n <div class="snippet">\n <pre><code>';if(c=d.sampleJSON){c=c.call(k,{hash:{},data:i})}else{c=k.sampleJSON;c=typeof c===f?c.apply(k):c}g+=h(c)+'</code></pre>\n <small class="notice"></small>\n </div>\n</div>\n\n';return g})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.status_code=b(function(e,k,d,j,i){this.compilerInfo=[4,">= 1.0.0"];d=this.merge(d,e.helpers);i=i||{};var g="",c,f="function",h=this.escapeExpression;g+="<td width='15%' class='code'>";if(c=d.code){c=c.call(k,{hash:{},data:i})}else{c=k.code;c=typeof c===f?c.apply(k):c}g+=h(c)+"</td>\n<td>";if(c=d.message){c=c.call(k,{hash:{},data:i})}else{c=k.message;c=typeof c===f?c.apply(k):c}if(c||c===0){g+=c}g+="</td>\n<td width='50%'><span class=\"model-signature\" /></td>";return g})})();(function(){var j,r,u,o,l,k,n,m,i,p,s,q,h,c,g,f,e,d,b,a,x,w,t={}.hasOwnProperty,v=function(B,z){for(var y in z){if(t.call(z,y)){B[y]=z[y]}}function A(){this.constructor=B}A.prototype=z.prototype;B.prototype=new A();B.__super__=z.prototype;return B};s=(function(z){v(y,z);function y(){q=y.__super__.constructor.apply(this,arguments);return q}y.prototype.dom_id="swagger_ui";y.prototype.options=null;y.prototype.api=null;y.prototype.headerView=null;y.prototype.mainView=null;y.prototype.initialize=function(A){var B=this;if(A==null){A={}}if(A.dom_id!=null){this.dom_id=A.dom_id;delete A.dom_id}if($("#"+this.dom_id)==null){$("body").append('<div id="'+this.dom_id+'"></div>')}this.options=A;this.options.success=function(){return B.render()};this.options.progress=function(C){return B.showMessage(C)};this.options.failure=function(C){return B.onLoadFailure(C)};this.headerView=new r({el:$("#header")});return this.headerView.on("update-swagger-ui",function(C){return B.updateSwaggerUi(C)})};y.prototype.updateSwaggerUi=function(A){this.options.url=A.url;return this.load()};y.prototype.load=function(){var B,A;if((A=this.mainView)!=null){A.clear()}B=this.options.url;if(B.indexOf("http")!==0){B=this.buildUrl(window.location.href.toString(),B)}this.options.url=B;this.headerView.update(B);this.api=new SwaggerApi(this.options);this.api.build();return this.api};y.prototype.render=function(){var A=this;this.showMessage("Finished Loading Resource Information. Rendering Swagger UI...");this.mainView=new u({model:this.api,el:$("#"+this.dom_id),swaggerOptions:this.options}).render();this.showMessage();switch(this.options.docExpansion){case"full":Docs.expandOperationsForResource("");break;case"list":Docs.collapseOperationsForResource("")}if(this.options.onComplete){this.options.onComplete(this.api,this)}return setTimeout(function(){return Docs.shebang()},400)};y.prototype.buildUrl=function(C,A){var B,D;log("base is "+C);if(A.indexOf("/")===0){D=C.split("/");C=D[0]+"//"+D[2];return C+A}else{B=C.length;if(C.indexOf("?")>-1){B=Math.min(B,C.indexOf("?"))}if(C.indexOf("#")>-1){B=Math.min(B,C.indexOf("#"))}C=C.substring(0,B);if(C.indexOf("/",C.length-1)!==-1){return C+A}return C+"/"+A}};y.prototype.showMessage=function(A){if(A==null){A=""}$("#message-bar").removeClass("message-fail");$("#message-bar").addClass("message-success");return $("#message-bar").html(A)};y.prototype.onLoadFailure=function(A){var B;if(A==null){A=""}$("#message-bar").removeClass("message-success");$("#message-bar").addClass("message-fail");B=$("#message-bar").html(A);if(this.options.onFailure!=null){this.options.onFailure(A)}return B};return y})(Backbone.Router);window.SwaggerUi=s;r=(function(z){v(y,z);function y(){h=y.__super__.constructor.apply(this,arguments);return h}y.prototype.events={"click #show-pet-store-icon":"showPetStore","click #show-wordnik-dev-icon":"showWordnikDev","click #explore":"showCustom","keyup #input_baseUrl":"showCustomOnKeyup","keyup #input_apiKey":"showCustomOnKeyup"};y.prototype.initialize=function(){};y.prototype.showPetStore=function(A){return this.trigger("update-swagger-ui",{url:"http://petstore.swagger.wordnik.com/api/api-swagger-ui"})};y.prototype.showWordnikDev=function(A){return this.trigger("update-swagger-ui",{url:"http://api.wordnik.com/v4/resources.json"})};y.prototype.showCustomOnKeyup=function(A){if(A.keyCode===13){return this.showCustom()}};y.prototype.showCustom=function(A){if(A!=null){A.preventDefault()}return this.trigger("update-swagger-ui",{url:$("#input_baseUrl").val(),apiKey:$("#input_apiKey").val()})};y.prototype.update=function(B,C,A){if(A==null){A=false}$("#input_baseUrl").val(B);if(A){return this.trigger("update-swagger-ui",{url:B})}};return y})(Backbone.View);u=(function(y){var z;v(A,y);function A(){g=A.__super__.constructor.apply(this,arguments);return g}z={alpha:function(C,B){return C.path.localeCompare(B.path)},method:function(C,B){return C.method.localeCompare(B.method)}};A.prototype.initialize=function(D){var C,H,F,E,B,G;if(D==null){D={}}if(D.swaggerOptions.sorter){F=D.swaggerOptions.sorter;H=z[F];G=this.model.apisArray;for(E=0,B=G.length;E<B;E++){C=G[E];C.operationsArray.sort(H)}if(F==="alpha"){return this.model.apisArray.sort(H)}}};A.prototype.render=function(){var C,H,E,F,D,B,G;$(this.el).html(Handlebars.templates.main(this.model));F={};C=0;G=this.model.apisArray;for(D=0,B=G.length;D<B;D++){E=G[D];H=E.name;while(typeof F[H]!=="undefined"){H=H+"_"+C;C+=1}E.id=H;F[H]=E;this.addResource(E)}return this};A.prototype.addResource=function(C){var B;B=new n({model:C,tagName:"li",id:"resource_"+C.id,className:"resource",swaggerOptions:this.options.swaggerOptions});return $("#resources").append(B.render().el)};A.prototype.clear=function(){return $(this.el).html("")};return A})(Backbone.View);n=(function(z){v(y,z);function y(){f=y.__super__.constructor.apply(this,arguments);return f}y.prototype.initialize=function(){};y.prototype.render=function(){var B,G,D,C,E,A,F;$(this.el).html(Handlebars.templates.resource(this.model));D={};F=this.model.operationsArray;for(E=0,A=F.length;E<A;E++){C=F[E];B=0;G=C.nickname;while(typeof D[G]!=="undefined"){G=G+"_"+B;B+=1}D[G]=C;C.nickname=G;C.parentId=this.model.id;this.addOperation(C)}$(".toggleEndpointList",this.el).click(this.callDocs.bind(this,"toggleEndpointListForResource"));$(".collapseResource",this.el).click(this.callDocs.bind(this,"collapseOperationsForResource"));$(".expandResource",this.el).click(this.callDocs.bind(this,"expandOperationsForResoruce"));return this};y.prototype.addOperation=function(A){var B;A.number=this.number;B=new o({model:A,tagName:"li",className:"endpoint",swaggerOptions:this.options.swaggerOptions});$(".endpoints",$(this.el)).append(B.render().el);return this.number++};y.prototype.callDocs=function(B,A){A.preventDefault();return Docs[B](A.currentTarget.getAttribute("data-id"))};return y})(Backbone.View);o=(function(z){v(y,z);function y(){e=y.__super__.constructor.apply(this,arguments);return e}y.prototype.invocationUrl=null;y.prototype.events={"submit .sandbox":"submitOperation","click .submit":"submitOperation","click .response_hider":"hideResponse","click .toggleOperation":"toggleOperationContent","mouseenter .api-ic":"mouseEnter","mouseout .api-ic":"mouseExit"};y.prototype.initialize=function(){};y.prototype.mouseEnter=function(F){var D,E,I,B,A,J,G,C,K,H;D=$(F.currentTarget.parentNode).find("#api_information_panel");K=F.pageX;H=F.pageY;J=$(window).scrollLeft();G=$(window).scrollTop();B=J+$(window).width();A=G+$(window).height();C=D.width();E=D.height();if(K+C>B){K=B-C}if(K<J){K=J}if(H+E>A){H=A-E}if(H<G){H=G}I={};I.top=H;I.left=K;D.css(I);return $(F.currentTarget.parentNode).find("#api_information_panel").show()};y.prototype.mouseExit=function(A){return $(A.currentTarget.parentNode).find("#api_information_panel").hide()};y.prototype.render=function(){var Q,R,P,O,I,N,J,M,K,H,L,G,F,E,C,T,V,U,S,D,B,A,W;R=true;if(!R){this.model.isReadOnly=true}this.model.oauth=null;if(this.model.authorizations){D=this.model.authorizations;for(P in D){L=D[P];if(P==="oauth2"){if(this.model.oauth===null){this.model.oauth={}}if(this.model.oauth.scopes===void 0){this.model.oauth.scopes=[]}for(G=0,T=L.length;G<T;G++){O=L[G];this.model.oauth.scopes.push(O)}}}}$(this.el).html(Handlebars.templates.operation(this.model));if(this.model.responseClassSignature&&this.model.responseClassSignature!=="string"){M={sampleJSON:this.model.responseSampleJSON,isParam:false,signature:this.model.responseClassSignature};J=new i({model:M,tagName:"div"});$(".model-signature",$(this.el)).append(J.render().el)}else{$(".model-signature",$(this.el)).html(this.model.type)}Q={isParam:false};Q.consumes=this.model.consumes;Q.produces=this.model.produces;B=this.model.parameters;for(F=0,V=B.length;F<V;F++){I=B[F];H=I.type||I.dataType;if(H.toLowerCase()==="file"){if(!Q.consumes){log("set content type ");Q.consumes="multipart/form-data"}}}N=new m({model:Q});$(".response-content-type",$(this.el)).append(N.render().el);A=this.model.parameters;for(E=0,U=A.length;E<U;E++){I=A[E];this.addParameter(I,Q.consumes)}W=this.model.responseMessages;for(C=0,S=W.length;C<S;C++){K=W[C];this.addStatusCode(K)}return this};y.prototype.addParameter=function(C,A){var B;C.consumes=A;B=new k({model:C,tagName:"tr",readOnly:this.model.isReadOnly});return $(".operation-params",$(this.el)).append(B.render().el)};y.prototype.addStatusCode=function(B){var A;A=new p({model:B,tagName:"tr"});return $(".operation-status",$(this.el)).append(A.render().el)};y.prototype.submitOperation=function(O){var Q,G,N,D,I,A,J,M,L,K,P,F,C,H,E,B;if(O!=null){O.preventDefault()}G=$(".sandbox",$(this.el));Q=true;G.find("input.required").each(function(){var R=this;$(this).removeClass("error");if(jQuery.trim($(this).val())===""){$(this).addClass("error");$(this).wiggle({callback:function(){return $(R).focus()}});return Q=false}});if(Q){D={};A={parent:this};N=false;H=G.find("input");for(M=0,P=H.length;M<P;M++){I=H[M];if((I.value!=null)&&jQuery.trim(I.value).length>0){D[I.name]=I.value}if(I.type==="file"){N=true}}E=G.find("textarea");for(L=0,F=E.length;L<F;L++){I=E[L];if((I.value!=null)&&jQuery.trim(I.value).length>0){D.body=I.value}}B=G.find("select");for(K=0,C=B.length;K<C;K++){I=B[K];J=this.getSelectedValue(I);if((J!=null)&&jQuery.trim(J).length>0){D[I.name]=J}}A.responseContentType=$("div select[name=responseContentType]",$(this.el)).val();A.requestContentType=$("div select[name=parameterContentType]",$(this.el)).val();$(".response_throbber",$(this.el)).show();if(N){return this.handleFileUpload(D,G)}else{return this.model["do"](D,A,this.showCompleteStatus,this.showErrorStatus,this)}}};y.prototype.success=function(A,B){return B.showCompleteStatus(A)};y.prototype.handleFileUpload=function(R,I){var M,H,C,N,L,K,P,J,G,F,D,Q,U,T,S,E,B,A,V,O=this;E=I.serializeArray();for(J=0,Q=E.length;J<Q;J++){N=E[J];if((N.value!=null)&&jQuery.trim(N.value).length>0){R[N.name]=N.value}}M=new FormData();P=0;B=this.model.parameters;for(G=0,U=B.length;G<U;G++){K=B[G];if(K.paramType==="form"){if(K.type.toLowerCase()!=="file"&&R[K.name]!==void 0){M.append(K.name,R[K.name])}}}C={};A=this.model.parameters;for(F=0,T=A.length;F<T;F++){K=A[F];if(K.paramType==="header"){C[K.name]=R[K.name]}}log(C);V=I.find('input[type~="file"]');for(D=0,S=V.length;D<S;D++){H=V[D];if(typeof H.files[0]!=="undefined"){M.append($(H).attr("name"),H.files[0]);P+=1}}this.invocationUrl=this.model.supportHeaderParams()?(C=this.model.getHeaderParams(R),this.model.urlify(R,false)):this.model.urlify(R,true);$(".request_url",$(this.el)).html("<pre></pre>");$(".request_url pre",$(this.el)).text(this.invocationUrl);L={type:this.model.method,url:this.invocationUrl,headers:C,data:M,dataType:"json",contentType:false,processData:false,error:function(X,Y,W){return O.showErrorStatus(O.wrap(X),O)},success:function(W){return O.showResponse(W,O)},complete:function(W){return O.showCompleteStatus(O.wrap(W),O)}};if(window.authorizations){window.authorizations.apply(L)}if(P===0){L.data.append("fake","true")}jQuery.ajax(L);return false};y.prototype.wrap=function(E){var C,F,H,B,G,D,A;H={};F=E.getAllResponseHeaders().split("\r");for(D=0,A=F.length;D<A;D++){B=F[D];C=B.split(":");if(C[0]!==void 0&&C[1]!==void 0){H[C[0].trim()]=C[1].trim()}}G={};G.content={};G.content.data=E.responseText;G.headers=H;G.request={};G.request.url=this.invocationUrl;G.status=E.status;return G};y.prototype.getSelectedValue=function(A){var D,C,F,B,E;if(!A.multiple){return A.value}else{C=[];E=A.options;for(F=0,B=E.length;F<B;F++){D=E[F];if(D.selected){C.push(D.value)}}if(C.length>0){return C.join(",")}else{return null}}};y.prototype.hideResponse=function(A){if(A!=null){A.preventDefault()}$(".response",$(this.el)).slideUp();return $(".response_hider",$(this.el)).fadeOut()};y.prototype.showResponse=function(A){var B;B=JSON.stringify(A,null,"\t").replace(/\n/g,"<br>");return $(".response_body",$(this.el)).html(escape(B))};y.prototype.showErrorStatus=function(B,A){return A.showStatus(B)};y.prototype.showCompleteStatus=function(B,A){return A.showStatus(B)};y.prototype.formatXml=function(H){var D,G,B,I,N,J,C,A,L,M,F,E,K;A=/(>)(<)(\/*)/g;M=/[ ]*(.*)[ ]+\n/g;D=/(<.+>)(.+\n)/g;H=H.replace(A,"$1\n$2$3").replace(M,"$1\n").replace(D,"$1\n$2");C=0;G="";N=H.split("\n");B=0;I="other";L={"single->single":0,"single->closing":-1,"single->opening":0,"single->other":0,"closing->single":0,"closing->closing":-1,"closing->opening":0,"closing->other":0,"opening->single":1,"opening->closing":0,"opening->opening":1,"opening->other":1,"other->single":0,"other->closing":-1,"other->opening":0,"other->other":0};F=function(T){var P,O,R,V,S,Q,U;Q={single:Boolean(T.match(/<.+\/>/)),closing:Boolean(T.match(/<\/.+>/)),opening:Boolean(T.match(/<[^!?].*>/))};S=((function(){var W;W=[];for(R in Q){U=Q[R];if(U){W.push(R)}}return W})())[0];S=S===void 0?"other":S;P=I+"->"+S;I=S;V="";B+=L[P];V=((function(){var X,Y,W;W=[];for(O=X=0,Y=B;0<=Y?X<Y:X>Y;O=0<=Y?++X:--X){W.push(" ")}return W})()).join("");if(P==="opening->closing"){return G=G.substr(0,G.length-1)+T+"\n"}else{return G+=V+T+"\n"}};for(E=0,K=N.length;E<K;E++){J=N[E];F(J)}return G};y.prototype.showStatus=function(F){var C,H,J,D,A,E,I,G,B;if(F.content===void 0){H=F.data;B=F.url}else{H=F.content.data;B=F.request.url}D=F.headers;J=D&&D["Content-Type"]?D["Content-Type"].split(";")[0].trim():null;if(!H){C=$("<code />").text("no content");E=$('<pre class="json" />').append(C)}else{if(J==="application/json"||/\+json$/.test(J)){C=$("<code />").text(JSON.stringify(JSON.parse(H),null," "));E=$('<pre class="json" />').append(C)}else{if(J==="application/xml"||/\+xml$/.test(J)){C=$("<code />").text(this.formatXml(H));E=$('<pre class="xml" />').append(C)}else{if(J==="text/html"){C=$("<code />").html(H);E=$('<pre class="xml" />').append(C)}else{if(/^image\//.test(J)){E=$("<img>").attr("src",B)}else{C=$("<code />").text(H);E=$('<pre class="json" />').append(C)}}}}}I=E;$(".request_url",$(this.el)).html("<pre></pre>");$(".request_url pre",$(this.el)).text(B);$(".response_code",$(this.el)).html("<pre>"+F.status+"</pre>");$(".response_body",$(this.el)).html(I);$(".response_headers",$(this.el)).html("<pre>"+_.escape(JSON.stringify(F.headers,null," ")).replace(/\n/g,"<br>")+"</pre>");$(".response",$(this.el)).slideDown();$(".response_hider",$(this.el)).show();$(".response_throbber",$(this.el)).hide();G=$(".response_body",$(this.el))[0];A=this.options.swaggerOptions;if(A.highlightSizeThreshold&&F.data.length>A.highlightSizeThreshold){return G}else{return hljs.highlightBlock(G)}};y.prototype.toggleOperationContent=function(){var A;A=$("#"+Docs.escapeResourceName(this.model.parentId)+"_"+this.model.nickname+"_content");if(A.is(":visible")){return Docs.collapseOperation(A)}else{return Docs.expandOperation(A)}};return y})(Backbone.View);p=(function(z){v(y,z);function y(){d=y.__super__.constructor.apply(this,arguments);return d}y.prototype.initialize=function(){};y.prototype.render=function(){var B,A,C;C=this.template();$(this.el).html(C(this.model));if(swaggerUi.api.models.hasOwnProperty(this.model.responseModel)){B={sampleJSON:JSON.stringify(swaggerUi.api.models[this.model.responseModel].createJSONSample(),null,2),isParam:false,signature:swaggerUi.api.models[this.model.responseModel].getMockSignature()};A=new i({model:B,tagName:"div"});$(".model-signature",this.$el).append(A.render().el)}else{$(".model-signature",this.$el).html("")}return this};y.prototype.template=function(){return Handlebars.templates.status_code};return y})(Backbone.View);k=(function(z){v(y,z);function y(){b=y.__super__.constructor.apply(this,arguments);return b}y.prototype.initialize=function(){return Handlebars.registerHelper("isArray",function(B,A){if(B.type.toLowerCase()==="array"||B.allowMultiple){return A.fn(this)}else{return A.inverse(this)}})};y.prototype.render=function(){var G,A,C,F,B,H,E,D;D=this.model.type||this.model.dataType;if(this.model.paramType==="body"){this.model.isBody=true}if(D.toLowerCase()==="file"){this.model.isFile=true}E=this.template();$(this.el).html(E(this.model));B={sampleJSON:this.model.sampleJSON,isParam:true,signature:this.model.signature};if(this.model.sampleJSON){H=new i({model:B,tagName:"div"});$(".model-signature",$(this.el)).append(H.render().el)}else{$(".model-signature",$(this.el)).html(this.model.signature)}A=false;if(this.model.isBody){A=true}G={isParam:A};G.consumes=this.model.consumes;if(A){C=new l({model:G});$(".parameter-content-type",$(this.el)).append(C.render().el)}else{F=new m({model:G});$(".response-content-type",$(this.el)).append(F.render().el)}return this};y.prototype.template=function(){if(this.model.isList){return Handlebars.templates.param_list}else{if(this.options.readOnly){if(this.model.required){return Handlebars.templates.param_readonly_required}else{return Handlebars.templates.param_readonly}}else{if(this.model.required){return Handlebars.templates.param_required}else{return Handlebars.templates.param}}}};return y})(Backbone.View);i=(function(z){v(y,z);function y(){a=y.__super__.constructor.apply(this,arguments);return a}y.prototype.events={"click a.description-link":"switchToDescription","click a.snippet-link":"switchToSnippet","mousedown .snippet":"snippetToTextArea"};y.prototype.initialize=function(){};y.prototype.render=function(){var A;A=this.template();$(this.el).html(A(this.model));this.switchToSnippet();this.isParam=this.model.isParam;if(this.isParam){$(".notice",$(this.el)).text("Click to set as parameter value")}return this};y.prototype.template=function(){return Handlebars.templates.signature};y.prototype.switchToDescription=function(A){if(A!=null){A.preventDefault()}$(".snippet",$(this.el)).hide();$(".description",$(this.el)).show();$(".description-link",$(this.el)).addClass("selected");return $(".snippet-link",$(this.el)).removeClass("selected")};y.prototype.switchToSnippet=function(A){if(A!=null){A.preventDefault()}$(".description",$(this.el)).hide();$(".snippet",$(this.el)).show();$(".snippet-link",$(this.el)).addClass("selected");return $(".description-link",$(this.el)).removeClass("selected")};y.prototype.snippetToTextArea=function(A){var B;if(this.isParam){if(A!=null){A.preventDefault()}B=$("textarea",$(this.el.parentNode.parentNode.parentNode));if($.trim(B.val())===""){return B.val(this.model.sampleJSON)}}};return y})(Backbone.View);j=(function(y){v(z,y);function z(){x=z.__super__.constructor.apply(this,arguments);return x}z.prototype.initialize=function(){};z.prototype.render=function(){var A;A=this.template();$(this.el).html(A(this.model));$("label[for=contentType]",$(this.el)).text("Response Content Type");return this};z.prototype.template=function(){return Handlebars.templates.content_type};return z})(Backbone.View);m=(function(y){v(z,y);function z(){w=z.__super__.constructor.apply(this,arguments);return w}z.prototype.initialize=function(){};z.prototype.render=function(){var A;A=this.template();$(this.el).html(A(this.model));$("label[for=responseContentType]",$(this.el)).text("Response Content Type");return this};z.prototype.template=function(){return Handlebars.templates.response_content_type};return z})(Backbone.View);l=(function(z){v(y,z);function y(){c=y.__super__.constructor.apply(this,arguments);return c}y.prototype.initialize=function(){};y.prototype.render=function(){var A;A=this.template();$(this.el).html(A(this.model));$("label[for=parameterContentType]",$(this.el)).text("Parameter content type:");return this};y.prototype.template=function(){return Handlebars.templates.parameter_content_type};return y})(Backbone.View)}).call(this);
@@ -0,0 +1,31 @@
1
+ type: map
2
+ class: Nucleus::Vendor
3
+ desc: vendor class
4
+ required: yes
5
+ mapping:
6
+ "id": { type: text, required: yes, unique: yes }
7
+ "name": { type: text, required: yes, unique: yes }
8
+ "providers":
9
+ type: seq
10
+ required: yes
11
+ sequence:
12
+ - type: map
13
+ class: Nucleus::Provider
14
+ desc: provider class
15
+ required: yes
16
+ mapping:
17
+ "id": { type: text, required: yes, unique: yes }
18
+ "name": { type: text, required: yes, unique: yes }
19
+ "endpoints":
20
+ type: seq
21
+ required: yes
22
+ sequence:
23
+ - type: map
24
+ class: Nucleus::Endpoint
25
+ desc: endpoint class
26
+ mapping:
27
+ "id": { type: text, required: yes, unique: yes }
28
+ "name": { type: text, required: yes, unique: yes }
29
+ "url": { type: str, required: yes, unique: yes }
30
+ "app_domain": { type: str, required: no, unique: yes }
31
+ "trust": { type: bool, required: no, unique: no }
@@ -0,0 +1,17 @@
1
+ type: map
2
+ class: Nucleus::API::Requirements
3
+ desc: Requirements that must be met by any adapter
4
+ required: yes
5
+ mapping:
6
+ "version": { type: text, required: yes, unique: yes }
7
+ "methods":
8
+ type: seq
9
+ required: yes
10
+ sequence:
11
+ - type: map
12
+ class: Nucleus::API::RequiredMethod
13
+ desc: A method that must be responded to by the adapter
14
+ required: yes
15
+ mapping:
16
+ "name": { type: text, required: yes, unique: yes }
17
+ "arguments": { type: int, required: no, unique: no }
@@ -0,0 +1,61 @@
1
+ FactoryGirl.define do
2
+ sequence :uuid do |_|
3
+ SecureRandom.uuid
4
+ end
5
+
6
+ factory :adapter, class: Nucleus::AdapterIndexEntry do
7
+ url { Faker::Internet.url }
8
+ id nil
9
+ adapter_clazz nil
10
+ end
11
+
12
+ factory :endpoint, class: Nucleus::Endpoint do
13
+ id { generate(:uuid) }
14
+ name { Faker::Internet.slug }
15
+ url { Faker::Internet.url }
16
+ created_at { (Faker::Date.between(180.days.ago, 90.days.ago)).iso8601 }
17
+ updated_at { (Faker::Date.between(90.days.ago, Date.today)).iso8601 }
18
+ provider nil
19
+
20
+ after(:create) do |endpoint|
21
+ # associate with provider
22
+ unless endpoint.provider.nil?
23
+ # TODO: find a solution how to test when multiple API versions are to be supported
24
+ dao = Nucleus::API::DB::ProviderDao.instance('v1')
25
+ provider = dao.get endpoint.provider
26
+ provider.endpoints = [] if provider.endpoints.nil?
27
+ provider.endpoints << endpoint.id
28
+ # save updated association
29
+ dao.set provider
30
+ end
31
+ end
32
+ end
33
+
34
+ factory :provider, class: Nucleus::Provider do
35
+ id { generate(:uuid) }
36
+ name { Faker::App.name }
37
+ created_at { (Faker::Date.between(180.days.ago, 90.days.ago)).iso8601 }
38
+ updated_at { (Faker::Date.between(90.days.ago, Date.today)).iso8601 }
39
+ vendor nil
40
+
41
+ after(:create) do |provider|
42
+ # associate with vendor
43
+ unless provider.vendor.nil?
44
+ # TODO: find a solution how to test when multiple API versions are to be supported
45
+ dao = Nucleus::API::DB::VendorDao.instance('v1')
46
+ vendor = dao.get provider.vendor
47
+ vendor.providers = [] if vendor.providers.nil?
48
+ vendor.providers << provider.id
49
+ # save updated association
50
+ dao.set vendor
51
+ end
52
+ end
53
+ end
54
+
55
+ factory :vendor, class: Nucleus::Vendor do
56
+ id { generate(:uuid) }
57
+ name { Faker::App.name }
58
+ created_at { (Faker::Date.between(180.days.ago, 90.days.ago)).iso8601 }
59
+ updated_at { (Faker::Date.between(90.days.ago, Date.today)).iso8601 }
60
+ end
61
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec/integration/integration_spec_helper'
2
+
3
+ describe Nucleus::API::V1::Auth do
4
+ after { Nucleus::TestDataGenerator.clean }
5
+
6
+ let!(:vendor_a) { create(:vendor) }
7
+ let!(:vendor_b) { create(:vendor) }
8
+ let!(:provider_a) { create(:provider, vendor: vendor_a.id) }
9
+ let!(:provider_b) { create(:provider, vendor: vendor_b.id) }
10
+ let!(:endpoint_a) { create(:endpoint, provider: provider_a.id) }
11
+ let!(:endpoint_b) { create(:endpoint, provider: provider_b.id) }
12
+ let!(:adapter_a) { create(:adapter, id: endpoint_a.id, adapter_clazz: Nucleus::Adapters::V1::Heroku) }
13
+ let!(:adapter_b) { create(:adapter, id: endpoint_b.id, adapter_clazz: Nucleus::Adapters::V1::CloudFoundryV2) }
14
+
15
+ # tests case when 'use RequestStore::Middleware' was not applied
16
+ context 'With alternating endpoint requests' do
17
+ before do
18
+ allow_any_instance_of(Nucleus::Adapters::V1::Heroku).to receive(:auth_client) do
19
+ token_auth = double(Nucleus::Adapters::TokenAuthClient)
20
+ allow(token_auth).to receive(:authenticate) { token_auth }
21
+ allow(token_auth).to receive(:auth_header) { { 'Authorization' => 'bearer 1234567890' } }
22
+ token_auth
23
+ end
24
+ allow_any_instance_of(Nucleus::Adapters::V1::CloudFoundryV2).to receive(:auth_client) do
25
+ oauth = double(Nucleus::Adapters::OAuth2AuthClient)
26
+ allow(oauth).to receive(:authenticate) { oauth }
27
+ allow(oauth).to receive(:auth_header) { { 'Authorization' => 'bearer 0987654321' } }
28
+ allow(oauth).to receive(:refresh) { oauth }
29
+ oauth
30
+ end
31
+
32
+ allow_any_instance_of(Nucleus::Adapters::V1::Heroku).to receive(:applications).and_wrap_original do |m, _|
33
+ unless m.receiver.send(:headers)['Authorization'] == 'bearer 1234567890'
34
+ fail Nucleus::Errors::EndpointAuthenticationError, 'Bad authentication credentials'
35
+ end
36
+ []
37
+ end
38
+ call_count = 0
39
+ allow_any_instance_of(Nucleus::Adapters::V1::CloudFoundryV2).to receive(:applications).and_wrap_original do |m, _|
40
+ unless m.receiver.send(:headers)['Authorization'] == 'bearer 0987654321'
41
+ fail Nucleus::Errors::EndpointAuthenticationError, 'Bad authentication credentials'
42
+ end
43
+ call_count += 1
44
+ fail Nucleus::Errors::EndpointAuthenticationError, 'Fail 1st attempt' if call_count == 1
45
+ []
46
+ end
47
+ end
48
+ it 'credentials are not re-used for different requests' do
49
+ headers_a = { 'HTTP_AUTHORIZATION' => 'Basic ' + ['username_a:password_a'].pack('m*').gsub(/\n/, '') }
50
+ get "/endpoints/#{endpoint_a.id}/applications", headers_a
51
+ expect(response.status).to eq(200)
52
+
53
+ headers_b = { 'HTTP_AUTHORIZATION' => 'Basic ' + ['username_b:password_b'].pack('m*').gsub(/\n/, '') }
54
+ get "/endpoints/#{endpoint_b.id}/applications", headers_b
55
+ expect(response.status).to eq(200)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,167 @@
1
+ require 'spec/spec_helper'
2
+ require 'spec/integration/integration_spec_helper'
3
+
4
+ describe Nucleus::API::V1::Endpoints do
5
+ after { Nucleus::TestDataGenerator.clean }
6
+
7
+ let!(:vendor) { create(:vendor) }
8
+ let!(:provider) { create(:provider, vendor: vendor.id) }
9
+ let!(:endpoint_a) { create(:endpoint, provider: provider.id) }
10
+ let!(:endpoint_b) { create(:endpoint, provider: provider.id) }
11
+
12
+ context 'GET /endpoints response' do
13
+ before { get "/providers/#{provider[:id]}/endpoints" }
14
+ include_examples 'a valid GET request'
15
+ it 'has endpoint-list like structure' do
16
+ expect_json_types(size: :int, endpoints: :array_of_objects, _links: :object)
17
+ end
18
+ # # TODO contains all required fields
19
+ # it 'contains all required fields as highlighted in the documentation' do
20
+ # expect_json_keys('endpoints.0', Nucleus::API::Models::Endpoints.documentation[:items]
21
+ # .find { |k, v| !!v[:required] } )
22
+ # end
23
+ it 'shows the retrieved number of endpoints' do
24
+ expect(json_body[:size]).to eq 2
25
+ expect_json_sizes(endpoints: 2)
26
+ end
27
+ it 'lists all endpoints' do
28
+ expect(json_body[:endpoints][0][:id]).to eq endpoint_a.id
29
+ expect(json_body[:endpoints][1][:id]).to eq endpoint_b.id
30
+ end
31
+ end
32
+
33
+ context 'GET /endpoints/:id' do
34
+ before { get "/endpoints/#{endpoint_a.id}" }
35
+ include_examples 'a valid GET request'
36
+ it 'has the structure of an endpoint object' do
37
+ expect_json_types(id: :string, name: :string, url: :string, created_at: :date,
38
+ updated_at: :date, _links: :object)
39
+ end
40
+ it 'contains the requested endpoint' do
41
+ expect(json_body[:id]).to eq endpoint_a.id
42
+ end
43
+ end
44
+
45
+ context 'DELETE /endpoints/:id' do
46
+ before { delete "/endpoints/#{endpoint_a.id}" }
47
+ include_examples 'a valid DELETE request'
48
+
49
+ context 'causes the endpoint list' do
50
+ before { get "/providers/#{provider[:id]}/endpoints" }
51
+ it 'to not include the endpoint anymore' do
52
+ expect(json_body[:size]).to eq 1
53
+ expect_json_sizes(endpoints: 1)
54
+ end
55
+ end
56
+ end
57
+
58
+ context 'PATCH /endpoints/:id' do
59
+ let!(:updated_name) { Faker::Internet.slug }
60
+ let!(:updated_url) { Faker::Internet.url }
61
+
62
+ context 'with a valid body' do
63
+ before { patch "/endpoints/#{endpoint_a.id}", endpoint: { name: updated_name, url: updated_url } }
64
+ include_examples 'a valid PATCH request'
65
+
66
+ context 'causes the endpoint retrieval' do
67
+ before { get "/endpoints/#{endpoint_a.id}" }
68
+ include_examples 'a valid GET request'
69
+ it 'to show the requested resource' do
70
+ expect(json_body[:id]).to eq endpoint_a.id
71
+ end
72
+ it 'to show the updated values' do
73
+ expect(json_body[:name]).to eq updated_name
74
+ expect(json_body[:url]).to eq updated_url
75
+ end
76
+ it 'to show an updated updated_at timestamp' do
77
+ expect(json_body[:updated_at]).to be >= endpoint_a.updated_at
78
+ end
79
+ it 'has the original value of fields that were not changed' do
80
+ expect(json_body[:created_at]).to eq endpoint_a.created_at
81
+ end
82
+ end
83
+ end
84
+
85
+ context 'with a partial body' do
86
+ let!(:updated_name) { Faker::Internet.slug }
87
+
88
+ before { patch "/endpoints/#{endpoint_a.id}", endpoint: { name: updated_name } }
89
+ include_examples 'a valid PATCH request'
90
+
91
+ context 'shows that a repeated endpoint retrieval' do
92
+ before { get "/endpoints/#{endpoint_a.id}" }
93
+ include_examples 'a valid GET request'
94
+ it 'contains the requested resource' do
95
+ expect(json_body[:id]).to eq endpoint_a.id
96
+ end
97
+ it 'contains the updated value' do
98
+ expect(json_body[:name]).to eq updated_name
99
+ end
100
+ it 'has the original value of fields that were not changed' do
101
+ expect(json_body[:url]).to eq endpoint_a.url
102
+ end
103
+ end
104
+ end
105
+
106
+ context 'with a malformed body' do
107
+ let!(:updated_name) { Faker::Internet.slug }
108
+ let!(:updated_url) { Faker::Internet.url }
109
+ before { patch "/endpoints/#{endpoint_a.id}", name: updated_name, url: updated_url }
110
+ include_examples 'a bad request'
111
+ end
112
+ end
113
+
114
+ context 'POST /providers/:id/endpoints' do
115
+ context 'with a valid body' do
116
+ let!(:ep_name) { Faker::Internet.slug }
117
+ let!(:ep_url) { Faker::Internet.url }
118
+ before { post "/providers/#{provider.id}/endpoints", endpoint: { name: ep_name, url: ep_url } }
119
+ include_examples 'a valid POST request'
120
+ it 'responds with an endpoint object' do
121
+ expect_json_types(id: :string, name: :string, url: :string, created_at: :date,
122
+ updated_at: :date, _links: :object)
123
+ end
124
+
125
+ context 'causes the' do
126
+ context 'endpoint list' do
127
+ before { get "/providers/#{provider[:id]}/endpoints" }
128
+ include_examples 'a valid GET request'
129
+ it 'to include one more endpoint' do
130
+ expect(json_body[:size]).to eq 3
131
+ expect_json_sizes(endpoints: 3)
132
+ end
133
+ end
134
+
135
+ context 'endpoint retrieval of the created resource' do
136
+ before { get "/endpoints/#{json_body[:id]}" }
137
+ include_examples 'a valid GET request'
138
+ it 'shows an endpoint with the correct values' do
139
+ expect(json_body[:name]).to eq ep_name
140
+ expect(json_body[:url]).to eq ep_url
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ context 'with the body values not nested in an endpoint object' do
147
+ let!(:updated_name) { Faker::Internet.slug }
148
+ let!(:updated_url) { Faker::Internet.url }
149
+ before { post "/providers/#{provider.id}/endpoints", name: updated_name, url: updated_url }
150
+ include_examples 'a bad request'
151
+
152
+ context 'causes the endpoint list' do
153
+ before { get "/providers/#{provider[:id]}/endpoints" }
154
+ include_examples 'a valid GET request'
155
+ it 'to not contain more endpoints than before' do
156
+ expect(json_body[:size]).to eq 2
157
+ expect_json_sizes(endpoints: 2)
158
+ end
159
+ end
160
+ end
161
+ end
162
+
163
+ context 'when not authenticated' do
164
+ before { get "/endpoints/#{endpoint_a.id}/applications" }
165
+ include_examples 'an unauthorized request'
166
+ end
167
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec/integration/integration_spec_helper'
2
+
3
+ describe 'API Error schema' do
4
+ context 'GET with invalid accept header' do
5
+ context 'version invalid' do
6
+ let!(:header) { { 'HTTP_ACCEPT' => 'application/vnd.nucleus-invalidversion' } }
7
+
8
+ context 'for valid endpoint' do
9
+ before { get '/vendors', header }
10
+ include_examples 'a not accepted request'
11
+ end
12
+
13
+ context 'for an invalid endpoint' do
14
+ before { get '/vendorsdreamcomestrue', header }
15
+ include_examples 'an unknown requested resource'
16
+ end
17
+ end
18
+ context 'vendor invalid' do
19
+ let!(:header) { { 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v1' } }
20
+
21
+ context 'for valid endpoint' do
22
+ before { get '/vendors', header }
23
+ include_examples 'a not accepted request'
24
+ end
25
+
26
+ context 'for an invalid endpoint' do
27
+ before { get '/vendorsdreamcomestrue', header }
28
+ include_examples 'an unknown requested resource'
29
+ end
30
+ end
31
+ context 'content type invalid' do
32
+ before { get '/vendors', 'HTTP_ACCEPT' => 'application/vnd.nucleus-v1+application/xml' }
33
+ include_examples 'a not accepted request'
34
+ end
35
+ end
36
+ context 'GET with missing accept header' do
37
+ context 'for valid endpoint' do
38
+ before { get '/vendors' }
39
+ include_examples 'a valid GET request'
40
+ end
41
+
42
+ context 'for an invalid endpoint' do
43
+ before { get '/vendorsdreamcomestrue' }
44
+ include_examples 'an unknown requested resource'
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,157 @@
1
+ require 'spec/integration/integration_spec_helper'
2
+
3
+ describe Nucleus::API::V1::Providers do
4
+ after { Nucleus::TestDataGenerator.clean }
5
+
6
+ let!(:vendor) { create(:vendor) }
7
+ let!(:provider_a) { create(:provider, vendor: vendor.id) }
8
+ let!(:provider_b) { create(:provider, vendor: vendor.id) }
9
+ let!(:endpoint_a) { create(:endpoint, provider: provider_a.id) }
10
+ let!(:endpoint_b) { create(:endpoint, provider: provider_a.id) }
11
+ let!(:endpoint_c) { create(:endpoint, provider: provider_b.id) }
12
+
13
+ describe 'GET /vendors/:vendor_id/providers response' do
14
+ before { get "/vendors/#{vendor.id}/providers" }
15
+ include_examples 'a valid GET request'
16
+ it 'has provider-list like structure' do
17
+ expect_json_types(size: :int, providers: :array_of_objects, _links: :object)
18
+ end
19
+
20
+ # TODO: contains all required fields
21
+
22
+ it 'shows the retrieved number of providers' do
23
+ expect(json_body[:size]).to eq 2
24
+ expect_json_sizes(providers: 2)
25
+ end
26
+ it 'lists all providers' do
27
+ expect(json_body[:providers][0][:id]).to eq provider_a.id
28
+ expect(json_body[:providers][1][:id]).to eq provider_b.id
29
+ end
30
+ end
31
+
32
+ describe 'GET /vendors/:vendor_id/providers response (repeated)' do
33
+ before do
34
+ get "/vendors/#{vendor.id}/providers"
35
+ # 2nd call, previous issue caused providers the be shown only once
36
+ get "/vendors/#{vendor.id}/providers"
37
+ end
38
+ include_examples 'a valid GET request'
39
+ it 'has provider-list like structure' do
40
+ expect_json_types(size: :int, providers: :array_of_objects, _links: :object)
41
+ end
42
+
43
+ # TODO: contains all required fields
44
+
45
+ it 'shows the retrieved number of providers' do
46
+ expect(json_body[:size]).to eq 2
47
+ expect_json_sizes(providers: 2)
48
+ end
49
+ it 'lists all providers' do
50
+ expect(json_body[:providers][0][:id]).to eq provider_a.id
51
+ expect(json_body[:providers][1][:id]).to eq provider_b.id
52
+ end
53
+ end
54
+
55
+ describe 'GET /providers/:id' do
56
+ before { get "/providers/#{provider_a.id}" }
57
+ include_examples 'a valid GET request'
58
+ it 'has the structure of an provider object' do
59
+ expect_json_types(id: :string, name: :string, created_at: :date, updated_at: :date,
60
+ endpoints: :array_of_objects, _links: :object)
61
+ end
62
+ it 'contains the requested provider' do
63
+ expect(json_body[:id]).to eq provider_a.id
64
+ end
65
+ end
66
+
67
+ describe 'DELETE /providers/:id' do
68
+ before { delete "/providers/#{provider_a.id}" }
69
+ include_examples 'a valid DELETE request'
70
+
71
+ describe 'proves that the provider list' do
72
+ before { get "/vendors/#{vendor.id}/providers" }
73
+ it 'does not include the provider anymore' do
74
+ expect(json_body[:size]).to eq 1
75
+ expect_json_sizes(providers: 1)
76
+ end
77
+ end
78
+ end
79
+
80
+ describe 'PATCH /providers/:id' do
81
+ let!(:updated_name) { Faker::Internet.slug }
82
+
83
+ context 'with a valid body' do
84
+ before { patch "/providers/#{provider_a.id}", provider: { name: updated_name } }
85
+ include_examples 'a valid PATCH request'
86
+
87
+ describe 'proves that the provider retrieval' do
88
+ before { get "/providers/#{provider_a.id}" }
89
+ include_examples 'a valid GET request'
90
+ it 'shows the requested resource' do
91
+ expect(json_body[:id]).to eq provider_a.id
92
+ end
93
+ it 'shows the updated values' do
94
+ expect(json_body[:name]).to eq updated_name
95
+ end
96
+ it 'shows an updated updated_at timestamp' do
97
+ expect(json_body[:updated_at]).to be >= provider_a.updated_at
98
+ end
99
+ it 'has the original value of fields that were not changed' do
100
+ expect(json_body[:created_at]).to eq provider_a.created_at
101
+ end
102
+ end
103
+ end
104
+
105
+ context 'with a malformed body' do
106
+ let!(:updated_name) { Faker::Internet.slug }
107
+ before { patch "/providers/#{provider_a.id}", name: updated_name }
108
+ include_examples 'a bad request'
109
+ end
110
+ end
111
+
112
+ describe 'POST /vendors/:id/providers' do
113
+ context 'with a valid body' do
114
+ let!(:p_name) { Faker::Internet.slug }
115
+ before { post "/vendors/#{vendor.id}/providers", provider: { name: p_name } }
116
+ include_examples 'a valid POST request'
117
+ it 'responds with a provider object' do
118
+ expect_json_types(id: :string, name: :string, created_at: :date, updated_at: :date,
119
+ endpoints: :array_of_objects, _links: :object)
120
+ end
121
+
122
+ describe 'proves that the' do
123
+ describe 'provider list' do
124
+ before { get "/vendors/#{vendor.id}/providers" }
125
+ include_examples 'a valid GET request'
126
+ it 'includes one additional provider' do
127
+ expect(json_body[:size]).to eq 3
128
+ expect_json_sizes(providers: 3)
129
+ end
130
+ end
131
+
132
+ describe 'provider retrieval of the created resource' do
133
+ before { get "/providers/#{json_body[:id]}" }
134
+ include_examples 'a valid GET request'
135
+ it 'shows a provider with the correct values' do
136
+ expect(json_body[:name]).to eq p_name
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ context 'with the body values not nested in a provider object' do
143
+ let!(:updated_name) { Faker::Internet.slug }
144
+ before { post "/vendors/#{vendor.id}/providers", name: updated_name }
145
+ include_examples 'a bad request'
146
+
147
+ context 'proves that the provider list' do
148
+ before { get "/vendors/#{vendor.id}/providers" }
149
+ include_examples 'a valid GET request'
150
+ it 'does not contain more providers than before' do
151
+ expect(json_body[:size]).to eq 2
152
+ expect_json_sizes(providers: 2)
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end