Skip to content

Commit 12b5623

Browse files
authored
fix (walker): show description for $ref in fragments of type array (#23)
1 parent c16711d commit 12b5623

File tree

2 files changed

+118
-1
lines changed

2 files changed

+118
-1
lines changed

src/__tests__/tree.spec.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,101 @@ describe('SchemaTree', () => {
757757
}),
758758
);
759759
});
760+
761+
it('node of type array should adopt description of referenced node', () => {
762+
const schema = {
763+
definitions: {
764+
Cave: {
765+
type: 'string',
766+
summary: 'A cave',
767+
description: '_Everyone_ ~hates~ loves caves',
768+
},
769+
},
770+
type: 'object',
771+
properties: {
772+
caves: {
773+
type: 'array',
774+
items: {
775+
$ref: '#/definitions/Cave',
776+
},
777+
},
778+
},
779+
};
780+
781+
const tree = new SchemaTree(schema);
782+
tree.populate();
783+
784+
expect(
785+
// @ts-ignore
786+
tree.root.children[0].children[0].annotations.description,
787+
).toEqual('_Everyone_ ~hates~ loves caves');
788+
});
789+
790+
it('node of type array should keep its own description even when referenced node has a description', () => {
791+
const schema = {
792+
definitions: {
793+
Cave: {
794+
type: 'string',
795+
summary: 'A cave',
796+
description: '_Everyone_ ~hates~ loves caves',
797+
},
798+
},
799+
type: 'object',
800+
properties: {
801+
caves: {
802+
type: 'array',
803+
description: 'I have my own description',
804+
items: {
805+
$ref: '#/definitions/Cave',
806+
},
807+
},
808+
},
809+
};
810+
811+
const tree = new SchemaTree(schema);
812+
tree.populate();
813+
814+
expect(
815+
// @ts-ignore
816+
tree.root.children[0].children[0].annotations.description,
817+
).toEqual('I have my own description');
818+
});
819+
820+
it('referenced node description should appear for all properties with that ref', () => {
821+
const schema = {
822+
definitions: {
823+
Cave: {
824+
type: 'string',
825+
summary: 'A cave',
826+
description: '_Everyone_ ~hates~ loves caves',
827+
},
828+
},
829+
type: 'object',
830+
properties: {
831+
caves: {
832+
type: 'array',
833+
items: {
834+
$ref: '#/definitions/Cave',
835+
},
836+
},
837+
bear: {
838+
$ref: '#/definitions/Cave',
839+
},
840+
},
841+
};
842+
843+
const tree = new SchemaTree(schema);
844+
tree.populate();
845+
846+
expect(
847+
// @ts-ignore
848+
tree.root.children[0].children[0].annotations.description,
849+
).toEqual('_Everyone_ ~hates~ loves caves');
850+
expect(
851+
// @ts-ignore
852+
tree.root.children[0].children[1].annotations.description,
853+
).toEqual('_Everyone_ ~hates~ loves caves');
854+
});
760855
});
761856

762857
describe('position', () => {

src/walker/walker.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,29 @@ export class Walker extends EventEmitter<WalkerEmitter> {
295295
return [new ReferenceNode(fragment, null), fragment];
296296
}
297297
}
298-
298+
//fragment with type 'array' and no description should adopt description of $ref if it exists
299+
if (fragment.type === 'array' && fragment.description === void 0) {
300+
if (fragment.items !== void 0 && isObjectLiteral(fragment.items)) {
301+
for (const key of Object.keys(fragment.items)) {
302+
if (key === '$ref') {
303+
const refToResolve = fragment.items[key];
304+
if (typeof refToResolve !== 'string') {
305+
return [new ReferenceNode(fragment, '$ref is not a string'), fragment];
306+
} else if (walkingOptions.resolveRef !== null) {
307+
try {
308+
let newFragment = walkingOptions.resolveRef(path, refToResolve);
309+
if (newFragment.description !== void 0) {
310+
newFragment = { ...newFragment };
311+
Object.assign(fragment, { description: newFragment.description });
312+
}
313+
} catch (ex) {
314+
super.emit('error', createMagicError(ex));
315+
}
316+
}
317+
}
318+
}
319+
}
320+
}
299321
let initialFragment: ProcessedFragment = fragment;
300322
if (walkingOptions.mergeAllOf && SchemaCombinerName.AllOf in fragment) {
301323
try {

0 commit comments

Comments
 (0)