Skip to content

Commit df37903

Browse files
Alan-ChaErikWittern
authored andcommitted
Add tests utilizing anyOf and oneOf with allOf
Signed-off-by: Alan Cha <[email protected]>
1 parent 58bfd83 commit df37903

File tree

5 files changed

+411
-6
lines changed

5 files changed

+411
-6
lines changed

packages/openapi-to-graphql/lib/preprocessor.js

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

packages/openapi-to-graphql/lib/preprocessor.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/openapi-to-graphql/src/preprocessor.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,28 @@ function resolveAllOf(
991991
)
992992
}
993993

994+
// Collapse oneOf if applicable
995+
if ('oneOf' in resolvedSchema) {
996+
if (!('oneOf' in collapsedSchema)) {
997+
collapsedSchema.oneOf = []
998+
}
999+
1000+
resolvedSchema.oneOf.forEach(oneOfProperty => {
1001+
collapsedSchema.oneOf.push(oneOfProperty)
1002+
})
1003+
}
1004+
1005+
// Collapse anyOf if applicable
1006+
if ('anyOf' in resolvedSchema) {
1007+
if (!('anyOf' in collapsedSchema)) {
1008+
collapsedSchema.anyOf = []
1009+
}
1010+
1011+
resolvedSchema.anyOf.forEach(anyOfProperty => {
1012+
collapsedSchema.anyOf.push(anyOfProperty)
1013+
})
1014+
}
1015+
9941016
// Collapse required if applicable
9951017
if ('required' in resolvedSchema) {
9961018
if (!('required' in collapsedSchema)) {
@@ -1059,6 +1081,11 @@ function getMemberSchemaData(
10591081
return result
10601082
}
10611083

1084+
/**
1085+
* Check to see if there are cases of nested oneOf fields in the member schemas
1086+
*
1087+
* We currently cannot handle complex cases of oneOf and anyOf
1088+
*/
10621089
function hasNestedOneOfUsage(
10631090
collapsedSchema: SchemaObject,
10641091
oas: Oas3
@@ -1082,6 +1109,11 @@ function hasNestedOneOfUsage(
10821109
)
10831110
}
10841111

1112+
/**
1113+
* Check to see if there are cases of nested anyOf fields in the member schemas
1114+
*
1115+
* We currently cannot handle complex cases of oneOf and anyOf
1116+
*/
10851117
function hasNestedAnyOfUsage(
10861118
collapsedSchema: SchemaObject,
10871119
oas: Oas3
@@ -1105,6 +1137,12 @@ function hasNestedAnyOfUsage(
11051137
)
11061138
}
11071139

1140+
/**
1141+
* Create a data definition for anyOf is applicable
1142+
*
1143+
* anyOf should resolve into an object that contains the superset of all
1144+
* properties from the member schemas
1145+
*/
11081146
function createDataDefFromAnyOf(
11091147
saneName: string,
11101148
saneInputName: string,
@@ -1138,6 +1176,12 @@ function createDataDefFromAnyOf(
11381176
} = {}
11391177
const incompatibleProperties = new Set<string>()
11401178

1179+
/**
1180+
* TODO: Check for consistent properties across all member schemas and
1181+
* make them into non-nullable properties by manipulating the
1182+
* required field
1183+
*/
1184+
11411185
if (typeof collapsedSchema.properties === 'object') {
11421186
Object.keys(collapsedSchema.properties).forEach(propertyName => {
11431187
allProperties[propertyName] = [
@@ -1211,9 +1255,9 @@ function createDataDefFromAnyOf(
12111255
})
12121256
})
12131257

1214-
// Add in incompatible properties
1258+
// Add in incompatible properties
12151259
incompatibleProperties.forEach(propertyName => {
1216-
// TODO: add description
1260+
// TODO: add description
12171261
def.subDefinitions[propertyName] = {
12181262
targetGraphQLType: 'json'
12191263
}

packages/openapi-to-graphql/test/example_api4.test.ts

Lines changed: 191 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { Options } from '../lib/types/options'
1414
import { startServer, stopServer } from './example_api_server'
1515

1616
const oas = require('./fixtures/example_oas4.json')
17-
const PORT = 3004
17+
const PORT = 3007
1818
// Update PORT for this test case:
1919
oas.servers[0].variables.port.default = String(PORT)
2020

@@ -384,6 +384,93 @@ test('anyOf test with extraneous member schemas with external type\n\nEquivalent
384384
})
385385
})
386386

387+
/**
388+
* anyOf contains two member schemas and allOf contains an additional one
389+
*
390+
* None of the schemas have conflicts so all three should be utilized
391+
*/
392+
test('Basic anyOf test with allOf\n\nEquivalent to GET /anyOf10', () => {
393+
return graphql(createdSchema, anyOfQuery).then(result => {
394+
expect(
395+
result.data['__schema'].queryType.fields.find(field => {
396+
return field.name === 'anyOf10'
397+
})
398+
).toEqual({
399+
name: 'anyOf10',
400+
description: 'Basic anyOf test with allOf\n\nEquivalent to GET /anyOf10',
401+
type: {
402+
name: 'AnyOf10',
403+
kind: 'OBJECT',
404+
fields: [
405+
{
406+
name: 'anotherAttribute',
407+
type: {
408+
name: 'String'
409+
}
410+
},
411+
{
412+
name: 'commonAttribute',
413+
type: {
414+
name: 'String'
415+
}
416+
},
417+
{
418+
name: 'differentAttribute',
419+
type: {
420+
name: 'String'
421+
}
422+
}
423+
]
424+
}
425+
})
426+
})
427+
})
428+
429+
/**
430+
* anyOf contains two member schemas and allOf contains an additional one that
431+
* is nested in another anyOf
432+
*
433+
* Resolving the allOf should correctly collapse all of the (nested) anyOfs
434+
* and allow all three schemas to be utilized
435+
*/
436+
test('anyOf test with allOf, requiring anyOf collapse\n\nEquivalent to GET /anyOf11', () => {
437+
return graphql(createdSchema, anyOfQuery).then(result => {
438+
expect(
439+
result.data['__schema'].queryType.fields.find(field => {
440+
return field.name === 'anyOf11'
441+
})
442+
).toEqual({
443+
name: 'anyOf11',
444+
description:
445+
'anyOf test with allOf, requiring anyOf collapse\n\nEquivalent to GET /anyOf11',
446+
type: {
447+
name: 'AnyOf11',
448+
kind: 'OBJECT',
449+
fields: [
450+
{
451+
name: 'anotherAttribute',
452+
type: {
453+
name: 'String'
454+
}
455+
},
456+
{
457+
name: 'commonAttribute',
458+
type: {
459+
name: 'String'
460+
}
461+
},
462+
{
463+
name: 'differentAttribute',
464+
type: {
465+
name: 'String'
466+
}
467+
}
468+
]
469+
}
470+
})
471+
})
472+
})
473+
387474
/**
388475
* oneOf contains two member schemas
389476
*
@@ -503,3 +590,106 @@ test('oneOf test with extraneous member schemas\n\nEquivalent to GET /oneOf4', (
503590
})
504591
})
505592
})
593+
594+
/**
595+
* oneOf contains two member schemas and an allOf
596+
*
597+
* Only schemas within the oneOf should be utilized
598+
*
599+
* TODO: verify this behavior and also create a test with additional root properties
600+
*/
601+
test('Basic oneOf test with allOf\n\nEquivalent to GET /oneOf5', () => {
602+
return graphql(createdSchema, oneOfQuery).then(result => {
603+
expect(
604+
result.data['__schema'].queryType.fields.find(field => {
605+
return field.name === 'oneOf5'
606+
})
607+
).toEqual({
608+
name: 'oneOf5',
609+
description: 'Basic oneOf test with allOf\n\nEquivalent to GET /oneOf5',
610+
type: {
611+
name: 'OneOf5',
612+
kind: 'UNION',
613+
possibleTypes: [
614+
{
615+
name: 'CommonAttributeObject',
616+
fields: [
617+
{
618+
type: {
619+
name: 'String'
620+
}
621+
}
622+
]
623+
},
624+
{
625+
name: 'DifferentAttributeObject',
626+
fields: [
627+
{
628+
type: {
629+
name: 'String'
630+
}
631+
}
632+
]
633+
}
634+
]
635+
}
636+
})
637+
})
638+
})
639+
640+
/**
641+
* oneOf contains two member schemas and allOf contains an additional one that
642+
* is nested in another oneOf
643+
*
644+
* Resolving the allOf should correctly collapse all of the (nested) oneOfs
645+
* and allow all three schemas to be utilized
646+
*/
647+
test('oneOf test with allOf, requiring oneOf collapse\n\nEquivalent to GET /oneOf6', () => {
648+
return graphql(createdSchema, oneOfQuery).then(result => {
649+
expect(
650+
result.data['__schema'].queryType.fields.find(field => {
651+
return field.name === 'oneOf6'
652+
})
653+
).toEqual({
654+
name: 'oneOf6',
655+
description:
656+
'oneOf test with allOf, requiring oneOf collapse\n\nEquivalent to GET /oneOf6',
657+
type: {
658+
name: 'OneOf6',
659+
kind: 'UNION',
660+
possibleTypes: [
661+
{
662+
name: 'CommonAttributeObject',
663+
fields: [
664+
{
665+
type: {
666+
name: 'String'
667+
}
668+
}
669+
]
670+
},
671+
{
672+
name: 'DifferentAttributeObject',
673+
fields: [
674+
{
675+
type: {
676+
name: 'String'
677+
}
678+
}
679+
]
680+
},
681+
{
682+
name: 'AnotherAttributeObject',
683+
fields: [
684+
{
685+
type: {
686+
name: 'String'
687+
}
688+
}
689+
]
690+
}
691+
]
692+
}
693+
})
694+
})
695+
})

0 commit comments

Comments
 (0)