Skip to content

Commit 6f984ac

Browse files
authored
test(auth): update user after anonymous sign in (#433)
1 parent 7b0d661 commit 6f984ac

File tree

4 files changed

+141
-2
lines changed

4 files changed

+141
-2
lines changed

Examples/Examples.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
79AF04862B2CE586008761AD /* Debug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79AF04852B2CE586008761AD /* Debug.swift */; };
4444
79B1C80C2BABFF8000D991AA /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79B1C80B2BABFF8000D991AA /* ProfileView.swift */; };
4545
79B1C80E2BAC017C00D991AA /* AnyJSONView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79B1C80D2BAC017C00D991AA /* AnyJSONView.swift */; };
46+
79B3261C2BF359A50023661C /* UpdateProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79B3261B2BF359A50023661C /* UpdateProfileView.swift */; };
4647
79B8F4242B5FED7C0000E839 /* IdentifiedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 79B8F4232B5FED7C0000E839 /* IdentifiedCollections */; };
4748
79B8F4262B602F640000E839 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79B8F4252B602F640000E839 /* Logger.swift */; };
4849
79BD76772B59C3E300CA3D68 /* UserStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79BD76762B59C3E300CA3D68 /* UserStore.swift */; };
@@ -111,6 +112,7 @@
111112
79AF04852B2CE586008761AD /* Debug.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Debug.swift; sourceTree = "<group>"; };
112113
79B1C80B2BABFF8000D991AA /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = "<group>"; };
113114
79B1C80D2BAC017C00D991AA /* AnyJSONView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyJSONView.swift; sourceTree = "<group>"; };
115+
79B3261B2BF359A50023661C /* UpdateProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateProfileView.swift; sourceTree = "<group>"; };
114116
79B8F4252B602F640000E839 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
115117
79BD76762B59C3E300CA3D68 /* UserStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserStore.swift; sourceTree = "<group>"; };
116118
79BD76782B59C53900CA3D68 /* ChannelStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelStore.swift; sourceTree = "<group>"; };
@@ -273,6 +275,7 @@
273275
children = (
274276
79B1C80B2BABFF8000D991AA /* ProfileView.swift */,
275277
794C61D52BAD1E12000E6B0F /* UserIdentityList.swift */,
278+
79B3261B2BF359A50023661C /* UpdateProfileView.swift */,
276279
);
277280
path = Profile;
278281
sourceTree = "<group>";
@@ -498,6 +501,7 @@
498501
793895CC2954ABFF0044F2B8 /* RootView.swift in Sources */,
499502
7956406A2955AFBD0088A06F /* ErrorText.swift in Sources */,
500503
79AF04812B2CE261008761AD /* AuthView.swift in Sources */,
504+
79B3261C2BF359A50023661C /* UpdateProfileView.swift in Sources */,
501505
794EF1242955F3DE008C9526 /* TodoListRow.swift in Sources */,
502506
797EFB662BABD82A00098D6B /* BucketList.swift in Sources */,
503507
79E2B55C2B97A2310042CD21 /* UIApplicationExtensions.swift in Sources */,

Examples/Examples/Profile/ProfileView.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,17 @@ struct ProfileView: View {
1818
var body: some View {
1919
NavigationStack {
2020
List {
21-
if let user = user.flatMap({ try? AnyJSON($0) }) {
21+
if let user,
22+
let json = try? AnyJSON(user) {
2223
Section {
23-
AnyJSONView(value: user)
24+
AnyJSONView(value: json)
25+
}
26+
}
27+
28+
if let user {
29+
NavigationLink("Update profile") {
30+
UpdateProfileView(user: user)
31+
.navigationTitle("Update profile")
2432
}
2533
}
2634

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
//
2+
// UpdateProfileView.swift
3+
// Examples
4+
//
5+
// Created by Guilherme Souza on 14/05/24.
6+
//
7+
8+
import SwiftUI
9+
import Supabase
10+
11+
struct UpdateProfileView: View {
12+
let user: User
13+
14+
@State var email = ""
15+
@State var phone = ""
16+
17+
@State var otp = ""
18+
@State var showTokenField = false
19+
20+
var formUpdated: Bool {
21+
emailChanged || phoneChanged
22+
}
23+
24+
var emailChanged: Bool {
25+
email != user.email
26+
}
27+
28+
var phoneChanged: Bool {
29+
phone != user.phone
30+
}
31+
32+
var body: some View {
33+
Form {
34+
Section {
35+
TextField("Email", text: $email)
36+
.textContentType(.emailAddress)
37+
.keyboardType(.emailAddress)
38+
.autocorrectionDisabled()
39+
.textInputAutocapitalization(.never)
40+
TextField("Phone", text: $phone)
41+
.textContentType(.telephoneNumber)
42+
.keyboardType(.phonePad)
43+
.autocorrectionDisabled()
44+
.textInputAutocapitalization(.never)
45+
}
46+
47+
Section {
48+
Button("Update") {
49+
Task {
50+
await updateButtonTapped()
51+
}
52+
}
53+
.disabled(!formUpdated)
54+
}
55+
56+
if showTokenField {
57+
Section {
58+
TextField("OTP", text: $otp)
59+
Button("Verify") {
60+
Task {
61+
await verifyTapped()
62+
}
63+
}
64+
}
65+
}
66+
}
67+
.onAppear {
68+
email = user.email ?? ""
69+
phone = user.phone ?? ""
70+
}
71+
}
72+
73+
@MainActor
74+
private func updateButtonTapped() async {
75+
var attributes = UserAttributes()
76+
if emailChanged {
77+
attributes.email = email
78+
}
79+
80+
if phoneChanged {
81+
attributes.phone = phone
82+
}
83+
84+
do {
85+
try await supabase.auth.update(user: attributes, redirectTo: Constants.redirectToURL)
86+
87+
if phoneChanged {
88+
showTokenField = true
89+
}
90+
} catch {
91+
debug("Fail to update user: \(error)")
92+
}
93+
}
94+
95+
@MainActor
96+
private func verifyTapped() async {
97+
do {
98+
try await supabase.auth.verifyOTP(phone: phone, token: otp, type: .phoneChange)
99+
} catch {
100+
debug("Fail to verify OTP: \(error)")
101+
}
102+
}
103+
}
104+
105+
#Preview {
106+
UpdateProfileView(
107+
user: User(
108+
id: UUID(),
109+
appMetadata: [:],
110+
userMetadata: [:],
111+
aud: "",
112+
createdAt: Date(),
113+
updatedAt: Date()
114+
)
115+
)
116+
}

Tests/IntegrationTests/AuthClientIntegrationTests.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,17 @@ final class AuthClientIntegrationTests: XCTestCase {
193193
}
194194
}
195195

196+
func testSignInAnonymousAndLinkUserWithEmail() async throws {
197+
try await XCTAssertAuthChangeEvents([.initialSession, .signedIn, .userUpdated]) {
198+
try await authClient.signInAnonymously()
199+
200+
let email = mockEmail()
201+
let user = try await authClient.update(user: UserAttributes(email: email))
202+
203+
XCTAssertEqual(user.newEmail, email)
204+
}
205+
}
206+
196207
func testDeleteAccountAndSignOut() async throws {
197208
let response = try await signUpIfNeededOrSignIn(email: mockEmail(), password: mockPassword())
198209

0 commit comments

Comments
 (0)