⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content

Conversation

@stuartmorgan-g
Copy link
Collaborator

@stuartmorgan-g stuartmorgan-g commented Jan 13, 2026

Converts the existing native unit tests from Objective-C to Swift.

This was done as a few steps:

  • Direct conversion of the existing code (first pass by Gemini, but I checked it over and did some fixup).
  • Converted from XCTest to Swift Testing, for Migrate iOS plugin tests from XCTest to Swift Testing flutter#180787
  • Replaced global state with new loadGoogleServiceInfo and createTestPlugin helpers, because there was no reason the test needed to be so stateful, and removing the state makes the test-specific setup easier to follow (e.g., a subset of the tests didn't actually use the test-global plugin instance, but instead replaced it with a local copy, which made things confusing when moving between tests). It also allows adding suites.
  • Added suites for each method.
  • Combined some tests into parameterized tests.

Part of flutter/flutter#119103
Part of flutter/flutter#180787

Pre-Review Checklist

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. 2 3

@stuartmorgan-g
Copy link
Collaborator Author

@jmagman Do you want to review the Swift Testing aspect here since you've been looking at it? (This PR was prompted by wanting to get some hands-on experience with Swift Testing, and I'd been wanting to do the Swift conversion here already, so it seemed like a good opportunity to do both.)

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a great step forward, successfully converting the iOS unit tests from Objective-C to Swift and adopting the new Swift Testing framework. The code is well-structured, and the refactoring to reduce global state by introducing helper functions significantly improves test isolation and readability. I have a few minor suggestions to further enhance the clarity and robustness of the new Swift tests.

#expect(result?.error == nil)
#expect(result?.success != nil)
#expect(result?.success?.user.displayName == fakeUserProfile.name)
#expect(result?.success?.user.email == fakeUserProfile.email)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see warnings in Xcode:

Implicit capture of 'fakeUserProfile' requires that 'TestProfileData' conforms to 'Sendable'
Class 'TestProfileData' does not conform to the 'Sendable' protocol

Do the test fake helper classes inheriting from Objective-C classes need @unchecked Sendable?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I adjusted the test to only pass primitive types into the callback, rather than the test types.

Comment on lines 568 to 603
@Test func refreshTokensNoAuthKeychainError() async {
let plugin = createTestPlugin()
let fakeUser = addSignedInUser(to: plugin)

let sdkError = NSError(
domain: kGIDSignInErrorDomain, code: GIDSignInError.hasNoAuthInKeychain.rawValue,
userInfo: nil)
fakeUser.error = sdkError

await confirmation("completion called") { confirmed in
plugin.refreshedAuthorizationTokens(forUser: fakeUser.userID!) { result, error in
#expect(error == nil)
#expect(result?.success == nil)
#expect(result?.error?.type == .noAuthInKeychain)
confirmed()
}
}
}

@Test func refreshTokensCancelledError() async {
let plugin = createTestPlugin()
let fakeUser = addSignedInUser(to: plugin)

let sdkError = NSError(
domain: kGIDSignInErrorDomain, code: GIDSignInError.canceled.rawValue, userInfo: nil)
fakeUser.error = sdkError

await confirmation("completion called") { confirmed in
plugin.refreshedAuthorizationTokens(forUser: fakeUser.userID!) { result, error in
#expect(error == nil)
#expect(result?.success == nil)
#expect(result?.error?.type == .canceled)
confirmed()
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can get pretty cute with test parameterization (if you want to in this review, or the mechanical change is fine too).

For example, you can collapse these two tests into one, with parameters:

Suggested change
@Test func refreshTokensNoAuthKeychainError() async {
let plugin = createTestPlugin()
let fakeUser = addSignedInUser(to: plugin)
let sdkError = NSError(
domain: kGIDSignInErrorDomain, code: GIDSignInError.hasNoAuthInKeychain.rawValue,
userInfo: nil)
fakeUser.error = sdkError
await confirmation("completion called") { confirmed in
plugin.refreshedAuthorizationTokens(forUser: fakeUser.userID!) { result, error in
#expect(error == nil)
#expect(result?.success == nil)
#expect(result?.error?.type == .noAuthInKeychain)
confirmed()
}
}
}
@Test func refreshTokensCancelledError() async {
let plugin = createTestPlugin()
let fakeUser = addSignedInUser(to: plugin)
let sdkError = NSError(
domain: kGIDSignInErrorDomain, code: GIDSignInError.canceled.rawValue, userInfo: nil)
fakeUser.error = sdkError
await confirmation("completion called") { confirmed in
plugin.refreshedAuthorizationTokens(forUser: fakeUser.userID!) { result, error in
#expect(error == nil)
#expect(result?.success == nil)
#expect(result?.error?.type == .canceled)
confirmed()
}
}
}
@Test(arguments: [
(GIDSignInError.hasNoAuthInKeychain.rawValue, FSIGoogleSignInErrorCode.noAuthInKeychain),
(GIDSignInError.canceled.rawValue, .canceled),
])
func refreshTokensKnownErrors(
errorCode: Int,
expectedErrorCode: FSIGoogleSignInErrorCode
) async {
let plugin = createTestPlugin()
let fakeUser = addSignedInUser(to: plugin)
fakeUser.error = NSError(domain: kGIDSignInErrorDomain, code: errorCode, userInfo: nil)
await confirmation("completion called") { confirmed in
plugin.refreshedAuthorizationTokens(forUser: fakeUser.userID!) { result, error in
#expect(error == nil)
#expect(result?.success == nil)
#expect(result?.error?.type == expectedErrorCode)
confirmed()
}
}
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've parameterized several sets of tests. Unfortunately we lose the helpful test names (e.g. refreshTokensNoAuthKeychainError is now refreshTokensGIDSignInErrorDomainErrors > -4, FSIGoogleSignInErrorCode(rawValue: 2)), but I don't think that's probably a big deal. If it becomes annoying we can always add an extra fake initial parameter that's the test "name".

I also did a bit more refactoring to make the test fixture fully stateless so that I could adopt suites, and group each method's tests into a suite.

@stuartmorgan-g stuartmorgan-g added the override: no changelog needed Override the check requiring CHANGELOG updates for most changes label Jan 14, 2026
@stuartmorgan-g stuartmorgan-g added the override: no versioning needed Override the check requiring version bumps for most changes label Jan 14, 2026
@stuartmorgan-g

This comment was marked as outdated.

var exception: NSException?

// Results to use in completion callbacks.
var user: FSIGIDGoogleUser?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought FSIGIDGoogleUser is now a protocol so it is supposed to be an existential type here (any FSIGIDGoogleUser?)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, my Swift experience is still thin, and I'd missed the memo on the switch to explicit existentials in more recent versions of Swift. I think I've fixed all the cases here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. On a side note I didn't know they were planning to enforce that, created flutter/flutter#181005

@stuartmorgan-g stuartmorgan-g removed override: no versioning needed Override the check requiring version bumps for most changes override: no changelog needed Override the check requiring CHANGELOG updates for most changes labels Jan 14, 2026
@stuartmorgan-g
Copy link
Collaborator Author

I forgot Swift imports don't like Obj-C submodules. I'm not sure why it was failing in CI but working locally (Xcode version?) but to resolve it I just removed the modulemap, so there's no longer a distinction between test and non-test headers; this is the same thing we've had to do with some other plugins.

It shouldn't actually affect anything, since nobody should be importing the native framework anyway, but also it'll be temporary since I plan to convert the plugin to Swift shortly anyway.

@stuartmorgan-g
Copy link
Collaborator Author

(I did add a version bump though, since it's no longer a test-only change, even though I don't expect any client impact.)

@stuartmorgan-g stuartmorgan-g added the autosubmit Merge PR when tree becomes green via auto submit App label Jan 15, 2026
@auto-submit auto-submit bot merged commit 1252fdb into flutter:main Jan 15, 2026
81 checks passed
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jan 15, 2026
github-merge-queue bot pushed a commit to flutter/flutter that referenced this pull request Jan 15, 2026
flutter/packages@98b0325...ce3afa4

2026-01-15 [email protected] Manual roll Flutter from
793b0b8 to b45a73b (8 revisions) (flutter/packages#10799)
2026-01-15 [email protected] [path_provider] Re-release FFI
foundation version (flutter/packages#10722)
2026-01-15 [email protected] [google_sign_in] Convert iOS tests to
Swift (flutter/packages#10787)
2026-01-14 [email protected] [video_player] Update for UIScene
compatibility (flutter/packages#10676)
2026-01-14 [email protected] [pointer_interceptor_ios] Migrate XCTest to
Swift Testing (flutter/packages#10762)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC [email protected] on the revert to ensure that a
human
is aware of the problem.

To file a bug in Flutter:
https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
ikramhasan pushed a commit to ikramhasan/flutter that referenced this pull request Jan 15, 2026
…r#181035)

flutter/packages@98b0325...ce3afa4

2026-01-15 [email protected] Manual roll Flutter from
793b0b8 to b45a73b (8 revisions) (flutter/packages#10799)
2026-01-15 [email protected] [path_provider] Re-release FFI
foundation version (flutter/packages#10722)
2026-01-15 [email protected] [google_sign_in] Convert iOS tests to
Swift (flutter/packages#10787)
2026-01-14 [email protected] [video_player] Update for UIScene
compatibility (flutter/packages#10676)
2026-01-14 [email protected] [pointer_interceptor_ios] Migrate XCTest to
Swift Testing (flutter/packages#10762)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC [email protected] on the revert to ensure that a
human
is aware of the problem.

To file a bug in Flutter:
https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App p: google_sign_in platform-ios platform-macos

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants