Skip to content

Commit e6b8b5c

Browse files
committed
Merge pull request #574 from swagger-api/resolver-tests
resolver refactoring
2 parents d1897d7 + aae963c commit e6b8b5c

16 files changed

+1032
-1325
lines changed

browser/swagger-client.js

Lines changed: 414 additions & 1068 deletions
Large diffs are not rendered by default.

browser/swagger-client.min.js

Lines changed: 169 additions & 183 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/client.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ var SwaggerClient = module.exports = function (url, options) {
9393
this.resourceCount = 0;
9494
this.url = null;
9595
this.useJQuery = false;
96-
this.swaggerObject = {}
96+
this.swaggerObject = {};
9797

9898
this.clientAuthorizations = new auth.SwaggerAuthorizations();
9999

@@ -184,7 +184,7 @@ SwaggerClient.prototype.build = function (mock) {
184184
}
185185

186186
self.swaggerVersion = responseObj.swaggerVersion;
187-
self.swaggerObject = responseObj
187+
self.swaggerObject = responseObj;
188188

189189
if (responseObj.swagger && parseInt(responseObj.swagger) === 2) {
190190
self.swaggerVersion = responseObj.swagger;
@@ -194,11 +194,11 @@ SwaggerClient.prototype.build = function (mock) {
194194
self.isValid = true;
195195
} else {
196196
var converter = new SwaggerSpecConverter();
197-
self.oldSwaggerObject = self.swaggerObject
197+
self.oldSwaggerObject = self.swaggerObject;
198198

199199
converter.setDocumentationLocation(self.url);
200200
converter.convert(responseObj, self.clientAuthorizations, function(spec) {
201-
self.swaggerObject = spec
201+
self.swaggerObject = spec;
202202
new Resolver().resolve(spec, self.url, self.buildFromSpec, self);
203203
self.isValid = true;
204204
});
@@ -208,7 +208,7 @@ SwaggerClient.prototype.build = function (mock) {
208208
};
209209

210210
if (this.spec) {
211-
self.swaggerObject = this.spec
211+
self.swaggerObject = this.spec;
212212
setTimeout(function () {
213213
new Resolver().resolve(self.spec, self.buildFromSpec, self);
214214
}, 10);

lib/resolver.js

Lines changed: 85 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Resolver.prototype.processAllOf = function(name, definition, resolutionTable, un
2828
location = '/definitions/' + name + '/allOf';
2929
this.resolveInline(null, spec, property, resolutionTable, unresolvedRefs, location);
3030
}
31-
}
31+
};
3232

3333
Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) {
3434
var root = arg1, callback = arg2, scope = arg3, location, i;
@@ -115,6 +115,7 @@ Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) {
115115
// if the root is same as obj[i].root we can resolve locally
116116
var all = resolutionTable;
117117

118+
var parts;
118119
for(i = 0; i < all.length; i++) {
119120
var a = all[i];
120121
if(root === a.root) {
@@ -145,7 +146,7 @@ Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) {
145146
toResolve.push(a);
146147
}
147148
else {
148-
var parts = a.key.split('#');
149+
parts = a.key.split('#');
149150
if(parts.length === 2) {
150151
if(parts[0].indexOf('http://') === 0 || parts[0].indexOf('https://') === 0) {
151152
a.root = parts[0];
@@ -175,6 +176,17 @@ Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) {
175176
}
176177
else {
177178
if (a.resolveAs === 'inline') {
179+
if(a.key && a.key.indexOf('#') === -1 && a.key.charAt(0) !== '/') {
180+
// handle relative schema
181+
parts = a.root.split('/');
182+
location = '';
183+
for(i = 0; i < parts.length - 1; i++) {
184+
location += parts[i] + '/';
185+
}
186+
location += a.key;
187+
a.root = location;
188+
a.location = '';
189+
}
178190
toResolve.push(a);
179191
}
180192
}
@@ -208,15 +220,18 @@ Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) {
208220
on: {
209221
error: function () {
210222
processedCalls += 1;
211-
unresolvedRefs[item.key] = null;
223+
unresolvedRefs[item.key] = {
224+
root: item.root,
225+
location: item.location
226+
};
212227

213228
if (processedCalls === expectedCalls) {
214229
self.finish(spec, _root, resolutionTable, resolvedRefs, unresolvedRefs, callback);
215230
}
216231
}, // jshint ignore:line
217232
response: function (response) {
218233
var swagger = response.obj;
219-
self.resolveItem(swagger, _root, resolutionTable, resolvedRefs, unresolvedRefs, item);
234+
self.resolveItem(swagger, item.root, resolutionTable, resolvedRefs, unresolvedRefs, item);
220235
processedCalls += 1;
221236

222237
if (processedCalls === expectedCalls) {
@@ -242,23 +257,25 @@ Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) {
242257
Resolver.prototype.resolveItem = function(spec, root, resolutionTable, resolvedRefs, unresolvedRefs, item) {
243258
var path = item.location;
244259
var location = spec, parts = path.split('/');
245-
for (var j = 0; j < parts.length; j++) {
246-
var segment = parts[j];
247-
if(segment.indexOf('~1') !== -1) {
248-
segment = parts[j].replace(/~0/g, '~').replace(/~1/g, '/');
249-
if(segment.charAt(0) !== '/') {
250-
segment = '/' + segment;
260+
if(path !== '') {
261+
for (var j = 0; j < parts.length; j++) {
262+
var segment = parts[j];
263+
if (segment.indexOf('~1') !== -1) {
264+
segment = parts[j].replace(/~0/g, '~').replace(/~1/g, '/');
265+
if (segment.charAt(0) !== '/') {
266+
segment = '/' + segment;
267+
}
268+
}
269+
if (typeof location === 'undefined' || location === null) {
270+
break;
271+
}
272+
if (segment === '' && j === (parts.length - 1) && parts.length > 1) {
273+
location = null;
274+
break;
275+
}
276+
if (segment.length > 0) {
277+
location = location[segment];
251278
}
252-
}
253-
if (typeof location === 'undefined' || location === null) {
254-
break;
255-
}
256-
if(segment === '' && j === (parts.length - 1) && parts.length > 1) {
257-
location = null;
258-
break;
259-
}
260-
if (segment.length > 0) {
261-
location = location[segment];
262279
}
263280
}
264281
var resolved = item.key;
@@ -295,6 +312,9 @@ Resolver.prototype.finish = function (spec, root, resolutionTable, resolvedRefs,
295312
if (resolvedTo) {
296313
spec.definitions = spec.definitions || {};
297314
if (item.resolveAs === 'ref') {
315+
for (key in resolvedTo.obj) {
316+
var abs = this.retainRoot(resolvedTo.obj[key], item.root);
317+
}
298318
spec.definitions[resolvedTo.name] = resolvedTo.obj;
299319
item.obj.$ref = '#/definitions/' + resolvedTo.name;
300320
} else if (item.resolveAs === 'inline') {
@@ -359,7 +379,9 @@ Resolver.prototype.getRefs = function(spec, obj) {
359379
obj = obj || spec;
360380
var output = {};
361381
for(var key in obj) {
362-
if (!obj.hasOwnProperty(key)) continue;
382+
if (!obj.hasOwnProperty(key)) {
383+
continue;
384+
}
363385
var item = obj[key];
364386
if(key === '$ref' && typeof item === 'string') {
365387
output[item] = null;
@@ -471,13 +493,48 @@ Resolver.prototype.resolveInline = function (root, spec, property, resolutionTab
471493
};
472494

473495
Resolver.prototype.resolveTo = function (root, property, resolutionTable, location) {
496+
var sp, i;
474497
var ref = property.$ref;
475-
if (ref) {
498+
var lroot = root;
499+
if (typeof ref !== 'undefined') {
476500
if(ref.indexOf('#') >= 0) {
477-
location = ref.split('#')[1];
501+
var parts = ref.split('#');
502+
503+
// #/definitions/foo
504+
// foo.json#/bar
505+
if(parts[0] && ref.indexOf('/') === 0) {
506+
507+
}
508+
else if(parts[0] && ref.indexOf('http') === 0) {
509+
510+
}
511+
else if(parts[0] && parts[0].length > 0) {
512+
// relative file
513+
sp = root.split('/');
514+
lroot = '';
515+
for(i = 0; i < sp.length - 1; i++) {
516+
lroot += sp[i] + '/';
517+
}
518+
lroot += parts[0];
519+
}
520+
else {
521+
522+
}
523+
524+
location = parts[1];
525+
}
526+
else {
527+
// relative file
528+
sp = root.split('/');
529+
lroot = '';
530+
for(i = 0; i < sp.length - 1; i++) {
531+
lroot += sp[i] + '/';
532+
}
533+
lroot += ref;
534+
location = '';
478535
}
479536
resolutionTable.push({
480-
obj: property, resolveAs: 'ref', root: root, key: ref, location: location
537+
obj: property, resolveAs: 'ref', root: lroot, key: ref, location: location
481538
});
482539
} else if (property.type === 'array') {
483540
var items = property.items;
@@ -490,10 +547,12 @@ Resolver.prototype.resolveAllOf = function(spec, obj, depth) {
490547
obj = obj || spec;
491548
var name;
492549
for(var key in obj) {
493-
if (!obj.hasOwnProperty(key)) continue;
550+
if (!obj.hasOwnProperty(key)) {
551+
continue;
552+
}
494553
var item = obj[key];
495554
if(item === null) {
496-
throw new TypeError("Swagger 2.0 does not support null types (" + obj + "). See https://github.com/swagger-api/swagger-spec/issues/229.")
555+
throw new TypeError('Swagger 2.0 does not support null types (' + obj + '). See https://github.com/swagger-api/swagger-spec/issues/229.');
497556
}
498557
if(typeof item === 'object') {
499558
this.resolveAllOf(spec, item, depth + 1);

lib/schema-markup.js

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ module.exports.schemaToJSON = schemaToJSON;
2323

2424
function optionHtml(label, value) {
2525
return '<tr><td class="optionName">' + label + ':</td><td>' + value + '</td></tr>';
26-
};
26+
}
2727

2828
function typeFromJsonSchema(type, format) {
2929
var str;
@@ -51,7 +51,7 @@ function typeFromJsonSchema(type, format) {
5151
}
5252

5353
return str;
54-
};
54+
}
5555

5656
function getStringSignature(obj, baseComponent) {
5757
var str = '';
@@ -95,7 +95,7 @@ function getStringSignature(obj, baseComponent) {
9595
}
9696

9797
return str;
98-
};
98+
}
9999

100100
function schemaToJSON(schema, models, modelsToIgnore, modelPropertyMacro) {
101101
// Resolve the schema (Handle nested schemas)
@@ -104,7 +104,7 @@ function schemaToJSON(schema, models, modelsToIgnore, modelPropertyMacro) {
104104
if(typeof modelPropertyMacro !== 'function') {
105105
modelPropertyMacro = function(prop){
106106
return (prop || {}).default;
107-
}
107+
};
108108
}
109109

110110
modelsToIgnore= modelsToIgnore || {};
@@ -182,7 +182,7 @@ function schemaToJSON(schema, models, modelsToIgnore, modelPropertyMacro) {
182182
}
183183

184184
return output;
185-
};
185+
}
186186

187187
function schemaToHTML(name, schema, models, modelPropertyMacro) {
188188

@@ -229,7 +229,7 @@ function schemaToHTML(name, schema, models, modelPropertyMacro) {
229229
if(typeof modelPropertyMacro !== 'function') {
230230
modelPropertyMacro = function(prop){
231231
return (prop || {}).default;
232-
}
232+
};
233233
}
234234

235235
var references = {};
@@ -279,7 +279,7 @@ function schemaToHTML(name, schema, models, modelPropertyMacro) {
279279
}
280280

281281
return modelName;
282-
};
282+
}
283283

284284
function primitiveToHTML(schema) {
285285
var html = '<span class="propType">';
@@ -321,7 +321,8 @@ function schemaToHTML(name, schema, models, modelPropertyMacro) {
321321
html += '</span>';
322322

323323
return html;
324-
};
324+
}
325+
325326
function primitiveToOptionsHTML(schema, html) {
326327
var options = '';
327328
var type = schema.type || 'object';
@@ -415,7 +416,8 @@ function schemaToHTML(name, schema, models, modelPropertyMacro) {
415416
}
416417

417418
return html;
418-
};
419+
}
420+
419421
function processModel(schema, name) {
420422
var type = schema.type || 'object';
421423
var isArray = schema.type === 'array';
@@ -520,6 +522,5 @@ function schemaToHTML(name, schema, models, modelPropertyMacro) {
520522
}
521523

522524
return html + strongOpen + (isArray ? ']' : '}') + strongClose;
523-
};
524-
525-
};
525+
}
526+
}

lib/types/operation.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ var Operation = module.exports = function (parent, scheme, operationId, httpMeth
7979
}
8080
}
8181
}
82+
else {
83+
definitions = {};
84+
}
8285

8386
for (i = 0; i < this.parameters.length; i++) {
8487
var param = this.parameters[i];

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
}
99
],
1010
"description": "swagger-client is a javascript client for use with swaggering APIs.",
11-
"version": "2.1.3",
11+
"version": "2.1.4",
1212
"homepage": "http://swagger.io",
1313
"repository": {
1414
"type": "git",

test/auth.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ describe('2.0 authorizations', function () {
138138
});
139139

140140
it('does not apply api-key headers when the value has been manually added', function () {
141-
var params = { api_key: 'foo' };
141+
var params = { 'api_key': 'foo' };
142142

143143
var parameters = [
144144
{
@@ -148,11 +148,11 @@ describe('2.0 authorizations', function () {
148148
}
149149
];
150150
var authorizations = new auth.SwaggerAuthorizations();
151-
authorizations.add("Basic", new auth.ApiKeyAuthorization('api_key', 'bar', 'header'));
151+
authorizations.add('Basic', new auth.ApiKeyAuthorization('api_key', 'bar', 'header'));
152152
var op = new Operation({}, 'http', 'test', 'get', '/path', { parameters: parameters },
153153
{}, {}, authorizations);
154154
var req = op.execute(params, {mock : true});
155-
expect(req.headers.api_key).to.equal('foo');
155+
expect(req.headers['api_key']).to.equal('foo');
156156
});
157157

158158
it('does not apply password auth when the value has been manually added', function () {
@@ -166,7 +166,7 @@ describe('2.0 authorizations', function () {
166166
}
167167
];
168168
var authorizations = new auth.SwaggerAuthorizations();
169-
authorizations.add("Basic", new auth.PasswordAuthorization('bar', 'baz'));
169+
authorizations.add('Basic', new auth.PasswordAuthorization('bar', 'baz'));
170170
var op = new Operation({}, 'http', 'test', 'get', '/path', { parameters: parameters },
171171
{}, {}, authorizations);
172172
var req = op.execute(params, {mock : true});

0 commit comments

Comments
 (0)