Skip to content

Commit 5b61d94

Browse files
gh-action-runnergh-action-runner
authored andcommitted
Squashed 'apollo-ios-codegen/' changes from 25c79d7d..b535b1db
b535b1db Provide sensible defaults for required mock fields (#669) 85b45236 Update apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/DefaultMockValueProviding.swift 89118cab Wrap default enum values in .case() 860f02c9 Fix default enum name (match generated not json values) e85c3520 Remove unnecessary comma c39b9b93 Feedback round 1 47fc9106 Update custom scalar default value d6a562fa Modify behavior to provide sensible default values aba9fd96 Add flag to require non-optional mock fields git-subtree-dir: apollo-ios-codegen git-subtree-split: b535b1dbcf9b3e4748652d32ad3a4a8cdb5d82eb
1 parent 43334e1 commit 5b61d94

File tree

3 files changed

+105
-16
lines changed

3 files changed

+105
-16
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import GraphQLCompiler
2+
3+
protocol DefaultMockValueProviding {
4+
func defaultMockValue(config: ApolloCodegen.ConfigurationContext) -> String
5+
}
6+
7+
extension GraphQLType {
8+
func defaultMockValue(config: ApolloCodegen.ConfigurationContext) -> String {
9+
switch self {
10+
case .list:
11+
return "[]"
12+
case let .nonNull(innerType):
13+
return innerType.defaultMockValue(config: config)
14+
case let .entity(compositeType):
15+
guard let defaultMockingType = compositeType as? any DefaultMockValueProviding else {
16+
fatalError("Composite type does not provide a default mock object")
17+
}
18+
return defaultMockingType.defaultMockValue(config: config)
19+
case let .scalar(scalarType):
20+
return scalarType.defaultMockValue(config: config)
21+
case let .`enum`(enumType):
22+
return enumType.defaultMockValue(config: config)
23+
case .inputObject:
24+
fatalError("InputObjects aren't mocked")
25+
}
26+
}
27+
}
28+
29+
extension GraphQLScalarType: DefaultMockValueProviding {
30+
func defaultMockValue(config: ApolloCodegen.ConfigurationContext) -> String {
31+
switch name.schemaName {
32+
case "String", "ID":
33+
return "\"\""
34+
case "Int":
35+
return "0"
36+
case "Float":
37+
return "0.0"
38+
case "Boolean":
39+
return "false"
40+
default:
41+
return "try! .init(_jsonValue: \"\")"
42+
}
43+
}
44+
}
45+
46+
extension GraphQLEnumType: DefaultMockValueProviding {
47+
func defaultMockValue(config: ApolloCodegen.ConfigurationContext) -> String {
48+
guard let first = values.first else {
49+
fatalError("Cannot provide a default value for caseless enum \(name)")
50+
}
51+
return ".case(.\(first.render(as: .enumCase, config: config)))"
52+
}
53+
}
54+
55+
extension GraphQLObjectType: DefaultMockValueProviding {
56+
func defaultMockValue(config: ApolloCodegen.ConfigurationContext) -> String {
57+
return "Mock<\(name)>()"
58+
}
59+
}
60+
61+
extension GraphQLInterfaceType: DefaultMockValueProviding {
62+
func defaultMockValue(config: ApolloCodegen.ConfigurationContext) -> String {
63+
guard let implementingObject = implementingObjects.first else {
64+
fatalError("Cannot provide a default value for interface \(name) because no types conform to it.")
65+
}
66+
return "Mock<\(implementingObject.name)>()"
67+
}
68+
}
69+
70+
extension GraphQLUnionType: DefaultMockValueProviding {
71+
func defaultMockValue(config: ApolloCodegen.ConfigurationContext) -> String {
72+
guard let implementingType = types.first else {
73+
fatalError("Cannot provide a default value for empty union \(name)")
74+
}
75+
return "Mock<\(implementingType.name)>()"
76+
}
77+
}

Sources/ApolloCodegenLib/Templates/MockObjectTemplate.swift

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,23 @@ struct MockObjectTemplate: TemplateRenderer {
1515

1616
let target: TemplateTarget = .testMockFile
1717

18-
typealias TemplateField = (
19-
responseKey: String,
20-
propertyName: String,
21-
initializerParameterName: String?,
22-
type: GraphQLType,
23-
mockType: String,
24-
deprecationReason: String?
25-
)
18+
struct TemplateField {
19+
let responseKey: String
20+
let propertyName: String
21+
let initializerParameterName: String?
22+
let type: GraphQLType
23+
let mockType: String
24+
let deprecationReason: String?
25+
let config: ApolloCodegen.ConfigurationContext
26+
27+
func defaultInitializer(config: ApolloCodegen.ConfigurationContext) -> String? {
28+
if type.isNullable {
29+
return " = nil"
30+
} else {
31+
return " = \(type.defaultMockValue(config: config))"
32+
}
33+
}
34+
}
2635

2736
func renderBodyTemplate(
2837
nonFatalErrorRecorder: ApolloCodegen.NonFatalError.Recorder
@@ -31,13 +40,14 @@ struct MockObjectTemplate: TemplateRenderer {
3140
let fields: [TemplateField] = fields
3241
.sorted { $0.0 < $1.0 }
3342
.map {
34-
(
43+
TemplateField(
3544
responseKey: $0.0,
3645
propertyName: $0.0.asTestMockFieldPropertyName,
3746
initializerParameterName: $0.0.asTestMockInitializerParameterName,
3847
type: $0.1,
3948
mockType: mockTypeName(for: $0.1),
40-
deprecationReason: $0.deprecationReason
49+
deprecationReason: $0.deprecationReason,
50+
config: config
4151
)
4252
}
4353

@@ -66,7 +76,7 @@ struct MockObjectTemplate: TemplateRenderer {
6676
\(conflictingFieldNameProperties(fields))
6777
convenience init(
6878
\(fields.map { """
69-
\($0.propertyName)\(ifLet: $0.initializerParameterName, {" \($0)"}): \($0.mockType)? = nil
79+
\($0.propertyName)\(ifLet: $0.initializerParameterName, {" \($0)"}): \($0.mockType)\(ifLet: $0.defaultInitializer(config: config), { "\($0)" })
7080
""" }, separator: ",\n")
7181
) {
7282
self.init()
@@ -134,15 +144,18 @@ struct MockObjectTemplate: TemplateRenderer {
134144
case .scalar,
135145
.enum,
136146
.inputObject:
137-
return type.rendered(as: .testMockField(forceNonNull: true), config: config.config)
147+
return TemplateString(
148+
"\(type.rendered(as: .testMockField(forceNonNull: true),config: config.config))\(if: !forceNonNull, "?")"
149+
).description
138150
case .nonNull(let graphQLType):
139151
return nameReplacement(for: graphQLType, forceNonNull: true)
140152
case .list(let graphQLType):
141-
return "[\(nameReplacement(for: graphQLType, forceNonNull: false))]"
153+
return TemplateString(
154+
"[\(nameReplacement(for: graphQLType, forceNonNull: false))]\(if: !forceNonNull, "?")"
155+
).description
142156
}
143157
}
144158

145-
return nameReplacement(for: type, forceNonNull: true)
159+
return nameReplacement(for: type, forceNonNull: false)
146160
}
147-
148161
}

Sources/GraphQLCompiler/GraphQLSchema.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ public class GraphQLNamedType:
6565
}
6666

6767
public final class GraphQLScalarType: GraphQLNamedType {
68-
6968
public let specifiedByURL: String?
7069

7170
public var isCustomScalar: Bool {

0 commit comments

Comments
 (0)