Skip to content

Commit

Permalink
PR Comments
Browse files Browse the repository at this point in the history
  • Loading branch information
fjnoyp committed Jan 4, 2023
1 parent 09a1b6d commit 9d2f508
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ library amplify_analytics_pinpoint;

/// Overridable Flutter injected dependencies
export 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart'
show
AppLifecycleProvider,
CachedEventsPathProvider,
DeviceContextInfoProvider;
show AppLifecycleProvider;

/// Category Implementation
export 'src/analytics_plugin_impl.dart';
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,19 @@ class AmplifyAnalyticsPinpoint extends AmplifyAnalyticsPinpointDart {
/// {@macro amplify_analytics_pinpoint.analytics_plugin_impl}
AmplifyAnalyticsPinpoint({
@visibleForTesting SecureStorageInterface? endpointInfoStore,
@visibleForTesting CachedEventsPathProvider? pathProvider,
@visibleForTesting AppLifecycleProvider? appLifecycleProvider,
@visibleForTesting DeviceContextInfoProvider? deviceContextInfoProvider,
@visibleForTesting LegacyNativeDataProvider? legacyNativeDataProvider,
}) : super(
endpointInfoStore: endpointInfoStore ??
AmplifySecureStorage(
config: AmplifySecureStorageConfig(
scope: 'analyticsPinpoint',
),
),
pathProvider: pathProvider ?? FlutterPathProvider(),
pathProvider: FlutterPathProvider(),
appLifecycleProvider:
appLifecycleProvider ?? FlutterAppLifecycleProvider(),
deviceContextInfoProvider: deviceContextInfoProvider ??
const FlutterDeviceContextInfoProvider(),
legacyNativeDataProvider:
legacyNativeDataProvider ?? FlutterLegacyNativeDataProvider(),
deviceContextInfoProvider: const FlutterDeviceContextInfoProvider(),
legacyNativeDataProvider: FlutterLegacyNativeDataProvider(),
dbConnectFunction: db_common.connect,
);
}
1 change: 0 additions & 1 deletion packages/analytics/amplify_analytics_pinpoint/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ dev_dependencies:
sdk: flutter
pigeon: ^4.2.5

# The following section is specific to Flutter.
flutter:
plugin:
platforms:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'dart:convert';
import 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart';
import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/endpoint_client/endpoint_client.dart';
import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/endpoint_client/endpoint_global_fields_manager.dart';
import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/endpoint_client/endpoint_store_keys.dart';
import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/event_client/event_client.dart';
import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/event_client/event_storage_adapter.dart';
import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/event_creator/event_creator.dart';
Expand Down Expand Up @@ -70,15 +71,9 @@ class AmplifyAnalyticsPinpointDart extends AnalyticsPluginInterface {
/// Storage key for the static Pinpoint endpoint id
@visibleForTesting
static const String endpointIdStorageKey = 'UniqueId';
static const String _endpointInformationVersionKey =
'EndpointInformationVersionKey';
static const String _endpointGlobalAttrsKey = 'EndpointGlobalAttributesKey';
static const String _endpointGlobalMetricsKey = 'EndpointGlobalMetricsKey';

/// Version of metadata stored into the `endpointInfoStore`
/// If stored data changes, increment this value
static const String _endpointInformationCurrentVersionValue = '0';

late final EventCreator _eventCreator;
late final EndpointClient _endpointClient;
late final EventClient _eventClient;
Expand Down Expand Up @@ -145,34 +140,11 @@ class AmplifyAnalyticsPinpointDart extends AnalyticsPluginInterface {
deviceContextInfo: deviceContextInfo,
);

// Retrieve Unique ID
final endpointInformationVersion =
await _endpointInfoStore.read(key: _endpointInformationVersionKey);
String? retrievedEndpointId;

await _legacyNativeDataProvider?.initialize(appId);
retrievedEndpointId = await _legacyNativeDataProvider?.getEndpointId();
print('retrieved id: ${retrievedEndpointId ?? 'null'}');

if (endpointInformationVersion == null) {
_endpointInfoStore.write(
key: _endpointInformationVersionKey,
value: _endpointInformationCurrentVersionValue,
);

await _legacyNativeDataProvider?.initialize(appId);
retrievedEndpointId = await _legacyNativeDataProvider?.getEndpointId();

retrievedEndpointId ??= uuid();
await _endpointInfoStore.write(
key: endpointIdStorageKey,
value: retrievedEndpointId,
);
} else {
retrievedEndpointId =
await _endpointInfoStore.read(key: endpointIdStorageKey);
}
final fixedEndpointId = retrievedEndpointId!;
final fixedEndpointId = await retrieveEndpointId(
pinpointAppId: appId,
store: _endpointInfoStore,
legacyDataProvider: _legacyNativeDataProvider,
);

final endpoint = PublicEndpoint(
effectiveDate: DateTime.now().toUtc().toIso8601String(),
Expand Down Expand Up @@ -349,4 +321,39 @@ class AmplifyAnalyticsPinpointDart extends AnalyticsPluginInterface {
await _eventClient.close();
await _eventStorageAdapter.close();
}

@visibleForTesting

/// Retrieve the stored pinpoint endpoint id
static Future<String> retrieveEndpointId({
required String pinpointAppId,
required SecureStorageInterface store,
LegacyNativeDataProvider? legacyDataProvider,
}) async {
// Retrieve Unique ID
final endpointInformationVersion =
await store.read(key: EndpointStoreKey.version.name);
String? retrievedEndpointId;

// First time app load
if (endpointInformationVersion == null) {
store.write(
key: EndpointStoreKey.version.name,
value: EndpointStoreVersion.v1.name,
);

// Attempt to retrieve legacy data, else generate random uuid
await legacyDataProvider?.initialize(pinpointAppId);
retrievedEndpointId = await legacyDataProvider?.getEndpointId();

retrievedEndpointId ??= uuid();
await store.write(
key: endpointIdStorageKey,
value: retrievedEndpointId,
);
} else {
retrievedEndpointId = await store.read(key: endpointIdStorageKey);
}
return retrievedEndpointId!;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

/// Keys used to store info about the endpoint version store.
enum EndpointStoreKey {
/// The current version of the endpoint version store
version,
}

/// The endpoint store version.
enum EndpointStoreVersion {
/// The initial implementation of endpoint version store in Amplify Flutter Analytics.
v1,
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'dart:async';

/// {@template amplify_analytics_pinpoint.flutter_legacy_native_data_provider}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'dart:async';

import 'package:amplify_analytics_pinpoint_dart/amplify_analytics_pinpoint_dart.dart';
import 'package:amplify_analytics_pinpoint_dart/src/impl/analytics_client/endpoint_client/endpoint_store_keys.dart';
import 'package:amplify_secure_storage_dart/amplify_secure_storage_dart.dart';
import 'package:test/test.dart';

void main() {
group('Analytics Legacy Native Data Tests', () {
test('First app load, no legacy data, writes proper values', () async {
var readCalls = 0;
var writeCalls = 0;

final legacyDataProvider = MockLegacyNativeDataProvider();
final store = MockSecureStorage(
writeCallback: (key, value) {
// version written
if (writeCalls == 0) {
expect(key, EndpointStoreKey.version.name);
expect(value, EndpointStoreVersion.v1.name);
}
// endpoint written
else if (writeCalls == 1) {
expect(key, AmplifyAnalyticsPinpointDart.endpointIdStorageKey);
}
writeCalls++;
},
readCallback: (key) {
if (key == EndpointStoreKey.version.name) {
readCalls++;
return null;
}
fail('Read should not be called: $key');
},
deleteCallback: (key) {
fail('Delete should not be called: $key');
},
);

await AmplifyAnalyticsPinpointDart.retrieveEndpointId(
pinpointAppId: 'appId',
store: store,
legacyDataProvider: legacyDataProvider);

expect(writeCalls, 2);
expect(readCalls, 1);
});

test('First app load, legacy data, writes proper values', () async {
var readCalls = 0;
var writeCalls = 0;
const endpointId = 'endpointId';

final legacyDataProvider = MockLegacyNativeDataProvider(
endpointId: endpointId,
);

final store = MockSecureStorage(
writeCallback: (key, value) {
// version written
if (writeCalls == 0) {
expect(key, EndpointStoreKey.version.name);
expect(value, EndpointStoreVersion.v1.name);
}
// endpoint written
else if (writeCalls == 1) {
expect(key, AmplifyAnalyticsPinpointDart.endpointIdStorageKey);
expect(value, endpointId);
}
writeCalls++;
},
readCallback: (key) {
if (key == EndpointStoreKey.version.name) {
readCalls++;
return null;
}
fail('Read called with wrong key: $key');
},
deleteCallback: (key) {
fail('Delete should not be called: $key');
},
);

await AmplifyAnalyticsPinpointDart.retrieveEndpointId(
pinpointAppId: 'appId',
store: store,
legacyDataProvider: legacyDataProvider);

expect(writeCalls, 2);
expect(readCalls, 1);
});

test('Second app load, only read is called', () async {
var readCalls = 0;

final legacyDataProvider = MockLegacyNativeDataProvider(
getEndpointIdCallback: () {
fail('GetEndpointId should not be called');
},
);
final store = MockSecureStorage(
readCallback: (key) {
if (key == AmplifyAnalyticsPinpointDart.endpointIdStorageKey) {
readCalls++;
return 'storedEndpointId';
} else if (key == EndpointStoreKey.version.name) {
readCalls++;
return EndpointStoreVersion.v1.name;
}
fail('Read called with wrong key: $key');
},
writeCallback: (key, value) {
fail('Write should not be called: $key / $value');
},
deleteCallback: (key) {
fail('Delete should not be called: $key');
},
);

await AmplifyAnalyticsPinpointDart.retrieveEndpointId(
pinpointAppId: 'appId',
store: store,
legacyDataProvider: legacyDataProvider,
);

expect(readCalls, 2);
});
});
}

class MockLegacyNativeDataProvider implements LegacyNativeDataProvider {
MockLegacyNativeDataProvider({
this.endpointId,
this.getEndpointIdCallback,
});
final void Function()? getEndpointIdCallback;

final String? endpointId;

@override
Future<String?> getEndpointId() async {
getEndpointIdCallback?.call();
return endpointId;
}

@override
Future<void> initialize(String pinpointAppId) async {}
}

class MockSecureStorage implements SecureStorageInterface {
MockSecureStorage({
this.deleteCallback,
this.readCallback,
this.writeCallback,
});
final void Function(String)? deleteCallback;
final String? Function(String)? readCallback;
final void Function(String, String)? writeCallback;

@override
FutureOr<void> delete({required String key}) {
deleteCallback?.call(key);
}

@override
FutureOr<String?> read({required String key}) {
return readCallback?.call(key);
}

@override
FutureOr<void> write({required String key, required String value}) {
writeCallback?.call(key, value);
}
}

0 comments on commit 9d2f508

Please sign in to comment.