openapi-to-graphql-lxwang2
Version:
Generates a GraphQL schema for a given OpenAPI Specification (OAS)
680 lines (653 loc) • 17.1 kB
text/typescript
// Copyright IBM Corp. 2017,2018. All Rights Reserved.
// Node module: openapi-to-graphql
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict'
/* globals beforeAll, test, expect */
import { graphql } from 'graphql'
import * as openAPIToGraphQL from '../lib/index'
const oas = require('./fixtures/example_oas4.json')
// This test suite is used to verify the behavior of anyOf and oneOf handling
let createdSchema
/**
* Set up the schema
*/
beforeAll(() => {
return openAPIToGraphQL
.createGraphQLSchema(oas)
.then(({ schema, report }) => {
createdSchema = schema
})
})
const anyOfQuery = `{
__schema {
queryType {
fields {
name
description
type {
name
kind
fields {
name
type {
name
}
}
}
}
}
}
}`
const oneOfQuery = `{
__schema {
queryType {
fields {
name
description
type {
name
kind
possibleTypes {
name
fields {
type {
name
}
}
}
}
}
}
}
}`
/**
* anyOf contains two member schemas
*
* Both member schemas contain the same field 'commonAttribute'
*
* Because they are the same, the created GraphQL object should only have one
* 'commonAttribute' field
*/
test('Basic anyOf test using the same member schemas\n\nEquivalent to GET /anyOf', () => {
return graphql(createdSchema, anyOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'anyOf'
})
).toEqual({
name: 'anyOf',
description:
'Basic anyOf test using the same member schemas\n\nEquivalent to GET /anyOf',
type: {
name: 'AnyOf',
kind: 'OBJECT',
fields: [
{
name: 'commonAttribute',
type: {
name: 'String'
}
}
]
}
})
})
})
/**
* anyOf contains two member schemas
*
* One member schema contains a 'commonAttribute' field and the other
* member schema contains a 'differentAttribute' field
*
* Because they are the different, the created GraphQL object should have both
* fields
*/
test('Basic anyOf test with different member schemas\n\nEquivalent to GET /anyOf2', () => {
return graphql(createdSchema, anyOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'anyOf2'
})
).toEqual({
name: 'anyOf2',
description:
'Basic anyOf test with different member schemas\n\nEquivalent to GET /anyOf2',
type: {
name: 'AnyOf2',
kind: 'OBJECT',
fields: [
{
name: 'commonAttribute',
type: {
name: 'String'
}
},
{
name: 'differentAttribute',
type: {
name: 'String'
}
}
]
}
})
})
})
/**
* anyOf contains two member schemas
*
* Both member schemas contain the same complex nested field
*
* Because they are the same, the created GraphQL object should only have one
* field
*/
test('anyOf test with the same nested member schemas\n\nEquivalent to GET /anyOf3', () => {
return graphql(createdSchema, anyOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'anyOf3'
})
).toEqual({
name: 'anyOf3',
description:
'anyOf test with the same nested member schemas\n\nEquivalent to GET /anyOf3',
type: {
name: 'AnyOf3',
kind: 'OBJECT',
fields: [
{
name: 'commonAttribute',
type: {
name: 'CommonAttribute'
}
}
]
}
})
})
})
/**
* anyOf contains two member schemas
*
* The member schemas contain complex nested fields that are different at the root
* level.
*
* Because they are different at the root level, the created GraphQL object
* should have two fields.
*/
test('anyOf test with different nested member schemas\n\nEquivalent to GET /anyOf4', () => {
return graphql(createdSchema, anyOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'anyOf4'
})
).toEqual({
name: 'anyOf4',
description:
'anyOf test with different nested member schemas\n\nEquivalent to GET /anyOf4',
type: {
name: 'AnyOf4',
kind: 'OBJECT',
fields: [
{
name: 'commonAttribute',
type: {
name: 'CommonAttribute'
}
},
{
name: 'differentAttribute',
type: {
name: 'DifferentAttribute'
}
}
]
}
})
})
})
/**
* anyOf contains two member schemas
*
* The member schemas contain complex nested fields that are same at the root
* level but different at other levels.
*
* This leads to a conlict because the same field has different schemas. As a
* result, the field will use the arbitrary JSON type.
*/
test('anyOf test with different nested member schemas, leading to conflict\n\nEquivalent to GET /anyOf5', () => {
return graphql(createdSchema, anyOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'anyOf5'
})
).toEqual({
name: 'anyOf5',
description:
'anyOf test with different nested member schemas, leading to conflict\n\nEquivalent to GET /anyOf5',
type: {
name: 'AnyOf5',
kind: 'OBJECT',
fields: [
{
name: 'commonAttribute',
type: {
name: 'JSON'
}
}
]
}
})
})
})
/**
* anyOf contains two member schemas
*
* The member schemas are of different types. One is an object type and the other
* is an scalar type.
*
* This leads to a conlict. As a result, the field will use the arbitrary JSON
* type.
*/
test('anyOf test with incompatible member schema types\n\nEquivalent to GET /anyOf6', () => {
return graphql(createdSchema, anyOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'anyOf6'
})
).toEqual({
name: 'anyOf6',
description:
'anyOf test with incompatible member schema types\n\nEquivalent to GET /anyOf6',
type: {
name: 'JSON',
kind: 'SCALAR',
fields: null
}
})
})
})
/**
* anyOf contains three member schemas
*
* Only one of the member schemas is an object type schema.
*
* The created type should be able to pick out the object type schema without
* defaulting to the arbitrary JSON type.
*/
test('anyOf test with some extraneous member schemas\n\nEquivalent to GET /anyOf7', () => {
return graphql(createdSchema, anyOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'anyOf7'
})
).toEqual({
name: 'anyOf7',
description:
'anyOf test with some extraneous member schemas\n\nEquivalent to GET /anyOf7',
type: {
name: 'AnyOf7',
kind: 'OBJECT',
fields: [
{
name: 'commonAttribute',
type: {
name: 'String'
}
}
]
}
})
})
})
/**
* anyOf contains three member schemas
*
* None of the member schemas are object type schemas. As a result, it defaults to the
* arbitrary JSON type.
*/
test('anyOf test with no object type member schemas\n\nEquivalent to GET /anyOf8', () => {
return graphql(createdSchema, anyOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'anyOf8'
})
).toEqual({
name: 'anyOf8',
description:
'anyOf test with no object type member schemas\n\nEquivalent to GET /anyOf8',
type: {
name: 'JSON',
kind: 'SCALAR',
fields: null
}
})
})
})
/**
* anyOf contains three member schemas
*
* None of the member schemas are object type schemas but because there is an
* external type provided in the root schema, it can utilize the proper typing.
*/
test('anyOf test with extraneous member schemas with external type\n\nEquivalent to GET /anyOf9', () => {
return graphql(createdSchema, anyOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'anyOf9'
})
).toEqual({
name: 'anyOf9',
description:
'anyOf test with extraneous member schemas with external type\n\nEquivalent to GET /anyOf9',
type: {
name: 'Int',
kind: 'SCALAR',
fields: null
}
})
})
})
/**
* anyOf contains two member schemas and allOf contains an additional one
*
* None of the schemas have conflicts so all three should be utilized
*/
test('Basic anyOf test with allOf\n\nEquivalent to GET /anyOf10', () => {
return graphql(createdSchema, anyOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'anyOf10'
})
).toEqual({
name: 'anyOf10',
description: 'Basic anyOf test with allOf\n\nEquivalent to GET /anyOf10',
type: {
name: 'AnyOf10',
kind: 'OBJECT',
fields: [
{
name: 'anotherAttribute',
type: {
name: 'String'
}
},
{
name: 'commonAttribute',
type: {
name: 'String'
}
},
{
name: 'differentAttribute',
type: {
name: 'String'
}
}
]
}
})
})
})
/**
* anyOf contains two member schemas and allOf contains an additional one that
* is nested in another anyOf
*
* Resolving the allOf should correctly collapse all of the (nested) anyOfs
* and allow all three schemas to be utilized
*/
test('anyOf test with allOf, requiring anyOf collapse\n\nEquivalent to GET /anyOf11', () => {
return graphql(createdSchema, anyOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'anyOf11'
})
).toEqual({
name: 'anyOf11',
description:
'anyOf test with allOf, requiring anyOf collapse\n\nEquivalent to GET /anyOf11',
type: {
name: 'AnyOf11',
kind: 'OBJECT',
fields: [
{
name: 'anotherAttribute',
type: {
name: 'String'
}
},
{
name: 'commonAttribute',
type: {
name: 'String'
}
},
{
name: 'differentAttribute',
type: {
name: 'String'
}
}
]
}
})
})
})
/**
* oneOf contains two member schemas
*
* Because the schemas are different object types, the created GraphQL union
* type has two differnet member types.
*/
test('Basic oneOf test\n\nEquivalent to GET /oneOf', () => {
return graphql(createdSchema, oneOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'oneOf'
})
).toEqual({
name: 'oneOf',
description: 'Basic oneOf test\n\nEquivalent to GET /oneOf',
type: {
name: 'OneOf',
kind: 'UNION',
possibleTypes: [
{
name: 'CommonAttributeObject',
fields: [
{
type: {
name: 'String'
}
}
]
},
{
name: 'DifferentAttributeObject',
fields: [
{
type: {
name: 'String'
}
}
]
}
]
}
})
})
})
/**
* oneOf contains two member schemas
*
* Because one of the member schemas is not an object type, then default to
* the arbitrary JSON type.
*/
test('oneOf test with non-object type member schema\n\nEquivalent to GET /oneOf2', () => {
return graphql(createdSchema, oneOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'oneOf2'
})
).toEqual({
name: 'oneOf2',
description:
'oneOf test with non-object type member schema\n\nEquivalent to GET /oneOf2',
type: {
name: 'JSON',
kind: 'SCALAR',
possibleTypes: null
}
})
})
})
/**
* oneOf contains two member schemas
*
* None of the member schemas are object types, therefore default to
* the arbitrary JSON type.
*/
test('oneOf test with no object type member schemas\n\nEquivalent to GET /oneOf3', () => {
return graphql(createdSchema, oneOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'oneOf3'
})
).toEqual({
name: 'oneOf3',
description:
'oneOf test with no object type member schemas\n\nEquivalent to GET /oneOf3',
type: {
name: 'JSON',
kind: 'SCALAR',
possibleTypes: null
}
})
})
})
/**
* oneOf contains two member schemas
*
* The member schemas contain extranous data but because the root schema contains a
* type, it is able to utilize the proper type.
*/
test('oneOf test with extraneous member schemas\n\nEquivalent to GET /oneOf4', () => {
return graphql(createdSchema, oneOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'oneOf4'
})
).toEqual({
name: 'oneOf4',
description:
'oneOf test with extraneous member schemas\n\nEquivalent to GET /oneOf4',
type: {
name: 'Int',
kind: 'SCALAR',
possibleTypes: null
}
})
})
})
/**
* oneOf contains two member schemas and an allOf
*
* Only schemas within the oneOf should be utilized
*
* TODO: verify this behavior and also create a test with additional root properties
*/
test('Basic oneOf test with allOf\n\nEquivalent to GET /oneOf5', () => {
return graphql(createdSchema, oneOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'oneOf5'
})
).toEqual({
name: 'oneOf5',
description: 'Basic oneOf test with allOf\n\nEquivalent to GET /oneOf5',
type: {
name: 'OneOf5',
kind: 'UNION',
possibleTypes: [
{
name: 'CommonAttributeObject',
fields: [
{
type: {
name: 'String'
}
}
]
},
{
name: 'DifferentAttributeObject',
fields: [
{
type: {
name: 'String'
}
}
]
}
]
}
})
})
})
/**
* oneOf contains two member schemas and allOf contains an additional one that
* is nested in another oneOf
*
* Resolving the allOf should correctly collapse all of the (nested) oneOfs
* and allow all three schemas to be utilized
*/
test('oneOf test with allOf, requiring oneOf collapse\n\nEquivalent to GET /oneOf6', () => {
return graphql(createdSchema, oneOfQuery).then(result => {
expect(
result.data['__schema'].queryType.fields.find(field => {
return field.name === 'oneOf6'
})
).toEqual({
name: 'oneOf6',
description:
'oneOf test with allOf, requiring oneOf collapse\n\nEquivalent to GET /oneOf6',
type: {
name: 'OneOf6',
kind: 'UNION',
possibleTypes: [
{
name: 'CommonAttributeObject',
fields: [
{
type: {
name: 'String'
}
}
]
},
{
name: 'DifferentAttributeObject',
fields: [
{
type: {
name: 'String'
}
}
]
},
{
name: 'AnotherAttributeObject',
fields: [
{
type: {
name: 'String'
}
}
]
}
]
}
})
})
})