Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions src/components/Tables/ConfigOptions.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,59 @@ describe('getValueType with x-has-data-type', () => {
});
});

// An untitled $defs entry — pydantic publishes one for a model that overrides
// its JSON schema with a union wrapper (batch_size) — has no label to render,
// so both renderers expand the target instead of emitting an empty type.
const untitledUnionSchema = {
$defs: {
BatchSizeBounds: {
anyOf: [
{ type: 'integer', minimum: 1, maximum: 128 },
{
type: 'object',
title: 'BatchSizeBounds',
properties: { min: { type: 'integer' }, max: { type: 'integer' } },
required: ['min', 'max'],
},
],
},
},
};

describe('getValueType with an untitled $ref target', () => {
it('expands the union instead of rendering an empty type', () => {
const html = render(untitledUnionSchema, { $ref: '#/$defs/BatchSizeBounds' });
expect(html).toContain('integer');
expect(html).toContain('or');
expect(html).toContain('{min, max}');
});

it('names the keys of an inline object shape', () => {
const html = render(
{},
{ type: 'object', properties: { min: { type: 'integer' }, max: { type: 'integer' } } }
);
expect(html).toContain('{min, max}');
});

it('still renders the title of a titled $ref target', () => {
const schema = { $defs: { Commit: { title: 'Commit', type: 'object' } } };
expect(render(schema, { $ref: '#/$defs/Commit' })).toContain('Commit');
});
});

describe('getValueTypeText with an untitled $ref target', () => {
it('expands the union instead of emitting an empty cell', () => {
expect(
getValueTypeText(untitledUnionSchema as never, { $ref: '#/$defs/BatchSizeBounds' })
).toBe('integer or `{min, max}`');
});

it('does not crash on a dangling $ref', () => {
expect(getValueTypeText({ $defs: {} } as never, { $ref: '#/$defs/Gone' })).toBe('');
});
});

describe('getValueTypeText with x-has-data-type', () => {
it('emits a markdown link instead of the enum dump', () => {
expect(getValueTypeText({} as never, inlineMarked)).toBe(`[Queue dequeue reason](${HREF})`);
Expand Down
15 changes: 15 additions & 0 deletions src/components/Tables/ConfigOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,15 @@ export function getValueType(schema: object, definition: any): React.ReactElemen
valueType = <>list of {typeDescription}</>;
}
} else if (definition.$ref !== undefined) {
if (!getTitle(schema, definition.$ref)) {
// An untitled `$defs` entry carries a shape and no label — pydantic
// publishes one whenever a model overrides its JSON schema with a union
// wrapper. Expand the target so the union renders like an inline one,
// instead of showing an empty type.
const target = getItemFromSchema(schema, definition.$ref);
return target ? getValueType(schema, target) : null;
}

const typeLink = getTypeLink(definition.$ref);
const typeDescription = (
<div
Expand Down Expand Up @@ -290,6 +299,12 @@ export function getValueType(schema: object, definition: any): React.ReactElemen
// A map field (e.g. github_actions inputs): show "map of <value type>" so the
// templated value type still links to its data-types section.
valueType = <>map of {getValueType(schema, definition.additionalProperties)}</>;
} else if (definition.type === 'object' && definition.properties) {
// An inline object shape has no name to show: list its keys, which is what
// a reader needs to write the value.
valueType = (
<HighlightCode>{`{${Object.keys(definition.properties).join(', ')}}`}</HighlightCode>
Comment thread
JulianMaurin marked this conversation as resolved.
);
} else {
valueType = <HighlightCode>{definition.type}</HighlightCode>;
}
Expand Down
12 changes: 11 additions & 1 deletion src/util/schemaToMarkdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,13 @@ export function getValueTypeText(schema: Schema, definition: any): string {
}

if (definition.$ref !== undefined) {
return getTitle(schema, definition.$ref);
const title = getTitle(schema, definition.$ref);
if (title) {
return title;
}
// Untitled `$defs` entry: expand the target rather than emit an empty cell.
const target = getItemFromSchema(schema, definition.$ref);
return target ? getValueTypeText(schema, target) : '';
}

if (definition.anyOf || definition.oneOf || definition.allOf) {
Expand All @@ -92,6 +98,10 @@ export function getValueTypeText(schema: Schema, definition: any): string {
return definition.format;
}

if (definition.type === 'object' && definition.properties) {
return `\`{${Object.keys(definition.properties).join(', ')}}\``;
}

return definition.type || '';
}

Expand Down