Merge pull request #1027 from mohsen1/cs-to-js

Goodbye CoffeeScript!
This commit is contained in:
Tony Tam
2015-03-12 17:33:02 -07:00
36 changed files with 2992 additions and 1942 deletions

4
.jshintignore Normal file
View File

@@ -0,0 +1,4 @@
node_modules
src/main/javascript/doc.js
dist
lib

35
.jshintrc Normal file
View File

@@ -0,0 +1,35 @@
{
"node": true,
"browser": true,
"esnext": true,
"bitwise": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": false,
"newcap": true,
"noarg": true,
"quotmark": "single",
"regexp": true,
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"smarttabs": true,
"globals": {
"Backbone": false,
"_": false,
"$": false,
"jQuery": false,
"marked": false,
"Docs": false,
"SwaggerClient": false,
"Handlebars": false,
"ApiKeyAuthorization": false,
"PasswordAuthorization": false,
"hljs": false,
"SwaggerUi": false,
"swaggerUi": false // TODO: remove me
}
}

View File

@@ -5,4 +5,9 @@ node_js:
install:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- npm install
- npm i -g jshint
- npm install
script:
- jshint .
- npm test

3106
dist/swagger-ui.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -2,9 +2,7 @@
var gulp = require('gulp');
var es = require('event-stream');
var gutil = require('gulp-util');
var clean = require('gulp-clean');
var coffee = require('gulp-coffee');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
@@ -32,7 +30,7 @@ gulp.task('clean', function() {
return gulp
.src('./dist', {read: false})
.pipe(clean({force: true}))
.on('error', gutil.log);
.on('error', log);
});
/**
@@ -47,16 +45,6 @@ function templates() {
namespace: 'Handlebars.templates',
noRedeclare: true, // Avoid duplicate declarations
}))
.on('error', gutil.log);
}
/**
* Processes CoffeeScript files
*/
function coffeescript () {
return gulp
.src(['./src/main/coffeescript/**/*.coffee'])
.pipe(coffee({bare: true}))
.on('error', log);
}
@@ -66,17 +54,17 @@ function coffeescript () {
gulp.task('dist', ['clean'], function() {
return es.merge(
gulp.src('./src/main/javascript/doc.js'),
coffeescript(),
gulp.src('./src/main/javascript/**/*.js'),
templates()
)
.pipe(order(['docs.js', 'scripts.js', 'templates.js']))
.pipe(order(['scripts.js', 'templates.js']))
.pipe(concat('swagger-ui.js'))
.pipe(header(banner, { pkg: pkg } ))
.pipe(gulp.dest('./dist'))
.pipe(uglify())
.on('error', log)
.pipe(rename({extname: '.min.js'}))
.on('error', gutil.log)
.on('error', log)
.pipe(gulp.dest('./dist'))
.pipe(connect.reload());
});
@@ -108,20 +96,20 @@ gulp.task('copy', ['less'], function() {
gulp
.src(['./lib/**/*.{js,map}'])
.pipe(gulp.dest('./dist/lib'))
.on('error', log)
.on('error', log);
// copy all files inside html folder
gulp
.src(['./src/main/html/**/*'])
.pipe(gulp.dest('./dist'))
.on('error', log)
.on('error', log);
});
/**
* Watch for changes and recompile
*/
gulp.task('watch', function() {
return watch(['./src/**/*.{coffee,js,less,handlebars,html}'], function() {
return watch(['./src/**/*.{coffee,js,less,handlebars}'], function() {
gulp.start('default');
});
});
@@ -137,9 +125,9 @@ gulp.task('connect', function() {
});
function log(error) {
console.log(error.toString());
console.error(error.toString && error.toString());
}
gulp.task('default', ['dist', 'copy']);
gulp.task('serve', ['connect', 'watch', 'default'])
gulp.task('serve', ['connect', 'watch']);

View File

@@ -28,7 +28,6 @@
"express": "^4.12.0",
"gulp": "^3.8.11",
"gulp-clean": "^0.3.1",
"gulp-coffee": "^2.3.1",
"gulp-concat": "^2.5.2",
"gulp-connect": "^2.2.0",
"gulp-declare": "^0.3.0",
@@ -38,7 +37,6 @@
"gulp-order": "^1.1.1",
"gulp-rename": "^1.2.0",
"gulp-uglify": "^1.1.0",
"gulp-util": "^3.0.4",
"gulp-watch": "^4.1.1",
"gulp-wrap": "^0.11.0",
"http-server": "git+https://github.com/nodeapps/http-server.git",

View File

@@ -1,5 +0,0 @@
Handlebars.registerHelper('sanitize', (html) ->
# Strip the script tags from the html, and return it as a Handlebars.SafeString
html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
return new Handlebars.SafeString(html)
)

View File

@@ -1,31 +0,0 @@
class ApiKeyButton extends Backbone.View
initialize: ->
render: ->
template = @template()
$(@el).html(template(@model))
@
events:
"click #apikey_button" : "toggleApiKeyContainer"
"click #apply_api_key" : "applyApiKey"
applyApiKey: ->
window.authorizations.add(@model.name, new ApiKeyAuthorization(@model.name, $("#input_apiKey_entry").val(), @model.in))
window.swaggerUi.load()
elem = $('#apikey_container').show()
toggleApiKeyContainer: ->
if $('#apikey_container').length > 0
elem = $('#apikey_container').first()
if elem.is ':visible'
elem.hide()
else
# hide others
$('.auth_container').hide()
elem.show()
template: ->
Handlebars.templates.apikey_button_view

View File

@@ -1,34 +0,0 @@
class BasicAuthButton extends Backbone.View
initialize: ->
render: ->
template = @template()
$(@el).html(template(@model))
@
events:
"click #basic_auth_button" : "togglePasswordContainer"
"click #apply_basic_auth" : "applyPassword"
applyPassword: ->
username = $(".input_username").val()
password = $(".input_password").val()
window.authorizations.add(@model.type, new PasswordAuthorization("basic", username, password))
window.swaggerUi.load()
elem = $('#basic_auth_container').hide()
togglePasswordContainer: ->
if $('#basic_auth_container').length > 0
elem = $('#basic_auth_container').show()
if elem.is ':visible'
elem.slideUp()
else
# hide others
$('.auth_container').hide()
elem.show()
template: ->
Handlebars.templates.basic_auth_button_view

View File

@@ -1,14 +0,0 @@
class ContentTypeView extends Backbone.View
initialize: ->
render: ->
template = @template()
$(@el).html(template(@model))
$('label[for=contentType]', $(@el)).text('Response Content Type')
@
template: ->
Handlebars.templates.content_type

View File

@@ -1,37 +0,0 @@
class HeaderView extends Backbone.View
events: {
'click #show-pet-store-icon' : 'showPetStore'
'click #show-wordnik-dev-icon' : 'showWordnikDev'
'click #explore' : 'showCustom'
'keyup #input_baseUrl' : 'showCustomOnKeyup'
'keyup #input_apiKey' : 'showCustomOnKeyup'
}
initialize: ->
showPetStore: (e) ->
@trigger(
'update-swagger-ui'
{url:"http://petstore.swagger.wordnik.com/api/api-docs"}
)
showWordnikDev: (e) ->
@trigger(
'update-swagger-ui'
{url:"http://api.wordnik.com/v4/resources.json"}
)
showCustomOnKeyup: (e) ->
@showCustom() if e.keyCode is 13
showCustom: (e) ->
e?.preventDefault()
@trigger(
'update-swagger-ui'
{url: $('#input_baseUrl').val(), apiKey: $('#input_apiKey').val()}
)
update: (url, apiKey, trigger = false) ->
$('#input_baseUrl').val url
#$('#input_apiKey').val apiKey
@trigger 'update-swagger-ui', {url:url} if trigger

View File

@@ -1,14 +0,0 @@
class ParameterContentTypeView extends Backbone.View
initialize: ->
render: ->
template = @template()
$(@el).html(template(@model))
$('label[for=parameterContentType]', $(@el)).text('Parameter content type:')
@
template: ->
Handlebars.templates.parameter_content_type

View File

@@ -1,79 +0,0 @@
class ParameterView extends Backbone.View
initialize: ->
Handlebars.registerHelper 'isArray',
(param, opts) ->
if param.type.toLowerCase() == 'array' || param.allowMultiple
opts.fn(@)
else
opts.inverse(@)
render: ->
type = @model.type || @model.dataType
if typeof type is 'undefined'
schema = @model.schema
if schema and schema['$ref']
ref = schema['$ref']
if ref.indexOf('#/definitions/') is 0
type = ref.substring('#/definitions/'.length)
else
type = ref
@model.type = type
@model.paramType = @model.in || @model.paramType
@model.isBody = true if @model.paramType == 'body' or @model.in == 'body'
@model.isFile = true if type and type.toLowerCase() == 'file'
@model.default = (@model.default || @model.defaultValue)
if@model.allowableValues
@model.isList = true
template = @template()
$(@el).html(template(@model))
signatureModel =
sampleJSON: @model.sampleJSON
isParam: true
signature: @model.signature
if @model.sampleJSON
signatureView = new SignatureView({model: signatureModel, tagName: 'div'})
$('.model-signature', $(@el)).append signatureView.render().el
else
$('.model-signature', $(@el)).html(@model.signature)
isParam = false
if @model.isBody
isParam = true
contentTypeModel =
isParam: isParam
contentTypeModel.consumes = @model.consumes
if isParam
parameterContentTypeView = new ParameterContentTypeView({model: contentTypeModel})
$('.parameter-content-type', $(@el)).append parameterContentTypeView.render().el
else
responseContentTypeView = new ResponseContentTypeView({model: contentTypeModel})
$('.response-content-type', $(@el)).append responseContentTypeView.render().el
@
# Return an appropriate template based on if the parameter is a list, readonly, required
template: ->
if @model.isList
Handlebars.templates.param_list
else
if @options.readOnly
if @model.required
Handlebars.templates.param_readonly_required
else
Handlebars.templates.param_readonly
else
if @model.required
Handlebars.templates.param_required
else
Handlebars.templates.param

View File

@@ -1,14 +0,0 @@
class ResponseContentTypeView extends Backbone.View
initialize: ->
render: ->
template = @template()
$(@el).html(template(@model))
$('label[for=responseContentType]', $(@el)).text('Response Content Type')
@
template: ->
Handlebars.templates.response_content_type

View File

@@ -1,51 +0,0 @@
class SignatureView extends Backbone.View
events: {
'click a.description-link' : 'switchToDescription'
'click a.snippet-link' : 'switchToSnippet'
'mousedown .snippet' : 'snippetToTextArea'
}
initialize: ->
render: ->
template = @template()
$(@el).html(template(@model))
@switchToSnippet()
@isParam = @model.isParam
if @isParam
$('.notice', $(@el)).text('Click to set as parameter value')
@
template: ->
Handlebars.templates.signature
# handler for show signature
switchToDescription: (e) ->
e?.preventDefault()
$(".snippet", $(@el)).hide()
$(".description", $(@el)).show()
$('.description-link', $(@el)).addClass('selected')
$('.snippet-link', $(@el)).removeClass('selected')
# handler for show sample
switchToSnippet: (e) ->
e?.preventDefault()
$(".description", $(@el)).hide()
$(".snippet", $(@el)).show()
$('.snippet-link', $(@el)).addClass('selected')
$('.description-link', $(@el)).removeClass('selected')
# handler for snippet to text area
snippetToTextArea: (e) ->
if @isParam
e?.preventDefault()
textArea = $('textarea', $(@el.parentNode.parentNode.parentNode))
if $.trim(textArea.val()) == ''
textArea.val(@model.sampleJSON)

View File

@@ -0,0 +1,197 @@
'use strict';
window.SwaggerUi = Backbone.Router.extend({
dom_id: 'swagger_ui',
// Attributes
options: null,
api: null,
headerView: null,
mainView: null,
// SwaggerUi accepts all the same options as SwaggerApi
initialize: function(options) {
options = options || {};
// Allow dom_id to be overridden
if (options.dom_id) {
this.dom_id = options.dom_id;
delete options.dom_id;
}
if (!options.supportedSubmitMethods){
options.supportedSubmitMethods = [
'get',
'put',
'post',
'delete',
'head',
'options',
'patch'
];
}
// Create an empty div which contains the dom_id
if (! $('#' + this.dom_id)){
$('body').append('<div id="' + this.dom_id + '"></div>') ;
}
this.options = options;
// set marked options
marked.setOptions({gfm: true});
// Set the callbacks
var that = this;
this.options.success = function() { return that.render(); };
this.options.progress = function(d) { return that.showMessage(d); };
this.options.failure = function(d) { return that.onLoadFailure(d); };
// Create view to handle the header inputs
this.headerView = new SwaggerUi.Views.HeaderView({el: $('#header')});
// Event handler for when the baseUrl/apiKey is entered by user
this.headerView.on('update-swagger-ui', function(data) {
return this.updateSwaggerUi(data);
});
},
// Set an option after initializing
setOption: function(option, value) {
this.options[option] = value;
},
// Get the value of a previously set option
getOption: function(option) {
return this.options[option];
},
// Event handler for when url/key is received from user
updateSwaggerUi: function(data){
this.options.url = data.url;
this.load();
},
// Create an api and render
load: function(){
// Initialize the API object
if (this.mainView) {
this.mainView.clear();
}
var url = this.options.url;
if (url && url.indexOf('http') !== 0) {
url = this.buildUrl(window.location.href.toString(), url);
}
this.options.url = url;
this.headerView.update(url);
this.api = new SwaggerClient(this.options);
},
// collapse all sections
collapseAll: function(){
Docs.collapseEndpointListForResource('');
},
// list operations for all sections
listAll: function(){
Docs.collapseOperationsForResource('');
},
// expand operations for all sections
expandAll: function(){
Docs.expandOperationsForResource('');
},
// This is bound to success handler for SwaggerApi
// so it gets called when SwaggerApi completes loading
render: function(){
this.showMessage('Finished Loading Resource Information. Rendering Swagger UI...');
this.mainView = new SwaggerUi.Views.MainView({
model: this.api,
el: $('#' + this.dom_id),
swaggerOptions: this.options
}).render();
this.showMessage();
switch (this.options.docExpansion) {
case 'full':
this.expandAll(); break;
case 'list':
this.listAll(); break;
default:
break;
}
this.renderGFM();
if (this.options.onComplete){
this.options.onComplete(this.api, this);
}
setTimeout(Docs.shebang.bind(this), 100);
},
buildUrl: function(base, url){
if (url.indexOf('/') === 0) {
var parts = base.split('/');
base = parts[0] + '//' + parts[2];
return base + url;
} else {
var endOfPath = base.length;
if (base.indexOf('?') > -1){
endOfPath = Math.min(endOfPath, base.indexOf('?'));
}
if (base.indexOf('#') > -1){
endOfPath = Math.min(endOfPath, base.indexOf('#'));
}
base = base.substring(0, endOfPath);
if (base.indexOf('/', base.length - 1 ) !== -1){
return base + url;
}
return base + '/' + url;
}
},
// Shows message on topbar of the ui
showMessage: function(data){
if (data === undefined) {
data = '';
}
$('#message-bar').removeClass('message-fail');
$('#message-bar').addClass('message-success');
$('#message-bar').html(data);
},
// shows message in red
onLoadFailure: function(data){
if (data === undefined) {
data = '';
}
$('#message-bar').removeClass('message-success');
$('#message-bar').addClass('message-fail');
var val = $('#message-bar').html(data);
if (this.options.onFailure) {
this.options.onFailure(data);
}
return val;
},
// Renders GFM for elements with 'markdown' class
renderGFM: function(){
$('.markdown').each(function(){
$(this).html(marked($(this).html()));
});
}
});
window.SwaggerUi.Views = {};

View File

@@ -1,22 +1,25 @@
'use strict';
$(function() {
// Helper function for vertically aligning DOM elements
// http://www.seodenver.com/simple-vertical-align-plugin-for-jquery/
$.fn.vAlign = function() {
return this.each(function(i){
var ah = $(this).height();
var ph = $(this).parent().height();
var mh = (ph - ah) / 2;
$(this).css('margin-top', mh);
return this.each(function(){
var ah = $(this).height();
var ph = $(this).parent().height();
var mh = (ph - ah) / 2;
$(this).css('margin-top', mh);
});
};
$.fn.stretchFormtasticInputWidthToParent = function() {
return this.each(function(i){
var p_width = $(this).closest("form").innerWidth();
var p_padding = parseInt($(this).closest("form").css('padding-left') ,10) + parseInt($(this).closest("form").css('padding-right'), 10);
var this_padding = parseInt($(this).css('padding-left'), 10) + parseInt($(this).css('padding-right'), 10);
$(this).css('width', p_width - p_padding - this_padding);
return this.each(function(){
var p_width = $(this).closest("form").innerWidth();
var p_padding = parseInt($(this).closest("form").css('padding-left') ,10) + parseInt($(this).closest('form').css('padding-right'), 10);
var this_padding = parseInt($(this).css('padding-left'), 10) + parseInt($(this).css('padding-right'), 10);
$(this).css('width', p_width - p_padding - this_padding);
});
};
@@ -38,7 +41,7 @@ $(function() {
$(this).removeClass('error');
// Tack the error style on if the input is empty..
if ($(this).val() == '') {
if ($(this).val() === '') {
$(this).addClass('error');
$(this).wiggle();
error_free = false;
@@ -51,7 +54,7 @@ $(function() {
});
function clippyCopiedCallback(a) {
function clippyCopiedCallback() {
$('#api_key_copied').fadeIn().delay(1000).fadeOut();
// var b = $("#clippy_tooltip_" + a);
@@ -62,16 +65,16 @@ function clippyCopiedCallback(a) {
}
// Logging function that accounts for browsers that don't have window.console
log = function(){
function log(){
log.history = log.history || [];
log.history.push(arguments);
if(this.console){
console.log( Array.prototype.slice.call(arguments)[0] );
}
};
}
// Handle browsers that do console incorrectly (IE9 and below, see http://stackoverflow.com/a/5539378/7913)
if (Function.prototype.bind && console && typeof console.log == "object") {
if (Function.prototype.bind && console && typeof console.log === "object") {
[
"log","info","warn","error","assert","dir","clear","profile","profileEnd"
].forEach(function (method) {

View File

@@ -0,0 +1,7 @@
'use strict';
Handlebars.registerHelper('sanitize', function(html) {
// Strip the script tags from the html, and return it as a Handlebars.SafeString
html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
return new Handlebars.SafeString(html);
});

View File

@@ -0,0 +1,51 @@
'use strict';
SwaggerUi.Views.ApiKeyButton = Backbone.View.extend({ // TODO: append this to global SwaggerUi
events:{
'click #apikey_button' : 'toggleApiKeyContainer',
'click #apply_api_key' : 'applyApiKey'
},
initialize: function(){},
render: function(){
var template = this.template();
$(this.el).html(template(this.model));
return this;
},
applyApiKey: function(){
var keyAuth = new ApiKeyAuthorization(
this.model.name,
$('#input_apiKey_entry').val(),
this.model.in
);
window.authorizations.add(this.model.name, keyAuth);
window.swaggerUi.load();
$('#apikey_container').show();
},
toggleApiKeyContainer: function(){
if ($('#apikey_container').length > 0) {
var elem = $('#apikey_container').first();
if (elem.is(':visible')){
elem.hide();
} else {
// hide others
$('.auth_container').hide();
elem.show();
}
}
},
template: function(){
return Handlebars.templates.apikey_button_view;
}
});

View File

@@ -0,0 +1,46 @@
'use strict';
SwaggerUi.Views.BasicAuthButton = Backbone.View.extend({
initialize: function () {},
render: function(){
var template = this.template();
$(this.el).html(template(this.model));
return this;
},
events: {
'click #basic_auth_button' : 'togglePasswordContainer',
'click #apply_basic_auth' : 'applyPassword'
},
applyPassword: function(){
var username = $('.input_username').val();
var password = $('.input_password').val();
var basicAuth = new PasswordAuthorization('basic', username, password);
window.authorizations.add(this.model.type, basicAuth);
window.swaggerUi.load();
$('#basic_auth_container').hide();
},
togglePasswordContainer: function(){
if ($('#basic_auth_container').length > 0) {
var elem = $('#basic_auth_container').show();
if (elem.is(':visible')){
elem.slideUp();
} else {
// hide others
$('.auth_container').hide();
elem.show();
}
}
},
template: function(){
return Handlebars.templates.basic_auth_button_view;
}
});

View File

@@ -0,0 +1,13 @@
'use strict';
SwaggerUi.Views.ContentTypeView = Backbone.View.extend({
initialize: function() {},
render: function(){
$(this.el).html(Handlebars.templates.content_type(this.model));
$('label[for=contentType]', $(this.el)).text('Response Content Type');
return this;
}
});

View File

@@ -0,0 +1,55 @@
'use strict';
SwaggerUi.Views.HeaderView = Backbone.View.extend({
events: {
'click #show-pet-store-icon' : 'showPetStore',
'click #show-wordnik-dev-icon' : 'showWordnikDev',
'click #explore' : 'showCustom',
'keyup #input_baseUrl' : 'showCustomOnKeyup',
'keyup #input_apiKey' : 'showCustomOnKeyup'
},
initialize: function(){},
showPetStore: function(){
this.trigger('update-swagger-ui', {
url:'http://petstore.swagger.wordnik.com/api/api-docs'
});
},
showWordnikDev: function(){
this.trigger('update-swagger-ui', {
url: 'http://api.wordnik.com/v4/resources.json'
});
},
showCustomOnKeyup: function(e){
if (e.keyCode === 13) {
this.showCustom();
}
},
showCustom: function(e){
if (e) {
e.preventDefault();
}
this.trigger('update-swagger-ui', {
url: $('#input_baseUrl').val(),
apiKey: $('#input_apiKey').val()
});
},
update: function(url, apiKey, trigger){
if (trigger === undefined) {
trigger = false;
}
$('#input_baseUrl').val(url);
//$('#input_apiKey').val(apiKey);
if (trigger) {
this.trigger('update-swagger-ui', {url:url});
}
}
});

View File

@@ -0,0 +1,108 @@
'use strict';
SwaggerUi.Views.MainView = Backbone.View.extend({
// TODO: sorters were not used in any place, do we need them?
// sorters = {
// alpha : function(a,b){ return a.path.localeCompare(b.path); },
// method : function(a,b){ return a.method.localeCompare(b.method); },
// },
initialize: function(opts){
opts = opts || {};
// set up the UI for input
this.model.auths = [];
var key, value;
for (key in this.model.securityDefinitions) {
value = this.model.securityDefinitions[key];
this.model.auths.push({
name: key,
type: value.type,
value: value
});
}
if (this.model.swaggerVersion === '2.0') {
if ('validatorUrl' in opts.swaggerOptions) {
// Validator URL specified explicitly
this.model.validatorUrl = opts.swaggerOptions.validatorUrl;
} else if (this.model.url.indexOf('localhost') > 0) {
// Localhost override
this.model.validatorUrl = null;
} else {
// Default validator
this.model.validatorUrl = 'http://online.swagger.io/validator';
}
}
},
render: function(){
if (this.model.securityDefinitions) {
for (var name in this.model.securityDefinitions) {
var auth = this.model.securityDefinitions[name];
var button;
if (auth.type === 'apiKey' && $('#apikey_button').length === 0) {
button = new SwaggerUi.Views.ApiKeyButton({model: auth}).render().el;
$('.auth_main_container').append(button);
}
if (auth.type === 'basicAuth' && $('#basic_auth_button').length === 0) {
button = new SwaggerUi.Views.BasicAuthButton({model: auth}).render().el;
$('.auth_main_container').append(button);
}
}
}
// Render the outer container for resources
$(this.el).html(Handlebars.templates.main(this.model));
// Render each resource
var resources = {};
var counter = 0;
for (var i = 0; i < this.model.apisArray.length; i++) {
var resource = this.model.apisArray[i];
var id = resource.name;
while (typeof resources[id] !== 'undefined') {
id = id + '_' + counter;
counter += 1;
}
resource.id = id;
resources[id] = resource;
this.addResource(resource, this.model.auths);
}
$('.propWrap').hover(function onHover(){
$('.optionsWrapper', $(this)).show();
}, function offhover(){
$('.optionsWrapper', $(this)).hide();
});
return this;
},
addResource: function(resource, auths){
// Render a resource and add it to resources li
resource.id = resource.id.replace(/\s/g, '_');
var resourceView = new SwaggerUi.Views.ResourceView({
model: resource,
tagName: 'li',
id: 'resource_' + resource.id,
className: 'resource',
auths: auths,
swaggerOptions: this.options.swaggerOptions
});
$('#resources').append(resourceView.render().el);
},
clear: function(){
$(this.el).html('');
}
});

View File

@@ -0,0 +1,624 @@
'use strict';
SwaggerUi.Views.OperationView = Backbone.View.extend({
invocationUrl: null,
events: {
'submit .sandbox' : 'submitOperation',
'click .submit' : 'submitOperation',
'click .response_hider' : 'hideResponse',
'click .toggleOperation' : 'toggleOperationContent',
'mouseenter .api-ic' : 'mouseEnter',
'mouseout .api-ic' : 'mouseExit',
},
initialize: function(opts) {
opts = opts || {};
this.auths = opts.auths;
this.parentId = this.model.parentId;
this.nickname = this.model.nickname;
return this;
},
mouseEnter: function(e) {
var elem = $(this.el).find('.content');
var x = e.pageX;
var y = e.pageY;
var scX = $(window).scrollLeft();
var scY = $(window).scrollTop();
var scMaxX = scX + $(window).width();
var scMaxY = scY + $(window).height();
var wd = elem.width();
var hgh = elem.height();
if (x + wd > scMaxX) {
x = scMaxX - wd;
}
if (x < scX) {
x = scX;
}
if (y + hgh > scMaxY) {
y = scMaxY - hgh;
}
if (y < scY) {
y = scY;
}
var pos = {};
pos.top = y;
pos.left = x;
elem.css(pos);
$(e.currentTarget.parentNode).find('#api_information_panel').show();
},
mouseExit: function(e) {
$(e.currentTarget.parentNode).find('#api_information_panel').hide();
},
// Note: copied from CoffeeScript compiled file
// TODO: redactor
render: function() {
var a, auth, auths, code, contentTypeModel, isMethodSubmissionSupported, k, key, l, len, len1, len2, len3, len4, m, modelAuths, n, o, p, param, q, ref, ref1, ref2, ref3, ref4, ref5, responseContentTypeView, responseSignatureView, schema, schemaObj, scopeIndex, signatureModel, statusCode, successResponse, type, v, value;
isMethodSubmissionSupported = jQuery.inArray(this.model.method, this.model.supportedSubmitMethods()) >= 0;
if (!isMethodSubmissionSupported) {
this.model.isReadOnly = true;
}
this.model.description = this.model.description || this.model.notes;
if (this.model.description) {
this.model.description = this.model.description.replace(/(?:\r\n|\r|\n)/g, '<br />');
}
this.model.oauth = null;
modelAuths = this.model.authorizations || this.model.security;
if (modelAuths) {
if (Array.isArray(modelAuths)) {
for (l = 0, len = modelAuths.length; l < len; l++) {
auths = modelAuths[l];
for (key in auths) {
auth = auths[key];
for (a in this.auths) {
auth = this.auths[a];
if (auth.type === 'oauth2') {
this.model.oauth = {};
this.model.oauth.scopes = [];
ref1 = auth.value.scopes;
for (k in ref1) {
v = ref1[k];
scopeIndex = auths[key].indexOf(k);
if (scopeIndex >= 0) {
o = {
scope: k,
description: v
};
this.model.oauth.scopes.push(o);
}
}
}
}
}
}
} else {
for (k in modelAuths) {
v = modelAuths[k];
if (k === 'oauth2') {
if (this.model.oauth === null) {
this.model.oauth = {};
}
if (this.model.oauth.scopes === void 0) {
this.model.oauth.scopes = [];
}
for (m = 0, len1 = v.length; m < len1; m++) {
o = v[m];
this.model.oauth.scopes.push(o);
}
}
}
}
}
if (typeof this.model.responses !== 'undefined') {
this.model.responseMessages = [];
ref2 = this.model.responses;
for (code in ref2) {
value = ref2[code];
schema = null;
schemaObj = this.model.responses[code].schema;
if (schemaObj && schemaObj.$ref) {
schema = schemaObj.$ref;
if (schema.indexOf('#/definitions/') === 0) {
schema = schema.substring('#/definitions/'.length);
}
}
this.model.responseMessages.push({
code: code,
message: value.description,
responseModel: schema
});
}
}
if (typeof this.model.responseMessages === 'undefined') {
this.model.responseMessages = [];
}
signatureModel = null;
if (this.model.successResponse) {
successResponse = this.model.successResponse;
for (key in successResponse) {
value = successResponse[key];
this.model.successCode = key;
if (typeof value === 'object' && typeof value.createJSONSample === 'function') {
signatureModel = {
sampleJSON: JSON.stringify(value.createJSONSample(), void 0, 2),
isParam: false,
signature: value.getMockSignature()
};
}
}
} else if (this.model.responseClassSignature && this.model.responseClassSignature !== 'string') {
signatureModel = {
sampleJSON: this.model.responseSampleJSON,
isParam: false,
signature: this.model.responseClassSignature
};
}
$(this.el).html(Handlebars.templates.operation(this.model));
if (signatureModel) {
responseSignatureView = new SwaggerUi.Views.SignatureView({
model: signatureModel,
tagName: 'div'
});
$('.model-signature', $(this.el)).append(responseSignatureView.render().el);
} else {
this.model.responseClassSignature = 'string';
$('.model-signature', $(this.el)).html(this.model.type);
}
contentTypeModel = {
isParam: false
};
contentTypeModel.consumes = this.model.consumes;
contentTypeModel.produces = this.model.produces;
ref3 = this.model.parameters;
for (n = 0, len2 = ref3.length; n < len2; n++) {
param = ref3[n];
type = param.type || param.dataType || '';
if (typeof type === 'undefined') {
schema = param.schema;
if (schema && schema.$ref) {
ref = schema.$ref;
if (ref.indexOf('#/definitions/') === 0) {
type = ref.substring('#/definitions/'.length);
} else {
type = ref;
}
}
}
if (type && type.toLowerCase() === 'file') {
if (!contentTypeModel.consumes) {
contentTypeModel.consumes = 'multipart/form-data';
}
}
param.type = type;
}
responseContentTypeView = new SwaggerUi.Views.ResponseContentTypeView({
model: contentTypeModel
});
$('.response-content-type', $(this.el)).append(responseContentTypeView.render().el);
ref4 = this.model.parameters;
for (p = 0, len3 = ref4.length; p < len3; p++) {
param = ref4[p];
this.addParameter(param, contentTypeModel.consumes);
}
ref5 = this.model.responseMessages;
for (q = 0, len4 = ref5.length; q < len4; q++) {
statusCode = ref5[q];
this.addStatusCode(statusCode);
}
return this;
},
addParameter: function(param, consumes) {
// Render a parameter
param.consumes = consumes;
var paramView = new SwaggerUi.Views.ParameterView({
model: param,
tagName: 'tr',
readOnly: this.model.isReadOnly
});
$('.operation-params', $(this.el)).append(paramView.render().el);
},
addStatusCode: function(statusCode) {
// Render status codes
var statusCodeView = new SwaggerUi.Views.StatusCodeView({model: statusCode, tagName: 'tr'});
$('.operation-status', $(this.el)).append(statusCodeView.render().el);
},
// Note: copied from CoffeeScript compiled file
// TODO: redactor
submitOperation: function(e) {
var error_free, form, isFileUpload, l, len, len1, len2, m, map, n, o, opts, ref1, ref2, ref3, val;
if (e !== null) {
e.preventDefault();
}
form = $('.sandbox', $(this.el));
error_free = true;
form.find('input.required').each(function() {
$(this).removeClass('error');
if (jQuery.trim($(this).val()) === '') {
$(this).addClass('error');
$(this).wiggle({
callback: (function(_this) {
return function() {
$(_this).focus();
};
})(this)
});
error_free = false;
}
});
form.find('textarea.required').each(function() {
$(this).removeClass('error');
if (jQuery.trim($(this).val()) === '') {
$(this).addClass('error');
$(this).wiggle({
callback: (function(_this) {
return function() {
return $(_this).focus();
};
})(this)
});
error_free = false;
}
});
if (error_free) {
map = {};
opts = {
parent: this
};
isFileUpload = false;
ref1 = form.find('input');
for (l = 0, len = ref1.length; l < len; l++) {
o = ref1[l];
if ((o.value !== null) && jQuery.trim(o.value).length > 0) {
map[o.name] = o.value;
}
if (o.type === 'file') {
map[o.name] = o.files[0];
isFileUpload = true;
}
}
ref2 = form.find('textarea');
for (m = 0, len1 = ref2.length; m < len1; m++) {
o = ref2[m];
if ((o.value !== null) && jQuery.trim(o.value).length > 0) {
map[o.name] = o.value;
}
}
ref3 = form.find('select');
for (n = 0, len2 = ref3.length; n < len2; n++) {
o = ref3[n];
val = this.getSelectedValue(o);
if ((val !== null) && jQuery.trim(val).length > 0) {
map[o.name] = val;
}
}
opts.responseContentType = $('div select[name=responseContentType]', $(this.el)).val();
opts.requestContentType = $('div select[name=parameterContentType]', $(this.el)).val();
$('.response_throbber', $(this.el)).show();
if (isFileUpload) {
return this.handleFileUpload(map, form);
} else {
return this.model['do'](map, opts, this.showCompleteStatus, this.showErrorStatus, this);
}
}
},
success: function(response, parent) {
parent.showCompleteStatus(response);
},
// Note: This is compiled code
// TODO: Refactor
handleFileUpload: function(map, form) {
var bodyParam, el, headerParams, l, len, len1, len2, len3, m, n, o, obj, p, param, params, ref1, ref2, ref3, ref4;
ref1 = form.serializeArray();
for (l = 0, len = ref1.length; l < len; l++) {
o = ref1[l];
if ((o.value !== null) && jQuery.trim(o.value).length > 0) {
map[o.name] = o.value;
}
}
bodyParam = new FormData();
params = 0;
ref2 = this.model.parameters;
for (m = 0, len1 = ref2.length; m < len1; m++) {
param = ref2[m];
if (param.paramType === 'form' || param['in'] === 'formData') {
if (param.type.toLowerCase() !== 'file' && map[param.name] !== void 0) {
bodyParam.append(param.name, map[param.name]);
}
}
}
headerParams = {};
ref3 = this.model.parameters;
for (n = 0, len2 = ref3.length; n < len2; n++) {
param = ref3[n];
if (param.paramType === 'header') {
headerParams[param.name] = map[param.name];
}
}
ref4 = form.find('input[type~="file"]');
for (p = 0, len3 = ref4.length; p < len3; p++) {
el = ref4[p];
if (typeof el.files[0] !== 'undefined') {
bodyParam.append($(el).attr('name'), el.files[0]);
params += 1;
}
}
this.invocationUrl = this.model.supportHeaderParams() ? (headerParams = this.model.getHeaderParams(map), delete headerParams['Content-Type'], this.model.urlify(map, false)) : this.model.urlify(map, true);
$('.request_url', $(this.el)).html('<pre></pre>');
$('.request_url pre', $(this.el)).text(this.invocationUrl);
obj = {
type: this.model.method,
url: this.invocationUrl,
headers: headerParams,
data: bodyParam,
dataType: 'json',
contentType: false,
processData: false,
error: (function(_this) {
return function(data) {
return _this.showErrorStatus(_this.wrap(data), _this);
};
})(this),
success: (function(_this) {
return function(data) {
return _this.showResponse(data, _this);
};
})(this),
complete: (function(_this) {
return function(data) {
return _this.showCompleteStatus(_this.wrap(data), _this);
};
})(this)
};
if (window.authorizations) {
window.authorizations.apply(obj);
}
if (params === 0) {
obj.data.append('fake', 'true');
}
jQuery.ajax(obj);
return false;
// end of file-upload nastiness
},
// wraps a jquery response as a shred response
wrap: function(data) {
var h, headerArray, headers, i, l, len, o;
headers = {};
headerArray = data.getAllResponseHeaders().split('\r');
for (l = 0, len = headerArray.length; l < len; l++) {
i = headerArray[l];
h = i.match(/^([^:]*?):(.*)$/);
if (!h) {
h = [];
}
h.shift();
if (h[0] !== void 0 && h[1] !== void 0) {
headers[h[0].trim()] = h[1].trim();
}
}
o = {};
o.content = {};
o.content.data = data.responseText;
o.headers = headers;
o.request = {};
o.request.url = this.invocationUrl;
o.status = data.status;
return o;
},
getSelectedValue: function(select) {
if (!select.multiple) {
return select.value;
} else {
var options = [];
for (var l = 0, len = select.options.length; l < len; l++) {
var opt = select.options[l];
if (opt.selected) {
options.push(opt.value);
}
}
if (options.length > 0) {
return options;
} else {
return null;
}
}
},
// handler for hide response link
hideResponse: function(e) {
if (e) { e.preventDefault(); }
$('.response', $(this.el)).slideUp();
$('.response_hider', $(this.el)).fadeOut();
},
// Show response from server
showResponse: function(response) {
var prettyJson = JSON.stringify(response, null, '\t').replace(/\n/g, '<br>');
$('.response_body', $(this.el)).html(_.escape(prettyJson));
},
// Show error from server
showErrorStatus: function(data, parent) {
parent.showStatus(data);
},
// show the status codes
showCompleteStatus: function(data, parent){
parent.showStatus(data);
},
// Adapted from http://stackoverflow.com/a/2893259/454004
// Note: directly ported from CoffeeScript
// TODO: Cleanup CoffeeScript artifacts
formatXml: function(xml) {
var contexp, fn, formatted, indent, l, lastType, len, lines, ln, pad, reg, transitions, wsexp;
reg = /(>)(<)(\/*)/g;
wsexp = /[ ]*(.*)[ ]+\n/g;
contexp = /(<.+>)(.+\n)/g;
xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2');
pad = 0;
formatted = '';
lines = xml.split('\n');
indent = 0;
lastType = 'other';
transitions = {
'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
};
fn = function(ln) {
var fromTo, j, key, padding, type, types, value;
types = {
single: Boolean(ln.match(/<.+\/>/)),
closing: Boolean(ln.match(/<\/.+>/)),
opening: Boolean(ln.match(/<[^!?].*>/))
};
type = ((function() {
var results;
results = [];
for (key in types) {
value = types[key];
if (value) {
results.push(key);
}
}
return results;
})())[0];
type = type === void 0 ? 'other' : type;
fromTo = lastType + '->' + type;
lastType = type;
padding = '';
indent += transitions[fromTo];
padding = ((function() {
var m, ref1, results;
results = [];
for (j = m = 0, ref1 = indent; 0 <= ref1 ? m < ref1 : m > ref1; j = 0 <= ref1 ? ++m : --m) {
results.push(' ');
}
return results;
})()).join('');
if (fromTo === 'opening->closing') {
formatted = formatted.substr(0, formatted.length - 1) + ln + '\n';
} else {
formatted += padding + ln + '\n';
}
};
for (l = 0, len = lines.length; l < len; l++) {
ln = lines[l];
fn(ln);
}
return formatted;
},
// puts the response data in UI
showStatus: function(response) {
var url, content;
if (response.content === undefined) {
content = response.data;
url = response.url;
} else {
content = response.content.data;
url = response.request.url;
}
var headers = response.headers;
// if server is nice, and sends content-type back, we can use it
var contentType = null;
if (headers) {
contentType = headers['Content-Type'] || headers['content-type'];
if (contentType) {
contentType = contentType.split(';')[0].trim();
}
}
$('.response_body', $(this.el)).removeClass('json');
$('.response_body', $(this.el)).removeClass('xml');
var supportsAudioPlayback = function(contentType){
var audioElement = document.createElement('audio');
return !!(audioElement.canPlayType && audioElement.canPlayType(contentType).replace(/no/, ''));
};
var pre;
var code;
if (!content) {
code = $('<code />').text('no content');
pre = $('<pre class="json" />').append(code);
} else if (contentType === 'application/json' || /\+json$/.test(contentType)) {
var json = null;
try {
json = JSON.stringify(JSON.parse(content), null, ' ');
} catch (_error) {
json = 'can\'t parse JSON. Raw result:\n\n' + content;
}
code = $('<code />').text(json);
pre = $('<pre class="json" />').append(code);
} else if (contentType === 'application/xml' || /\+xml$/.test(contentType)) {
code = $('<code />').text(this.formatXml(content));
pre = $('<pre class="xml" />').append(code);
} else if (contentType === 'text/html') {
code = $('<code />').html(_.escape(content));
pre = $('<pre class="xml" />').append(code);
} else if (/^image\//.test(contentType)) {
pre = $('<img>').attr('src', url);
} else if (/^audio\//.test(contentType) && supportsAudioPlayback(contentType)) {
pre = $('<audio controls>').append($('<source>').attr('src', url).attr('type', contentType));
} else {
code = $('<code />').text(content);
pre = $('<pre class="json" />').append(code);
}
var response_body = pre;
$('.request_url', $(this.el)).html('<pre></pre>');
$('.request_url pre', $(this.el)).text(url);
$('.response_code', $(this.el)).html('<pre>' + response.status + '</pre>');
$('.response_body', $(this.el)).html(response_body);
$('.response_headers', $(this.el)).html('<pre>' + _.escape(JSON.stringify(response.headers, null, ' ')).replace(/\n/g, '<br>') + '</pre>');
$('.response', $(this.el)).slideDown();
$('.response_hider', $(this.el)).show();
$('.response_throbber', $(this.el)).hide();
var response_body_el = $('.response_body', $(this.el))[0];
// only highlight the response if response is less than threshold, default state is highlight response
var opts = this.options.swaggerOptions;
if (opts.highlightSizeThreshold && response.data.length > opts.highlightSizeThreshold) {
return response_body_el;
} else {
return hljs.highlightBlock(response_body_el);
}
},
toggleOperationContent: function() {
var elem = $('#' + Docs.escapeResourceName(this.parentId + '_' + this.nickname + '_content'));
if (elem.is(':visible')){
Docs.collapseOperation(elem);
} else {
Docs.expandOperation(elem);
}
}
});

View File

@@ -0,0 +1,14 @@
'use strict';
SwaggerUi.Views.ParameterContentTypeView = Backbone.View.extend({
initialize: function () {},
render: function(){
$(this.el).html(Handlebars.templates.parameter_content_type(this.model));
$('label[for=parameterContentType]', $(this.el)).text('Parameter content type:');
return this;
}
});

View File

@@ -0,0 +1,101 @@
'use strict';
SwaggerUi.Views.ParameterView = Backbone.View.extend({
initialize: function(){
Handlebars.registerHelper('isArray', function(param, opts) {
if (param.type.toLowerCase() === 'array' || param.allowMultiple) {
opts.fn(this);
} else {
opts.inverse(this);
}
});
},
render: function() {
var type = this.model.type || this.model.dataType;
if (typeof type === 'undefined') {
var schema = this.model.schema;
if (schema && schema.$ref) {
var ref = schema.$ref;
if (ref.indexOf('#/definitions/') === 0) {
type = ref.substring('#/definitions/'.length);
} else {
type = ref;
}
}
}
this.model.type = type;
this.model.paramType = this.model.in || this.model.paramType;
this.model.isBody = this.model.paramType === 'body' || this.model.in === 'body';
this.model.isFile = type && type.toLowerCase() === 'file';
this.model.default = (this.model.default || this.model.defaultValue);
if (this.model.allowableValues) {
this.model.isList = true;
}
var template = this.template();
$(this.el).html(template(this.model));
var signatureModel = {
sampleJSON: this.model.sampleJSON,
isParam: true,
signature: this.model.signature
};
if (this.model.sampleJSON) {
var signatureView = new SwaggerUi.Views.SignatureView({model: signatureModel, tagName: 'div'});
$('.model-signature', $(this.el)).append(signatureView.render().el);
}
else {
$('.model-signature', $(this.el)).html(this.model.signature);
}
var isParam = false;
if (this.model.isBody) {
isParam = true;
}
var contentTypeModel = {
isParam: isParam
};
contentTypeModel.consumes = this.model.consumes;
if (isParam) {
var parameterContentTypeView = new SwaggerUi.Views.ParameterContentTypeView({model: contentTypeModel});
$('.parameter-content-type', $(this.el)).append(parameterContentTypeView.render().el);
}
else {
var responseContentTypeView = new SwaggerUi.Views.ResponseContentTypeView({model: contentTypeModel});
$('.response-content-type', $(this.el)).append(responseContentTypeView.render().el);
}
return this;
},
// Return an appropriate template based on if the parameter is a list, readonly, required
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;
}
}
}
}
});

View File

@@ -0,0 +1,71 @@
'use strict';
SwaggerUi.Views.ResourceView = Backbone.View.extend({
initialize: function(opts) {
opts = opts || {};
this.auths = opts.auths;
if ('' === this.model.description) {
this.model.description = null;
}
if (this.model.description) {
this.model.summary = this.model.description;
}
},
render: function(){
var methods = {};
$(this.el).html(Handlebars.templates.resource(this.model));
// Render each operation
for (var i = 0; i < this.model.operationsArray.length; i++) {
var operation = this.model.operationsArray[i];
var counter = 0;
var id = operation.nickname;
while (typeof methods[id] !== 'undefined') {
id = id + '_' + counter;
counter += 1;
}
methods[id] = operation;
operation.nickname = id;
operation.parentId = this.model.id;
this.addOperation(operation);
}
$('.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, 'expandOperationsForResource'));
return this;
},
addOperation: function(operation) {
operation.number = this.number;
// Render an operation and add it to operations li
var operationView = new SwaggerUi.Views.OperationView({
model: operation,
tagName: 'li',
className: 'endpoint',
swaggerOptions: this.options.swaggerOptions,
auths: this.auths
});
$('.endpoints', $(this.el)).append(operationView.render().el);
this.number++;
},
// Generic Event handler (`Docs` is global)
callDocs: function(fnName, e) {
e.preventDefault();
Docs[fnName](e.currentTarget.getAttribute('data-id'));
}
});

View File

@@ -0,0 +1,13 @@
'use strict';
SwaggerUi.Views.ResponseContentTypeView = Backbone.View.extend({
initialize: function(){},
render: function(){
$(this.el).html(Handlebars.templates.response_content_type(this.model));
$('label[for=responseContentType]', $(this.el)).text('Response Content Type');
return this;
}
});

View File

@@ -0,0 +1,60 @@
'use strict';
SwaggerUi.Views.SignatureView = Backbone.View.extend({
events: {
'click a.description-link' : 'switchToDescription',
'click a.snippet-link' : 'switchToSnippet',
'mousedown .snippet' : 'snippetToTextArea'
},
initialize: function () {
},
render: function(){
$(this.el).html(Handlebars.templates.signature(this.model));
this.switchToSnippet();
this.isParam = this.model.isParam;
if (this.isParam) {
$('.notice', $(this.el)).text('Click to set as parameter value');
}
return this;
},
// handler for show signature
switchToDescription: function(e){
if (e) { e.preventDefault(); }
$('.snippet', $(this.el)).hide();
$('.description', $(this.el)).show();
$('.description-link', $(this.el)).addClass('selected');
$('.snippet-link', $(this.el)).removeClass('selected');
},
// handler for show sample
switchToSnippet: function(e){
if (e) { e.preventDefault(); }
$('.description', $(this.el)).hide();
$('.snippet', $(this.el)).show();
$('.snippet-link', $(this.el)).addClass('selected');
$('.description-link', $(this.el)).removeClass('selected');
},
// handler for snippet to text area
snippetToTextArea: function(e) {
if (this.isParam) {
if (e) { e.preventDefault(); }
var textArea = $('textarea', $(this.el.parentNode.parentNode.parentNode));
if ($.trim(textArea.val()) === '') {
textArea.val(this.model.sampleJSON);
}
}
}
});

View File

@@ -0,0 +1,26 @@
'use strict';
SwaggerUi.Views.StatusCodeView = Backbone.View.extend({
initialize: function () {
},
render: function(){
$(this.el).html(Handlebars.templates.status_code(this.model));
// TODO get rid of "swaggerUi" global dependency
if (swaggerUi.api.models.hasOwnProperty(this.model.responseModel)) {
var responseModel = {
sampleJSON: JSON.stringify(swaggerUi.api.models[this.model.responseModel].createJSONSample(), null, 2),
isParam: false,
signature: swaggerUi.api.models[this.model.responseModel].getMockSignature(),
};
var responseModelView = new SwaggerUi.Views.SignatureView({model: responseModel, tagName: 'div'});
$('.model-signature', this.$el).append(responseModelView.render().el);
} else {
$('.model-signature', this.$el).html('');
}
return this;
}
});

10
test/.jshintrc Normal file
View File

@@ -0,0 +1,10 @@
{
"extends": "../.jshintrc",
"expr": true,
"jasmine": true,
"globals": {
"before": false,
"after": false,
"expect": true
}
}

View File

@@ -1,6 +1,7 @@
/*
* Web driver manager
*/
'use strict';
var webdriver = require('selenium-webdriver');

View File

@@ -1,6 +1,8 @@
/*
* Swagger UI and Specs Servers
*/
'use strict';
var path = require('path');
var createServer = require('http-server').createServer;

View File

@@ -1,3 +1,5 @@
'use strict';
var expect = require('chai').expect;
var driver = require('./driver');
var servers = require('./servers');
@@ -13,7 +15,7 @@ var elements = [
'header'
];
describe('swagger 1.x spec tests', function (done) {
describe('swagger 1.x spec tests', function () {
this.timeout(10 * 1000);
before(function (done) {
@@ -27,8 +29,9 @@ describe('swagger 1.x spec tests', function (done) {
var errors = [];
browserLogs.forEach(function(log){
// 900 and above is "error" level. Console should not have any errors
if (log.level.value > 900)
if (log.level.value > 900) {
console.log('browser error message:', log.message); errors.push(log);
}
});
expect(errors).to.be.empty;
done();
@@ -46,7 +49,7 @@ describe('swagger 1.x spec tests', function (done) {
elements.forEach(function (id) {
it('should render element: ' + id, function (done) {
var locator = webdriver.By.id(id)
var locator = webdriver.By.id(id);
driver.isElementPresent(locator).then(function (isPresent) {
expect(isPresent).to.be.true;
done();
@@ -63,7 +66,7 @@ describe('swagger 1.x spec tests', function (done) {
});
it('should find the pet link', function(done){
var locator = webdriver.By.xpath("//*[@data-id='pet']");
var locator = webdriver.By.xpath('//*[@data-id="pet"]');
driver.isElementPresent(locator).then(function (isPresent) {
expect(isPresent).to.be.true;
done();
@@ -71,7 +74,7 @@ describe('swagger 1.x spec tests', function (done) {
});
it('should find the pet resource description', function(done){
var locator = webdriver.By.xpath("//div[contains(., 'Operations about pets')]");
var locator = webdriver.By.xpath('//div[contains(., "Operations about pets")]');
driver.findElements(locator).then(function (elements) {
expect(elements.length).to.not.equal(0);
done();
@@ -79,7 +82,7 @@ describe('swagger 1.x spec tests', function (done) {
});
it('should find the user link', function(done){
var locator = webdriver.By.xpath("//*[@data-id='user']");
var locator = webdriver.By.xpath('//*[@data-id="user"]');
driver.isElementPresent(locator).then(function (isPresent) {
expect(isPresent).to.be.true;
done();
@@ -87,7 +90,7 @@ describe('swagger 1.x spec tests', function (done) {
});
it('should find the store link', function(done){
var locator = webdriver.By.xpath("//*[@data-id='store']");
var locator = webdriver.By.xpath('//*[@data-id="store"]');
driver.isElementPresent(locator).then(function (isPresent) {
expect(isPresent).to.be.true;
done();

View File

@@ -1,3 +1,5 @@
'use strict';
var expect = require('chai').expect;
var webdriver = require('selenium-webdriver');
var driver = require('./driver');
@@ -14,7 +16,7 @@ var elements = [
'header'
];
describe('swagger 2.0 spec tests', function (done) {
describe('swagger 2.0 spec tests', function () {
this.timeout(10 * 1000);
before(function (done) {
@@ -28,8 +30,9 @@ describe('swagger 2.0 spec tests', function (done) {
var errors = [];
browserLogs.forEach(function(log){
// 900 and above is "error" level. Console should not have any errors
if (log.level.value > 900)
if (log.level.value > 900) {
console.log('browser error message:', log.message); errors.push(log);
}
});
expect(errors).to.be.empty;
done();
@@ -80,7 +83,7 @@ describe('swagger 2.0 spec tests', function (done) {
});
it('should find the pet link', function(done){
var locator = webdriver.By.xpath("//*[@data-id='pet']");
var locator = webdriver.By.xpath('//*[@data-id="pet"]');
driver.isElementPresent(locator).then(function (isPresent) {
expect(isPresent).to.be.true;
done();
@@ -88,7 +91,7 @@ describe('swagger 2.0 spec tests', function (done) {
});
it('should find the pet resource description', function(done){
var locator = webdriver.By.xpath("//div[contains(., 'Everything about your Pets')]");
var locator = webdriver.By.xpath('//div[contains(., "Everything about your Pets")]');
driver.findElements(locator).then(function (elements) {
expect(elements.length).to.not.equal(0);
done();
@@ -96,7 +99,7 @@ describe('swagger 2.0 spec tests', function (done) {
});
it('should find the user link', function(done){
var locator = webdriver.By.xpath("//*[@data-id='user']");
var locator = webdriver.By.xpath('//*[@data-id="user"]');
driver.isElementPresent(locator).then(function (isPresent) {
expect(isPresent).to.be.true;
done();
@@ -104,7 +107,7 @@ describe('swagger 2.0 spec tests', function (done) {
});
it('should find the store link', function(done){
var locator = webdriver.By.xpath("//*[@data-id='store']");
var locator = webdriver.By.xpath('//*[@data-id="store"]');
driver.isElementPresent(locator).then(function (isPresent) {
expect(isPresent).to.be.true;
done();