diff --git a/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/LocalCacheMutations/AllAnimalsLocalCacheMutation.graphql.swift b/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/LocalCacheMutations/AllAnimalsLocalCacheMutation.graphql.swift index 7647d2047..c6b233e5f 100644 --- a/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/LocalCacheMutations/AllAnimalsLocalCacheMutation.graphql.swift +++ b/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/LocalCacheMutations/AllAnimalsLocalCacheMutation.graphql.swift @@ -60,10 +60,7 @@ public class AllAnimalsLocalCacheMutation: LocalCacheMutation { set { __data["skinCovering"] = newValue } } - public var asBird: AsBird? { - get { _asInlineFragment() } - set { if let newData = newValue?.__data._data { __data._data = newData }} - } + public var asBird: AsBird? { _asInlineFragment() } public init( __typename: String, diff --git a/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/Operations/Queries/FindPetQuery.graphql.swift b/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/Operations/Queries/FindPetQuery.graphql.swift new file mode 100644 index 000000000..d93ffd47c --- /dev/null +++ b/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/Operations/Queries/FindPetQuery.graphql.swift @@ -0,0 +1,81 @@ +// @generated +// This file was automatically generated and should not be edited. + +@_exported import ApolloAPI + +public class FindPetQuery: GraphQLQuery { + public static let operationName: String = "FindPet" + public static let operationDocument: ApolloAPI.OperationDocument = .init( + definition: .init( + #"query FindPet($input: PetSearchInput!) { findPet(input: $input) { __typename id humanName } }"# + )) + + public var input: PetSearchInput + + public init(input: PetSearchInput) { + self.input = input + } + + public var __variables: Variables? { ["input": input] } + + public struct Data: AnimalKingdomAPI.SelectionSet { + public let __data: DataDict + public init(_dataDict: DataDict) { __data = _dataDict } + + public static var __parentType: any ApolloAPI.ParentType { AnimalKingdomAPI.Objects.Query } + public static var __selections: [ApolloAPI.Selection] { [ + .field("findPet", [FindPet].self, arguments: ["input": .variable("input")]), + ] } + + public var findPet: [FindPet] { __data["findPet"] } + + public init( + findPet: [FindPet] + ) { + self.init(_dataDict: DataDict( + data: [ + "__typename": AnimalKingdomAPI.Objects.Query.typename, + "findPet": findPet._fieldData, + ], + fulfilledFragments: [ + ObjectIdentifier(FindPetQuery.Data.self) + ] + )) + } + + /// FindPet + /// + /// Parent Type: `Pet` + public struct FindPet: AnimalKingdomAPI.SelectionSet { + public let __data: DataDict + public init(_dataDict: DataDict) { __data = _dataDict } + + public static var __parentType: any ApolloAPI.ParentType { AnimalKingdomAPI.Interfaces.Pet } + public static var __selections: [ApolloAPI.Selection] { [ + .field("__typename", String.self), + .field("id", AnimalKingdomAPI.ID.self), + .field("humanName", String?.self), + ] } + + public var id: AnimalKingdomAPI.ID { __data["id"] } + public var humanName: String? { __data["humanName"] } + + public init( + __typename: String, + id: AnimalKingdomAPI.ID, + humanName: String? = nil + ) { + self.init(_dataDict: DataDict( + data: [ + "__typename": __typename, + "id": id, + "humanName": humanName, + ], + fulfilledFragments: [ + ObjectIdentifier(FindPetQuery.Data.FindPet.self) + ] + )) + } + } + } +} diff --git a/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/Schema/InputObjects/PetSearchInput.graphql.swift b/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/Schema/InputObjects/PetSearchInput.graphql.swift new file mode 100644 index 000000000..a45811b72 --- /dev/null +++ b/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/Schema/InputObjects/PetSearchInput.graphql.swift @@ -0,0 +1,21 @@ +// @generated +// This file was automatically generated and should not be edited. + +import ApolloAPI + +public enum PetSearchInput: OneOfInputObject { + case ownerID(ID) + case petID(ID) + case searchFilters(PetSearchFilters) + + public var __data: InputDict { + switch self { + case .ownerID(let value): + return InputDict(["ownerID": value]) + case .petID(let value): + return InputDict(["petID": value]) + case .searchFilters(let value): + return InputDict(["searchFilters": value]) + } + } +} \ No newline at end of file diff --git a/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/Schema/SchemaMetadata.graphql.swift b/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/Schema/SchemaMetadata.graphql.swift index ef715bed9..40aaec02a 100644 --- a/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/Schema/SchemaMetadata.graphql.swift +++ b/Sources/AnimalKingdomAPI/AnimalKingdomAPI/Sources/Schema/SchemaMetadata.graphql.swift @@ -20,17 +20,17 @@ public enum SchemaMetadata: ApolloAPI.SchemaMetadata { public static func objectType(forTypename typename: String) -> ApolloAPI.Object? { switch typename { - case "Query": return AnimalKingdomAPI.Objects.Query - case "Human": return AnimalKingdomAPI.Objects.Human + case "Bird": return AnimalKingdomAPI.Objects.Bird case "Cat": return AnimalKingdomAPI.Objects.Cat + case "Crocodile": return AnimalKingdomAPI.Objects.Crocodile case "Dog": return AnimalKingdomAPI.Objects.Dog - case "Bird": return AnimalKingdomAPI.Objects.Bird case "Fish": return AnimalKingdomAPI.Objects.Fish - case "Rat": return AnimalKingdomAPI.Objects.Rat - case "PetRock": return AnimalKingdomAPI.Objects.PetRock - case "Crocodile": return AnimalKingdomAPI.Objects.Crocodile case "Height": return AnimalKingdomAPI.Objects.Height + case "Human": return AnimalKingdomAPI.Objects.Human case "Mutation": return AnimalKingdomAPI.Objects.Mutation + case "PetRock": return AnimalKingdomAPI.Objects.PetRock + case "Query": return AnimalKingdomAPI.Objects.Query + case "Rat": return AnimalKingdomAPI.Objects.Rat default: return nil } } diff --git a/Sources/AnimalKingdomAPI/AnimalKingdomAPI/TestMocks/MockObject+Interfaces.graphql.swift b/Sources/AnimalKingdomAPI/AnimalKingdomAPI/TestMocks/MockObject+Interfaces.graphql.swift index 069d9f380..0fcfc230e 100644 --- a/Sources/AnimalKingdomAPI/AnimalKingdomAPI/TestMocks/MockObject+Interfaces.graphql.swift +++ b/Sources/AnimalKingdomAPI/AnimalKingdomAPI/TestMocks/MockObject+Interfaces.graphql.swift @@ -6,7 +6,7 @@ import AnimalKingdomAPI public extension MockObject { typealias Animal = Interface - typealias WarmBlooded = Interface - typealias Pet = Interface typealias HousePet = Interface + typealias Pet = Interface + typealias WarmBlooded = Interface } diff --git a/Sources/AnimalKingdomAPI/AnimalKingdomAPI/TestMocks/Query+Mock.graphql.swift b/Sources/AnimalKingdomAPI/AnimalKingdomAPI/TestMocks/Query+Mock.graphql.swift index f7f267b0f..8405fbed7 100644 --- a/Sources/AnimalKingdomAPI/AnimalKingdomAPI/TestMocks/Query+Mock.graphql.swift +++ b/Sources/AnimalKingdomAPI/AnimalKingdomAPI/TestMocks/Query+Mock.graphql.swift @@ -12,6 +12,7 @@ public class Query: MockObject { public struct MockFields { @Field<[Animal]>("allAnimals") public var allAnimals @Field<[ClassroomPet?]>("classroomPets") public var classroomPets + @Field<[Pet]>("findPet") public var findPet @Field<[Pet]>("pets") public var pets } } @@ -20,11 +21,13 @@ public extension Mock where O == Query { convenience init( allAnimals: [(any AnyMock)]? = nil, classroomPets: [(any AnyMock)?]? = nil, + findPet: [(any AnyMock)]? = nil, pets: [(any AnyMock)]? = nil ) { self.init() _setList(allAnimals, for: \.allAnimals) _setList(classroomPets, for: \.classroomPets) + _setList(findPet, for: \.findPet) _setList(pets, for: \.pets) } } diff --git a/Sources/AnimalKingdomAPI/animalkingdom-graphql/AnimalSchema.graphqls b/Sources/AnimalKingdomAPI/animalkingdom-graphql/AnimalSchema.graphqls index c83dfa75f..4e67e5228 100644 --- a/Sources/AnimalKingdomAPI/animalkingdom-graphql/AnimalSchema.graphqls +++ b/Sources/AnimalKingdomAPI/animalkingdom-graphql/AnimalSchema.graphqls @@ -2,6 +2,7 @@ type Query { allAnimals: [Animal!]! classroomPets: [ClassroomPet] pets(filters: PetSearchFilters!): [Pet!]! + findPet(input: PetSearchInput!): [Pet!]! } type Mutation { @@ -12,6 +13,12 @@ scalar CustomDate scalar Object +input PetSearchInput @oneOf { + ownerID: ID + petID: ID + searchFilters: PetSearchFilters +} + input PetAdoptionInput { ownerID: ID! petID: ID! diff --git a/Sources/AnimalKingdomAPI/animalkingdom-graphql/FindPetQuery.graphql b/Sources/AnimalKingdomAPI/animalkingdom-graphql/FindPetQuery.graphql new file mode 100644 index 000000000..4bbf27ce7 --- /dev/null +++ b/Sources/AnimalKingdomAPI/animalkingdom-graphql/FindPetQuery.graphql @@ -0,0 +1,7 @@ +query FindPet($input: PetSearchInput!) { + findPet(input: $input) { + id + humanName + } +} + diff --git a/Sources/GitHubAPI/GitHubAPI/Sources/Schema/SchemaMetadata.graphql.swift b/Sources/GitHubAPI/GitHubAPI/Sources/Schema/SchemaMetadata.graphql.swift index b120de54c..476001c29 100644 --- a/Sources/GitHubAPI/GitHubAPI/Sources/Schema/SchemaMetadata.graphql.swift +++ b/Sources/GitHubAPI/GitHubAPI/Sources/Schema/SchemaMetadata.graphql.swift @@ -20,8 +20,6 @@ public enum SchemaMetadata: ApolloAPI.SchemaMetadata { public static func objectType(forTypename typename: String) -> ApolloAPI.Object? { switch typename { - case "Query": return GitHubAPI.Objects.Query - case "Repository": return GitHubAPI.Objects.Repository case "AddedToProjectEvent": return GitHubAPI.Objects.AddedToProjectEvent case "App": return GitHubAPI.Objects.App case "AssignedEvent": return GitHubAPI.Objects.AssignedEvent @@ -30,47 +28,20 @@ public enum SchemaMetadata: ApolloAPI.SchemaMetadata { case "BaseRefChangedEvent": return GitHubAPI.Objects.BaseRefChangedEvent case "BaseRefForcePushedEvent": return GitHubAPI.Objects.BaseRefForcePushedEvent case "Blob": return GitHubAPI.Objects.Blob - case "Commit": return GitHubAPI.Objects.Commit - case "Issue": return GitHubAPI.Objects.Issue - case "PullRequest": return GitHubAPI.Objects.PullRequest - case "Milestone": return GitHubAPI.Objects.Milestone case "Bot": return GitHubAPI.Objects.Bot - case "EnterpriseUserAccount": return GitHubAPI.Objects.EnterpriseUserAccount - case "Mannequin": return GitHubAPI.Objects.Mannequin - case "Organization": return GitHubAPI.Objects.Organization - case "Team": return GitHubAPI.Objects.Team - case "User": return GitHubAPI.Objects.User - case "CheckRun": return GitHubAPI.Objects.CheckRun - case "ClosedEvent": return GitHubAPI.Objects.ClosedEvent - case "ConvertToDraftEvent": return GitHubAPI.Objects.ConvertToDraftEvent - case "CrossReferencedEvent": return GitHubAPI.Objects.CrossReferencedEvent - case "Gist": return GitHubAPI.Objects.Gist - case "Topic": return GitHubAPI.Objects.Topic - case "MergedEvent": return GitHubAPI.Objects.MergedEvent - case "PullRequestCommit": return GitHubAPI.Objects.PullRequestCommit - case "ReadyForReviewEvent": return GitHubAPI.Objects.ReadyForReviewEvent - case "Release": return GitHubAPI.Objects.Release - case "RepositoryTopic": return GitHubAPI.Objects.RepositoryTopic - case "ReviewDismissedEvent": return GitHubAPI.Objects.ReviewDismissedEvent - case "TeamDiscussion": return GitHubAPI.Objects.TeamDiscussion - case "CommitComment": return GitHubAPI.Objects.CommitComment - case "GistComment": return GitHubAPI.Objects.GistComment - case "IssueComment": return GitHubAPI.Objects.IssueComment - case "PullRequestReview": return GitHubAPI.Objects.PullRequestReview - case "CommitCommentThread": return GitHubAPI.Objects.CommitCommentThread - case "PullRequestCommitCommentThread": return GitHubAPI.Objects.PullRequestCommitCommentThread - case "PullRequestReviewComment": return GitHubAPI.Objects.PullRequestReviewComment - case "Project": return GitHubAPI.Objects.Project - case "TeamDiscussionComment": return GitHubAPI.Objects.TeamDiscussionComment - case "RepositoryVulnerabilityAlert": return GitHubAPI.Objects.RepositoryVulnerabilityAlert - case "Tag": return GitHubAPI.Objects.Tag - case "Tree": return GitHubAPI.Objects.Tree case "BranchProtectionRule": return GitHubAPI.Objects.BranchProtectionRule + case "CheckRun": return GitHubAPI.Objects.CheckRun case "CheckSuite": return GitHubAPI.Objects.CheckSuite + case "ClosedEvent": return GitHubAPI.Objects.ClosedEvent case "CodeOfConduct": return GitHubAPI.Objects.CodeOfConduct case "CommentDeletedEvent": return GitHubAPI.Objects.CommentDeletedEvent + case "Commit": return GitHubAPI.Objects.Commit + case "CommitComment": return GitHubAPI.Objects.CommitComment + case "CommitCommentThread": return GitHubAPI.Objects.CommitCommentThread case "ConnectedEvent": return GitHubAPI.Objects.ConnectedEvent + case "ConvertToDraftEvent": return GitHubAPI.Objects.ConvertToDraftEvent case "ConvertedNoteToIssueEvent": return GitHubAPI.Objects.ConvertedNoteToIssueEvent + case "CrossReferencedEvent": return GitHubAPI.Objects.CrossReferencedEvent case "DemilestonedEvent": return GitHubAPI.Objects.DemilestonedEvent case "DependencyGraphManifest": return GitHubAPI.Objects.DependencyGraphManifest case "DeployKey": return GitHubAPI.Objects.DeployKey @@ -87,26 +58,36 @@ public enum SchemaMetadata: ApolloAPI.SchemaMetadata { case "EnterpriseServerUserAccount": return GitHubAPI.Objects.EnterpriseServerUserAccount case "EnterpriseServerUserAccountEmail": return GitHubAPI.Objects.EnterpriseServerUserAccountEmail case "EnterpriseServerUserAccountsUpload": return GitHubAPI.Objects.EnterpriseServerUserAccountsUpload + case "EnterpriseUserAccount": return GitHubAPI.Objects.EnterpriseUserAccount case "ExternalIdentity": return GitHubAPI.Objects.ExternalIdentity + case "Gist": return GitHubAPI.Objects.Gist + case "GistComment": return GitHubAPI.Objects.GistComment case "HeadRefDeletedEvent": return GitHubAPI.Objects.HeadRefDeletedEvent case "HeadRefForcePushedEvent": return GitHubAPI.Objects.HeadRefForcePushedEvent case "HeadRefRestoredEvent": return GitHubAPI.Objects.HeadRefRestoredEvent case "IpAllowListEntry": return GitHubAPI.Objects.IpAllowListEntry + case "Issue": return GitHubAPI.Objects.Issue + case "IssueComment": return GitHubAPI.Objects.IssueComment + case "IssueCommentConnection": return GitHubAPI.Objects.IssueCommentConnection + case "IssueConnection": return GitHubAPI.Objects.IssueConnection case "Label": return GitHubAPI.Objects.Label case "LabeledEvent": return GitHubAPI.Objects.LabeledEvent case "Language": return GitHubAPI.Objects.Language case "License": return GitHubAPI.Objects.License case "LockedEvent": return GitHubAPI.Objects.LockedEvent + case "Mannequin": return GitHubAPI.Objects.Mannequin case "MarkedAsDuplicateEvent": return GitHubAPI.Objects.MarkedAsDuplicateEvent case "MarketplaceCategory": return GitHubAPI.Objects.MarketplaceCategory case "MarketplaceListing": return GitHubAPI.Objects.MarketplaceListing case "MembersCanDeleteReposClearAuditEntry": return GitHubAPI.Objects.MembersCanDeleteReposClearAuditEntry case "MembersCanDeleteReposDisableAuditEntry": return GitHubAPI.Objects.MembersCanDeleteReposDisableAuditEntry case "MembersCanDeleteReposEnableAuditEntry": return GitHubAPI.Objects.MembersCanDeleteReposEnableAuditEntry + case "MentionedEvent": return GitHubAPI.Objects.MentionedEvent + case "MergedEvent": return GitHubAPI.Objects.MergedEvent + case "Milestone": return GitHubAPI.Objects.Milestone + case "MilestonedEvent": return GitHubAPI.Objects.MilestonedEvent + case "MovedColumnsInProjectEvent": return GitHubAPI.Objects.MovedColumnsInProjectEvent case "OauthApplicationCreateAuditEntry": return GitHubAPI.Objects.OauthApplicationCreateAuditEntry - case "OrgOauthAppAccessApprovedAuditEntry": return GitHubAPI.Objects.OrgOauthAppAccessApprovedAuditEntry - case "OrgOauthAppAccessDeniedAuditEntry": return GitHubAPI.Objects.OrgOauthAppAccessDeniedAuditEntry - case "OrgOauthAppAccessRequestedAuditEntry": return GitHubAPI.Objects.OrgOauthAppAccessRequestedAuditEntry case "OrgAddBillingManagerAuditEntry": return GitHubAPI.Objects.OrgAddBillingManagerAuditEntry case "OrgAddMemberAuditEntry": return GitHubAPI.Objects.OrgAddMemberAuditEntry case "OrgBlockUserAuditEntry": return GitHubAPI.Objects.OrgBlockUserAuditEntry @@ -121,49 +102,22 @@ public enum SchemaMetadata: ApolloAPI.SchemaMetadata { case "OrgEnableTwoFactorRequirementAuditEntry": return GitHubAPI.Objects.OrgEnableTwoFactorRequirementAuditEntry case "OrgInviteMemberAuditEntry": return GitHubAPI.Objects.OrgInviteMemberAuditEntry case "OrgInviteToBusinessAuditEntry": return GitHubAPI.Objects.OrgInviteToBusinessAuditEntry + case "OrgOauthAppAccessApprovedAuditEntry": return GitHubAPI.Objects.OrgOauthAppAccessApprovedAuditEntry + case "OrgOauthAppAccessDeniedAuditEntry": return GitHubAPI.Objects.OrgOauthAppAccessDeniedAuditEntry + case "OrgOauthAppAccessRequestedAuditEntry": return GitHubAPI.Objects.OrgOauthAppAccessRequestedAuditEntry case "OrgRemoveBillingManagerAuditEntry": return GitHubAPI.Objects.OrgRemoveBillingManagerAuditEntry case "OrgRemoveMemberAuditEntry": return GitHubAPI.Objects.OrgRemoveMemberAuditEntry case "OrgRemoveOutsideCollaboratorAuditEntry": return GitHubAPI.Objects.OrgRemoveOutsideCollaboratorAuditEntry case "OrgRestoreMemberAuditEntry": return GitHubAPI.Objects.OrgRestoreMemberAuditEntry case "OrgRestoreMemberMembershipOrganizationAuditEntryData": return GitHubAPI.Objects.OrgRestoreMemberMembershipOrganizationAuditEntryData + case "OrgRestoreMemberMembershipRepositoryAuditEntryData": return GitHubAPI.Objects.OrgRestoreMemberMembershipRepositoryAuditEntryData + case "OrgRestoreMemberMembershipTeamAuditEntryData": return GitHubAPI.Objects.OrgRestoreMemberMembershipTeamAuditEntryData case "OrgUnblockUserAuditEntry": return GitHubAPI.Objects.OrgUnblockUserAuditEntry case "OrgUpdateDefaultRepositoryPermissionAuditEntry": return GitHubAPI.Objects.OrgUpdateDefaultRepositoryPermissionAuditEntry case "OrgUpdateMemberAuditEntry": return GitHubAPI.Objects.OrgUpdateMemberAuditEntry case "OrgUpdateMemberRepositoryCreationPermissionAuditEntry": return GitHubAPI.Objects.OrgUpdateMemberRepositoryCreationPermissionAuditEntry case "OrgUpdateMemberRepositoryInvitationPermissionAuditEntry": return GitHubAPI.Objects.OrgUpdateMemberRepositoryInvitationPermissionAuditEntry - case "PrivateRepositoryForkingDisableAuditEntry": return GitHubAPI.Objects.PrivateRepositoryForkingDisableAuditEntry - case "OrgRestoreMemberMembershipRepositoryAuditEntryData": return GitHubAPI.Objects.OrgRestoreMemberMembershipRepositoryAuditEntryData - case "PrivateRepositoryForkingEnableAuditEntry": return GitHubAPI.Objects.PrivateRepositoryForkingEnableAuditEntry - case "RepoAccessAuditEntry": return GitHubAPI.Objects.RepoAccessAuditEntry - case "RepoAddMemberAuditEntry": return GitHubAPI.Objects.RepoAddMemberAuditEntry - case "RepoAddTopicAuditEntry": return GitHubAPI.Objects.RepoAddTopicAuditEntry - case "RepoRemoveTopicAuditEntry": return GitHubAPI.Objects.RepoRemoveTopicAuditEntry - case "RepoArchivedAuditEntry": return GitHubAPI.Objects.RepoArchivedAuditEntry - case "RepoChangeMergeSettingAuditEntry": return GitHubAPI.Objects.RepoChangeMergeSettingAuditEntry - case "RepoConfigDisableAnonymousGitAccessAuditEntry": return GitHubAPI.Objects.RepoConfigDisableAnonymousGitAccessAuditEntry - case "RepoConfigDisableCollaboratorsOnlyAuditEntry": return GitHubAPI.Objects.RepoConfigDisableCollaboratorsOnlyAuditEntry - case "RepoConfigDisableContributorsOnlyAuditEntry": return GitHubAPI.Objects.RepoConfigDisableContributorsOnlyAuditEntry - case "RepoConfigDisableSockpuppetDisallowedAuditEntry": return GitHubAPI.Objects.RepoConfigDisableSockpuppetDisallowedAuditEntry - case "RepoConfigEnableAnonymousGitAccessAuditEntry": return GitHubAPI.Objects.RepoConfigEnableAnonymousGitAccessAuditEntry - case "RepoConfigEnableCollaboratorsOnlyAuditEntry": return GitHubAPI.Objects.RepoConfigEnableCollaboratorsOnlyAuditEntry - case "RepoConfigEnableContributorsOnlyAuditEntry": return GitHubAPI.Objects.RepoConfigEnableContributorsOnlyAuditEntry - case "RepoConfigEnableSockpuppetDisallowedAuditEntry": return GitHubAPI.Objects.RepoConfigEnableSockpuppetDisallowedAuditEntry - case "RepoConfigLockAnonymousGitAccessAuditEntry": return GitHubAPI.Objects.RepoConfigLockAnonymousGitAccessAuditEntry - case "RepoConfigUnlockAnonymousGitAccessAuditEntry": return GitHubAPI.Objects.RepoConfigUnlockAnonymousGitAccessAuditEntry - case "RepoCreateAuditEntry": return GitHubAPI.Objects.RepoCreateAuditEntry - case "RepoDestroyAuditEntry": return GitHubAPI.Objects.RepoDestroyAuditEntry - case "RepoRemoveMemberAuditEntry": return GitHubAPI.Objects.RepoRemoveMemberAuditEntry - case "TeamAddRepositoryAuditEntry": return GitHubAPI.Objects.TeamAddRepositoryAuditEntry - case "OrgRestoreMemberMembershipTeamAuditEntryData": return GitHubAPI.Objects.OrgRestoreMemberMembershipTeamAuditEntryData - case "TeamAddMemberAuditEntry": return GitHubAPI.Objects.TeamAddMemberAuditEntry - case "TeamChangeParentTeamAuditEntry": return GitHubAPI.Objects.TeamChangeParentTeamAuditEntry - case "TeamRemoveMemberAuditEntry": return GitHubAPI.Objects.TeamRemoveMemberAuditEntry - case "TeamRemoveRepositoryAuditEntry": return GitHubAPI.Objects.TeamRemoveRepositoryAuditEntry - case "RepositoryVisibilityChangeDisableAuditEntry": return GitHubAPI.Objects.RepositoryVisibilityChangeDisableAuditEntry - case "RepositoryVisibilityChangeEnableAuditEntry": return GitHubAPI.Objects.RepositoryVisibilityChangeEnableAuditEntry - case "MentionedEvent": return GitHubAPI.Objects.MentionedEvent - case "MilestonedEvent": return GitHubAPI.Objects.MilestonedEvent - case "MovedColumnsInProjectEvent": return GitHubAPI.Objects.MovedColumnsInProjectEvent + case "Organization": return GitHubAPI.Objects.Organization case "OrganizationIdentityProvider": return GitHubAPI.Objects.OrganizationIdentityProvider case "OrganizationInvitation": return GitHubAPI.Objects.OrganizationInvitation case "Package": return GitHubAPI.Objects.Package @@ -172,21 +126,57 @@ public enum SchemaMetadata: ApolloAPI.SchemaMetadata { case "PackageVersion": return GitHubAPI.Objects.PackageVersion case "PinnedEvent": return GitHubAPI.Objects.PinnedEvent case "PinnedIssue": return GitHubAPI.Objects.PinnedIssue + case "PrivateRepositoryForkingDisableAuditEntry": return GitHubAPI.Objects.PrivateRepositoryForkingDisableAuditEntry + case "PrivateRepositoryForkingEnableAuditEntry": return GitHubAPI.Objects.PrivateRepositoryForkingEnableAuditEntry + case "Project": return GitHubAPI.Objects.Project case "ProjectCard": return GitHubAPI.Objects.ProjectCard case "ProjectColumn": return GitHubAPI.Objects.ProjectColumn case "PublicKey": return GitHubAPI.Objects.PublicKey + case "PullRequest": return GitHubAPI.Objects.PullRequest + case "PullRequestCommit": return GitHubAPI.Objects.PullRequestCommit + case "PullRequestCommitCommentThread": return GitHubAPI.Objects.PullRequestCommitCommentThread + case "PullRequestReview": return GitHubAPI.Objects.PullRequestReview + case "PullRequestReviewComment": return GitHubAPI.Objects.PullRequestReviewComment case "PullRequestReviewThread": return GitHubAPI.Objects.PullRequestReviewThread case "Push": return GitHubAPI.Objects.Push case "PushAllowance": return GitHubAPI.Objects.PushAllowance + case "Query": return GitHubAPI.Objects.Query case "Reaction": return GitHubAPI.Objects.Reaction + case "ReadyForReviewEvent": return GitHubAPI.Objects.ReadyForReviewEvent case "Ref": return GitHubAPI.Objects.Ref case "ReferencedEvent": return GitHubAPI.Objects.ReferencedEvent + case "Release": return GitHubAPI.Objects.Release case "ReleaseAsset": return GitHubAPI.Objects.ReleaseAsset case "RemovedFromProjectEvent": return GitHubAPI.Objects.RemovedFromProjectEvent case "RenamedTitleEvent": return GitHubAPI.Objects.RenamedTitleEvent case "ReopenedEvent": return GitHubAPI.Objects.ReopenedEvent + case "RepoAccessAuditEntry": return GitHubAPI.Objects.RepoAccessAuditEntry + case "RepoAddMemberAuditEntry": return GitHubAPI.Objects.RepoAddMemberAuditEntry + case "RepoAddTopicAuditEntry": return GitHubAPI.Objects.RepoAddTopicAuditEntry + case "RepoArchivedAuditEntry": return GitHubAPI.Objects.RepoArchivedAuditEntry + case "RepoChangeMergeSettingAuditEntry": return GitHubAPI.Objects.RepoChangeMergeSettingAuditEntry + case "RepoConfigDisableAnonymousGitAccessAuditEntry": return GitHubAPI.Objects.RepoConfigDisableAnonymousGitAccessAuditEntry + case "RepoConfigDisableCollaboratorsOnlyAuditEntry": return GitHubAPI.Objects.RepoConfigDisableCollaboratorsOnlyAuditEntry + case "RepoConfigDisableContributorsOnlyAuditEntry": return GitHubAPI.Objects.RepoConfigDisableContributorsOnlyAuditEntry + case "RepoConfigDisableSockpuppetDisallowedAuditEntry": return GitHubAPI.Objects.RepoConfigDisableSockpuppetDisallowedAuditEntry + case "RepoConfigEnableAnonymousGitAccessAuditEntry": return GitHubAPI.Objects.RepoConfigEnableAnonymousGitAccessAuditEntry + case "RepoConfigEnableCollaboratorsOnlyAuditEntry": return GitHubAPI.Objects.RepoConfigEnableCollaboratorsOnlyAuditEntry + case "RepoConfigEnableContributorsOnlyAuditEntry": return GitHubAPI.Objects.RepoConfigEnableContributorsOnlyAuditEntry + case "RepoConfigEnableSockpuppetDisallowedAuditEntry": return GitHubAPI.Objects.RepoConfigEnableSockpuppetDisallowedAuditEntry + case "RepoConfigLockAnonymousGitAccessAuditEntry": return GitHubAPI.Objects.RepoConfigLockAnonymousGitAccessAuditEntry + case "RepoConfigUnlockAnonymousGitAccessAuditEntry": return GitHubAPI.Objects.RepoConfigUnlockAnonymousGitAccessAuditEntry + case "RepoCreateAuditEntry": return GitHubAPI.Objects.RepoCreateAuditEntry + case "RepoDestroyAuditEntry": return GitHubAPI.Objects.RepoDestroyAuditEntry + case "RepoRemoveMemberAuditEntry": return GitHubAPI.Objects.RepoRemoveMemberAuditEntry + case "RepoRemoveTopicAuditEntry": return GitHubAPI.Objects.RepoRemoveTopicAuditEntry + case "Repository": return GitHubAPI.Objects.Repository case "RepositoryInvitation": return GitHubAPI.Objects.RepositoryInvitation + case "RepositoryTopic": return GitHubAPI.Objects.RepositoryTopic + case "RepositoryVisibilityChangeDisableAuditEntry": return GitHubAPI.Objects.RepositoryVisibilityChangeDisableAuditEntry + case "RepositoryVisibilityChangeEnableAuditEntry": return GitHubAPI.Objects.RepositoryVisibilityChangeEnableAuditEntry + case "RepositoryVulnerabilityAlert": return GitHubAPI.Objects.RepositoryVulnerabilityAlert case "ReviewDismissalAllowance": return GitHubAPI.Objects.ReviewDismissalAllowance + case "ReviewDismissedEvent": return GitHubAPI.Objects.ReviewDismissedEvent case "ReviewRequest": return GitHubAPI.Objects.ReviewRequest case "ReviewRequestRemovedEvent": return GitHubAPI.Objects.ReviewRequestRemovedEvent case "ReviewRequestedEvent": return GitHubAPI.Objects.ReviewRequestedEvent @@ -199,18 +189,28 @@ public enum SchemaMetadata: ApolloAPI.SchemaMetadata { case "StatusCheckRollup": return GitHubAPI.Objects.StatusCheckRollup case "StatusContext": return GitHubAPI.Objects.StatusContext case "SubscribedEvent": return GitHubAPI.Objects.SubscribedEvent + case "Tag": return GitHubAPI.Objects.Tag + case "Team": return GitHubAPI.Objects.Team + case "TeamAddMemberAuditEntry": return GitHubAPI.Objects.TeamAddMemberAuditEntry + case "TeamAddRepositoryAuditEntry": return GitHubAPI.Objects.TeamAddRepositoryAuditEntry + case "TeamChangeParentTeamAuditEntry": return GitHubAPI.Objects.TeamChangeParentTeamAuditEntry + case "TeamDiscussion": return GitHubAPI.Objects.TeamDiscussion + case "TeamDiscussionComment": return GitHubAPI.Objects.TeamDiscussionComment + case "TeamRemoveMemberAuditEntry": return GitHubAPI.Objects.TeamRemoveMemberAuditEntry + case "TeamRemoveRepositoryAuditEntry": return GitHubAPI.Objects.TeamRemoveRepositoryAuditEntry + case "Topic": return GitHubAPI.Objects.Topic case "TransferredEvent": return GitHubAPI.Objects.TransferredEvent + case "Tree": return GitHubAPI.Objects.Tree case "UnassignedEvent": return GitHubAPI.Objects.UnassignedEvent case "UnlabeledEvent": return GitHubAPI.Objects.UnlabeledEvent case "UnlockedEvent": return GitHubAPI.Objects.UnlockedEvent case "UnmarkedAsDuplicateEvent": return GitHubAPI.Objects.UnmarkedAsDuplicateEvent case "UnpinnedEvent": return GitHubAPI.Objects.UnpinnedEvent case "UnsubscribedEvent": return GitHubAPI.Objects.UnsubscribedEvent + case "User": return GitHubAPI.Objects.User case "UserBlockedEvent": return GitHubAPI.Objects.UserBlockedEvent case "UserContentEdit": return GitHubAPI.Objects.UserContentEdit case "UserStatus": return GitHubAPI.Objects.UserStatus - case "IssueConnection": return GitHubAPI.Objects.IssueConnection - case "IssueCommentConnection": return GitHubAPI.Objects.IssueCommentConnection default: return nil } } diff --git a/Sources/StarWarsAPI/StarWarsAPI/Sources/Schema/SchemaMetadata.graphql.swift b/Sources/StarWarsAPI/StarWarsAPI/Sources/Schema/SchemaMetadata.graphql.swift index bbccc342e..ca87f8c17 100644 --- a/Sources/StarWarsAPI/StarWarsAPI/Sources/Schema/SchemaMetadata.graphql.swift +++ b/Sources/StarWarsAPI/StarWarsAPI/Sources/Schema/SchemaMetadata.graphql.swift @@ -20,13 +20,13 @@ public enum SchemaMetadata: ApolloAPI.SchemaMetadata { public static func objectType(forTypename typename: String) -> ApolloAPI.Object? { switch typename { - case "Query": return StarWarsAPI.Objects.Query - case "Human": return StarWarsAPI.Objects.Human case "Droid": return StarWarsAPI.Objects.Droid + case "Human": return StarWarsAPI.Objects.Human + case "Mutation": return StarWarsAPI.Objects.Mutation + case "Query": return StarWarsAPI.Objects.Query + case "Review": return StarWarsAPI.Objects.Review case "Starship": return StarWarsAPI.Objects.Starship case "Subscription": return StarWarsAPI.Objects.Subscription - case "Review": return StarWarsAPI.Objects.Review - case "Mutation": return StarWarsAPI.Objects.Mutation default: return nil } } diff --git a/Sources/UploadAPI/UploadAPI/Sources/Schema/SchemaMetadata.graphql.swift b/Sources/UploadAPI/UploadAPI/Sources/Schema/SchemaMetadata.graphql.swift index 90bbb308e..7c3ed0979 100644 --- a/Sources/UploadAPI/UploadAPI/Sources/Schema/SchemaMetadata.graphql.swift +++ b/Sources/UploadAPI/UploadAPI/Sources/Schema/SchemaMetadata.graphql.swift @@ -20,8 +20,8 @@ public enum SchemaMetadata: ApolloAPI.SchemaMetadata { public static func objectType(forTypename typename: String) -> ApolloAPI.Object? { switch typename { - case "Mutation": return UploadAPI.Objects.Mutation case "File": return UploadAPI.Objects.File + case "Mutation": return UploadAPI.Objects.Mutation default: return nil } } diff --git a/Tests/ApolloCodegenInternalTestHelpers/MockGraphQLType.swift b/Tests/ApolloCodegenInternalTestHelpers/MockGraphQLType.swift index a00059be5..5f893da5c 100644 --- a/Tests/ApolloCodegenInternalTestHelpers/MockGraphQLType.swift +++ b/Tests/ApolloCodegenInternalTestHelpers/MockGraphQLType.swift @@ -138,12 +138,14 @@ public extension GraphQLInputObjectType { _ name: String, fields: [GraphQLInputField] = [], documentation: String? = nil, - config: ApolloCodegenConfiguration = .mock() + config: ApolloCodegenConfiguration = .mock(), + isOneOf: Bool = false ) -> GraphQLInputObjectType { GraphQLInputObjectType( name: GraphQLName(schemaName: name), documentation: documentation, - fields: OrderedDictionary.init(uniqueKeysWithValues: fields.map({ ($0.render(config: config), $0) })) + fields: OrderedDictionary.init(uniqueKeysWithValues: fields.map({ ($0.render(config: config), $0) })), + isOneOf: isOneOf ) } } diff --git a/Tests/ApolloCodegenTests/ApolloCodegenTests.swift b/Tests/ApolloCodegenTests/ApolloCodegenTests.swift index 70ead76df..b2670457f 100644 --- a/Tests/ApolloCodegenTests/ApolloCodegenTests.swift +++ b/Tests/ApolloCodegenTests/ApolloCodegenTests.swift @@ -680,6 +680,7 @@ class ApolloCodegenTests: XCTestCase { directoryURL.appendingPathComponent("Sources/Schema/Unions/ClassroomPet.graphql.swift").path, + directoryURL.appendingPathComponent("Sources/Schema/InputObjects/PetSearchInput.graphql.swift").path, directoryURL.appendingPathComponent("Sources/Schema/InputObjects/PetAdoptionInput.graphql.swift").path, directoryURL.appendingPathComponent("Sources/Schema/InputObjects/PetSearchFilters.graphql.swift").path, directoryURL.appendingPathComponent("Sources/Schema/InputObjects/MeasurementsInput.graphql.swift").path, @@ -705,7 +706,7 @@ class ApolloCodegenTests: XCTestCase { directoryURL.appendingPathComponent("Sources/Operations/Queries/ClassroomPetsQuery.graphql.swift").path, directoryURL.appendingPathComponent("Sources/Operations/Queries/DogQuery.graphql.swift").path, directoryURL.appendingPathComponent("Sources/Operations/Queries/PetSearchQuery.graphql.swift").path, - directoryURL.appendingPathComponent("Sources/Operations/Queries/PetSearchQuery.graphql.swift").path, + directoryURL.appendingPathComponent("Sources/Operations/Queries/FindPetQuery.graphql.swift").path, directoryURL.appendingPathComponent("Sources/Operations/Mutations/PetAdoptionMutation.graphql.swift").path, directoryURL.appendingPathComponent("Sources/Fragments/PetDetails.graphql.swift").path, @@ -794,6 +795,7 @@ class ApolloCodegenTests: XCTestCase { directoryURL.appendingPathComponent("Sources/Unions/ClassroomPet.graphql.swift").path, directoryURL.appendingPathComponent("Sources/InputObjects/PetAdoptionInput.graphql.swift").path, directoryURL.appendingPathComponent("Sources/InputObjects/PetSearchFilters.graphql.swift").path, + directoryURL.appendingPathComponent("Sources/InputObjects/PetSearchInput.graphql.swift").path, directoryURL.appendingPathComponent("Sources/InputObjects/MeasurementsInput.graphql.swift").path, directoryURL.appendingPathComponent("Sources/Objects/Height.graphql.swift").path, directoryURL.appendingPathComponent("Sources/Objects/Query.graphql.swift").path, @@ -815,7 +817,7 @@ class ApolloCodegenTests: XCTestCase { operationsOutputURL.appendingPathComponent("Queries/AllAnimalsIncludeSkipQuery.graphql.swift").path, operationsOutputURL.appendingPathComponent("Queries/ClassroomPetsQuery.graphql.swift").path, operationsOutputURL.appendingPathComponent("Queries/PetSearchQuery.graphql.swift").path, - operationsOutputURL.appendingPathComponent("Queries/PetSearchQuery.graphql.swift").path, + operationsOutputURL.appendingPathComponent("Queries/FindPetQuery.graphql.swift").path, operationsOutputURL.appendingPathComponent("Mutations/PetAdoptionMutation.graphql.swift").path, operationsOutputURL.appendingPathComponent("Fragments/PetDetails.graphql.swift").path, @@ -979,6 +981,7 @@ class ApolloCodegenTests: XCTestCase { directoryURL.appendingPathComponent("RelativePath/Sources/Schema/InputObjects/PetAdoptionInput.graphql.swift").path, directoryURL.appendingPathComponent("RelativePath/Sources/Schema/InputObjects/PetSearchFilters.graphql.swift").path, + directoryURL.appendingPathComponent("RelativePath/Sources/Schema/InputObjects/PetSearchInput.graphql.swift").path, directoryURL.appendingPathComponent("RelativePath/Sources/Schema/InputObjects/MeasurementsInput.graphql.swift").path, directoryURL.appendingPathComponent("RelativePath/Sources/Schema/Objects/Height.graphql.swift").path, @@ -1001,6 +1004,7 @@ class ApolloCodegenTests: XCTestCase { directoryURL.appendingPathComponent("RelativePath/Sources/Operations/Queries/DogQuery.graphql.swift").path, directoryURL.appendingPathComponent("RelativePath/Sources/Operations/Queries/AllAnimalsIncludeSkipQuery.graphql.swift").path, directoryURL.appendingPathComponent("RelativePath/Sources/Operations/Queries/ClassroomPetsQuery.graphql.swift").path, + directoryURL.appendingPathComponent("RelativePath/Sources/Operations/Queries/FindPetQuery.graphql.swift").path, directoryURL.appendingPathComponent("RelativePath/Sources/Operations/Queries/PetSearchQuery.graphql.swift").path, directoryURL.appendingPathComponent("RelativePath/Sources/Operations/Queries/PetSearchQuery.graphql.swift").path, directoryURL.appendingPathComponent("RelativePath/Sources/Operations/Mutations/PetAdoptionMutation.graphql.swift").path, @@ -1092,6 +1096,7 @@ class ApolloCodegenTests: XCTestCase { directoryURL.appendingPathComponent("RelativePath/Sources/InputObjects/PetAdoptionInput.graphql.swift").path, directoryURL.appendingPathComponent("RelativePath/Sources/InputObjects/PetSearchFilters.graphql.swift").path, + directoryURL.appendingPathComponent("RelativePath/Sources/InputObjects/PetSearchInput.graphql.swift").path, directoryURL.appendingPathComponent("RelativePath/Sources/InputObjects/MeasurementsInput.graphql.swift").path, directoryURL.appendingPathComponent("RelativePath/Sources/Objects/Height.graphql.swift").path, @@ -1114,6 +1119,7 @@ class ApolloCodegenTests: XCTestCase { directoryURL.appendingPathComponent("RelativeOperations/Queries/DogQuery.graphql.swift").path, directoryURL.appendingPathComponent("RelativeOperations/Queries/AllAnimalsIncludeSkipQuery.graphql.swift").path, directoryURL.appendingPathComponent("RelativeOperations/Queries/ClassroomPetsQuery.graphql.swift").path, + directoryURL.appendingPathComponent("RelativeOperations/Queries/FindPetQuery.graphql.swift").path, directoryURL.appendingPathComponent("RelativeOperations/Queries/PetSearchQuery.graphql.swift").path, directoryURL.appendingPathComponent("RelativeOperations/Queries/PetSearchQuery.graphql.swift").path, directoryURL.appendingPathComponent("RelativeOperations/Mutations/PetAdoptionMutation.graphql.swift").path, diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/OneOfInputObjectTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/OneOfInputObjectTemplateTests.swift new file mode 100644 index 000000000..5374d0d13 --- /dev/null +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/OneOfInputObjectTemplateTests.swift @@ -0,0 +1,1652 @@ +import XCTest +import Nimble +@testable import ApolloCodegenLib +import Apollo +import GraphQLCompiler + +class OneOfInputObjectTemplateTests: XCTestCase { + var subject: OneOfInputObjectTemplate! + + override func tearDownWithError() throws { + subject = nil + try super.tearDownWithError() + } + + private func buildSubject( + name: String = "MockOneOfInput", + customName: String? = nil, + fields: [GraphQLInputField] = [], + isOneOf: Bool = true, + documentation: String? = nil, + config: ApolloCodegenConfiguration = .mock(.swiftPackageManager) + ) { + let inputObject = GraphQLInputObjectType.mock( + name, + fields: fields, + documentation: documentation, + config: config, + isOneOf: isOneOf + ) + inputObject.name.customName = customName + + subject = OneOfInputObjectTemplate( + graphqlInputObject: inputObject, + config: ApolloCodegen.ConfigurationContext(config: config) + ) + } + + private func renderSubject() -> String { + subject.renderBodyTemplate(nonFatalErrorRecorder: .init()).description + } + + func test_render_generateOneOfInputObject_withCaseAndInputDictVariable() throws { + // given + buildSubject( + name: "mockOneOfInput", + fields: [GraphQLInputField.mock("field", type: .scalar(.integer()), defaultValue: nil)] + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case field(Int) + + public var __data: InputDict { + switch self { + case .field(let value): + return InputDict(["field": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + // MARK: Access Level Tests + + func test_render_givenOneOfInputObjectWithValidAndDeprecatedFields_whenModuleType_swiftPackageManager_generatesAllWithPublicAccess() throws { + // given + buildSubject( + fields: [ + GraphQLInputField.mock( + "fieldOne", + type: .nonNull(.string()), + defaultValue: nil, + deprecationReason: "Not used anymore!" + ), + GraphQLInputField.mock( + "fieldTwo", + type: .nonNull(.string()), + defaultValue: nil + ) + ], + config: .mock(.swiftPackageManager) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + @available(*, deprecated, message: "Not used anymore!") + case fieldOne(String) + case fieldTwo(String) + + public var __data: InputDict { + switch self { + case .fieldOne(let value): + return InputDict(["fieldOne": value]) + case .fieldTwo(let value): + return InputDict(["fieldTwo": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected)) + } + + func test_render_givenOneOfInputObjectWithValidAndDeprecatedFields_whenModuleType_other_generatesAllWithPublicAccess() { + // given + buildSubject( + fields: [ + GraphQLInputField.mock( + "fieldOne", + type: .nonNull(.string()), + defaultValue: nil, + deprecationReason: "Not used anymore!" + ), + GraphQLInputField.mock( + "fieldTwo", + type: .nonNull(.string()), + defaultValue: nil + ) + ], + config: .mock(.other) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + @available(*, deprecated, message: "Not used anymore!") + case fieldOne(String) + case fieldTwo(String) + + public var __data: InputDict { + switch self { + case .fieldOne(let value): + return InputDict(["fieldOne": value]) + case .fieldTwo(let value): + return InputDict(["fieldTwo": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test_render_givenOneOInputObjectWithValidAndDeprecatedFields_whenModuleType_embeddedInTarget_withPublicAccessModifier_generatesAllWithPublicAccess() { + // given + buildSubject( + fields: [ + GraphQLInputField.mock( + "fieldOne", + type: .nonNull(.string()), + defaultValue: nil, + deprecationReason: "Not used anymore!" + ), + GraphQLInputField.mock( + "fieldTwo", + type: .nonNull(.string()), + defaultValue: nil + ) + ], + config: .mock(.embeddedInTarget(name: "TestTarget", accessModifier: .public)) + ) + + let expected = """ + enum MockOneOfInput: OneOfInputObject { + @available(*, deprecated, message: "Not used anymore!") + case fieldOne(String) + case fieldTwo(String) + + public var __data: InputDict { + switch self { + case .fieldOne(let value): + return InputDict(["fieldOne": value]) + case .fieldTwo(let value): + return InputDict(["fieldTwo": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test_render_givenOneOfInputObjectWithValidAndDeprecatedFields_whenModuleType_embeddedInTarget_withInternalAccessModifier_generatesAllWithInternalAccess() { + // given + buildSubject( + fields: [ + GraphQLInputField.mock( + "fieldOne", + type: .nonNull(.string()), + defaultValue: nil, + deprecationReason: "Not used anymore!" + ), + GraphQLInputField.mock( + "fieldTwo", + type: .nonNull(.string()), + defaultValue: nil + ) + ], + config: .mock(.embeddedInTarget(name: "TestTarget", accessModifier: .internal)) + ) + + let expected = """ + enum MockOneOfInput: OneOfInputObject { + @available(*, deprecated, message: "Not used anymore!") + case fieldOne(String) + case fieldTwo(String) + + var __data: InputDict { + switch self { + case .fieldOne(let value): + return InputDict(["fieldOne": value]) + case .fieldTwo(let value): + return InputDict(["fieldTwo": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + // MARK: Casing Tests + + func test__render__givenLowercasedOneOfInputObjectField__generatesCorrectlyCasedSwiftDefinition() throws { + // given + buildSubject( + name: "mockInput", + fields: [GraphQLInputField.mock("field", type: .scalar(.integer()), defaultValue: nil)] + ) + + let expected = "public enum MockInput: OneOfInputObject {" + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenUppercasedOneOfInputObjectField__generatesCorrectlyCasedSwiftDefinition() throws { + // given + buildSubject( + name: "MOCKInput", + fields: [GraphQLInputField.mock("field", type: .scalar(.integer()), defaultValue: nil)] + ) + + let expected = "public enum MOCKInput: OneOfInputObject {" + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenMixedCaseOneOfInputObjectField__generatesCorrectlyCasedSwiftDefinition() throws { + // given + buildSubject( + name: "mOcK_Input", + fields: [GraphQLInputField.mock("field", type: .scalar(.integer()), defaultValue: nil)] + ) + + let expected = "public enum MOcK_Input: OneOfInputObject {" + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__casing__givenSchemaName_generatesWithNoCaseConversion() throws { + // given + let fields: [GraphQLInputField] = [ + GraphQLInputField.mock( + "InputField", + type: .inputObject(.mock( + "InnerInputObject", + fields: [ + GraphQLInputField.mock("InnerStringField", type: .scalar(.string()), defaultValue: nil) + ] + )), + defaultValue: nil + ), + GraphQLInputField.mock( + "inputField", + type: .inputObject(.mock( + "InnerInputObject", + fields: [ + GraphQLInputField.mock("innerStringField", type: .scalar(.string()), defaultValue: nil) + ] + )), + defaultValue: nil + ) + ] + + buildSubject( + fields: fields, + config: .mock(schemaNamespace: "testschema", + output: .mock( + moduleType: .swiftPackageManager, + operations: .relative(subpath: nil) + ), + options: .init( + conversionStrategies: .init(inputObjects: .none) + ) + ) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case InputField(Testschema.InnerInputObject) + case inputField(Testschema.InnerInputObject) + + public var __data: InputDict { + switch self { + case .InputField(let value): + return InputDict(["InputField": value]) + case .inputField(let value): + return InputDict(["inputField": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__casing__givenSchemaNameLowercased_nonListField_generatesWithFirstUppercasedNamespace() throws { + // given + let fields: [GraphQLInputField] = [ + GraphQLInputField.mock( + "enumField", + type: .enum(.mock(name: "EnumValue")), + defaultValue: nil + ), + GraphQLInputField.mock( + "inputField", + type: .inputObject(.mock( + "InnerInputObject", + fields: [ + GraphQLInputField.mock("innerStringField", type: .scalar(.string()), defaultValue: nil) + ] + )), + defaultValue: nil + ) + ] + + buildSubject( + fields: fields, + config: .mock(schemaNamespace: "testschema", output: .mock( + moduleType: .swiftPackageManager, + operations: .relative(subpath: nil))) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case enumField(GraphQLEnum) + case inputField(Testschema.InnerInputObject) + + public var __data: InputDict { + switch self { + case .enumField(let value): + return InputDict(["enumField": value]) + case .inputField(let value): + return InputDict(["inputField": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__casing__givenUppercasedSchemaName_nonListField_generatesWithUppercasedNamespace() throws { + // given + let fields: [GraphQLInputField] = [ + GraphQLInputField.mock( + "enumField", + type: .enum(.mock(name: "EnumValue")), + defaultValue: nil + ), + GraphQLInputField.mock( + "inputField", + type: .inputObject(.mock( + "InnerInputObject", + fields: [ + GraphQLInputField.mock("innerStringField", type: .scalar(.string()), defaultValue: nil) + ] + )), + defaultValue: nil + ) + ] + + buildSubject( + fields: fields, + config: .mock(schemaNamespace: "TESTSCHEMA", output: .mock( + moduleType: .swiftPackageManager, + operations: .relative(subpath: nil))) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case enumField(GraphQLEnum) + case inputField(TESTSCHEMA.InnerInputObject) + + public var __data: InputDict { + switch self { + case .enumField(let value): + return InputDict(["enumField": value]) + case .inputField(let value): + return InputDict(["inputField": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__casing__givenCapitalizedSchemaName_nonListField_generatesWithCapitalizedNamespace() throws { + // given + let fields: [GraphQLInputField] = [ + GraphQLInputField.mock( + "enumField", + type: .enum(.mock(name: "EnumValue")), + defaultValue: nil + ), + GraphQLInputField.mock( + "inputField", + type: .inputObject(.mock( + "InnerInputObject", + fields: [ + GraphQLInputField.mock("innerStringField", type: .scalar(.string()), defaultValue: nil) + ] + )), + defaultValue: nil + ) + ] + + buildSubject( + fields: fields, + config: .mock(schemaNamespace: "TestSchema", output: .mock( + moduleType: .swiftPackageManager, + operations: .relative(subpath: nil))) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case enumField(GraphQLEnum) + case inputField(TestSchema.InnerInputObject) + + public var __data: InputDict { + switch self { + case .enumField(let value): + return InputDict(["enumField": value]) + case .inputField(let value): + return InputDict(["inputField": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__casing__givenLowercasedSchemaName_listField_generatesWithFirstUppercasedNamespace() throws { + // given + buildSubject( + fields: [GraphQLInputField.mock( + "listNullableItem", + type: .list(.enum(.mock(name: "EnumValue"))), + defaultValue: nil)], + config: .mock( + schemaNamespace: "testschema", + output: .mock(moduleType: .swiftPackageManager, operations: .relative(subpath: nil)) + ) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case listNullableItem([GraphQLEnum?]) + + public var __data: InputDict { + switch self { + case .listNullableItem(let value): + return InputDict(["listNullableItem": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__casing__givenUppercasedSchemaName_listField_generatesWithUppercasedNamespace() throws { + // given + buildSubject( + fields: [GraphQLInputField.mock( + "listNullableItem", + type: .list(.enum(.mock(name: "EnumValue"))), + defaultValue: nil)], + config: .mock( + schemaNamespace: "TESTSCHEMA", + output: .mock(moduleType: .swiftPackageManager, operations: .relative(subpath: nil)) + ) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case listNullableItem([GraphQLEnum?]) + + public var __data: InputDict { + switch self { + case .listNullableItem(let value): + return InputDict(["listNullableItem": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__casing__givenCapitalizedSchemaName_listField_generatesWithCapitalizedNamespace() throws { + // given + buildSubject( + fields: [GraphQLInputField.mock( + "listNullableItem", + type: .list(.enum(.mock(name: "EnumValue"))), + defaultValue: nil)], + config: .mock( + schemaNamespace: "TestSchema", + output: .mock(moduleType:.swiftPackageManager ,operations: .relative(subpath: nil)) + ) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case listNullableItem([GraphQLEnum?]) + + public var __data: InputDict { + switch self { + case .listNullableItem(let value): + return InputDict(["listNullableItem": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + // MARK: Field Type Tests + + func test__render__givenSingleFieldType__generatesCaseAndDataDict() throws { + // given + buildSubject(fields: [ + GraphQLInputField.mock("field", type: .scalar(.string()), defaultValue: nil) + ]) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case field(String) + + public var __data: InputDict { + switch self { + case .field(let value): + return InputDict(["field": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: false)) + } + + func test__render__givenSingleFieldTypeInMixedCase__generatesCaseAndDataDictWithCorrectCasing() throws { + // given + buildSubject(fields: [ + GraphQLInputField.mock("Field", type: .scalar(.string()), defaultValue: nil) + ]) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case field(String) + + public var __data: InputDict { + switch self { + case .field(let value): + return InputDict(["Field": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: false)) + } + + func test__render__givenSingleFieldTypeInAllUppercase__generatesCaseAndDataDictWithCorrectCasing() throws { + // given + buildSubject(fields: [ + GraphQLInputField.mock("FIELDNAME", type: .scalar(.string()), defaultValue: nil) + ]) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case fieldname(String) + + public var __data: InputDict { + switch self { + case .fieldname(let value): + return InputDict(["FIELDNAME": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: false)) + } + + func test__render__givenAllPossibleSchemaInputFieldTypes__generatesCasesAndDataDict() throws { + // given + buildSubject(fields: [ + GraphQLInputField.mock( + "stringField", + type: .scalar(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "intField", + type: .scalar(.integer()), + defaultValue: nil + ), + GraphQLInputField.mock( + "boolField", + type: .scalar(.boolean()), + defaultValue: nil + ), + GraphQLInputField.mock( + "floatField", + type: .scalar(.float()), + defaultValue: nil + ), + GraphQLInputField.mock( + "customScalarField", + type: .scalar(.mock(name: "CustomScalar")), + defaultValue: nil + ), + GraphQLInputField.mock( + "lowercaseCustomScalarField", + type: .scalar(.mock(name: "lowercaseCustomScalar")), + defaultValue: nil + ), + GraphQLInputField.mock( + "enumField", + type: .enum(.mock(name: "EnumType")), + defaultValue: nil + ), + GraphQLInputField.mock( + "lowercaseEnumField", + type: .enum(.mock(name: "lowercaseEnumType")), + defaultValue: nil + ), + GraphQLInputField.mock( + "inputField", + type: .inputObject(.mock( + "InnerInputObject", + fields: [ + GraphQLInputField.mock("innerStringField", type: .scalar(.string()), defaultValue: nil) + ] + )), + defaultValue: nil + ), + GraphQLInputField.mock( + "lowercaseInputField", + type: .inputObject(.mock( + "lowercaseInnerInputObject", + fields: [ + GraphQLInputField.mock("innerStringField", type: .scalar(.string()), defaultValue: nil) + ] + )), + defaultValue: nil + ), + GraphQLInputField.mock( + "listField", + type: .list(.scalar(.string())), + defaultValue: nil + ) + ], config: .mock(.swiftPackageManager, schemaNamespace: "TestSchema")) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case stringField(String) + case intField(Int) + case boolField(Bool) + case floatField(Double) + case customScalarField(CustomScalar) + case lowercaseCustomScalarField(LowercaseCustomScalar) + case enumField(GraphQLEnum) + case lowercaseEnumField(GraphQLEnum) + case inputField(InnerInputObject) + case lowercaseInputField(LowercaseInnerInputObject) + case listField([String?]) + + public var __data: InputDict { + switch self { + case .stringField(let value): + return InputDict(["stringField": value]) + case .intField(let value): + return InputDict(["intField": value]) + case .boolField(let value): + return InputDict(["boolField": value]) + case .floatField(let value): + return InputDict(["floatField": value]) + case .customScalarField(let value): + return InputDict(["customScalarField": value]) + case .lowercaseCustomScalarField(let value): + return InputDict(["lowercaseCustomScalarField": value]) + case .enumField(let value): + return InputDict(["enumField": value]) + case .lowercaseEnumField(let value): + return InputDict(["lowercaseEnumField": value]) + case .inputField(let value): + return InputDict(["inputField": value]) + case .lowercaseInputField(let value): + return InputDict(["lowercaseInputField": value]) + case .listField(let value): + return InputDict(["listField": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenSchemaModuleInputFieldTypes__generatesCasesAndDataDict_withNamespaceWhenRequired() throws { + // given + let fields: [GraphQLInputField] = [ + GraphQLInputField.mock( + "enumField", + type: .enum(.mock(name: "EnumValue")), + defaultValue: nil + ), + GraphQLInputField.mock( + "inputField", + type: .inputObject(.mock( + "InnerInputObject", + fields: [ + GraphQLInputField.mock("innerStringField", type: .scalar(.string()), defaultValue: nil) + ] + )), + defaultValue: nil + ) + ] + + let expectedNoNamespace = """ + case enumField(GraphQLEnum) + case inputField(InnerInputObject) + """ + + let expectedWithNamespace = """ + case enumField(GraphQLEnum) + case inputField(TestSchema.InnerInputObject) + """ + + let tests: [(config: ApolloCodegenConfiguration.FileOutput, expected: String)] = [ + (.mock(moduleType: .swiftPackageManager, operations: .relative(subpath: nil)), expectedWithNamespace), + (.mock(moduleType: .swiftPackageManager, operations: .absolute(path: "custom")), expectedWithNamespace), + (.mock(moduleType: .swiftPackageManager, operations: .inSchemaModule), expectedNoNamespace), + (.mock(moduleType: .other, operations: .relative(subpath: nil)), expectedWithNamespace), + (.mock(moduleType: .other, operations: .absolute(path: "custom")), expectedWithNamespace), + (.mock(moduleType: .other, operations: .inSchemaModule), expectedNoNamespace), + (.mock(moduleType: .embeddedInTarget(name: "CustomTarget", accessModifier: .public), operations: .relative(subpath: nil)), expectedWithNamespace), + (.mock(moduleType: .embeddedInTarget(name: "CustomTarget", accessModifier: .public), operations: .absolute(path: "custom")), expectedWithNamespace), + (.mock(moduleType: .embeddedInTarget(name: "CustomTarget", accessModifier: .public), operations: .inSchemaModule), expectedNoNamespace) + ] + + for test in tests { + // given + buildSubject(fields: fields, config: .mock(output: test.config)) + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(test.expected, atLine: 2, ignoringExtraLines: true)) + } + } + + // MARK: Documentation Tests + + func test__render__givenSchemaDocumentation_include_hasDocumentation_shouldGenerateDocumentationComment() throws { + // given + let documentation = "This is some great documentation!" + buildSubject( + fields: [ + GraphQLInputField.mock("fieldOne", + type: .nonNull(.string()), + defaultValue: nil, + documentation: "Field Documentation!") + ], + documentation: documentation, + config: .mock(.swiftPackageManager, options: .init(schemaDocumentation: .include)) + ) + + let expected = """ + /// \(documentation) + public enum MockOneOfInput: OneOfInputObject { + /// Field Documentation! + case fieldOne(String) + """ + + // when + let rendered = renderSubject() + + // then + expect(rendered).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenSchemaDocumentation_exclude_hasDocumentation_shouldNotGenerateDocumentationComment() throws { + // given + let documentation = "This is some great documentation!" + buildSubject( + fields: [ + GraphQLInputField.mock("fieldOne", + type: .nonNull(.string()), + defaultValue: nil, + documentation: "Field Documentation!") + ], + documentation: documentation, + config: .mock(.swiftPackageManager, options: .init(schemaDocumentation: .exclude)) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case fieldOne(String) + """ + + // when + let rendered = renderSubject() + + // then + expect(rendered).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + // MARK: Deprecation Tests + + func test__render__givenDeprecatedField_includeDeprecationWarnings_shouldGenerateWarning() throws { + // given + buildSubject( + fields: [ + GraphQLInputField.mock( + "fieldOne", + type: .nonNull(.string()), + defaultValue: nil, + deprecationReason: "Not used anymore!" + ) + ], + config: .mock( + .swiftPackageManager, + options: .init(schemaDocumentation: .include, warningsOnDeprecatedUsage: .include) + ) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + @available(*, deprecated, message: "Not used anymore!") + case fieldOne(String) + """ + + // when + let rendered = renderSubject() + + // then + expect(rendered).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenDeprecatedField_excludeDeprecationWarnings_shouldNotGenerateWarning() throws { + // given + buildSubject( + fields: [ + GraphQLInputField.mock( + "fieldOne", + type: .nonNull(.string()), + defaultValue: nil, + deprecationReason: "Not used anymore!" + ) + ], + config: .mock( + .swiftPackageManager, + options: .init(schemaDocumentation: .include,warningsOnDeprecatedUsage: .exclude) + ) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case fieldOne(String) + """ + + // when + let rendered = renderSubject() + + // then + expect(rendered).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenDeprecatedField_andDocumentation_includeDeprecationWarnings_shouldGenerateWarning_afterDocumentation() throws { + // given + let documentation = "This is some great documentation!" + buildSubject( + fields: [ + GraphQLInputField.mock( + "fieldOne", + type: .nonNull(.string()), + defaultValue: nil, + documentation: "Field Documentation!", + deprecationReason: "Not used anymore!" + ) + ], + documentation: documentation, + config: .mock( + .swiftPackageManager, + options: .init(schemaDocumentation: .include,warningsOnDeprecatedUsage: .include) + ) + ) + + let expected = """ + /// This is some great documentation! + public enum MockOneOfInput: OneOfInputObject { + /// Field Documentation! + @available(*, deprecated, message: "Not used anymore!") + case fieldOne(String) + """ + + // when + let rendered = renderSubject() + + // then + expect(rendered).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenDeprecatedField_andDocumentation_excludeDeprecationWarnings_shouldNotGenerateWarning_afterDocumentation() throws { + // given + let documentation = "This is some great documentation!" + buildSubject( + fields: [ + GraphQLInputField.mock( + "fieldOne", + type: .nonNull(.string()), + defaultValue: nil, + documentation: "Field Documentation!") + ], + documentation: documentation, + config: .mock( + .swiftPackageManager, + options: .init(schemaDocumentation: .include,warningsOnDeprecatedUsage: .exclude) + ) + ) + + let expected = """ + /// This is some great documentation! + public enum MockOneOfInput: OneOfInputObject { + /// Field Documentation! + case fieldOne(String) + """ + + // when + let rendered = renderSubject() + + // then + expect(rendered).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenDeprecatedAndValidFields_includeDeprecationWarnings_shouldGenerateWarnings() throws { + // given + buildSubject( + fields: [ + GraphQLInputField.mock( + "fieldOne", + type: .nonNull(.string()), + defaultValue: nil, + deprecationReason: "Not used anymore!" + ), + GraphQLInputField.mock( + "fieldTwo", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "fieldThree", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "fieldFour", + type: .nonNull(.string()), + defaultValue: nil, + deprecationReason: "Stop using this field!" + ) + ], + config: .mock( + .swiftPackageManager, + options: .init(schemaDocumentation: .include,warningsOnDeprecatedUsage: .include) + ) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + @available(*, deprecated, message: "Not used anymore!") + case fieldOne(String) + case fieldTwo(String) + case fieldThree(String) + @available(*, deprecated, message: "Stop using this field!") + case fieldFour(String) + """ + + // when + let rendered = renderSubject() + + // then + expect(rendered).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenDeprecatedAndValidFields_excludeDeprecationWarnings_shouldNotGenerateWarning_afterDocumentation() throws { + // given + buildSubject( + fields: [ + GraphQLInputField.mock( + "fieldOne", + type: .nonNull(.string()), + defaultValue: nil, + deprecationReason: "Not used anymore!" + ), + GraphQLInputField.mock( + "fieldTwo", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "fieldThree", + type: .nonNull(.string()), + defaultValue: nil, + deprecationReason: "Stop using this field!" + ) + ], + config: .mock( + .swiftPackageManager, + options: .init(schemaDocumentation: .include,warningsOnDeprecatedUsage: .exclude) + ) + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case fieldOne(String) + case fieldTwo(String) + case fieldThree(String) + """ + + // when + let rendered = renderSubject() + + // then + expect(rendered).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + // MARK: Reserved Keywords + Special Names + + func test__render__givenFieldsUsingReservedNames__generateCasesAndDataDictWithEscaping() throws { + // given + let fields = [ + GraphQLInputField.mock( + "associatedtype", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "class", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "deinit", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "enum", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "extension", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "fileprivate", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "func", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "import", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "init", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "inout", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "internal", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "let", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "operator", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "private", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "precedencegroup", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "protocol", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "public", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "rethrows", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "static", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "struct", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "subscript", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "typealias", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "var", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "break", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "case", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "catch", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "continue", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "default", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "defer", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "do", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "else", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "fallthrough", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "for", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "guard", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "if", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "in", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "repeat", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "return", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "throw", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "switch", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "where", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "while", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "as", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "false", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "is", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "nil", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "self", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "super", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "throws", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "true", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "try", + type: .nonNull(.string()), + defaultValue: nil + ), + GraphQLInputField.mock( + "_", + type: .nonNull(.string()), + defaultValue: nil + ), + ] + + buildSubject( + fields: fields, + config: .mock(.swiftPackageManager, + options: .init( + conversionStrategies: .init(inputObjects: .none) + ), + schemaNamespace: "TestSchema") + ) + + let expected = """ + public enum MockOneOfInput: OneOfInputObject { + case `associatedtype`(String) + case `class`(String) + case `deinit`(String) + case `enum`(String) + case `extension`(String) + case `fileprivate`(String) + case `func`(String) + case `import`(String) + case `init`(String) + case `inout`(String) + case `internal`(String) + case `let`(String) + case `operator`(String) + case `private`(String) + case `precedencegroup`(String) + case `protocol`(String) + case `public`(String) + case `rethrows`(String) + case `static`(String) + case `struct`(String) + case `subscript`(String) + case `typealias`(String) + case `var`(String) + case `break`(String) + case `case`(String) + case `catch`(String) + case `continue`(String) + case `default`(String) + case `defer`(String) + case `do`(String) + case `else`(String) + case `fallthrough`(String) + case `for`(String) + case `guard`(String) + case `if`(String) + case `in`(String) + case `repeat`(String) + case `return`(String) + case `throw`(String) + case `switch`(String) + case `where`(String) + case `while`(String) + case `as`(String) + case `false`(String) + case `is`(String) + case `nil`(String) + case `self`(String) + case `super`(String) + case `throws`(String) + case `true`(String) + case `try`(String) + case `_`(String) + + public var __data: InputDict { + switch self { + case .`associatedtype`(let value): + return InputDict(["associatedtype": value]) + case .`class`(let value): + return InputDict(["class": value]) + case .`deinit`(let value): + return InputDict(["deinit": value]) + case .`enum`(let value): + return InputDict(["enum": value]) + case .`extension`(let value): + return InputDict(["extension": value]) + case .`fileprivate`(let value): + return InputDict(["fileprivate": value]) + case .`func`(let value): + return InputDict(["func": value]) + case .`import`(let value): + return InputDict(["import": value]) + case .`init`(let value): + return InputDict(["init": value]) + case .`inout`(let value): + return InputDict(["inout": value]) + case .`internal`(let value): + return InputDict(["internal": value]) + case .`let`(let value): + return InputDict(["let": value]) + case .`operator`(let value): + return InputDict(["operator": value]) + case .`private`(let value): + return InputDict(["private": value]) + case .`precedencegroup`(let value): + return InputDict(["precedencegroup": value]) + case .`protocol`(let value): + return InputDict(["protocol": value]) + case .`public`(let value): + return InputDict(["public": value]) + case .`rethrows`(let value): + return InputDict(["rethrows": value]) + case .`static`(let value): + return InputDict(["static": value]) + case .`struct`(let value): + return InputDict(["struct": value]) + case .`subscript`(let value): + return InputDict(["subscript": value]) + case .`typealias`(let value): + return InputDict(["typealias": value]) + case .`var`(let value): + return InputDict(["var": value]) + case .`break`(let value): + return InputDict(["break": value]) + case .`case`(let value): + return InputDict(["case": value]) + case .`catch`(let value): + return InputDict(["catch": value]) + case .`continue`(let value): + return InputDict(["continue": value]) + case .`default`(let value): + return InputDict(["default": value]) + case .`defer`(let value): + return InputDict(["defer": value]) + case .`do`(let value): + return InputDict(["do": value]) + case .`else`(let value): + return InputDict(["else": value]) + case .`fallthrough`(let value): + return InputDict(["fallthrough": value]) + case .`for`(let value): + return InputDict(["for": value]) + case .`guard`(let value): + return InputDict(["guard": value]) + case .`if`(let value): + return InputDict(["if": value]) + case .`in`(let value): + return InputDict(["in": value]) + case .`repeat`(let value): + return InputDict(["repeat": value]) + case .`return`(let value): + return InputDict(["return": value]) + case .`throw`(let value): + return InputDict(["throw": value]) + case .`switch`(let value): + return InputDict(["switch": value]) + case .`where`(let value): + return InputDict(["where": value]) + case .`while`(let value): + return InputDict(["while": value]) + case .`as`(let value): + return InputDict(["as": value]) + case .`false`(let value): + return InputDict(["false": value]) + case .`is`(let value): + return InputDict(["is": value]) + case .`nil`(let value): + return InputDict(["nil": value]) + case .`self`(let value): + return InputDict(["self": value]) + case .`super`(let value): + return InputDict(["super": value]) + case .`throws`(let value): + return InputDict(["throws": value]) + case .`true`(let value): + return InputDict(["true": value]) + case .`try`(let value): + return InputDict(["try": value]) + case .`_`(let value): + return InputDict(["_": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__generatesOneOfInputObject_usingReservedKeyword_asEscapedType() throws { + let keywords = ["Type", "type"] + + keywords.forEach { keyword in + // given + buildSubject( + name: keyword, + fields: [GraphQLInputField.mock("field", type: .scalar(.integer()), defaultValue: nil)] + ) + + let expected = """ + public enum \(keyword.firstUppercased)_InputObject: OneOfInputObject { + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + } + + // MARK: - Schema Customization Tests + + func test__render__givenOneOfInputObjectAndField_withCustomNames_shouldRenderWithCustomNames() throws { + // given + let customInputField = GraphQLInputField.mock( + "myField", + type: .nonNull(.string()), + defaultValue: nil + ) + customInputField.name.customName = "myCustomField" + buildSubject( + name: "MyInputObject", + customName: "MyCustomInputObject", + fields: [ + GraphQLInputField.mock( + "fieldOne", + type: .nonNull(.string()), + defaultValue: nil + ), + customInputField + ] + ) + + let expected = """ + // Renamed from GraphQL schema value: 'MyInputObject' + public enum MyCustomInputObject: OneOfInputObject { + case fieldOne(String) + // Renamed from GraphQL schema value: 'myField' + case myCustomField(String) + + public var __data: InputDict { + switch self { + case .fieldOne(let value): + return InputDict(["fieldOne": value]) + case .myCustomField(let value): + return InputDict(["myField": value]) + } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + +} diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/SwiftPackageManagerModuleTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/SwiftPackageManagerModuleTemplateTests.swift index 6e086c9ca..7758a4658 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/SwiftPackageManagerModuleTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/SwiftPackageManagerModuleTemplateTests.swift @@ -291,7 +291,7 @@ class SwiftPackageManagerModuleTemplateTests: XCTestCase { let expected = """ dependencies: [ - .package(path: "\(path)"), + .package(name: "apollo-ios", path: "\(path)"), ], """ // when diff --git a/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/LocalCacheMutations/AllAnimalsLocalCacheMutation.graphql.swift b/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/LocalCacheMutations/AllAnimalsLocalCacheMutation.graphql.swift index c40552f27..a36338a99 100644 --- a/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/LocalCacheMutations/AllAnimalsLocalCacheMutation.graphql.swift +++ b/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/LocalCacheMutations/AllAnimalsLocalCacheMutation.graphql.swift @@ -61,10 +61,7 @@ public extension MyAPI { set { __data["skinCovering"] = newValue } } - public var asBird: AsBird? { - get { _asInlineFragment() } - set { if let newData = newValue?.__data._data { __data._data = newData }} - } + public var asBird: AsBird? { _asInlineFragment() } public init( __typename: String, diff --git a/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/Operations/Queries/FindPetQuery.graphql.swift b/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/Operations/Queries/FindPetQuery.graphql.swift new file mode 100644 index 000000000..ef6054fb9 --- /dev/null +++ b/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/Operations/Queries/FindPetQuery.graphql.swift @@ -0,0 +1,53 @@ +// @generated +// This file was automatically generated and should not be edited. + +@_exported import ApolloAPI + +public extension MyAPI { + class FindPetQuery: GraphQLQuery { + public static let operationName: String = "FindPet" + public static let operationDocument: ApolloAPI.OperationDocument = .init( + definition: .init( + #"query FindPet($input: PetSearchInput!) { findPet(input: $input) { __typename id humanName } }"# + )) + + public var input: PetSearchInput + + public init(input: PetSearchInput) { + self.input = input + } + + public var __variables: Variables? { ["input": input] } + + public struct Data: MyAPI.SelectionSet { + public let __data: DataDict + public init(_dataDict: DataDict) { __data = _dataDict } + + public static var __parentType: any ApolloAPI.ParentType { MyAPI.Objects.Query } + public static var __selections: [ApolloAPI.Selection] { [ + .field("findPet", [FindPet].self, arguments: ["input": .variable("input")]), + ] } + + public var findPet: [FindPet] { __data["findPet"] } + + /// FindPet + /// + /// Parent Type: `Pet` + public struct FindPet: MyAPI.SelectionSet { + public let __data: DataDict + public init(_dataDict: DataDict) { __data = _dataDict } + + public static var __parentType: any ApolloAPI.ParentType { MyAPI.Interfaces.Pet } + public static var __selections: [ApolloAPI.Selection] { [ + .field("__typename", String.self), + .field("id", MyAPI.ID.self), + .field("humanName", String?.self), + ] } + + public var id: MyAPI.ID { __data["id"] } + public var humanName: String? { __data["humanName"] } + } + } + } + +} \ No newline at end of file diff --git a/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/Schema/InputObjects/PetSearchInput.graphql.swift b/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/Schema/InputObjects/PetSearchInput.graphql.swift new file mode 100644 index 000000000..f8670eeb0 --- /dev/null +++ b/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/Schema/InputObjects/PetSearchInput.graphql.swift @@ -0,0 +1,23 @@ +// @generated +// This file was automatically generated and should not be edited. + +import ApolloAPI + +public extension MyAPI { + enum PetSearchInput: OneOfInputObject { + case ownerID(ID) + case petID(ID) + case searchFilters(PetSearchFilters) + + public var __data: InputDict { + switch self { + case .ownerID(let value): + return InputDict(["ownerID": value]) + case .petID(let value): + return InputDict(["petID": value]) + case .searchFilters(let value): + return InputDict(["searchFilters": value]) + } + } + } +} \ No newline at end of file diff --git a/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/Schema/SchemaMetadata.graphql.swift b/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/Schema/SchemaMetadata.graphql.swift index f9bb451e3..ff5a850d5 100644 --- a/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/Schema/SchemaMetadata.graphql.swift +++ b/Tests/TestCodeGenConfigurations/CodegenXCFramework/CodegenXCFramework/MyAPI/Schema/SchemaMetadata.graphql.swift @@ -29,17 +29,17 @@ public extension MyAPI { public static func objectType(forTypename typename: String) -> ApolloAPI.Object? { switch typename { - case "Query": return MyAPI.Objects.Query - case "Human": return MyAPI.Objects.Human + case "Bird": return MyAPI.Objects.Bird case "Cat": return MyAPI.Objects.Cat + case "Crocodile": return MyAPI.Objects.Crocodile case "Dog": return MyAPI.Objects.Dog - case "Bird": return MyAPI.Objects.Bird case "Fish": return MyAPI.Objects.Fish - case "Rat": return MyAPI.Objects.Rat - case "PetRock": return MyAPI.Objects.PetRock - case "Crocodile": return MyAPI.Objects.Crocodile case "Height": return MyAPI.Objects.Height + case "Human": return MyAPI.Objects.Human case "Mutation": return MyAPI.Objects.Mutation + case "PetRock": return MyAPI.Objects.PetRock + case "Query": return MyAPI.Objects.Query + case "Rat": return MyAPI.Objects.Rat default: return nil } } diff --git a/Tests/TestCodeGenConfigurations/SPMInXcodeProject/apollo-codegen-config.json b/Tests/TestCodeGenConfigurations/SPMInXcodeProject/apollo-codegen-config.json index 256daa6f0..38b6b2848 100644 --- a/Tests/TestCodeGenConfigurations/SPMInXcodeProject/apollo-codegen-config.json +++ b/Tests/TestCodeGenConfigurations/SPMInXcodeProject/apollo-codegen-config.json @@ -56,8 +56,14 @@ "schemaTypes" : { "path" : "./AnimalKingdomAPI", "moduleType" : { - "swiftPackageManager" : { - + "swiftPackage" : { + "apolloSDKDependency" : { + "sdkVersion" : { + "local" : { + "path" : "../../../../apollo-ios" + } + } + } } } }, diff --git a/Tests/TestCodeGenConfigurations/SwiftPackageManager/apollo-codegen-config.json b/Tests/TestCodeGenConfigurations/SwiftPackageManager/apollo-codegen-config.json index 256daa6f0..38b6b2848 100644 --- a/Tests/TestCodeGenConfigurations/SwiftPackageManager/apollo-codegen-config.json +++ b/Tests/TestCodeGenConfigurations/SwiftPackageManager/apollo-codegen-config.json @@ -56,8 +56,14 @@ "schemaTypes" : { "path" : "./AnimalKingdomAPI", "moduleType" : { - "swiftPackageManager" : { - + "swiftPackage" : { + "apolloSDKDependency" : { + "sdkVersion" : { + "local" : { + "path" : "../../../../apollo-ios" + } + } + } } } }, diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/CodegenConfiguration/ApolloCodegenConfiguration.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/CodegenConfiguration/ApolloCodegenConfiguration.swift index cb5d9f2d6..a482bcd8c 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/CodegenConfiguration/ApolloCodegenConfiguration.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/CodegenConfiguration/ApolloCodegenConfiguration.swift @@ -386,7 +386,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable { decoder: decoder ) - url = try values.decode(String.self, forKey: .url) + url = try values.decodeIfPresent(String.self, forKey: .url) ?? "https://github.com/apollographql/apollo-ios" if let version = try? values.decodeIfPresent(SDKVersion.self, forKey: .sdkVersion) { sdkVersion = version @@ -394,11 +394,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable { let version = try SDKVersion(fromString: versionString) sdkVersion = version } else { - throw DecodingError.typeMismatch(Self.self, DecodingError.Context.init( - codingPath: values.codingPath, - debugDescription: "No valid 'sdkVersion' provided.", - underlyingError: nil - )) + sdkVersion = .default } } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/ConfigurationValidation.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/ConfigurationValidation.swift index 552c74afd..84a625d27 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/ConfigurationValidation.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/ConfigurationValidation.swift @@ -33,9 +33,13 @@ extension ApolloCodegen.ConfigurationContext { throw ApolloCodegen.Error.schemaNameConflict(name: self.schemaNamespace) } - if case .swiftPackage = self.output.testMocks, - self.output.schemaTypes.moduleType != .swiftPackage() { - throw ApolloCodegen.Error.testMocksInvalidSwiftPackageConfiguration + if case .swiftPackage = self.output.testMocks { + switch self.output.schemaTypes.moduleType { + case .swiftPackage(_), .swiftPackageManager: + break + default: + throw ApolloCodegen.Error.testMocksInvalidSwiftPackageConfiguration + } } if case .swiftPackage = self.output.schemaTypes.moduleType, diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/FileGenerator.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/FileGenerator.swift index 0e8f33499..2dbb8c7a0 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/FileGenerator.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/FileGenerator.swift @@ -112,7 +112,7 @@ enum FileTarget: Equatable { forConfig config: ApolloCodegen.ConfigurationContext ) -> String { var moduleSubpath: String = "/" - if config.output.schemaTypes.moduleType == .swiftPackage() { + if case .swiftPackage = config.output.schemaTypes.moduleType { moduleSubpath += "Sources/" } if config.output.operations.isInModule { @@ -132,7 +132,7 @@ enum FileTarget: Equatable { switch config.output.operations { case .inSchemaModule: var url = URL(fileURLWithPath: config.output.schemaTypes.path, relativeTo: config.rootURL) - if config.output.schemaTypes.moduleType == .swiftPackage() { + if case .swiftPackage = config.output.schemaTypes.moduleType { url = url.appendingPathComponent("Sources") } @@ -167,7 +167,7 @@ enum FileTarget: Equatable { switch config.output.operations { case .inSchemaModule: var url = URL(fileURLWithPath: config.output.schemaTypes.path, relativeTo: config.rootURL) - if config.output.schemaTypes.moduleType == .swiftPackage() { + if case .swiftPackage = config.output.schemaTypes.moduleType { url = url.appendingPathComponent("Sources") } if !operation.isLocalCacheMutation { diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/InputObjectFileGenerator.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/InputObjectFileGenerator.swift index e72433f58..d2bf15b69 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/InputObjectFileGenerator.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/InputObjectFileGenerator.swift @@ -10,7 +10,11 @@ struct InputObjectFileGenerator: FileGenerator { let config: ApolloCodegen.ConfigurationContext var template: any TemplateRenderer { - InputObjectTemplate(graphqlInputObject: graphqlInputObject, config: config) + if graphqlInputObject.isOneOf { + OneOfInputObjectTemplate(graphqlInputObject: graphqlInputObject, config: config) + } else { + InputObjectTemplate(graphqlInputObject: graphqlInputObject, config: config) + } } var target: FileTarget { .inputObject } var fileName: String { graphqlInputObject.render(as: .filename) } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/InputObjectTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/InputObjectTemplate.swift index d5e5c3622..637ce990f 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/InputObjectTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/InputObjectTemplate.swift @@ -15,7 +15,7 @@ struct InputObjectTemplate: TemplateRenderer { func renderBodyTemplate( nonFatalErrorRecorder: ApolloCodegen.NonFatalError.Recorder ) -> TemplateString { - let (validFields, deprecatedFields) = filterFields(graphqlInputObject.fields) + let (validFields, deprecatedFields) = graphqlInputObject.fields.filterFields() let memberAccessControl = accessControlModifier(for: .member) return TemplateString( @@ -63,23 +63,6 @@ struct InputObjectTemplate: TemplateRenderer { config.options.warningsOnDeprecatedUsage == .include } - private func filterFields( - _ fields: GraphQLInputFieldDictionary - ) -> (valid: GraphQLInputFieldDictionary, deprecated: GraphQLInputFieldDictionary) { - var valid: GraphQLInputFieldDictionary = [:] - var deprecated: GraphQLInputFieldDictionary = [:] - - for (key, value) in fields { - if let _ = value.deprecationReason { - deprecated[key] = value - } else { - valid[key] = value - } - } - - return (valid: valid, deprecated: deprecated) - } - private func deprecatedMessage(for fields: GraphQLInputFieldDictionary) -> String { guard !fields.isEmpty else { return "" } @@ -123,3 +106,22 @@ struct InputObjectTemplate: TemplateRenderer { """ } } + +extension GraphQLInputFieldDictionary { + + func filterFields() -> (valid: GraphQLInputFieldDictionary, deprecated: GraphQLInputFieldDictionary) { + var valid: GraphQLInputFieldDictionary = [:] + var deprecated: GraphQLInputFieldDictionary = [:] + + for (key, value) in self { + if let _ = value.deprecationReason { + deprecated[key] = value + } else { + valid[key] = value + } + } + + return (valid: valid, deprecated: deprecated) + } + +} diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/OneOfInputObjectTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/OneOfInputObjectTemplate.swift new file mode 100644 index 000000000..9d407aaa3 --- /dev/null +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/OneOfInputObjectTemplate.swift @@ -0,0 +1,52 @@ +import Foundation +import GraphQLCompiler +import TemplateString + +struct OneOfInputObjectTemplate: TemplateRenderer { + + let graphqlInputObject: GraphQLInputObjectType + + let config: ApolloCodegen.ConfigurationContext + + let target: TemplateTarget = .schemaFile(type: .inputObject) + + func renderBodyTemplate( + nonFatalErrorRecorder: ApolloCodegen.NonFatalError.Recorder + ) -> TemplateString { + let memberAccessControl = accessControlModifier(for: .member) + + return TemplateString( + """ + \(documentation: graphqlInputObject.documentation, config: config) + \(graphqlInputObject.name.typeNameDocumentation) + \(accessControlModifier(for: .parent))\ + enum \(graphqlInputObject.render(as: .typename)): OneOfInputObject { + \(graphqlInputObject.fields.map({ "\(FieldCaseTemplate($1))" }), separator: "\n") + + \(memberAccessControl)var __data: InputDict { + switch self { + \(graphqlInputObject.fields.map({ "\(FieldCaseDataTemplate($1))" }), separator: "\n") + } + } + } + """ + ) + } + + private func FieldCaseTemplate(_ field: GraphQLInputField) -> TemplateString { + """ + \(documentation: field.documentation, config: config) + \(deprecationReason: field.deprecationReason, config: config) + \(field.name.typeNameDocumentation) + case \(field.render(config: config))(\(field.type.renderAsInputValue(inNullable: false, config: config.config))) + """ + } + + private func FieldCaseDataTemplate(_ field: GraphQLInputField) -> TemplateString { + """ + case .\(field.render(config: config))(let value): + return InputDict(["\(field.name.schemaName)": value]) + """ + } + +} diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLType+Rendered.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLType+Rendered.swift index 1e302dc94..388c3436a 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLType+Rendered.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLType+Rendered.swift @@ -71,7 +71,7 @@ extension GraphQLType { // MARK: Input Value - private func renderAsInputValue( + func renderAsInputValue( inNullable: Bool, config: ApolloCodegenConfiguration ) -> String { diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/SwiftPackageManagerModuleTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/SwiftPackageManagerModuleTemplate.swift index c544e1dfd..6a3d259c0 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/SwiftPackageManagerModuleTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/SwiftPackageManagerModuleTemplate.swift @@ -124,7 +124,7 @@ fileprivate extension ApolloCodegenConfiguration.SchemaTypesFileOutput.ModuleTyp """ case .local(let path): return """ - .package(path: "\(path)") + .package(name: "apollo-ios", path: "\(path)") """ } } diff --git a/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLSchema.swift b/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLSchema.swift index e3e9f804b..c6064ee5f 100644 --- a/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLSchema.swift +++ b/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLSchema.swift @@ -154,8 +154,11 @@ public typealias GraphQLInputFieldDictionary = OrderedDictionary