From 66ca8c230796ec76d7317adced66a8d653a2ff74 Mon Sep 17 00:00:00 2001 From: Peter Obiechina <43280227+peterBrxwn@users.noreply.github.com> Date: Wed, 17 Jan 2024 12:20:25 +0100 Subject: [PATCH 1/4] updated pull documentation (#192) * updated pull documentation * simplified --- lib/src/user_profile.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/user_profile.dart b/lib/src/user_profile.dart index c8eaf6d1..b5c82e8e 100644 --- a/lib/src/user_profile.dart +++ b/lib/src/user_profile.dart @@ -50,8 +50,8 @@ abstract class UserProfile { /// [String value] - value to add to array Future pushUnique(String key, String value); - /// Create array property, if property does not exist and remove value from array - /// You can only use it on array properties or properties that do not exist yet + /// If a custom property exists and its value is an array, then this will remove the specified value from that array. + /// You can only use it on array properties that exist. /// [String key] - property name for array property /// [String value] - value to remove from array Future pull(String key, String value); From 835cdcd1366303bed0d9aadc4042daff07be9107 Mon Sep 17 00:00:00 2001 From: turtledreams <62231246+turtledreams@users.noreply.github.com> Date: Mon, 29 Jan 2024 19:34:01 +0900 Subject: [PATCH 2/4] dry run recommendations (#199) --- .pubignore | 4 +++- example/lib/page_views.dart | 2 +- lib/src/remote_config.dart | 3 ++- pubspec.yaml | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.pubignore b/.pubignore index 4f38bc24..f34a6634 100644 --- a/.pubignore +++ b/.pubignore @@ -1 +1,3 @@ -example/android/app/google-services.json \ No newline at end of file +.idea/ +example/android/app/google-services.json +example/ios/Podfile.lock \ No newline at end of file diff --git a/example/lib/page_views.dart b/example/lib/page_views.dart index b33700de..8e260915 100644 --- a/example/lib/page_views.dart +++ b/example/lib/page_views.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; class ViewsPage extends StatelessWidget { final List viewNames = ['viewName', 'viewName1']; - final List viewIDs = ['temp_id_1', 'temp_id_2'];//set initial temporary values + final List viewIDs = ['temp_id_1', 'temp_id_2']; //set initial temporary values Future recordViewHome() async { Map segments = {'Cats': 123, 'Moons': 9.98, 'Moose': 'Deer'}; diff --git a/lib/src/remote_config.dart b/lib/src/remote_config.dart index d38500fd..67606107 100644 --- a/lib/src/remote_config.dart +++ b/lib/src/remote_config.dart @@ -2,7 +2,8 @@ import 'experiment_information.dart'; /// REMOTE CONFIG / AB TESTING class RCData { - Object? value; /// stores the RC value + /// stores the RC value + Object? value; bool isCurrentUsersData; RCData(this.value, this.isCurrentUsersData); diff --git a/pubspec.yaml b/pubspec.yaml index c4c1f602..c77827e1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -10,7 +10,7 @@ platforms: ios: environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.12.0 <4.0.0" flutter: ">=2.0.0" dependencies: From 969a961ed7eacc01b9bd9e890647005f99f7a75c Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray <57103426+arifBurakDemiray@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:12:35 +0000 Subject: [PATCH 3/4] [Flutter] Add warnings to all SDK example apps that would check if propper credentials have been set or it still has the defaults. (#196) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add warning for default * Update config_object.dart * lint --------- Co-authored-by: turtledreams <62231246+turtledreams@users.noreply.github.com> Co-authored-by: Artūrs Kadiķis --- example/lib/config_object.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/example/lib/config_object.dart b/example/lib/config_object.dart index de12643b..ae5aee30 100644 --- a/example/lib/config_object.dart +++ b/example/lib/config_object.dart @@ -7,7 +7,7 @@ import 'package:countly_flutter/countly_flutter.dart'; // where you initialize the Countly SDK. // This is just an example of how you can create a class to hold the CountlyConfig object because we used way too many methods here. class CountlyConfiguration { - static final String SERVER_URL = 'https://xxx.count.ly'; // MANDATORY !! + static final String SERVER_URL = 'https://your.server.ly'; // MANDATORY !! static final String APP_KEY = 'YOUR_APP_KEY'; // MANDATORY !! // These are optional values that you can set for the Countly SDK @@ -30,10 +30,12 @@ class CountlyConfiguration { }; static CountlyConfig getConfig() { - CountlyConfig config = CountlyConfig(SERVER_URL, APP_KEY)..setLoggingEnabled(true); - config.apm.enableForegroundBackgroundTracking().enableManualAppLoadedTrigger().setAppStartTimestampOverride(123456789).enableAppStartTimeTracking(); - return config // Enable countly internal debugging logs + if (SERVER_URL == 'https://your.server.ly' || APP_KEY == 'YOUR_APP_KEY') { + print('Please do not use default set of app key and server url'); + } + + return CountlyConfig(SERVER_URL, APP_KEY)..setLoggingEnabled(true) // Enable countly internal debugging logs // Currently only logging is enabled for debugging purposes // Below you can see most of the methods that you can use to configure the Countly SDK From 2e6aa82753da444542660b4f64dc7b7b4d7b6ab9 Mon Sep 17 00:00:00 2001 From: turtledreams <62231246+turtledreams@users.noreply.github.com> Date: Tue, 6 Feb 2024 22:48:29 +0900 Subject: [PATCH 4/4] Foreground Background automation (#200) * remove tests from root * automate android fb * slash * triplle message * finalized version --- .../AP_200_notEnabledNothingWorking_test.dart | 9 +++-- ...AP_204_FBTrackingEnabled_working_test.dart | 16 +++++--- ...bleFBAndStartTimeTracking_manual_test.dart | 6 +-- ...bleFBAndStartTimeTracking_manual_test.dart | 6 +-- .../sc-AP-appPerformanceMonit/notes.md | 2 +- example/integration_test/utils.dart | 27 +++++++++++++- example/pubspec.yaml | 1 + example/test/widget_test.dart | 25 ------------- integration_test/foo/bar_test.dart | 19 ---------- integration_test/test_utility.dart | 37 ------------------- pubspec.yaml | 4 -- test/countly_flutter_test.dart | 18 --------- 12 files changed, 48 insertions(+), 122 deletions(-) delete mode 100644 example/test/widget_test.dart delete mode 100644 integration_test/foo/bar_test.dart delete mode 100644 integration_test/test_utility.dart delete mode 100644 test/countly_flutter_test.dart diff --git a/example/integration_test/sc-AP-appPerformanceMonit/AP_200_notEnabledNothingWorking_test.dart b/example/integration_test/sc-AP-appPerformanceMonit/AP_200_notEnabledNothingWorking_test.dart index e6fffe89..e3bfac53 100644 --- a/example/integration_test/sc-AP-appPerformanceMonit/AP_200_notEnabledNothingWorking_test.dart +++ b/example/integration_test/sc-AP-appPerformanceMonit/AP_200_notEnabledNothingWorking_test.dart @@ -12,10 +12,11 @@ void main() { config.apm.setAppStartTimestampOverride(1620000000000); // set app start timestamp and it should be ignored await Countly.initWithConfig(config); - // wait for 5 seconds. Go to background and come back to foreground manually. - // TODO(turtledreams): automate this - print('Waiting for 5 seconds...'); - await tester.pump(Duration(seconds: 5)); + // go foreground and background + // TODO: this automation is Android only, iOS automation is not supported yet + goBackgroundAndForeground(); + + Countly.appLoadingFinished(); // this should be ignored // check if there are no apm related requests in the queue // should be 2 begin session and 1 end session (because we manually went to background and came back to foreground) diff --git a/example/integration_test/sc-AP-appPerformanceMonit/AP_204_FBTrackingEnabled_working_test.dart b/example/integration_test/sc-AP-appPerformanceMonit/AP_204_FBTrackingEnabled_working_test.dart index 295ccabf..fd02501a 100644 --- a/example/integration_test/sc-AP-appPerformanceMonit/AP_204_FBTrackingEnabled_working_test.dart +++ b/example/integration_test/sc-AP-appPerformanceMonit/AP_204_FBTrackingEnabled_working_test.dart @@ -1,4 +1,5 @@ import 'package:countly_flutter/countly_flutter.dart'; +import 'package:flutter_foreground_task/flutter_foreground_task.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; import '../utils.dart'; @@ -7,7 +8,7 @@ import '../utils.dart'; /// 2 apm requests should be sent /// 1 for foreground and 1 for background /// Currently this test is not automated and F/B actions should be done manually -/// TODO: automate this +/// TODO: automate this for iOS void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); @@ -16,16 +17,19 @@ void main() { config.apm.enableForegroundBackgroundTracking(); await Countly.initWithConfig(config); - // wait for 5 seconds. go to background manually - print('Waiting for 5 seconds... Go background'); - await tester.pump(Duration(seconds: 5)); + // go foreground and background + // TODO: this automation is Android only, iOS automation is not supported yet + FlutterForegroundTask.minimizeApp(); + print('waiting for 2 seconds, go to background'); + await tester.pump(Duration(seconds: 2)); // foreground apm request should be sent List apmReqs = await getAndPrintWantedElementsWithParamFromAllQueues('apm'); expect(apmReqs.length, 1); - print('Waiting for 5 seconds... Back to foreground'); - await tester.pump(Duration(seconds: 5)); + FlutterForegroundTask.launchApp(); + print('waiting for 2 seconds, go to foreground'); + await tester.pump(Duration(seconds: 2)); // background apm request should be sent apmReqs = await getAndPrintWantedElementsWithParamFromAllQueues('apm'); diff --git a/example/integration_test/sc-AP-appPerformanceMonit/AP_207A_enableFBAndStartTimeTracking_manual_test.dart b/example/integration_test/sc-AP-appPerformanceMonit/AP_207A_enableFBAndStartTimeTracking_manual_test.dart index 12b91bae..df3bb435 100644 --- a/example/integration_test/sc-AP-appPerformanceMonit/AP_207A_enableFBAndStartTimeTracking_manual_test.dart +++ b/example/integration_test/sc-AP-appPerformanceMonit/AP_207A_enableFBAndStartTimeTracking_manual_test.dart @@ -15,9 +15,9 @@ void main() { // trigger app loaded await Countly.appLoadingFinished(); - // wait for 5 seconds. go to background manually - print('Waiting for 5 seconds...'); - await tester.pump(Duration(seconds: 5)); + // go foreground and background + // TODO: this automation is Android only, iOS automation is not supported yet + goBackgroundAndForeground(); // check if there is 3 apm related requests in the queue List apmRequests = await getAndPrintWantedElementsWithParamFromAllQueues('apm'); diff --git a/example/integration_test/sc-AP-appPerformanceMonit/AP_207B_enableFBAndStartTimeTracking_manual_test.dart b/example/integration_test/sc-AP-appPerformanceMonit/AP_207B_enableFBAndStartTimeTracking_manual_test.dart index d2a2494a..7475a5e8 100644 --- a/example/integration_test/sc-AP-appPerformanceMonit/AP_207B_enableFBAndStartTimeTracking_manual_test.dart +++ b/example/integration_test/sc-AP-appPerformanceMonit/AP_207B_enableFBAndStartTimeTracking_manual_test.dart @@ -18,9 +18,9 @@ void main() { // trigger app loaded await Countly.appLoadingFinished(); - // wait for 5 seconds. go to background manually - print('Waiting for 5 seconds...'); - await tester.pump(Duration(seconds: 5)); + // go foreground and background + // TODO: this automation is Android only, iOS automation is not supported yet + goBackgroundAndForeground(); // check if there is 3 apm related requests in the queue List apmRequests = await getAndPrintWantedElementsWithParamFromAllQueues('apm'); diff --git a/example/integration_test/sc-AP-appPerformanceMonit/notes.md b/example/integration_test/sc-AP-appPerformanceMonit/notes.md index 108aaafa..73429b55 100644 --- a/example/integration_test/sc-AP-appPerformanceMonit/notes.md +++ b/example/integration_test/sc-AP-appPerformanceMonit/notes.md @@ -1,5 +1,5 @@ ## Test that needs manual interaction -Currently as we don't have a way to trigger app foregraound/background action with code, the following tests need manual human interaction to go F/B when waiting log is printed: +For iOS, currently as we don't have a way to trigger app foregraound action with code, the following tests need manual human interaction to go F/B when waiting log is printed: 200, 204, 207A, 207B ## Legacy call (setRecordAppStartTime) diff --git a/example/integration_test/utils.dart b/example/integration_test/utils.dart index bf08f193..116967fe 100644 --- a/example/integration_test/utils.dart +++ b/example/integration_test/utils.dart @@ -1,14 +1,14 @@ import 'dart:convert'; import 'dart:io'; - import 'package:flutter/services.dart'; +import 'package:flutter_foreground_task/flutter_foreground_task.dart'; import 'package:flutter_test/flutter_test.dart'; const MethodChannel _channelTest = MethodChannel('countly_flutter'); // Base config options for tests final String SERVER_URL = 'https://xxx.count.ly'; -final String APP_KEY = 'YOUR_APP_KEY'; +final String APP_KEY = 'YOUR_APP_KEY'; // change this for ios tests /// Get request queue from native side (list of strings) Future> getRequestQueue() async { @@ -108,3 +108,26 @@ Future> getApmParamsFromRequest(String request) async { Map apmParams = json.decode(queryParams['apm']![0]); return apmParams; } + +/// Go to background and foreground +void goBackgroundAndForeground() { + FlutterForegroundTask.minimizeApp(); + if (Platform.isIOS) { + printMessageMultipleTimes('will now go to background, get ready to go foreground manually', 3); + } + sleep(Duration(seconds: 2)); + FlutterForegroundTask.launchApp(); + if (Platform.isIOS) { + printMessageMultipleTimes('waiting for 3 seconds, now go to foreground', 3); + } + sleep(Duration(seconds: 3)); +} + +/// Print message x times +/// [String message] - message +/// [int times] - times +void printMessageMultipleTimes(String message, int times) { + for (int i = 0; i < times; i++) { + print(message); + } +} diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 7348e128..f71d9a72 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -27,6 +27,7 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter + flutter_foreground_task: 6.0.0+1 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart deleted file mode 100644 index 51a53472..00000000 --- a/example/test/widget_test.dart +++ /dev/null @@ -1,25 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:countly_flutter_example/main.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - testWidgets('Verify Platform version', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that platform version is retrieved. - expect( - find.byWidgetPredicate( - (Widget widget) => widget is Text && widget.data!.startsWith('Running on:'), - ), - findsOneWidget, - ); - }); -} diff --git a/integration_test/foo/bar_test.dart b/integration_test/foo/bar_test.dart deleted file mode 100644 index e170f983..00000000 --- a/integration_test/foo/bar_test.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:countly_flutter/countly_flutter.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import '../test_utility.dart'; - -void main() { - testWidgets('Bar Test', (tester) async { - // initialize the SDK - CountlyConfig config = createBaseConfig(); - await Countly.initWithConfig(config); - - // wait 1 second - await Future.delayed(const Duration(seconds: 1)); - - // check if device id is set correctly - String? id = await Countly.getCurrentDeviceId(); - expect(DEVICE_ID, equals(id)); - }); -} diff --git a/integration_test/test_utility.dart b/integration_test/test_utility.dart deleted file mode 100644 index 113cc0b8..00000000 --- a/integration_test/test_utility.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'package:countly_flutter/countly_config.dart'; - -/* -Countly Flutter SDK Test Structure -Test Should grouped according to modules -Each module would have a separate folder under integration_test -In each folder would have a separate file for each test case -Each test case file would have a SINGLE!! test case -Tests should start by initializing the SDK -Then wait for 1 second (or enough) -Then tests should follow accordingly -*/ - -/* -To run the tests at the root of the project run: - flutter clean - flutter pub get - flutter test integration_test -This would go through each test under the integration_test folder (and sub folders) -*/ - -// Constants -// ignore: constant_identifier_names -const String SERVER_URL = 'https://xxx.count.ly'; -// ignore: constant_identifier_names -const String APP_KEY = 'YOUR_APP_KEY'; -// ignore: constant_identifier_names -const String DEVICE_ID = 'DEVICE_ID'; - -/// Creates a base CountlyConfig object for testing. -CountlyConfig createBaseConfig() { - CountlyConfig config = CountlyConfig(SERVER_URL, APP_KEY) - ..setRequiresConsent(false) - ..setDeviceId(DEVICE_ID) - ..setLoggingEnabled(true); - return config; -} diff --git a/pubspec.yaml b/pubspec.yaml index c77827e1..b0e5f189 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -21,10 +21,6 @@ dependencies: dev_dependencies: flutter_lints: ^2.0.1 - flutter_test: - sdk: flutter - integration_test: - sdk: flutter flutter: plugin: diff --git a/test/countly_flutter_test.dart b/test/countly_flutter_test.dart deleted file mode 100644 index f9a78238..00000000 --- a/test/countly_flutter_test.dart +++ /dev/null @@ -1,18 +0,0 @@ -// ignore_for_file: deprecated_member_use - -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - const MethodChannel channel = MethodChannel('countly_flutter'); - - setUp(() { - channel.setMockMethodCallHandler((MethodCall methodCall) async { - return '42'; - }); - }); - - tearDown(() { - channel.setMockMethodCallHandler(null); - }); -}