mirror of
https://github.com/hasura/graphql-engine.git
synced 2025-01-05 22:34:22 +03:00
35d9c059db
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9420 Co-authored-by: Nicolas Beaussart <7281023+beaussan@users.noreply.github.com> GitOrigin-RevId: 31d983ae8573c91ac5bf11066770f776941c3a11
746 lines
19 KiB
Plaintext
746 lines
19 KiB
Plaintext
// 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'
|
|
|
|
import { graphql, GraphQLSchema } from 'graphql'
|
|
import { afterAll, beforeAll, expect, test } from '@jest/globals'
|
|
|
|
import * as openAPIToGraphQL from '../src/index'
|
|
|
|
const oas = require('./fixtures/example_oas4.json')
|
|
|
|
let createdSchema: GraphQLSchema
|
|
|
|
// This test suite is used to verify the behavior of anyOf and oneOf handling
|
|
|
|
// 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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
|
|
*
|
|
* Base schema has no target GraphQL type. One member schema has an integer
|
|
* target type and the other two have no target types. Therefore, use integer
|
|
* type.
|
|
*/
|
|
test('anyOf test with no object type member schemas\n\nEquivalent to GET /anyOf8', () => {
|
|
return graphql({ schema: createdSchema, source: 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: 'Int',
|
|
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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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({ schema: createdSchema, source: 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'
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
})
|
|
})
|
|
})
|
|
|
|
/**
|
|
* oneOf contains two member schemas, each with allOf
|
|
*
|
|
* oneOf also contains a link object
|
|
*
|
|
* Resolving the oneOf and allOfs should correctly create a union of two object
|
|
* types, each object type with a link field from the oneOf schema
|
|
*/
|
|
test('oneOf test with allOfs, requiring oneOf collapse\n\nEquivalent to GET /OneOfWithAllOfsAndLink', () => {
|
|
return graphql({ schema: createdSchema, source: oneOfQuery }).then((result) => {
|
|
expect(
|
|
result.data['__schema']['queryType'].fields.find((field) => {
|
|
return field.name === 'oneOfWithAllOfsAndLink'
|
|
})
|
|
).toEqual({
|
|
"name": "oneOfWithAllOfsAndLink",
|
|
"description": "Equivalent to GET /oneOfWithAllOfsAndLink",
|
|
"type": {
|
|
"name": "OneOfWithAllOfsAndLink",
|
|
"kind": "UNION",
|
|
"possibleTypes": [
|
|
{
|
|
"name": "One",
|
|
"fields": [
|
|
{
|
|
"type": {
|
|
"name": "String"
|
|
}
|
|
},
|
|
{
|
|
"type": {
|
|
"name": "String"
|
|
}
|
|
},
|
|
{
|
|
"type": {
|
|
"name": "String"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "Two",
|
|
"fields": [
|
|
{
|
|
"type": {
|
|
"name": "String"
|
|
}
|
|
},
|
|
{
|
|
"type": {
|
|
"name": "String"
|
|
}
|
|
},
|
|
{
|
|
"type": {
|
|
"name": "String"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
})
|
|
})
|
|
})
|