Skip to content

Commit 70d5f17

Browse files
authored
fix: don't classify remote document references as indirect circrefs (#1265)
1 parent 851b830 commit 70d5f17

File tree

3 files changed

+114
-1
lines changed

3 files changed

+114
-1
lines changed

src/specmap/lib/refs.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,11 @@ function pointerIsAParent(pointer, parentPointer) {
330330
return true
331331
}
332332
const nextChar = pointer.charAt(parentPointer.length)
333+
const lastParentChar = parentPointer.slice(-1)
334+
333335
return pointer.indexOf(parentPointer) === 0
334336
&& (!nextChar || nextChar === '/' || nextChar === '#')
337+
&& lastParentChar !== '#'
335338
}
336339

337340

test/specmap/refs.js

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ describe('refs', function () {
435435
})
436436

437437
describe('deeply resolved', function () {
438-
it('should resolve deeply nested $refs, across documents', function () {
438+
it('should resolve deeply serial $refs, across documents', function () {
439439
xmock().get('http://example.com/doc-a', function (req, res, next) {
440440
xmock().restore()
441441
return res.send({
@@ -462,5 +462,57 @@ describe('refs', function () {
462462
})
463463
})
464464
})
465+
it('should resolve deeply nested $refs, across documents', function () {
466+
xmock().get('http://example.com/doc-a', function (req, res, next) {
467+
xmock().restore()
468+
return res.send({
469+
two: {
470+
innerTwo: {
471+
$ref: '#/three'
472+
}
473+
},
474+
three: {
475+
innerThree: {
476+
$ref: '#/four'
477+
}
478+
},
479+
four: {
480+
four: 4,
481+
}
482+
})
483+
})
484+
485+
return mapSpec({
486+
plugins: [plugins.refs],
487+
spec: {
488+
result: {
489+
$ref: 'http://example.com/doc-a#'
490+
}
491+
},
492+
context: {
493+
baseDoc: 'http://example.com/main.json'
494+
}
495+
}).then((res) => {
496+
expect(res.spec).toEqual({
497+
result: {
498+
two: {
499+
innerTwo: {
500+
innerThree: {
501+
four: 4
502+
}
503+
}
504+
},
505+
three: {
506+
innerThree: {
507+
four: 4
508+
}
509+
},
510+
four: {
511+
four: 4
512+
}
513+
}
514+
})
515+
})
516+
})
465517
})
466518
})

test/subtree-resolver.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
11
import expect, {spyOn, createSpy} from 'expect'
2+
import xmock from 'xmock'
23
import resolve from '../src/subtree-resolver'
34

45
describe('subtree $ref resolver', function () {
6+
let xapp
7+
8+
before(() => {
9+
xapp = xmock()
10+
})
11+
12+
after(() => {
13+
xapp.restore()
14+
})
15+
16+
beforeEach(() => {
17+
// refs.clearCache()
18+
})
19+
520
it('should resolve a subtree of an object, and return the targeted subtree', async function () {
621
const input = {
722
a: {
@@ -253,4 +268,47 @@ describe('subtree $ref resolver', function () {
253268
}
254269
})
255270
})
271+
it('should fully resolve across remote documents correctly', async () => {
272+
const input = {
273+
foo: {
274+
bar: {
275+
$ref: './remote.json'
276+
}
277+
}
278+
}
279+
280+
xmock().get('http://example.com/remote.json', function (req, res, next) {
281+
xmock().restore()
282+
return res.send({
283+
baz: {
284+
$ref: '#/remoteOther'
285+
},
286+
remoteOther: {
287+
result: 'it works!'
288+
}
289+
})
290+
})
291+
292+
const res = await resolve(input, [], {
293+
baseDoc: 'http://example.com/main.json'
294+
})
295+
296+
expect(res).toEqual({
297+
errors: [],
298+
spec: {
299+
foo: {
300+
bar: {
301+
$$ref: './remote.json',
302+
baz: {
303+
$$ref: '#/remoteOther',
304+
result: 'it works!'
305+
},
306+
remoteOther: {
307+
result: 'it works!'
308+
}
309+
}
310+
}
311+
}
312+
})
313+
})
256314
})

0 commit comments

Comments
 (0)