Skip to content

Commit

Permalink
fix(api): selection set with optional association
Browse files Browse the repository at this point in the history
  • Loading branch information
lawmicha committed Jun 2, 2020
1 parent c9e9ae8 commit e8b3f69
Show file tree
Hide file tree
Showing 11 changed files with 425 additions and 6 deletions.
36 changes: 32 additions & 4 deletions Amplify.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@
21420AA0237222A900FA140C /* AWSAuthorizationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21420A8D237222A900FA140C /* AWSAuthorizationType.swift */; };
2144226C234BDD9B009357F7 /* StorageUploadFileRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2144226B234BDD9B009357F7 /* StorageUploadFileRequest.swift */; };
2144226E234BDE23009357F7 /* StorageUploadFileOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2144226D234BDE23009357F7 /* StorageUploadFileOperation.swift */; };
214F49772486D8A200DA616C /* UserFollowers+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 214F49712486D8A100DA616C /* UserFollowers+Schema.swift */; };
214F49782486D8A200DA616C /* UserFollowing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 214F49722486D8A200DA616C /* UserFollowing.swift */; };
214F49792486D8A200DA616C /* UserFollowing+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 214F49732486D8A200DA616C /* UserFollowing+Schema.swift */; };
214F497A2486D8A200DA616C /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 214F49742486D8A200DA616C /* User.swift */; };
214F497B2486D8A200DA616C /* User+Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 214F49752486D8A200DA616C /* User+Schema.swift */; };
214F497C2486D8A200DA616C /* UserFollowers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 214F49762486D8A200DA616C /* UserFollowers.swift */; };
214F497E2486DA5000DA616C /* GraphQLRequestOptionalAssociationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 214F497D2486DA5000DA616C /* GraphQLRequestOptionalAssociationTests.swift */; };
21558E3E237BB4BF0032A5BB /* GraphQLRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21558E3D237BB4BF0032A5BB /* GraphQLRequest.swift */; };
21558E40237CB8640032A5BB /* GraphQLError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21558E3F237CB8640032A5BB /* GraphQLError.swift */; };
216879FE23636A0A004A056E /* RepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 216879FD23636A0A004A056E /* RepeatingTimer.swift */; };
Expand Down Expand Up @@ -302,6 +309,7 @@
B99EF4B723DB072000D821BC /* Temporal+Hashable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B99EF4B623DB072000D821BC /* Temporal+Hashable.swift */; };
B9A329CC243559BF00C5B80C /* TimeInterval+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9A329CB243559BF00C5B80C /* TimeInterval+Helper.swift */; };
B9A6A4E024452E0D00AC2792 /* AccessLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9A6A4DF24452E0D00AC2792 /* AccessLevel.swift */; };
B9AA09F12473CA29000E6FBB /* PostStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9AA09F02473CA29000E6FBB /* PostStatus.swift */; };
B9AE8FD923D8C609002742F9 /* TemporalFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9AE8FD823D8C609002742F9 /* TemporalFormat.swift */; };
B9AE8FDB23D8C643002742F9 /* TemporalFormat+Time.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9AE8FDA23D8C643002742F9 /* TemporalFormat+Time.swift */; };
B9AF547A23F324DB0059E6C4 /* TemporalOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9AF547923F324DB0059E6C4 /* TemporalOperation.swift */; };
Expand All @@ -310,7 +318,6 @@
B9B50DC423D917BB0086F1E1 /* TemporalFormat+Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9B50DC323D917BB0086F1E1 /* TemporalFormat+Date.swift */; };
B9B50DC623D918020086F1E1 /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9B50DC523D918020086F1E1 /* Date.swift */; };
B9B50DC823DA15890086F1E1 /* DataStoreError+Temporal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9B50DC723DA15890086F1E1 /* DataStoreError+Temporal.swift */; };
B9AA09F12473CA29000E6FBB /* PostStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9AA09F02473CA29000E6FBB /* PostStatus.swift */; };
B9B64A9F23FCBF7E00730B68 /* ModelValueConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9B64A9E23FCBF7E00730B68 /* ModelValueConverter.swift */; };
B9DCA263240F217C00075E22 /* AnyEncodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9DCA262240F217C00075E22 /* AnyEncodableTests.swift */; };
B9FAA10B23878122009414B4 /* ModelField+Association.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FAA10A23878122009414B4 /* ModelField+Association.swift */; };
Expand Down Expand Up @@ -706,6 +713,13 @@
21420A8D237222A900FA140C /* AWSAuthorizationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AWSAuthorizationType.swift; sourceTree = "<group>"; };
2144226B234BDD9B009357F7 /* StorageUploadFileRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageUploadFileRequest.swift; sourceTree = "<group>"; };
2144226D234BDE23009357F7 /* StorageUploadFileOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageUploadFileOperation.swift; sourceTree = "<group>"; };
214F49712486D8A100DA616C /* UserFollowers+Schema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UserFollowers+Schema.swift"; sourceTree = "<group>"; };
214F49722486D8A200DA616C /* UserFollowing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserFollowing.swift; sourceTree = "<group>"; };
214F49732486D8A200DA616C /* UserFollowing+Schema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UserFollowing+Schema.swift"; sourceTree = "<group>"; };
214F49742486D8A200DA616C /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
214F49752486D8A200DA616C /* User+Schema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "User+Schema.swift"; sourceTree = "<group>"; };
214F49762486D8A200DA616C /* UserFollowers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserFollowers.swift; sourceTree = "<group>"; };
214F497D2486DA5000DA616C /* GraphQLRequestOptionalAssociationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphQLRequestOptionalAssociationTests.swift; sourceTree = "<group>"; };
21558E3D237BB4BF0032A5BB /* GraphQLRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphQLRequest.swift; sourceTree = "<group>"; };
21558E3F237CB8640032A5BB /* GraphQLError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphQLError.swift; sourceTree = "<group>"; };
215F4BCAAB89FA54AA121BDE /* Pods-AmplifyAWSPlugins-AWSPluginsCore-AWSPinpointAnalyticsPlugin.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AmplifyAWSPlugins-AWSPluginsCore-AWSPinpointAnalyticsPlugin.release.xcconfig"; path = "Target Support Files/Pods-AmplifyAWSPlugins-AWSPluginsCore-AWSPinpointAnalyticsPlugin/Pods-AmplifyAWSPlugins-AWSPluginsCore-AWSPinpointAnalyticsPlugin.release.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1038,6 +1052,7 @@
B99EF4B623DB072000D821BC /* Temporal+Hashable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Temporal+Hashable.swift"; sourceTree = "<group>"; };
B9A329CB243559BF00C5B80C /* TimeInterval+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TimeInterval+Helper.swift"; sourceTree = "<group>"; };
B9A6A4DF24452E0D00AC2792 /* AccessLevel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessLevel.swift; sourceTree = "<group>"; };
B9AA09F02473CA29000E6FBB /* PostStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostStatus.swift; sourceTree = "<group>"; };
B9AE8FD823D8C609002742F9 /* TemporalFormat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemporalFormat.swift; sourceTree = "<group>"; };
B9AE8FDA23D8C643002742F9 /* TemporalFormat+Time.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TemporalFormat+Time.swift"; sourceTree = "<group>"; };
B9AF547923F324DB0059E6C4 /* TemporalOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemporalOperation.swift; sourceTree = "<group>"; };
Expand All @@ -1046,7 +1061,6 @@
B9B50DC323D917BB0086F1E1 /* TemporalFormat+Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TemporalFormat+Date.swift"; sourceTree = "<group>"; };
B9B50DC523D918020086F1E1 /* Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = "<group>"; };
B9B50DC723DA15890086F1E1 /* DataStoreError+Temporal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataStoreError+Temporal.swift"; sourceTree = "<group>"; };
B9AA09F02473CA29000E6FBB /* PostStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostStatus.swift; sourceTree = "<group>"; };
B9B64A9E23FCBF7E00730B68 /* ModelValueConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelValueConverter.swift; sourceTree = "<group>"; };
B9DCA262240F217C00075E22 /* AnyEncodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEncodableTests.swift; sourceTree = "<group>"; };
B9FAA10A23878122009414B4 /* ModelField+Association.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ModelField+Association.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1500,6 +1514,7 @@
2129BE322394828B006363A1 /* GraphQLRequestModelTests.swift */,
219A888623EB89C200BBC5F2 /* GraphQLRequestAnyModelWithSyncTests.swift */,
21A3FDB8246494CD00E76120 /* GraphQLRequestAuthRuleTests.swift */,
214F497D2486DA5000DA616C /* GraphQLRequestOptionalAssociationTests.swift */,
);
path = GraphQLRequest;
sourceTree = "<group>";
Expand Down Expand Up @@ -2182,8 +2197,8 @@
B952182D237E21B900F53237 /* Models */ = {
isa = PBXGroup;
children = (
B952182F237E21B900F53237 /* schema.graphql */,
FAF512AD23986791001ADF4E /* AmplifyModels.swift */,
B9FAA10C23878BD6009414B4 /* Associations */,
210B3E35245CB86500F43848 /* Blog.swift */,
210B3E38245CB88D00F43848 /* Blog+Schema.swift */,
B9521830237E21B900F53237 /* Comment.swift */,
Expand All @@ -2193,7 +2208,13 @@
B9521831237E21B900F53237 /* Post+Schema.swift */,
2129BE002394627B006363A1 /* PostCommentModelRegistration.swift */,
B9AA09F02473CA29000E6FBB /* PostStatus.swift */,
B9FAA10C23878BD6009414B4 /* Associations */,
B952182F237E21B900F53237 /* schema.graphql */,
214F49742486D8A200DA616C /* User.swift */,
214F49752486D8A200DA616C /* User+Schema.swift */,
214F49762486D8A200DA616C /* UserFollowers.swift */,
214F49712486D8A100DA616C /* UserFollowers+Schema.swift */,
214F49722486D8A200DA616C /* UserFollowing.swift */,
214F49732486D8A200DA616C /* UserFollowing+Schema.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -3958,6 +3979,7 @@
2183A56823EA4A8E00232880 /* GraphQLDeleteMutationTests.swift in Sources */,
21A3FDB42463C49F00E76120 /* ModelReadUpdateAuthRuleTests.swift in Sources */,
2183A56323EA4A7800232880 /* GraphQLSubscriptionTests.swift in Sources */,
214F497E2486DA5000DA616C /* GraphQLRequestOptionalAssociationTests.swift in Sources */,
2129BE562395CAF9006363A1 /* PaginatedListTests.swift in Sources */,
2183A56723EA4A8B00232880 /* GraphQLCreateMutationTests.swift in Sources */,
2183A56623EA4A8700232880 /* GraphQLSyncQueryTests.swift in Sources */,
Expand Down Expand Up @@ -4413,22 +4435,28 @@
B9FAA11823879A57009414B4 /* Author+Schema.swift in Sources */,
B9521836237E21BA00F53237 /* Post+Schema.swift in Sources */,
FA4A955F239ADEBD008E876E /* MockResponder.swift in Sources */,
214F497A2486D8A200DA616C /* User.swift in Sources */,
B9FAA11223878C96009414B4 /* UserAccount+Schema.swift in Sources */,
FACA36152327FC39000E74F6 /* MessageReporter.swift in Sources */,
FAF512AE23986791001ADF4E /* AmplifyModels.swift in Sources */,
B9FAA11C23879B35009414B4 /* Book.swift in Sources */,
210B3E39245CB88D00F43848 /* Blog+Schema.swift in Sources */,
214F49772486D8A200DA616C /* UserFollowers+Schema.swift in Sources */,
B9FAA11423878CEA009414B4 /* UserProfile+Schema.swift in Sources */,
214F49792486D8A200DA616C /* UserFollowing+Schema.swift in Sources */,
FACA361D2327FC84000E74F6 /* MockAPICategoryPlugin.swift in Sources */,
B9FAA11023878C5E009414B4 /* UserProfile.swift in Sources */,
B9AA09F12473CA29000E6FBB /* PostStatus.swift in Sources */,
210B3E36245CB86500F43848 /* Blog.swift in Sources */,
214F497B2486D8A200DA616C /* User+Schema.swift in Sources */,
B9FAA12023879BD0009414B4 /* BookAuthor+Schema.swift in Sources */,
21F40A4023A295470074678E /* TestCommonConstants.swift in Sources */,
214F497C2486D8A200DA616C /* UserFollowers.swift in Sources */,
B9521835237E21BA00F53237 /* Comment.swift in Sources */,
FACA361E2327FC8E000E74F6 /* MockAnalyticsCategoryPlugin.swift in Sources */,
2129BE012394627B006363A1 /* PostCommentModelRegistration.swift in Sources */,
B9FAA10E23878BF3009414B4 /* UserAccount.swift in Sources */,
214F49782486D8A200DA616C /* UserFollowing.swift in Sources */,
21F40A3C23A2952C0074678E /* AuthHelper.swift in Sources */,
B4F3E9FA24314ECC00F23296 /* MockAuthCategoryPlugin.swift in Sources */,
FA1846EE23998E44009B9D01 /* MockAPIResponders.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ extension SelectionSet {

func withModelFields(_ fields: [ModelField]) {
fields.forEach { field in
let isRequiredAssociation = field.isRequired && field.isAssociationOwner
if isRequiredAssociation, let associatedModel = field.associatedModel {
if field.isAssociationOwner, let associatedModel = field.associatedModel {
let child = SelectionSet(value: .init(name: field.name, fieldType: .model))
child.withModelFields(associatedModel.schema.graphQLFields)
self.addChild(settingParentOf: child)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
//
// Copyright 2018-2020 Amazon.com,
// Inc. or its affiliates. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import XCTest

@testable import Amplify
@testable import AmplifyTestCommon
@testable import AWSPluginsCore

class GraphQLRequestOptionalAssociationTests: XCTestCase {
override func setUp() {
ModelRegistry.register(modelType: User.self)
ModelRegistry.register(modelType: UserFollowing.self)
ModelRegistry.register(modelType: UserFollowers.self)
}

override func tearDown() {
ModelRegistry.reset()
}

func testCreateUserGraphQLRequest() {
let user = User(name: "username")
let documentStringValue = """
mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) {
id
name
__typename
}
}
"""
let request = GraphQLRequest<User>.create(user)
XCTAssertEqual(documentStringValue, request.document)

guard let variables = request.variables else {
XCTFail("The request doesn't contain variables")
return
}
guard let input = variables["input"] as? [String: Any] else {
XCTFail("The document variables property doesn't contain a valid input")
return
}
XCTAssertEqual(input["id"] as? String, user.id)
XCTAssertEqual(input["name"] as? String, user.name)
}

func testCreateUserFollowingGraphQLRequest() {
let user1 = User(name: "user1")
let user2 = User(name: "user2")
let userFollowing = UserFollowing(user: user1, followingUser: user2)
let documentStringValue = """
mutation CreateUserFollowing($input: CreateUserFollowingInput!) {
createUserFollowing(input: $input) {
id
followingUser {
id
name
__typename
}
user {
id
name
__typename
}
__typename
}
}
"""
let request = GraphQLRequest<User>.create(userFollowing)
XCTAssertEqual(documentStringValue, request.document)
guard let variables = request.variables else {
XCTFail("The request doesn't contain variables")
return
}
guard let input = variables["input"] as? [String: Any] else {
XCTFail("The document variables property doesn't contain a valid input")
return
}
XCTAssertEqual(input["id"] as? String, userFollowing.id)
XCTAssertEqual(input["userFollowingUserId"] as? String, user1.id)
XCTAssertEqual(input["userFollowingFollowingUserId"] as? String, user2.id)
}

func testQueryUserFollowingGraphQLRequest() {
let documentStringValue = """
query GetUserFollowing($id: ID!) {
getUserFollowing(id: $id) {
id
followingUser {
id
name
__typename
}
user {
id
name
__typename
}
__typename
}
}
"""
let request = GraphQLRequest<UserFollowing>.get(UserFollowing.self, byId: "id")
XCTAssertEqual(documentStringValue, request.document)
guard let variables = request.variables else {
XCTFail("The request doesn't contain variables")
return
}
XCTAssertEqual(variables["id"] as? String, "id")
}

func testQueryUserGraphQLRequest() {
let documentStringValue = """
query GetUser($id: ID!) {
getUser(id: $id) {
id
name
__typename
}
}
"""
let request = GraphQLRequest<UserFollowing>.get(User.self, byId: "id")
XCTAssertEqual(documentStringValue, request.document)
guard let variables = request.variables else {
XCTFail("The request doesn't contain variables")
return
}
XCTAssertEqual(variables["id"] as? String, "id")
}

func testListUserFollowingGraphQLRequest() {
let documentStringValue = """
query ListUserFollowings($limit: Int) {
listUserFollowings(limit: $limit) {
items {
id
followingUser {
id
name
__typename
}
user {
id
name
__typename
}
__typename
}
nextToken
}
}
"""
let request = GraphQLRequest<UserFollowing>.list(UserFollowing.self)
XCTAssertEqual(documentStringValue, request.document)
guard let variables = request.variables else {
XCTFail("The request doesn't contain variables")
return
}
XCTAssertEqual(variables["limit"] as? Int, 1_000)
}

func testSubscribeToUserFollowingGraphQLRequest() {
let documentStringValue = """
subscription OnCreateUserFollowing {
onCreateUserFollowing {
id
followingUser {
id
name
__typename
}
user {
id
name
__typename
}
__typename
}
}
"""
let request = GraphQLRequest<UserFollowing>.subscription(of: UserFollowing.self, type: .onCreate)
XCTAssertEqual(documentStringValue, request.document)
XCTAssertNil(request.variables)
}
}
Loading

0 comments on commit e8b3f69

Please sign in to comment.