Skip to content

Commit c6f38ab

Browse files
committed
improve test cases
1 parent ebd835d commit c6f38ab

File tree

4 files changed

+105
-16
lines changed

4 files changed

+105
-16
lines changed

src/definitions/input.ts

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ See the License for the specific language governing permissions and
1111
limitations under the License.
1212
*/
1313

14-
import { GraphQLSchema, InputObjectTypeDefinitionNode } from "graphql";
14+
import {
15+
GraphQLSchema,
16+
InputObjectTypeDefinitionNode,
17+
Kind,
18+
TypeNode,
19+
} from "graphql";
1520
import { shouldIncludeTypeDefinition } from "../helpers/should-include-type-definition";
1621
import { buildTypeMetadata } from "../helpers/build-type-metadata";
1722
import { buildAnnotations } from "../helpers/build-annotations";
@@ -27,9 +32,21 @@ export function buildInputObjectDefinition(
2732
return "";
2833
}
2934

30-
const typeNameWithoutInput = node.name.value.replace("Input", "");
31-
const matchingType = schema.getType(typeNameWithoutInput);
32-
if (matchingType) {
35+
const typeNameWithoutInput = getTypeNameWithoutInput(node.name.value);
36+
const matchingType = schema.getType(typeNameWithoutInput)?.astNode;
37+
const matchingTypeFields =
38+
matchingType?.kind === Kind.OBJECT_TYPE_DEFINITION
39+
? matchingType.fields
40+
: [];
41+
const inputFields = node.fields;
42+
const fieldsMatch = matchingTypeFields?.every((field) => {
43+
const matchingInputField = inputFields?.find(
44+
(inputField) => inputField.name.value === field.name.value,
45+
);
46+
if (!matchingInputField) return false;
47+
return fieldsAreEquivalent(field.type, matchingInputField.type);
48+
});
49+
if (matchingTypeFields?.length && fieldsMatch) {
3350
return "";
3451
}
3552

@@ -60,3 +77,30 @@ export function buildInputObjectDefinition(
6077
${classMembers}
6178
)`;
6279
}
80+
81+
function getTypeNameWithoutInput(name: string) {
82+
return name.endsWith("Input") ? name.replace("Input", "") : name;
83+
}
84+
85+
function fieldsAreEquivalent(
86+
typeField: TypeNode,
87+
inputField: TypeNode,
88+
): boolean {
89+
switch (typeField.kind) {
90+
case Kind.NAMED_TYPE:
91+
return (
92+
inputField.kind === Kind.NAMED_TYPE &&
93+
typeField.name.value === getTypeNameWithoutInput(inputField.name.value)
94+
);
95+
case Kind.LIST_TYPE:
96+
return (
97+
inputField.kind === Kind.LIST_TYPE &&
98+
fieldsAreEquivalent(typeField.type, inputField.type)
99+
);
100+
case Kind.NON_NULL_TYPE:
101+
return (
102+
inputField.kind === Kind.NON_NULL_TYPE &&
103+
fieldsAreEquivalent(typeField.type, inputField.type)
104+
);
105+
}
106+
}

src/definitions/object.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,6 @@ export function buildObjectTypeDefinition(
3434
return "";
3535
}
3636

37-
const typeNameWithInput = `${node.name.value}Input`;
38-
const matchingInput = schema.getType(typeNameWithInput);
39-
const typeConsolidationAnnotation = matchingInput
40-
? "@GraphQLValidObjectLocations(locations = [GraphQLValidObjectLocations.Locations.INPUT_OBJECT, GraphQLValidObjectLocations.Locations.OBJECT])\n"
41-
: "";
42-
4337
const annotations = buildAnnotations({
4438
config,
4539
definitionNode: node,
@@ -63,7 +57,7 @@ ${getDataClassMembers({ node, schema, config, completableFuture: true })}
6357
}`;
6458
}
6559

66-
return `${annotations}${typeConsolidationAnnotation}data class ${name}(
60+
return `${annotations}data class ${name}(
6761
${getDataClassMembers({ node, schema, config })}
6862
)${interfaceInheritance}`;
6963
}

test/unit/should_consolidate_input_and_output_types/expected.kt

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,25 @@ package com.kotlin.generated
22

33
import com.expediagroup.graphql.generator.annotations.*
44

5-
@GraphQLValidObjectLocations(locations = [GraphQLValidObjectLocations.Locations.INPUT_OBJECT, GraphQLValidObjectLocations.Locations.OBJECT])
65
data class MyTypeToConsolidate(
6+
val field: List<String>? = null,
7+
val field2: NestedTypeToConsolidate? = null
8+
)
9+
10+
data class NestedTypeToConsolidate(
711
val field: String? = null
812
)
913

1014
@GraphQLDescription("A description for MyTypeToConsolidate2")
11-
@GraphQLValidObjectLocations(locations = [GraphQLValidObjectLocations.Locations.INPUT_OBJECT, GraphQLValidObjectLocations.Locations.OBJECT])
1215
data class MyTypeToConsolidate2(
1316
val field: String? = null
1417
)
1518

16-
@GraphQLValidObjectLocations(locations = [GraphQLValidObjectLocations.Locations.INPUT_OBJECT, GraphQLValidObjectLocations.Locations.OBJECT])
1719
data class MyTypeToConsolidate3(
1820
val field: String? = null
1921
)
2022

2123
@GraphQLDescription("It always uses the type description when consolidating")
22-
@GraphQLValidObjectLocations(locations = [GraphQLValidObjectLocations.Locations.INPUT_OBJECT, GraphQLValidObjectLocations.Locations.OBJECT])
2324
data class MyTypeToConsolidate4(
2425
val field: String? = null
2526
)
@@ -32,3 +33,21 @@ data class MyTypeNotToConsolidate(
3233
data class MyTypeToNotConsolidateInput(
3334
val field: String? = null
3435
)
36+
37+
data class MyTypeToNotConsolidate2(
38+
val field: String? = null
39+
)
40+
41+
data class MyTypeInputToNotConsolidate2(
42+
val field: String? = null
43+
)
44+
45+
data class MyTypeWhereFieldsDoNotMatch(
46+
val field: String? = null,
47+
val field2: String? = null
48+
)
49+
50+
data class MyTypeWhereFieldsDoNotMatchInput(
51+
val field: String? = null,
52+
val field2: Int? = null
53+
)

test/unit/should_consolidate_input_and_output_types/schema.graphql

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
# typical case where input and output types are consolidated
22

33
type MyTypeToConsolidate {
4-
field: String
4+
field: [String!]
5+
field2: NestedTypeToConsolidate
56
}
67

78
input MyTypeToConsolidateInput {
9+
field: [String!]
10+
field2: NestedTypeToConsolidateInput
11+
}
12+
13+
type NestedTypeToConsolidate {
14+
field: String
15+
}
16+
17+
input NestedTypeToConsolidateInput {
818
field: String
919
}
1020

@@ -52,3 +62,25 @@ type MyTypeNotToConsolidate {
5262
input MyTypeToNotConsolidateInput {
5363
field: String
5464
}
65+
66+
# case where type has input in the middle of the name
67+
68+
type MyTypeToNotConsolidate2 {
69+
field: String
70+
}
71+
72+
input MyTypeInputToNotConsolidate2 {
73+
field: String
74+
}
75+
76+
# case where type and input names match but fields do not match
77+
78+
type MyTypeWhereFieldsDoNotMatch {
79+
field: String
80+
field2: String
81+
}
82+
83+
input MyTypeWhereFieldsDoNotMatchInput {
84+
field: String
85+
field2: Int
86+
}

0 commit comments

Comments
 (0)