Skip to content

Commit d6583e6

Browse files
authored
test(data): Gen2 data customize auth doc example testing (#3705)
* test(data): Gen2 data customize auth doc example testing * address PR comments
1 parent d2454d8 commit d6583e6

33 files changed

+1601
-19
lines changed

AmplifyPlugins/API/Tests/APIHostApp/APIHostApp.xcodeproj/project.pbxproj

Lines changed: 165 additions & 1 deletion
Large diffs are not rendered by default.

AmplifyPlugins/API/Tests/APIHostApp/AWSAPIPluginGen2GraphQLTests/AWSAPIPluginGen2GraphQLBaseTest.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ import XCTest
1010
@_spi(InternalAmplifyConfiguration) @testable import Amplify
1111
@testable import APIHostApp
1212
@testable import AWSPluginsCore
13+
import AWSCognitoAuthPlugin
1314

1415
class AWSAPIPluginGen2GraphQLBaseTest: XCTestCase {
1516

17+
var defaultTestEmail = "test-\(UUID().uuidString)@amazon.com"
18+
1619
var amplifyConfig: AmplifyOutputsData!
1720

1821
override func setUp() {
@@ -39,11 +42,15 @@ class AWSAPIPluginGen2GraphQLBaseTest: XCTestCase {
3942
/// Setup API with given models
4043
/// - Parameter models: DataStore models
4144
func setup(withModels models: AmplifyModelRegistration,
42-
logLevel: LogLevel = .verbose) async {
45+
logLevel: LogLevel = .verbose,
46+
withAuthPlugin: Bool = false) async {
4347
do {
4448
setupConfig()
4549
Amplify.Logging.logLevel = logLevel
4650
try Amplify.add(plugin: AWSAPIPlugin(modelRegistration: models))
51+
if withAuthPlugin {
52+
try Amplify.add(plugin: AWSCognitoAuthPlugin())
53+
}
4754
try Amplify.configure(amplifyConfig)
4855

4956
} catch {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import Amplify
9+
import XCTest
10+
11+
enum AuthSignInHelper {
12+
13+
static func signOut() async {
14+
let session = try? await Amplify.Auth.fetchAuthSession()
15+
if session?.isSignedIn ?? false {
16+
_ = await Amplify.Auth.signOut()
17+
}
18+
}
19+
20+
static func signUpUser(
21+
username: String,
22+
password: String,
23+
email: String,
24+
phoneNumber: String? = nil) async throws -> Bool {
25+
26+
var userAttributes = [
27+
AuthUserAttribute(.email, value: email)
28+
]
29+
30+
if let phoneNumber = phoneNumber {
31+
userAttributes.append(AuthUserAttribute(.phoneNumber, value: phoneNumber))
32+
}
33+
34+
let options = AuthSignUpRequest.Options(
35+
userAttributes: userAttributes)
36+
let result = try await Amplify.Auth.signUp(username: username, password: password, options: options)
37+
return result.isSignUpComplete
38+
}
39+
40+
static func signInUser(username: String, password: String) async throws -> AuthSignInResult {
41+
return try await Amplify.Auth.signIn(username: username, password: password, options: nil)
42+
}
43+
44+
static func registerAndSignInUser(
45+
username: String,
46+
password: String,
47+
email: String,
48+
phoneNumber: String? = nil) async throws -> Bool {
49+
await signOut()
50+
let signedUp = try await AuthSignInHelper.signUpUser(
51+
username: username,
52+
password: password,
53+
email: email,
54+
phoneNumber: phoneNumber)
55+
guard signedUp else {
56+
throw AuthError.invalidState("Auth sign up failed", "", nil)
57+
}
58+
let result = try await AuthSignInHelper.signInUser(username: username, password: password)
59+
return result.isSignedIn
60+
}
61+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import Foundation
9+
import XCTest
10+
@testable import Amplify
11+
12+
final class GraphQLPost11Tests: AWSAPIPluginGen2GraphQLBaseTest {
13+
14+
// Code Snippet for
15+
// https://docs.amplify.aws/swift/build-a-backend/data/customize-authz/#configure-multiple-authorization-rules
16+
func testCodeSnippet() async throws {
17+
await setup(withModels: Post11Models(), withAuthPlugin: true)
18+
let username = "integTest\(UUID().uuidString)"
19+
let password = "P123@\(UUID().uuidString)"
20+
do {
21+
_ = try await AuthSignInHelper.registerAndSignInUser(
22+
username: username,
23+
password: password,
24+
email: defaultTestEmail)
25+
} catch {
26+
XCTFail("Could not sign up and sign in user \(error)")
27+
}
28+
29+
// Code Snippet begins
30+
do {
31+
let post = Post(title: "Hello World")
32+
let createdTodo = try await Amplify.API.mutate(request: .create(
33+
post,
34+
authMode: .amazonCognitoUserPools)).get()
35+
} catch {
36+
print("Failed to create post", error)
37+
// Code Snippet Ends
38+
XCTFail("Failed to create post \(error)")
39+
// Code Snippet Begins
40+
}
41+
42+
// Code Snippet ends
43+
await AuthSignInHelper.signOut()
44+
// Code Snippet begins
45+
46+
do {
47+
let queriedPosts = try await Amplify.API.query(request: .list(
48+
Post.self,
49+
authMode: .awsIAM)).get()
50+
print("Number of posts:", queriedPosts.count)
51+
52+
// Code Snippet Ends
53+
XCTAssertTrue(queriedPosts.count > 0 || queriedPosts.hasNextPage())
54+
// Code Snippet Begins
55+
} catch {
56+
print("Failed to list posts", error)
57+
// Code Snippet Ends
58+
XCTFail("Failed to list posts \(error)")
59+
// Code Snippet Begins
60+
}
61+
}
62+
}
63+
64+
extension GraphQLPost11Tests: DefaultLogger { }
65+
66+
extension GraphQLPost11Tests {
67+
typealias Post = Post11
68+
69+
struct Post11Models: AmplifyModelRegistration {
70+
public let version: String = "version"
71+
func registerModels(registry: ModelRegistry.Type) {
72+
ModelRegistry.register(modelType: Post11.self)
73+
}
74+
}
75+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// swiftlint:disable all
2+
import Amplify
3+
import Foundation
4+
5+
extension Post11 {
6+
// MARK: - CodingKeys
7+
public enum CodingKeys: String, ModelKey {
8+
case id
9+
case title
10+
case content
11+
case createdAt
12+
case updatedAt
13+
}
14+
15+
public static let keys = CodingKeys.self
16+
// MARK: - ModelSchema
17+
18+
public static let schema = defineSchema { model in
19+
let post11 = Post11.keys
20+
21+
model.authRules = [
22+
rule(allow: .public, provider: .iam, operations: [.read]),
23+
rule(allow: .owner, ownerField: "owner", identityClaim: "cognito:username", provider: .userPools, operations: [.create, .update, .delete, .read])
24+
]
25+
26+
model.listPluralName = "Post11s"
27+
model.syncPluralName = "Post11s"
28+
29+
model.attributes(
30+
.primaryKey(fields: [post11.id])
31+
)
32+
33+
model.fields(
34+
.field(post11.id, is: .required, ofType: .string),
35+
.field(post11.title, is: .optional, ofType: .string),
36+
.field(post11.content, is: .optional, ofType: .string),
37+
.field(post11.createdAt, is: .optional, isReadOnly: true, ofType: .dateTime),
38+
.field(post11.updatedAt, is: .optional, isReadOnly: true, ofType: .dateTime)
39+
)
40+
}
41+
public class Path: ModelPath<Post11> { }
42+
43+
public static var rootPath: PropertyContainerPath? { Path() }
44+
}
45+
46+
extension Post11: ModelIdentifiable {
47+
public typealias IdentifierFormat = ModelIdentifierFormat.Default
48+
public typealias IdentifierProtocol = DefaultModelIdentifier<Self>
49+
}
50+
extension ModelPath where ModelType == Post11 {
51+
public var id: FieldPath<String> {
52+
string("id")
53+
}
54+
public var title: FieldPath<String> {
55+
string("title")
56+
}
57+
public var content: FieldPath<String> {
58+
string("content")
59+
}
60+
public var createdAt: FieldPath<Temporal.DateTime> {
61+
datetime("createdAt")
62+
}
63+
public var updatedAt: FieldPath<Temporal.DateTime> {
64+
datetime("updatedAt")
65+
}
66+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// swiftlint:disable all
2+
import Amplify
3+
import Foundation
4+
5+
public struct Post11: Model {
6+
public let id: String
7+
public var title: String?
8+
public var content: String?
9+
public var createdAt: Temporal.DateTime?
10+
public var updatedAt: Temporal.DateTime?
11+
12+
public init(id: String = UUID().uuidString,
13+
title: String? = nil,
14+
content: String? = nil) {
15+
self.init(id: id,
16+
title: title,
17+
content: content,
18+
createdAt: nil,
19+
updatedAt: nil)
20+
}
21+
internal init(id: String = UUID().uuidString,
22+
title: String? = nil,
23+
content: String? = nil,
24+
createdAt: Temporal.DateTime? = nil,
25+
updatedAt: Temporal.DateTime? = nil) {
26+
self.id = id
27+
self.title = title
28+
self.content = content
29+
self.createdAt = createdAt
30+
self.updatedAt = updatedAt
31+
}
32+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import Foundation
9+
import XCTest
10+
@testable import Amplify
11+
12+
final class GraphQLTodo12Tests: AWSAPIPluginGen2GraphQLBaseTest {
13+
14+
// Code Snippet for
15+
// https://docs.amplify.aws/react/build-a-backend/data/customize-authz/public-data-access/#add-public-authorization-rule-using-api-key-based-authentication
16+
func testCodeSnippet() async throws {
17+
await setup(withModels: Todo12Models())
18+
19+
// Code Snippet begins
20+
do {
21+
let todo = Todo(content: "My new todo")
22+
let createdTodo = try await Amplify.API.mutate(request: .create(
23+
todo,
24+
authMode: .apiKey)).get()
25+
} catch {
26+
print("Failed to create todo", error)
27+
// Code Snippet Ends
28+
XCTFail("Failed to create todo \(error)")
29+
// Code Snippet Begins
30+
}
31+
}
32+
}
33+
34+
extension GraphQLTodo12Tests: DefaultLogger { }
35+
36+
extension GraphQLTodo12Tests {
37+
typealias Todo = Todo12
38+
39+
struct Todo12Models: AmplifyModelRegistration {
40+
public let version: String = "version"
41+
func registerModels(registry: ModelRegistry.Type) {
42+
ModelRegistry.register(modelType: Todo12.self)
43+
}
44+
}
45+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// swiftlint:disable all
2+
import Amplify
3+
import Foundation
4+
5+
extension Todo12 {
6+
// MARK: - CodingKeys
7+
public enum CodingKeys: String, ModelKey {
8+
case id
9+
case content
10+
case createdAt
11+
case updatedAt
12+
}
13+
14+
public static let keys = CodingKeys.self
15+
// MARK: - ModelSchema
16+
17+
public static let schema = defineSchema { model in
18+
let todo12 = Todo12.keys
19+
20+
model.authRules = [
21+
rule(allow: .public, provider: .apiKey, operations: [.create, .update, .delete, .read])
22+
]
23+
24+
model.listPluralName = "Todo12s"
25+
model.syncPluralName = "Todo12s"
26+
27+
model.attributes(
28+
.primaryKey(fields: [todo12.id])
29+
)
30+
31+
model.fields(
32+
.field(todo12.id, is: .required, ofType: .string),
33+
.field(todo12.content, is: .optional, ofType: .string),
34+
.field(todo12.createdAt, is: .optional, isReadOnly: true, ofType: .dateTime),
35+
.field(todo12.updatedAt, is: .optional, isReadOnly: true, ofType: .dateTime)
36+
)
37+
}
38+
public class Path: ModelPath<Todo12> { }
39+
40+
public static var rootPath: PropertyContainerPath? { Path() }
41+
}
42+
43+
extension Todo12: ModelIdentifiable {
44+
public typealias IdentifierFormat = ModelIdentifierFormat.Default
45+
public typealias IdentifierProtocol = DefaultModelIdentifier<Self>
46+
}
47+
extension ModelPath where ModelType == Todo12 {
48+
public var id: FieldPath<String> {
49+
string("id")
50+
}
51+
public var content: FieldPath<String> {
52+
string("content")
53+
}
54+
public var createdAt: FieldPath<Temporal.DateTime> {
55+
datetime("createdAt")
56+
}
57+
public var updatedAt: FieldPath<Temporal.DateTime> {
58+
datetime("updatedAt")
59+
}
60+
}

0 commit comments

Comments
 (0)