diff --git a/packages/graphql/src/schema/get-field-type-meta.test.ts b/packages/graphql/src/schema/get-field-type-meta.test.ts index 46ecc771a4..16304ab406 100644 --- a/packages/graphql/src/schema/get-field-type-meta.test.ts +++ b/packages/graphql/src/schema/get-field-type-meta.test.ts @@ -140,7 +140,7 @@ describe("getFieldTypeMeta", () => { expect(res).toMatchObject({ name: "ABC", - required: true, + required: false, array: true, pretty: "[ABC!]", }); diff --git a/packages/graphql/src/schema/get-field-type-meta.ts b/packages/graphql/src/schema/get-field-type-meta.ts index 3b08c7cf35..1409f924f7 100644 --- a/packages/graphql/src/schema/get-field-type-meta.ts +++ b/packages/graphql/src/schema/get-field-type-meta.ts @@ -47,7 +47,7 @@ function getFieldTypeMeta(field: FieldDefinitionNode | InputValueDefinitionNode) const name = getName(field.type); const pretty = getPrettyName(field.type); const array = /\[.+\]/g.test(pretty); - const required = pretty.includes("!"); + const required = field.type.kind === "NonNullType"; // Things to do with the T inside the Array [T] let arrayTypePretty = ""; diff --git a/packages/graphql/tests/integration/issues/#200.int.test.ts b/packages/graphql/tests/integration/issues/#200.int.test.ts new file mode 100644 index 0000000000..8594ca923b --- /dev/null +++ b/packages/graphql/tests/integration/issues/#200.int.test.ts @@ -0,0 +1,85 @@ +/* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Driver } from "neo4j-driver"; +import { graphql } from "graphql"; +import { generate } from "randomstring"; +import neo4j from "../neo4j"; +import { Neo4jGraphQL } from "../../../src/classes"; + +describe("https://github.com/neo4j/graphql/issues/200", () => { + let driver: Driver; + + beforeAll(async () => { + driver = await neo4j(); + }); + + afterAll(async () => { + await driver.close(); + }); + + test("should successfully execute given mutation", async () => { + const typeDefs = ` + type Category { + categoryId: ID! @id + name: String! + description: String! @default(value: "") + exampleImageLocations: [String!] + } + `; + + const neoSchema = new Neo4jGraphQL({ typeDefs }); + + const catOne = generate({ charset: "alphabetic" }); + const catTwo = generate({ charset: "alphabetic" }); + + const query = ` + mutation($catOne: String!, $catTwo: String!, $exampleImageLocations: [String!]) { + createCategories( + input: [ + { name: $catOne} + { name: $catTwo, exampleImageLocations: $exampleImageLocations } + ] + ) { + categories { + name + exampleImageLocations + } + } + } + `; + + const gqlResult = await graphql({ + schema: neoSchema.schema, + source: query, + variableValues: { catOne, catTwo, exampleImageLocations: [] }, + contextValue: { driver }, + }); + + expect(gqlResult.errors).toBeFalsy(); + + const cats = gqlResult?.data?.createCategories.categories as any[]; + + const one = cats.find((x) => x.name === catOne); + expect(one).toEqual({ name: catOne, exampleImageLocations: null }); + + const two = cats.find((x) => x.name === catTwo); + expect(two).toEqual({ name: catTwo, exampleImageLocations: [] }); + }); +}); diff --git a/packages/graphql/tests/tck/tck-test-files/schema/issues/#200.md b/packages/graphql/tests/tck/tck-test-files/schema/issues/#200.md new file mode 100644 index 0000000000..0f81e8fda4 --- /dev/null +++ b/packages/graphql/tests/tck/tck-test-files/schema/issues/#200.md @@ -0,0 +1,131 @@ +## #162 + + + +--- + +### 2 instances of DeleteInput type created + +**TypeDefs** + +```typedefs-input +type Category { + categoryId: ID! @id + name: String! + description: String! @default(value: "") + exampleImageLocations: [String!] +} +``` + +**Output** + +```schema-output +type Category { + categoryId: ID! + name: String! + description: String! + exampleImageLocations: [String!] +} + +input CategoryCreateInput { + name: String! + description: String! = "" + exampleImageLocations: [String!] +} + +input CategoryOptions { + """ + Specify one or more CategorySort objects to sort Categories by. The sorts will be applied in the order in which they are arranged in the array. + """ + sort: [CategorySort] + limit: Int + skip: Int +} + +""" +Fields to sort Categories by. The order in which sorts are applied is not guaranteed when specifying many fields in one CategorySort object. +""" +input CategorySort { + categoryId: SortDirection + name: SortDirection + description: SortDirection +} + +input CategoryUpdateInput { + name: String + description: String + exampleImageLocations: [String!] +} + +input CategoryWhere { + OR: [CategoryWhere!] + AND: [CategoryWhere!] + categoryId: ID + categoryId_NOT: ID + categoryId_IN: [ID] + categoryId_NOT_IN: [ID] + categoryId_CONTAINS: ID + categoryId_NOT_CONTAINS: ID + categoryId_STARTS_WITH: ID + categoryId_NOT_STARTS_WITH: ID + categoryId_ENDS_WITH: ID + categoryId_NOT_ENDS_WITH: ID + name: String + name_NOT: String + name_IN: [String] + name_NOT_IN: [String] + name_CONTAINS: String + name_NOT_CONTAINS: String + name_STARTS_WITH: String + name_NOT_STARTS_WITH: String + name_ENDS_WITH: String + name_NOT_ENDS_WITH: String + description: String + description_NOT: String + description_IN: [String] + description_NOT_IN: [String] + description_CONTAINS: String + description_NOT_CONTAINS: String + description_STARTS_WITH: String + description_NOT_STARTS_WITH: String + description_ENDS_WITH: String + description_NOT_ENDS_WITH: String + exampleImageLocations: [String!] + exampleImageLocations_NOT: [String!] + exampleImageLocations_INCLUDES: String + exampleImageLocations_NOT_INCLUDES: String +} + +type CreateCategoriesMutationResponse { + categories: [Category!]! +} + +type DeleteInfo { + nodesDeleted: Int! + relationshipsDeleted: Int! +} + +type Mutation { + createCategories(input: [CategoryCreateInput!]!): CreateCategoriesMutationResponse! + deleteCategories(where: CategoryWhere): DeleteInfo! + updateCategories(where: CategoryWhere, update: CategoryUpdateInput): UpdateCategoriesMutationResponse! +} + +type Query { + categories(where: CategoryWhere, options: CategoryOptions): [Category]! +} + +enum SortDirection { + """Sort by field values in ascending order.""" + ASC + + """Sort by field values in descending order.""" + DESC +} + +type UpdateCategoriesMutationResponse { + categories: [Category!]! +} +``` + +---