Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PSG-4629 #77

Merged
merged 52 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
5d14604
Passkey refactored
SinaSeylani Sep 4, 2024
e99ac73
OTP refactored
SinaSeylani Sep 4, 2024
a3704d4
Merge pull request #64 from passageidentity/PSG-4630
SinaSeylani Sep 4, 2024
ae51566
Merge remote-tracking branch 'origin/PSG-4629' into PSG-4632
SinaSeylani Sep 4, 2024
64f0916
passage_flutter updated
SinaSeylani Sep 4, 2024
29995d5
magiclink refactored
SinaSeylani Sep 5, 2024
a344fa6
social refactored
SinaSeylani Sep 5, 2024
bba2d6e
language added
SinaSeylani Sep 5, 2024
cd11cc4
language added
SinaSeylani Sep 5, 2024
fe5fc32
comments updated
SinaSeylani Sep 5, 2024
8122f6a
Magiclink class added
SinaSeylani Sep 5, 2024
ceb1e00
OneTimePasscode class added
SinaSeylani Sep 5, 2024
2657efd
AuthResult is not nullable for status
SinaSeylani Sep 5, 2024
6b5cc41
Merge pull request #66 from passageidentity/PSG-4631
SinaSeylani Sep 5, 2024
3b1f7fb
Merge branch 'PSG-4629' into PSG-4632
SinaSeylani Sep 5, 2024
2b704da
Merge pull request #65 from passageidentity/PSG-4632
SinaSeylani Sep 5, 2024
a45cb06
Merge remote-tracking branch 'origin/PSG-4629' into PSG-4633
SinaSeylani Sep 5, 2024
f0c2955
More refactoring for social
SinaSeylani Sep 5, 2024
257e8c3
ios func is back
SinaSeylani Sep 6, 2024
76fcf02
Hosted refactored
SinaSeylani Sep 6, 2024
5d50f22
Merge pull request #67 from passageidentity/PSG-4633
SinaSeylani Sep 6, 2024
876cc3d
Merge pull request #68 from passageidentity/PSG-4634
SinaSeylani Sep 6, 2024
fdd3dc3
Current user refactored
SinaSeylani Sep 6, 2024
6dde49d
Merge pull request #69 from passageidentity/PSG-4635
SinaSeylani Sep 9, 2024
c7fdab1
App class refactored
SinaSeylani Sep 9, 2024
1e37613
token store class refactored
SinaSeylani Sep 9, 2024
5588ab9
Var added to the passageflutter class
SinaSeylani Sep 9, 2024
cdaf3df
comments updated
SinaSeylani Sep 10, 2024
634a76c
Merge pull request #71 from passageidentity/PSG-4636
SinaSeylani Sep 10, 2024
1a47ba9
Camel cases varaibles removed
SinaSeylani Sep 10, 2024
e01b667
Merge branch 'PSG-4629' into PSG-4682
SinaSeylani Sep 10, 2024
fe3a436
Merge pull request #70 from passageidentity/PSG-4682
SinaSeylani Sep 10, 2024
dc5a6cb
method channels updated for android
SinaSeylani Sep 12, 2024
5e5098c
Merge pull request #72 from passageidentity/PSG-4641
SinaSeylani Sep 13, 2024
f65bedb
Method channels updated for JS
SinaSeylani Sep 17, 2024
ee0e411
Extra tests removed
SinaSeylani Sep 17, 2024
3e5f442
Merge pull request #73 from passageidentity/PSG-4643
SinaSeylani Sep 17, 2024
e2f0c09
Tests refactored, passage app class updated, passage current user cla…
SinaSeylani Sep 18, 2024
44c42f6
Merge pull request #74 from passageidentity/PSG-4644
SinaSeylani Sep 19, 2024
7ac7a93
ios code updated with passageswift
SinaSeylani Sep 20, 2024
1b2f31d
Merge pull request #75 from passageidentity/PSG-4642
SinaSeylani Sep 24, 2024
3d4fb71
Code updated for JS, Android and Ios
SinaSeylani Sep 27, 2024
9ce20d5
Merge remote-tracking branch 'origin/PSG-4629' into PSG-4821
SinaSeylani Sep 27, 2024
a6a1e86
CurrentUser.metadata can return null value
SinaSeylani Sep 27, 2024
a0a9dc1
Merge pull request #76 from passageidentity/PSG-4821
SinaSeylani Sep 27, 2024
ed71577
Extra comment removed
SinaSeylani Sep 27, 2024
8c48aaf
workflow updated
SinaSeylani Sep 27, 2024
6e05ded
tests updated
SinaSeylani Sep 27, 2024
2426884
pod updated, tests updated
SinaSeylani Sep 27, 2024
4cc4960
wofklow updated for ios
SinaSeylani Oct 1, 2024
130ad86
ios tests fixes
SinaSeylani Oct 1, 2024
12aa0cb
AppId is mandotory for init passage
SinaSeylani Oct 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- name: Set up Google Chrome and ChromeDriver
uses: browser-actions/setup-chrome@v1
with:
chrome-version: 127
chrome-version: 129
install-chromedriver: true
install-dependencies: true

Expand Down Expand Up @@ -135,12 +135,13 @@ jobs:
working-directory: ./integrationtestapp

- name: Install simulator
id: install-simulator
uses: futureware-tech/simulator-action@v3
with:
model: 'iPhone 14'

- name: Run iOS tests
run: flutter test integration_test/*.dart -d 2CBBC7F8-8C98-4142-8292-D5833BB30F8F --dart-define=MAILOSAUR_API_KEY=${{ secrets.MAILOSAUR_API_KEY }}
run: flutter test integration_test/*.dart -d ${{ steps.install-simulator.outputs.udid }} --dart-define=MAILOSAUR_API_KEY=${{ secrets.MAILOSAUR_API_KEY }}
working-directory: ./integrationtestapp
env:
MAILOSAUR_API_KEY: ${{ secrets.MAILOSAUR_API_KEY }}
5 changes: 4 additions & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ android {
dependencies {
testImplementation 'org.jetbrains.kotlin:kotlin-test'
testImplementation 'org.mockito:mockito-core:5.0.0'
implementation 'id.passage.android:passage:1.8.2'
implementation 'id.passage.android:passage:2.0.1'
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1'
implementation 'androidx.annotation:annotation:1.8.2'
}

testOptions {
Expand Down
3 changes: 1 addition & 2 deletions android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
rootProject.name = 'passage_flutter'
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
Expand All @@ -22,5 +21,5 @@ plugins {
id "com.android.application" version "8.5.2" apply false
id "org.jetbrains.kotlin.android" version "2.0.10" apply false
}

rootProject.name = 'passage_flutter'
include ":app"
398 changes: 292 additions & 106 deletions android/src/main/kotlin/id/passage/passage_flutter/PassageFlutter.kt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ internal enum class PassageFlutterError {
PASSKEY_ERROR,
USER_CANCELLED,
USER_UNAUTHORIZED,
USER_NOT_FOUND,
USER_INACTIVE,
USER_REQUEST,
USER_SERVER_ERROR,
METADATA_APP_NOT_FOUND,
METADATA_INVALID,
METADATA_FORBIDDEN,
METADATA_SERVER_ERROR,
OTP_ERROR,
MAGIC_LINK_ERROR,
TOKEN_ERROR,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package id.passage.passage_flutter

import id.passage.android.PassageAuthResult
import id.passage.android.model.AuthResult

internal fun PassageAuthResult.convertToMap(): HashMap<String, Any> {
internal fun AuthResult.convertToMap(): HashMap<String, Any> {
val authResultHashMap: HashMap<String, Any> = hashMapOf(
"auth_token" to authToken,
"redirect_url" to redirectUrl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,14 @@ class PassageFlutterPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {

override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (passageFlutter == null) {
passageFlutter = if (call.method == "initWithAppId") {
if (call.method == "initialize") {
val appId = call.argument<String>("appId") ?: return invalidArgumentError(result)
PassageFlutter(activity, appId)
} else {
PassageFlutter(activity)
passageFlutter = PassageFlutter(activity, appId)
}
}

when (call.method) {
"initWithAppId" -> {}
"overrideBasePath" -> {
passageFlutter?.overrideBasePath(call, result)
}
"initialize" -> {}
"registerWithPasskey" -> passageFlutter?.registerWithPasskey(call, result)
"loginWithPasskey" -> passageFlutter?.loginWithPasskey(call, result)
"deviceSupportsPasskeys" -> passageFlutter?.deviceSupportsPasskeys(result)
Expand All @@ -73,7 +68,12 @@ class PassageFlutterPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
"changePhone" -> passageFlutter?.changePhone(call, result)
"hostedAuthStart" -> passageFlutter?.hostedAuthStart(result)
"hostedAuthFinish" -> passageFlutter?.hostedAuthFinish(call, result)
"hostedLogout" -> passageFlutter?.hostedLogout(result)
"passkeys" -> passageFlutter?.passkeys(result);
"socialConnections" -> passageFlutter?.socialConnections(result)
"deleteSocialConnection" -> passageFlutter?.deleteSocialConnection(call, result)
"metaData" -> passageFlutter?.metaData(result);
"updateMetaData" -> passageFlutter?.updateMetaData(call, result)
"createUser" -> passageFlutter?.createUser(call, result)
else -> {
result.notImplemented()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="passage_auth_origin">YOUR_AUTH_ORIGIN</string>
<string name="passage_auth_origin">try-uat.passage.dev</string>
<string name="clientApiBasePath">https://auth-uat.passage.dev/v1</string>
<string name="asset_statements">
[{
\"include\": \"https://@string/passage_auth_origin/.well-known/assetlinks.json\"
Expand Down
57 changes: 57 additions & 0 deletions integrationtestapp/integration_test/app_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:passage_flutter/passage_flutter.dart';
import 'helper/integration_test_config.dart';
import 'package:integration_test/integration_test.dart';

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
PassageFlutter passage = PassageFlutter(IntegrationTestConfig.appIdPassage);

setUp(() async {
if (!kIsWeb) {
String basePath = IntegrationTestConfig.apiBaseUrl;
}
});


group('PassageAppTests', () {
test('testAppInfo', () async {
try {
final appInfo = await passage.app.info();
expect(appInfo.id.toString(), IntegrationTestConfig.appIdPassage);
} catch (e) {
fail('Test failed due to unexpected exception: $e');
}
});

test('testUserExists', () async {
try {
const identifier = IntegrationTestConfig.existingUserPassage;
final userInfo = await passage.app.userExists(identifier);
expect(userInfo, isNotNull);
} catch (e) {
fail('Test failed due to unexpected exception: $e');
}
});

test('testUserDoesNotExist', () async {
try {
final identifier = 'nonexistent_${DateTime.now().millisecondsSinceEpoch}@example.com';
final userInfo = await passage.app.userExists(identifier);
fail('Expected PassageError but got success');
} catch (e) {
//success
}
});

test('testUserDoesExist', () async {
try {
final newUser = await passage.app.createUser('newuser_${DateTime.now().millisecondsSinceEpoch}@example.com');
expect(newUser, isNotNull);
} catch (e) {
fail('Test failed due to unexpected exception: $e');
}
});
});
}
17 changes: 8 additions & 9 deletions integrationtestapp/integration_test/change_user_info_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ void main() {
setUp(() async {
if (!kIsWeb) {
String basePath = IntegrationTestConfig.apiBaseUrl;
await passage.overrideBasePath(basePath);
}
});

tearDown(() async {
try {
await passage.signOut();
await passage.currentUser.logout();
} catch (e) {
// an error happened during sign out
}
Expand All @@ -29,14 +28,14 @@ void main() {
Future<void> loginWithMagicLink() async {
try {
await passage
.newLoginMagicLink(IntegrationTestConfig.existingUserEmailMagicLink);
.magliclink.login(IntegrationTestConfig.existingUserEmailMagicLink);
await Future.delayed(const Duration(
milliseconds: IntegrationTestConfig.waitTimeMilliseconds));
final magicLinkStr = await MailosaurAPIClient.getMostRecentMagicLink();
if (magicLinkStr.isEmpty) {
fail('Test failed: Magic link is empty');
}
await passage.magicLinkActivate(magicLinkStr);
await passage.magliclink.activate(magicLinkStr);
} catch (e) {
fail('Expected to activate login magic link, but got an exception: $e');
}
Expand All @@ -48,7 +47,7 @@ void main() {
await loginWithMagicLink();
final date = DateTime.now().millisecondsSinceEpoch;
final identifier = '[email protected]';
final response = await passage.changeEmail(identifier);
final response = await passage.currentUser.changeEmail(identifier);
expect(response, isNotNull);
} catch (e) {
fail('Test failed due to unexpected exception: $e');
Expand All @@ -57,10 +56,10 @@ void main() {

test('testChangeEmailUnAuthed', () async {
try {
await passage.signOut();
await passage.currentUser.logout();
final date = DateTime.now().millisecondsSinceEpoch;
final identifier = '[email protected]';
await passage.changeEmail(identifier);
await passage.currentUser.changeEmail(identifier);
fail('Test should throw PassageError');
} catch (e) {
if (e is PassageError) {
Expand All @@ -74,7 +73,7 @@ void main() {
test('testChangePhoneInvalid', () async {
try {
await loginWithMagicLink();
final response = await passage.changePhone('444');
final response = await passage.currentUser.changePhone('444');
expect(response, isNotNull);
fail('Test should throw PassageError');
} catch (e) {
Expand All @@ -88,7 +87,7 @@ void main() {

test('testChangePhoneUnAuthed', () async {
try {
await passage.changePhone('+14155552671');
await passage.currentUser.changePhone('+14155552671');
fail('Test should throw PassageError');
} catch (e) {
if (e is PassageError) {
Expand Down
97 changes: 79 additions & 18 deletions integrationtestapp/integration_test/current_user_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:passage_flutter/passage_flutter.dart';
import 'package:passage_flutter/passage_flutter_models/meta_data.dart';
import 'package:passage_flutter/passage_flutter_models/passage_social_connection.dart';
import 'package:passage_flutter/passage_flutter_models/passage_user_social_connections.dart';
import 'package:passage_flutter/passage_flutter_models/passkey.dart';
import 'helper/integration_test_config.dart';
import 'helper/mailosaur_api_client.dart';
import 'package:flutter/foundation.dart';
Expand All @@ -10,16 +14,15 @@ void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
PassageFlutter passage = PassageFlutter(IntegrationTestConfig.appIdMagicLink);

setUp(() async {
setUpAll(() async {
if (!kIsWeb) {
String basePath = IntegrationTestConfig.apiBaseUrl;
await passage.overrideBasePath(basePath);
}
});

tearDown(() async {
try {
await passage.signOut();
await passage.currentUser.logout();
} catch (e) {
// an error happened during sign out
}
Expand All @@ -28,14 +31,15 @@ void main() {
Future<void> loginWithMagicLink() async {
try {
await passage
.newLoginMagicLink(IntegrationTestConfig.existingUserEmailMagicLink);
await Future.delayed(const Duration(
milliseconds: IntegrationTestConfig.waitTimeMilliseconds));
.magliclink
.login(IntegrationTestConfig.existingUserEmailMagicLink);
await Future.delayed(
const Duration(milliseconds: IntegrationTestConfig.waitTimeMilliseconds));
final magicLinkStr = await MailosaurAPIClient.getMostRecentMagicLink();
if (magicLinkStr.isEmpty) {
fail('Test failed: Magic link is empty');
}
await passage.magicLinkActivate(magicLinkStr);
await passage.magliclink.activate(magicLinkStr);
} catch (e) {
fail('Expected to activate login magic link, but got an exception: $e');
}
Expand All @@ -45,15 +49,15 @@ void main() {
test('testCurrentUser', () async {
try {
await loginWithMagicLink();
final response = await passage.getCurrentUser();
final response = await passage.currentUser.userInfo();
expect(response?.id, IntegrationTestConfig.currentUser.id);
expect(response?.email, IntegrationTestConfig.currentUser.email);
expect(response?.status, IntegrationTestConfig.currentUser.status);
expect(response?.emailVerified,
IntegrationTestConfig.currentUser.emailVerified);
expect(
response?.emailVerified, IntegrationTestConfig.currentUser.emailVerified);
expect(response?.phone, IntegrationTestConfig.currentUser.phone);
expect(response?.phoneVerified,
IntegrationTestConfig.currentUser.phoneVerified);
expect(
response?.phoneVerified, IntegrationTestConfig.currentUser.phoneVerified);
expect(response?.webauthn, IntegrationTestConfig.currentUser.webauthn);
} catch (e) {
fail('Test failed due to unexpected exception: $e');
Expand All @@ -62,13 +66,70 @@ void main() {

test('testCurrentUserNotAuthorized', () async {
try {
final response = await passage.getCurrentUser();
if (response == null) {
expect(true, true);
} else {
fail('Test failed: response must be null');
}
final response = await passage.currentUser.userInfo();
fail('Test failed: must throw an error');
} catch (e) {
//success
}
});

test('testPasskeys', () async {
try {
await loginWithMagicLink();
final passkeys = await passage.currentUser.passkeys();
expect(passkeys, isNotNull);
expect(passkeys, isA<List<Passkey>>());
} catch (e) {
fail('Test failed due to unexpected exception: $e');
}
});

test('testSocialConnections', () async {
try {
await loginWithMagicLink();
final socialConnections = await passage.currentUser.socialConnections();
expect(socialConnections, isNotNull);
expect(socialConnections, isA<UserSocialConnections>());
} catch (e) {
fail('Test failed due to unexpected exception: $e');
}
});

test('testDeleteSocialConnection', () async {
try {
await loginWithMagicLink();

final socialConnectionType = SocialConnection.github;
await passage.currentUser.deleteSocialConnection(socialConnectionType);
final socialConnections = await passage.currentUser.socialConnections();
expect(socialConnections, isNotNull);
} catch (e) {
fail('Test failed due to unexpected exception: $e');
}
});

test('testMetadata', () async {
try {
await loginWithMagicLink();
final metadata = await passage.currentUser.metadata();
expect(metadata, isNotNull);
expect(metadata, isA<Metadata>());
} catch (e) {
print(e.toString());
fail('Test failed due to unexpected exception: $e');
}
});

test('testUpdateMetadata', () async {
try {
await loginWithMagicLink();

Metadata newMetadata = Metadata(userMetadata: {'testkey': 'testValue'});
await passage.currentUser.updateMetadata(newMetadata);
final updatedMetadata = await passage.currentUser.metadata();
expect(updatedMetadata, isNotNull);
} catch (e) {
print(e.toString());
fail('Test failed due to unexpected exception: $e');
}
});
Expand Down
Loading
Loading