Skip to content

chore(auth): Unit tests for fetchCurrentDevice API #5074

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

Merged
merged 10 commits into from
Jul 16, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import 'package:amplify_auth_cognito_dart/src/sdk/cognito_identity_provider.dart
ForgotPasswordRequest,
GetUserAttributeVerificationCodeRequest,
GetUserRequest,
GetDeviceRequest,
ListDevicesRequest,
ResendConfirmationCodeRequest,
UserContextDataType,
Expand All @@ -39,6 +40,7 @@ import 'package:amplify_auth_cognito_dart/src/sdk/cognito_identity_provider.dart
VerifyUserAttributeRequest;
import 'package:amplify_auth_cognito_dart/src/sdk/sdk_bridge.dart';
import 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/analytics_metadata_type.dart';
import 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/get_device_response.dart';
import 'package:amplify_auth_cognito_dart/src/state/cognito_state_machine.dart';
import 'package:amplify_auth_cognito_dart/src/state/state.dart';
import 'package:amplify_auth_cognito_dart/src/util/cognito_iam_auth_provider.dart';
Expand Down Expand Up @@ -97,6 +99,7 @@ class AmplifyAuthCognitoDart extends AuthPluginInterface
late CognitoAuthStateMachine _stateMachine = CognitoAuthStateMachine(
dependencyManager: dependencies,
);

StreamSubscription<AuthState>? _stateMachineSubscription;

/// The underlying state machine, for use in subclasses.
Expand Down Expand Up @@ -993,6 +996,46 @@ class AmplifyAuthCognitoDart extends AuthPluginInterface
.result;
}

@override
Future<CognitoDevice> fetchCurrentDevice() async {
final tokens = await stateMachine.getUserPoolTokens();
final deviceSecrets = await _deviceRepo.get(tokens.username);
final deviceKey = deviceSecrets?.deviceKey;
if (deviceSecrets == null || deviceKey == null) {
throw const DeviceNotTrackedException();
}

late GetDeviceResponse response;

try {
response = await _cognitoIdp
.getDevice(
cognito.GetDeviceRequest(
deviceKey: deviceKey,
accessToken: tokens.accessToken.raw,
),
)
.result;
} on Exception catch (error) {
throw AuthException.fromException(error);
}

final device = response.device;
final attributes =
device.deviceAttributes ?? const <cognito.AttributeType>[];

return CognitoDevice(
id: deviceKey,
attributes: {
for (final attribute in attributes)
attribute.name: attribute.value ?? '',
},
createdDate: device.deviceCreateDate,
lastAuthenticatedDate: device.deviceLastAuthenticatedDate,
lastModifiedDate: device.deviceLastModifiedDate,
);
}

@override
Future<List<CognitoDevice>> fetchDevices() async {
final allDevices = <CognitoDevice>[];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'package:amplify_auth_cognito_dart/amplify_auth_cognito_dart.dart';
import 'package:amplify_auth_cognito_dart/src/credentials/cognito_keys.dart';
import 'package:amplify_auth_cognito_dart/src/credentials/device_metadata_repository.dart';
import 'package:amplify_auth_cognito_dart/src/sdk/cognito_identity_provider.dart';
import 'package:amplify_auth_cognito_test/common/mock_clients.dart';
import 'package:amplify_auth_cognito_test/common/mock_config.dart';
import 'package:amplify_auth_cognito_test/common/mock_secure_storage.dart';
import 'package:amplify_core/amplify_core.dart';
import 'package:test/test.dart';

void main() {
AmplifyLogger().logLevel = LogLevel.verbose;

final userPoolKeys = CognitoUserPoolKeys(userPoolConfig);
final identityPoolKeys = CognitoIdentityPoolKeys(identityPoolConfig);
final testAuthRepo = AmplifyAuthProviderRepository();
final mockDevice = DeviceType(deviceKey: deviceKey);
final mockDeviceResponse = GetDeviceResponse(device: mockDevice);

late DeviceMetadataRepository repo;
late AmplifyAuthCognitoDart plugin;

group('fetchCurrentDevice', () {
setUp(() async {
final secureStorage = MockSecureStorage();
seedStorage(
secureStorage,
userPoolKeys: userPoolKeys,
identityPoolKeys: identityPoolKeys,
deviceKeys: CognitoDeviceKeys(userPoolConfig, username),
);
plugin = AmplifyAuthCognitoDart(
secureStorageFactory: (_) => secureStorage,
);
await plugin.configure(
config: mockConfig,
authProviderRepo: testAuthRepo,
);
repo = plugin.stateMachine.getOrCreate<DeviceMetadataRepository>();
});

group('Cognito GetDevice returns successfully.', () {
setUp(() async {
final mockIdp = MockCognitoIdentityProviderClient(
getDevice: () async => mockDeviceResponse,
forgetDevice: () async {},
);
plugin.stateMachine.addInstance<CognitoIdentityProviderClient>(mockIdp);
});

test(
'This test should get the current device, where the current device id is equal to the local device id',
() async {
final secrets = await repo.get(username);
final currentDeviceKey = secrets?.deviceKey;
expect(currentDeviceKey, isNotNull);
final currentDevice = await plugin.fetchCurrentDevice();
expect(currentDeviceKey, currentDevice.id);
});

test(
'This test should throw a DeviceNotTrackedException when current device key is null',
() async {
await plugin.forgetDevice();
await expectLater(
plugin.fetchCurrentDevice,
throwsA(isA<DeviceNotTrackedException>()),
);
});
});

group('This test should have Cognito GetDevice throw a AWSHttpException',
() {
setUp(() async {
final mockIdp = MockCognitoIdentityProviderClient(
getDevice: () async => throw AWSHttpException(
AWSHttpRequest.get(Uri.parse('https://aws.amazon.com/cognito/')),
),
);
plugin.stateMachine.addInstance<CognitoIdentityProviderClient>(mockIdp);
});

test('This test should have Cognito GetDevice throw a NetworkException',
() async {
await expectLater(
plugin.fetchCurrentDevice,
throwsA(isA<NetworkException>()),
);
});
});

tearDown(() async {
await plugin.close();
});
});
}
Loading