From 486ab06b3d0409c85cebf364ce60dfdd4798db1c Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Sun, 15 Jan 2023 08:53:23 +0200 Subject: [PATCH 01/30] started unit tests --- app/build.gradle | 24 +++- app/publish.gradle | 126 +++++++++--------- .../appsflyer/AppsflyerIntegrationTests.java | 102 ++++++++++++++ .../appsflyer/ExampleUnitTest.java | 15 --- .../org.mockito.plugins.MockMaker | 1 + build.gradle | 2 +- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 6 +- 8 files changed, 190 insertions(+), 88 deletions(-) create mode 100644 app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java delete mode 100644 app/src/test/java/com/segment/analytics/android/integrations/appsflyer/ExampleUnitTest.java create mode 100644 app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker diff --git a/app/build.gradle b/app/build.gradle index 0a095e4..fad73f0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,15 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 26 + compileSdkVersion 32 defaultConfig { minSdkVersion 14 - targetSdkVersion 26 + targetSdkVersion 32 versionCode 1 versionName "1.0" + testApplicationId "com.example.test" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { @@ -19,15 +21,27 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + testOptions { + unitTests { + includeAndroidResources = true + } + } } dependencies { + implementation 'androidx.test.ext:junit:1.1.5' + testImplementation 'junit:junit:4.13.2' + testImplementation 'org.robolectric:robolectric:4.9.2' + implementation 'com.appsflyer:af-android-sdk:6.8.2' compileOnly 'com.android.installreferrer:installreferrer:2.1' compileOnly 'com.segment.analytics.android:analytics:4.+' - testImplementation 'junit:junit:4.12' - testImplementation 'org.mockito:mockito-core:1.10.19' + testImplementation 'com.android.installreferrer:installreferrer:2.1' + testImplementation 'com.segment.analytics.android:analytics:4.+' + + testImplementation 'org.mockito:mockito-core:3.4.0' testImplementation 'com.segment.analytics.android:analytics-tests:4.+' } -apply from: file('publish.gradle') \ No newline at end of file +//apply from: file('publish.gradle') \ No newline at end of file diff --git a/app/publish.gradle b/app/publish.gradle index fb33ec9..90ef088 100644 --- a/app/publish.gradle +++ b/app/publish.gradle @@ -1,63 +1,63 @@ -apply plugin: 'maven' -apply plugin: 'signing' - -afterEvaluate { project -> - uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - pom.groupId = GROUP - pom.artifactId = POM_ARTIFACT_ID - pom.version = VERSION_NAME - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) - } - pom.project { - name POM_NAME - packaging POM_PACKAGING - description POM_DESCRIPTION - url POM_URL - scm { - url POM_SCM_URL - connection POM_SCM_CONNECTION - developerConnection POM_SCM_DEV_CONNECTION - } - licenses { - license { - name POM_LICENCE_NAME - url POM_LICENCE_URL - distribution POM_LICENCE_DIST - } - } - developers { - developer { - id POM_DEVELOPER_ID - name POM_DEVELOPER_NAME - } - } - } - } - } - } - signing { - required { gradle.taskGraph.hasTask("uploadArchives") } - sign configurations.archives - } - task androidJavadocs(type: Javadoc) { - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) - if (JavaVersion.current().isJava8Compatible()) { - allprojects { - tasks.withType(Javadoc) { options.addStringOption('Xdoclint:none', '-quiet') } - } - } - } - task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { - archiveClassifier = 'javadoc' - from androidJavadocs.destinationDir - } - task androidSourcesJar(type: Jar) { - classifier = 'sources' - from android.sourceSets.main.java.sourceFiles - } - artifacts { archives androidJavadocsJar } -} \ No newline at end of file +//apply plugin: 'maven' +//apply plugin: 'signing' +// +//afterEvaluate { project -> +// uploadArchives { +// repositories { +// mavenDeployer { +// beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } +// pom.groupId = GROUP +// pom.artifactId = POM_ARTIFACT_ID +// pom.version = VERSION_NAME +// repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { +// authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) +// } +// pom.project { +// name POM_NAME +// packaging POM_PACKAGING +// description POM_DESCRIPTION +// url POM_URL +// scm { +// url POM_SCM_URL +// connection POM_SCM_CONNECTION +// developerConnection POM_SCM_DEV_CONNECTION +// } +// licenses { +// license { +// name POM_LICENCE_NAME +// url POM_LICENCE_URL +// distribution POM_LICENCE_DIST +// } +// } +// developers { +// developer { +// id POM_DEVELOPER_ID +// name POM_DEVELOPER_NAME +// } +// } +// } +// } +// } +// } +// signing { +// required { gradle.taskGraph.hasTask("uploadArchives") } +// sign configurations.archives +// } +// task androidJavadocs(type: Javadoc) { +// classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) +// if (JavaVersion.current().isJava8Compatible()) { +// allprojects { +// tasks.withType(Javadoc) { options.addStringOption('Xdoclint:none', '-quiet') } +// } +// } +// } +// task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { +// archiveClassifier = 'javadoc' +// from androidJavadocs.destinationDir +// } +// task androidSourcesJar(type: Jar) { +// classifier = 'sources' +// from android.sourceSets.main.java.sourceFiles +// } +// artifacts { archives androidJavadocsJar } +//} \ No newline at end of file diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java new file mode 100644 index 0000000..92e62d9 --- /dev/null +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -0,0 +1,102 @@ +package com.segment.analytics.android.integrations.appsflyer; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatcher; +import org.mockito.MockedStatic; + +import android.content.Context; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.appsflyer.AFInAppEventParameterName; +import com.appsflyer.AppsFlyerLib; +import com.segment.analytics.Analytics; +import com.segment.analytics.integrations.Logger; +import static org.mockito.Mockito.*; + +import java.lang.reflect.Field; + + +/** + * To work on unit tests, switch the Test Artifact in the Build Variants view. + */ +@RunWith(AndroidJUnit4.class) +public class AppsflyerIntegrationTests { + @Test + public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { + Context context = mock(Context.class); + Logger logger = new Logger("test", Analytics.LogLevel.INFO); + AppsFlyerLib appsflyer = mock(AppsFlyerLib.class); + String appsflyerDevKey = "appsflyerDevKey"; + boolean isDebug = logger.logLevel != Analytics.LogLevel.NONE; + AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(context,logger,appsflyer,appsflyerDevKey); + Assert.assertTrue(appsflyerIntegration.isDebug == isDebug); + Assert.assertTrue(appsflyerIntegration.appsFlyerDevKey == appsflyerDevKey); + Assert.assertTrue(appsflyerIntegration.appsflyer == appsflyer); + Assert.assertTrue(appsflyerIntegration.logger == logger); + Field field = AppsflyerIntegration.class.getDeclaredField("context"); + field.setAccessible(true); + Context contextInappsflyerIntegration = (Context) field.get(appsflyerIntegration); + Assert.assertTrue(contextInappsflyerIntegration == context); +// checking the static clause + Assert.assertTrue(appsflyerIntegration.MAPPER.get("revenue")== AFInAppEventParameterName.REVENUE); + Assert.assertTrue(appsflyerIntegration.MAPPER.get("currency")== AFInAppEventParameterName.CURRENCY); + } + +// @Test +// public void testAppsflyerIntegration_ctor_nullFlow() throws Exception { +// Context context = null; +// Logger logger = null; +// AppsFlyerLib appsflyer = null; +// String appsflyerDevKey = null; +//// the line below is a problem that needs to be sorted. +//// boolean isDebug = logger.logLevel != Analytics.LogLevel.NONE; +// AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(context,logger,appsflyer,appsflyerDevKey); +//// Assert.assertTrue(appsflyerIntegration.isDebug == isDebug); +// Assert.assertTrue(appsflyerIntegration.appsFlyerDevKey == appsflyerDevKey); +// Assert.assertTrue(appsflyerIntegration.appsflyer == appsflyer); +// Assert.assertTrue(appsflyerIntegration.logger == logger); +// Field field = AppsflyerIntegration.class.getDeclaredField("context"); +// field.setAccessible(true); +// Context contextInappsflyerIntegration = (Context) field.get(appsflyerIntegration); +// Assert.assertTrue(contextInappsflyerIntegration == context); +// } + // the issebug line in the ctor is a problem needs to be sorted. + + @Test + public void testAppsflyerIntegration_setManualMode_happyFlow() throws Exception { + Assert.assertTrue(AppsflyerIntegration.manualMode==false); + AppsflyerIntegration.setManualMode(true); + Assert.assertTrue(AppsflyerIntegration.manualMode==true); + AppsflyerIntegration.setManualMode(false); + Assert.assertTrue(AppsflyerIntegration.manualMode==false); + } + + @Test + public void testAppsflyerIntegration_startAppsFlyer_happyFlow() throws Exception { + MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); + AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); + staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); + Context context = mock(Context.class); + AppsflyerIntegration.startAppsFlyer(context); + verify(appsFlyerLib).start(context); + } + + @Test + public void testAppsflyerIntegration_startAppsFlyer_nilFlow() throws Exception { + MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); + AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); + staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); + AppsflyerIntegration.startAppsFlyer(null); + verify(appsFlyerLib,never()).start(any()); + } + + +// @Test +// public void testAppsflyerIntegration_getUnderlyingInstance_happyFlow() throws Exception { +// Assert.assertTrue(AppsflyerIntegration); +// } + +} \ No newline at end of file diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/ExampleUnitTest.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/ExampleUnitTest.java deleted file mode 100644 index 210297a..0000000 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/ExampleUnitTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.segment.analytics.android.integration.appsflyer; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * To work on unit tests, switch the Test Artifact in the Build Variants view. - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000..1f0955d --- /dev/null +++ b/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline diff --git a/build.gradle b/build.gradle index 3bf9fda..77267c5 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.3' + classpath 'com.android.tools.build:gradle:7.2.2' classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.21.2" } } diff --git a/gradle.properties b/gradle.properties index a18c791..425918d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -40,4 +40,4 @@ POM_DEVELOPER_ID=appsflyer POM_DEVELOPER_NAME=AppsFlyer, Inc. android.useAndroidX=true -android.enableJetifier=true +android.enableJetifier=false \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b0ec43a..50ecda4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu May 30 11:45:15 IDT 2019 +#Tue Jan 10 15:43:55 IST 2023 distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +zipStoreBase=GRADLE_USER_HOME From 65d266e50a203d25aae9590f88ffbe5bf2a39771 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Mon, 16 Jan 2023 09:58:58 +0200 Subject: [PATCH 02/30] saving changes of unit tests --- app/build.gradle | 11 ++- .../appsflyer/AppsflyerIntegrationTests.java | 86 +++++++++++++++++-- 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index fad73f0..a74e878 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -30,18 +30,23 @@ android { } dependencies { + testImplementation 'androidx.test:core:1.4.0' implementation 'androidx.test.ext:junit:1.1.5' testImplementation 'junit:junit:4.13.2' testImplementation 'org.robolectric:robolectric:4.9.2' - implementation 'com.appsflyer:af-android-sdk:6.8.2' compileOnly 'com.android.installreferrer:installreferrer:2.1' compileOnly 'com.segment.analytics.android:analytics:4.+' testImplementation 'com.android.installreferrer:installreferrer:2.1' testImplementation 'com.segment.analytics.android:analytics:4.+' - - testImplementation 'org.mockito:mockito-core:3.4.0' + testImplementation 'org.mockito:mockito-core:4.2.0' testImplementation 'com.segment.analytics.android:analytics-tests:4.+' + +// testImplementation 'junit:junit:4.12' +// testImplementation 'org.powermock:powermock-api-mockito2:2.0.9' +// testImplementation 'org.powermock:powermock-module-junit4:2.0.9' +// testImplementation 'org.powermock:powermock-module-junit4-rule:2.0.9' +// testImplementation 'org.powermock:powermock-classloading-xstream:2.0.9' } //apply from: file('publish.gradle') \ No newline at end of file diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index 92e62d9..d687e9c 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -1,27 +1,35 @@ package com.segment.analytics.android.integrations.appsflyer; +import org.jetbrains.annotations.NotNull; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatcher; import org.mockito.MockedStatic; +import org.mockito.Mockito; +import android.app.Activity; +import android.app.Application; import android.content.Context; +import android.os.Bundle; + import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.internal.platform.app.ActivityInvoker; import com.appsflyer.AFInAppEventParameterName; import com.appsflyer.AppsFlyerLib; import com.segment.analytics.Analytics; +import com.segment.analytics.ValueMap; +import com.segment.analytics.integrations.Integration; import com.segment.analytics.integrations.Logger; import static org.mockito.Mockito.*; - import java.lang.reflect.Field; - +import java.lang.reflect.Method; /** * To work on unit tests, switch the Test Artifact in the Build Variants view. */ + @RunWith(AndroidJUnit4.class) public class AppsflyerIntegrationTests { @Test @@ -93,10 +101,76 @@ public void testAppsflyerIntegration_startAppsFlyer_nilFlow() throws Exception { verify(appsFlyerLib,never()).start(any()); } + @Test + public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception { + MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); + AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); + staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); + Analytics analytics = mock(Analytics.class); + ValueMap settings = new ValueMap(); + settings.put("appsFlyerDevKey" , "devKey"); + settings.put("trackAttributionData" , true); + Logger logger = new Logger("test", Analytics.LogLevel.INFO); + Mockito.when(analytics.logger("AppsFlyer")).thenReturn(logger); + Application app = mock(Application.class); + Mockito.when(analytics.getApplication()).thenReturn(app); + AppsflyerIntegration.deepLinkListener = mock(AppsflyerIntegration.ExternalDeepLinkListener.class); + + Integration integration= (Integration) AppsflyerIntegration.FACTORY.create(settings,analytics); + verify(appsFlyerLib).setDebugLog(logger.logLevel!=Analytics.LogLevel.NONE); + ArgumentCaptor captorListener = ArgumentCaptor.forClass(AppsflyerIntegration.ConversionListener.class); + ArgumentCaptor captorDevKey = ArgumentCaptor.forClass(String.class); + ArgumentCaptor captorContext = ArgumentCaptor.forClass(Context.class); + verify(appsFlyerLib).init(captorDevKey.capture(), captorListener.capture() , captorContext.capture()); + Assert.assertTrue(captorListener.getValue()!=null); + Assert.assertTrue(captorListener.getValue() instanceof AppsflyerIntegration.ConversionListener); + Assert.assertTrue(captorDevKey.getValue() == settings.getString("appsFlyerDevKey")); + Assert.assertTrue(captorContext.getValue() == app.getApplicationContext()); + verify(appsFlyerLib).subscribeForDeepLink(AppsflyerIntegration.deepLinkListener); + } // @Test -// public void testAppsflyerIntegration_getUnderlyingInstance_happyFlow() throws Exception { -// Assert.assertTrue(AppsflyerIntegration); -// } +// public void testAppsflyerIntegration_FACTORYCreate_nilFlow() throws Exception { +// MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); +// AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); +// staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); +// Analytics analytics = mock(Analytics.class); +// ValueMap settings = new ValueMap(); +// settings.put("appsFlyerDevKey_wrong" , "devKey"); +// settings.put("trackAttributionData_wrong" , true); +// Logger logger = new Logger("test", Analytics.LogLevel.INFO); +// Mockito.when(analytics.logger("AppsFlyer")).thenReturn(logger); +// Application app = mock(Application.class); +// Mockito.when(analytics.getApplication()).thenReturn(app); +// AppsflyerIntegration.deepLinkListener = mock(AppsflyerIntegration.ExternalDeepLinkListener.class); +// +// Integration integration = +// (Integration) AppsflyerIntegration.FACTORY.create(settings,analytics); +// verify(appsFlyerLib).setDebugLog(logger.logLevel!=Analytics.LogLevel.NONE); +// ArgumentCaptor captorListener = ArgumentCaptor.forClass(AppsflyerIntegration.ConversionListener.class); +// ArgumentCaptor captorDevKey = ArgumentCaptor.forClass(String.class); +// ArgumentCaptor captorContext = ArgumentCaptor.forClass(Context.class); +// verify(appsFlyerLib).init(captorDevKey.capture(), captorListener.capture() , captorContext.capture()); +// Assert.assertTrue(captorListener.getValue()!=null); +// Assert.assertTrue(captorListener.getValue() instanceof AppsflyerIntegration.ConversionListener); +// Assert.assertTrue(captorDevKey.getValue() == settings.getString("appsFlyerDevKey")); +// Assert.assertTrue(captorContext.getValue() == app.getApplicationContext()); +// verify(appsFlyerLib).subscribeForDeepLink(AppsflyerIntegration.deepLinkListener); + + @Test + public void testAppsflyerIntegration_FACTORYKEY_happyFlow() throws Exception { + Assert.assertTrue(AppsflyerIntegration.FACTORY.key().equals("AppsFlyer")); + } + + @Test + public void testAppsflyerIntegration_onActivityCreated_nilFlow() throws Exception { + MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); + AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); + staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); + AppsflyerIntegration.manualMode=false; + AppsflyerIntegration appsflyerIntegration = mock(AppsflyerIntegration.class); + appsflyerIntegration.onActivityCreated(mock(Activity.class), mock(Bundle.class)); + verify(appsFlyerLib).start(any()); + } } \ No newline at end of file From d2d96d3a2717193392aaaf431a19b67f0e364c3a Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Wed, 18 Jan 2023 13:43:48 +0200 Subject: [PATCH 03/30] unit tests added --- .../appsflyer/AppsflyerIntegrationTests.java | 132 +++++++++++++++++- 1 file changed, 125 insertions(+), 7 deletions(-) diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index d687e9c..588aabf 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -19,12 +19,21 @@ import com.appsflyer.AFInAppEventParameterName; import com.appsflyer.AppsFlyerLib; import com.segment.analytics.Analytics; +import com.segment.analytics.Properties; +import com.segment.analytics.Traits; import com.segment.analytics.ValueMap; +import com.segment.analytics.integrations.IdentifyPayload; import com.segment.analytics.integrations.Integration; import com.segment.analytics.integrations.Logger; +import com.segment.analytics.integrations.TrackPayload; + import static org.mockito.Mockito.*; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.Date; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.Map; /** * To work on unit tests, switch the Test Artifact in the Build Variants view. @@ -32,6 +41,7 @@ @RunWith(AndroidJUnit4.class) public class AppsflyerIntegrationTests { + @Test public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { Context context = mock(Context.class); @@ -51,6 +61,8 @@ public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { // checking the static clause Assert.assertTrue(appsflyerIntegration.MAPPER.get("revenue")== AFInAppEventParameterName.REVENUE); Assert.assertTrue(appsflyerIntegration.MAPPER.get("currency")== AFInAppEventParameterName.CURRENCY); + + reset(context,appsflyer); } // @Test @@ -90,6 +102,8 @@ public void testAppsflyerIntegration_startAppsFlyer_happyFlow() throws Exception Context context = mock(Context.class); AppsflyerIntegration.startAppsFlyer(context); verify(appsFlyerLib).start(context); + reset(appsFlyerLib,context); + staticAppsFlyerLib.close(); } @Test @@ -99,8 +113,11 @@ public void testAppsflyerIntegration_startAppsFlyer_nilFlow() throws Exception { staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); AppsflyerIntegration.startAppsFlyer(null); verify(appsFlyerLib,never()).start(any()); + reset(appsFlyerLib); + staticAppsFlyerLib.close(); } +// @MockitoSession(MockitoSessions.SINGLE_USE) @Test public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception { MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); @@ -127,6 +144,8 @@ public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception Assert.assertTrue(captorDevKey.getValue() == settings.getString("appsFlyerDevKey")); Assert.assertTrue(captorContext.getValue() == app.getApplicationContext()); verify(appsFlyerLib).subscribeForDeepLink(AppsflyerIntegration.deepLinkListener); + reset(appsFlyerLib,analytics,app,AppsflyerIntegration.deepLinkListener); + staticAppsFlyerLib.close(); } // @Test @@ -162,15 +181,114 @@ public void testAppsflyerIntegration_FACTORYKEY_happyFlow() throws Exception { Assert.assertTrue(AppsflyerIntegration.FACTORY.key().equals("AppsFlyer")); } +// @Test +// public void testAppsflyerIntegration_onActivityCreated_nilFlow() throws Exception { +// MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); +// AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); +// staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); +// AppsflyerIntegration.manualMode=false; +// AppsflyerIntegration appsflyerIntegration = mock(AppsflyerIntegration.class); +// appsflyerIntegration.onActivityCreated(mock(Activity.class), mock(Bundle.class)); +// verify(appsFlyerLib).start(any()); +// } + @Test - public void testAppsflyerIntegration_onActivityCreated_nilFlow() throws Exception { - MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); + public void testAppsflyerIntegration_getUnderlyingInstance_happyFlow() throws Exception { AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); - staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); - AppsflyerIntegration.manualMode=false; - AppsflyerIntegration appsflyerIntegration = mock(AppsflyerIntegration.class); - appsflyerIntegration.onActivityCreated(mock(Activity.class), mock(Bundle.class)); - verify(appsFlyerLib).start(any()); + Logger logger = new Logger("test", Analytics.LogLevel.INFO); + AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(null,logger,appsFlyerLib,null); + Assert.assertTrue(appsflyerIntegration.getUnderlyingInstance().equals(appsFlyerLib)); + reset(appsFlyerLib); + } + + @Test + public void testAppsflyerIntegration_identify_happyFlow() throws Exception { + AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); + Logger logger = spy(new Logger("test", Analytics.LogLevel.INFO)); + AppsflyerIntegration appsflyerIntegration = spy(new AppsflyerIntegration(null,logger,appsFlyerLib,null)); + IdentifyPayload identifyPayload = mock(IdentifyPayload.class); + Traits traits = mock(Traits.class); + when(identifyPayload.userId()).thenReturn("moris"); + when(identifyPayload.traits()).thenReturn(traits); + when(traits.getString("currencyCode")).thenReturn("ILS"); + + appsflyerIntegration.identify(identifyPayload); + + verify(logger, never()).verbose(any()); + + Field customerUserIdField = AppsflyerIntegration.class.getDeclaredField("customerUserId"); + customerUserIdField.setAccessible(true); + String customerUserIdInappsflyerIntegration = (String) customerUserIdField.get(appsflyerIntegration); + Assert.assertTrue(customerUserIdInappsflyerIntegration.equals("moris")); + + Field currencyCodeField = AppsflyerIntegration.class.getDeclaredField("currencyCode"); + currencyCodeField.setAccessible(true); + String currencyCodeInappsflyerIntegration = (String) currencyCodeField.get(appsflyerIntegration); + Assert.assertTrue(currencyCodeInappsflyerIntegration.equals("ILS")); + reset(appsFlyerLib,identifyPayload,traits); } + @Test + public void testAppsflyerIntegration_identify_nilflow() throws Exception { + Logger logger = spy(new Logger("test", Analytics.LogLevel.INFO)); + AppsflyerIntegration appsflyerIntegration = spy(new AppsflyerIntegration(null,logger,null,null)); + IdentifyPayload identifyPayload = mock(IdentifyPayload.class); + Traits traits = mock(Traits.class); + when(identifyPayload.traits()).thenReturn(traits); + + appsflyerIntegration.identify(identifyPayload); + + verify(logger, times(1)).verbose("couldn't update 'Identify' attributes"); + reset(identifyPayload,traits); + } + + @Test + public void testAppsflyerIntegration_updateEndUserAttributes_happyflow() throws Exception { + AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); + Logger logger = spy(new Logger("test", Analytics.LogLevel.INFO)); + AppsflyerIntegration appsflyerIntegration = spy(new AppsflyerIntegration(null,logger,appsFlyerLib,null)); + Method updateEndUserAttributes = AppsflyerIntegration.class.getDeclaredMethod("updateEndUserAttributes"); + updateEndUserAttributes.setAccessible(true); + + Field customerUserIdField = AppsflyerIntegration.class.getDeclaredField("customerUserId"); + customerUserIdField.setAccessible(true); + customerUserIdField.set(appsflyerIntegration,"Moris"); + Field currencyCodeField = AppsflyerIntegration.class.getDeclaredField("currencyCode"); + currencyCodeField.setAccessible(true); + currencyCodeField.set(appsflyerIntegration, "ILS"); + + updateEndUserAttributes.invoke(appsflyerIntegration); + + verify(logger, times(1)).verbose("appsflyer.setCustomerUserId(%s)", "Moris"); + verify(logger, times(1)).verbose("appsflyer.setCurrencyCode(%s)", "ILS"); + verify(logger, times(1)).verbose("appsflyer.setDebugLog(%s)", true); + reset(appsFlyerLib); + } + + @Test + public void testAppsflyerIntegration_track_happyflow() throws Exception { + AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); + Logger logger = spy(new Logger("test", Analytics.LogLevel.INFO)); + AppsflyerIntegration appsflyerIntegration = spy(new AppsflyerIntegration(null,logger,appsFlyerLib,null)); + TrackPayload trackPayload = mock(TrackPayload.class); + String event = "event"; + Properties properties= mock(Properties.class); + Map afProperties = mock(Map.class); + MockedStatic staticUtils = mockStatic(com.segment.analytics.internal.Utils.class); + + when(trackPayload.event()).thenReturn(event); + when(trackPayload.properties()).thenReturn(properties); + staticUtils.when(()->com.segment.analytics.internal.Utils.transform(any(),any())).thenReturn(afProperties); + + appsflyerIntegration.track(trackPayload); + + Field contextField = AppsflyerIntegration.class.getDeclaredField("context"); + contextField.setAccessible(true); + Context contextInAppsflyerIntegration = (Context) contextField.get(appsflyerIntegration); + + verify(appsFlyerLib, times(1)).logEvent(contextInAppsflyerIntegration,event,afProperties); + verify(logger, times(1)).verbose("appsflyer.logEvent(context, %s, %s)", event, properties); + reset(appsFlyerLib,trackPayload,properties,afProperties); + staticUtils.close(); + } } \ No newline at end of file From f32687ee7a8acf3c504f1e528a4af2330c4bbc88 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Sun, 22 Jan 2023 17:15:34 +0200 Subject: [PATCH 04/30] new tests for nested class ConversionListener --- .../appsflyer/AppsflyerIntegrationTests.java | 7 - ...erIntegration_ConversionListenerTests.java | 251 ++++++++++++++++++ 2 files changed, 251 insertions(+), 7 deletions(-) create mode 100644 app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index 588aabf..82fc03a 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -1,6 +1,5 @@ package com.segment.analytics.android.integrations.appsflyer; -import org.jetbrains.annotations.NotNull; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -8,13 +7,10 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; -import android.app.Activity; import android.app.Application; import android.content.Context; -import android.os.Bundle; import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.internal.platform.app.ActivityInvoker; import com.appsflyer.AFInAppEventParameterName; import com.appsflyer.AppsFlyerLib; @@ -30,9 +26,6 @@ import static org.mockito.Mockito.*; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.Date; -import java.util.Dictionary; -import java.util.Hashtable; import java.util.Map; /** diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java new file mode 100644 index 0000000..8697ece --- /dev/null +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java @@ -0,0 +1,251 @@ +package com.segment.analytics.android.integrations.appsflyer; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +//import org.powermock.core.classloader.annotations.PrepareForTest; +//import org.powermock.modules.junit4.PowerMockRunner; +//import org.powermock.api.mockito.PowerMockito; +import android.app.Application; +import android.content.Context; +import android.content.SharedPreferences; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.appsflyer.AFInAppEventParameterName; +import com.appsflyer.AppsFlyerLib; +import com.segment.analytics.Analytics; +import com.segment.analytics.Properties; +import com.segment.analytics.Traits; +import com.segment.analytics.ValueMap; +import com.segment.analytics.integrations.IdentifyPayload; +import com.segment.analytics.integrations.Integration; +import com.segment.analytics.integrations.Logger; +import com.segment.analytics.integrations.TrackPayload; + +import static org.mockito.Mockito.*; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +//@PrepareForTest(Analytics.class) +//@RunWith(PowerMockRunner.class) +@RunWith(AndroidJUnit4.class) +public class AppsflyerIntegration_ConversionListenerTests { + +// @Test +// public void testAppsflyerIntegration_onConversionDataSuccess_happyFlow() throws Exception { +// Map conversionDataMocked = mock(Map.class); +// Analytics analytics = mock(Analytics.class); +// Application app = mock(Application.class); +// Context context = mock(Context.class); +// SharedPreferences sharedPreferences = mock(SharedPreferences.class); +// +// when(analytics.getApplication()).thenReturn(app); +// when(app.getApplicationContext()).thenReturn(context); +// when(context.getSharedPreferences(any(),any())).thenReturn(sharedPreferences); +// when(sharedPreferences.getBoolean(any(),any())).thenReturn(false); +// +// AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); +//// MockedStatic staticConversionListener = mockStatic(AppsflyerIntegration.ConversionListener.class); +//// +//// Method getFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getFlag",String.class); +//// getFlagMethod.setAccessible(true); +//// Method trackInstallAttributedMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("trackInstallAttributed",Map.class); +//// trackInstallAttributedMethod.setAccessible(true); +//// Method setFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("setFlag",String.class,boolean.class); +//// setFlagMethod.setAccessible(true); +// AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); +// +//// Method onConversionDataSuccessMethod = AppsflyerIntegration.ConversionListener.class.getMethod("onConversionDataSuccess",Map.class); +//// onConversionDataSuccessMethod.invoke(conversionListener, conversionDataMocked ); +// conversionListener.onConversionDataSuccess(conversionDataMocked); +// +// verify(conversionListener,times(1)).trackInstallAttributed(conversionDataMocked); +//// verify(AppsflyerIntegration.conversionListener,times(1)).onConversion(conversionDataMocked); +// } + +// @Test +// public void testAppsflyerIntegration_onConversionDataSuccess_happyFlow() throws Exception { +// Analytics analytics = PowerMockito.mock(Analytics.class); +// Map conversionDataMocked = Mockito.mock(Map.class); +// AppsflyerIntegration.ConversionListener conversionListener = PowerMockito.spy(new AppsflyerIntegration.ConversionListener(analytics)); +// conversionListener.onConversionDataSuccess(conversionDataMocked); +// PowerMockito.verifyPrivate(conversionListener).invoke("getFlag",String.class); +// } + + @Test + public void testAppsflyerIntegration_onAttributionFailure_happyFlow() throws Exception { + AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); + Analytics analytics = Mockito.mock(Analytics.class); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + String errorMsg = "error - test"; + conversionListener.onAttributionFailure(errorMsg); + verify(AppsflyerIntegration.conversionListener,times(1)).onAttributionFailure(errorMsg); + + reset(analytics,conversionListener); + } + +// @Test +// public void testAppsflyerIntegration_onAttributionFailure_nullFlow() throws Exception { +//// AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); +// Analytics analytics = Mockito.mock(Analytics.class); +// AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); +// String errorMsg = "error - test"; +// conversionListener.onAttributionFailure(errorMsg); +// verify(AppsflyerIntegration.conversionListener,never()).onAttributionFailure(errorMsg); +// } + + @Test + public void testAppsflyerIntegration_trackInstallAttributed_happyFlow() throws Exception { + Analytics analytics =mock(Analytics.class); + Map attributionData = new HashMap() + { + { + put("media_source", "media_source_moris"); + put("campaign", "campaign_moris"); + put("adgroup", "adgroup_moris"); + } + }; + + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + conversionListener.trackInstallAttributed(attributionData); + + Map campaign = new ValueMap() // + .putValue("source", attributionData.get("media_source")) + .putValue("name", attributionData.get("campaign")) + .putValue("ad_group", attributionData.get("adgroup")); + Properties properties = new Properties().putValue("provider", "AppsFlyer"); + properties.putAll(attributionData); + properties.remove("media_source"); + properties.remove("adgroup"); + properties.putValue("campaign", campaign); + verify(analytics,times(1)).track("Install Attributed", properties); + + reset(analytics); + } + + @Test + public void testAppsflyerIntegration_trackInstallAttributed_negativeFlow() throws Exception { + Analytics analytics =mock(Analytics.class); + Map attributionData = new HashMap(); + + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + conversionListener.trackInstallAttributed(attributionData); + + Map campaign = new ValueMap() // + .putValue("source", "") + .putValue("name", "") + .putValue("ad_group", ""); + Properties properties = new Properties().putValue("provider", "AppsFlyer"); + properties.putAll(attributionData); + properties.remove("media_source"); + properties.remove("adgroup"); + properties.putValue("campaign", campaign); + verify(analytics,times(1)).track("Install Attributed", properties); + reset(analytics); + } +//This flow breaks because there is no check for attributionData!=null in trackInstallAttributed method. +// @Test +// public void testAppsflyerIntegration_trackInstallAttributed_nullFlow() throws Exception { +// Analytics analytics =mock(Analytics.class); +// Map attributionData = null; +// +// AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); +// conversionListener.trackInstallAttributed(attributionData); +// +// Map campaign = new ValueMap() // +// .putValue("source", "") +// .putValue("name", "") +// .putValue("ad_group", ""); +// Properties properties = new Properties().putValue("provider", "AppsFlyer"); +// properties.putAll(attributionData); +// properties.remove("media_source"); +// properties.remove("adgroup"); +// properties.putValue("campaign", campaign); +// verify(analytics,times(1)).track("Install Attributed", properties); +// reset(analytics); +// } + + @Test + public void testAppsflyerIntegration_getContext_happyFlow() throws Exception { + Analytics analytics = mock(Analytics.class); + Application app = mock(Application.class); + Context context = mock(Context.class); + when(analytics.getApplication()).thenReturn(app); + when(app.getApplicationContext()).thenReturn(context); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + Method getContextMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getContext"); + getContextMethod.setAccessible(true); + Context resContext = (Context) getContextMethod.invoke(conversionListener); + Assert.assertTrue(resContext == context); + } + + @Test + public void testAppsflyerIntegration_getFlag_happyFlow() throws Exception { + String key="key"; + Analytics analytics = mock(Analytics.class); + Application app = mock(Application.class); + Context context = mock(Context.class); + SharedPreferences sharedPreferences = mock(SharedPreferences.class); + when(analytics.getApplication()).thenReturn(app); + when(app.getApplicationContext()).thenReturn(context); + when(context.getSharedPreferences("appsflyer-segment-data",0)).thenReturn(sharedPreferences); + when(sharedPreferences.getBoolean(key,false)).thenReturn(true); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + + Method getFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getFlag",String.class); + getFlagMethod.setAccessible(true); + boolean resBoolean = (Boolean) getFlagMethod.invoke(conversionListener,key); + + Assert.assertTrue(resBoolean==true); + } + + @Test + public void testAppsflyerIntegration_getFlag_nullFlow() throws Exception { + String key="key"; + Analytics analytics = mock(Analytics.class); + Application app = mock(Application.class); + Context context = null; + when(analytics.getApplication()).thenReturn(app); + when(app.getApplicationContext()).thenReturn(context); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + + Method getFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getFlag",String.class); + getFlagMethod.setAccessible(true); + boolean resBoolean = (Boolean) getFlagMethod.invoke(conversionListener,key); + + Assert.assertTrue(resBoolean==false); + } + + @Test + public void testAppsflyerIntegration_setFlag_happyFlow() throws Exception { + String key="key"; + boolean value=true; + Analytics analytics = mock(Analytics.class); + Application app = mock(Application.class); + Context context = mock(Context.class); + SharedPreferences sharedPreferences = mock(SharedPreferences.class); + SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class); + when(analytics.getApplication()).thenReturn(app); + when(app.getApplicationContext()).thenReturn(context); + when(context.getSharedPreferences("appsflyer-segment-data",0)).thenReturn(sharedPreferences); + when(sharedPreferences.edit()).thenReturn(editor); + + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + Method setFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("setFlag",String.class,boolean.class); + setFlagMethod.setAccessible(true); + setFlagMethod.invoke(conversionListener,key,value); + + if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD){ + verify(editor,times(1)).apply(); + } + else{ + verify(editor,times(1)).commit(); + } + } +} From ab2ad31858d1c1319d659dcb8ee363ebbd345108 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 24 Jan 2023 12:25:21 +0200 Subject: [PATCH 05/30] added test and rechecked the old ones. Still need coed refactors. --- ...erIntegration_ConversionListenerTests.java | 189 ++++++++++-------- 1 file changed, 105 insertions(+), 84 deletions(-) diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java index 8697ece..d433935 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java @@ -37,49 +37,42 @@ @RunWith(AndroidJUnit4.class) public class AppsflyerIntegration_ConversionListenerTests { -// @Test -// public void testAppsflyerIntegration_onConversionDataSuccess_happyFlow() throws Exception { -// Map conversionDataMocked = mock(Map.class); -// Analytics analytics = mock(Analytics.class); -// Application app = mock(Application.class); -// Context context = mock(Context.class); -// SharedPreferences sharedPreferences = mock(SharedPreferences.class); -// -// when(analytics.getApplication()).thenReturn(app); -// when(app.getApplicationContext()).thenReturn(context); -// when(context.getSharedPreferences(any(),any())).thenReturn(sharedPreferences); -// when(sharedPreferences.getBoolean(any(),any())).thenReturn(false); -// -// AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); -//// MockedStatic staticConversionListener = mockStatic(AppsflyerIntegration.ConversionListener.class); -//// -//// Method getFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getFlag",String.class); -//// getFlagMethod.setAccessible(true); -//// Method trackInstallAttributedMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("trackInstallAttributed",Map.class); -//// trackInstallAttributedMethod.setAccessible(true); -//// Method setFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("setFlag",String.class,boolean.class); -//// setFlagMethod.setAccessible(true); -// AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); -// -//// Method onConversionDataSuccessMethod = AppsflyerIntegration.ConversionListener.class.getMethod("onConversionDataSuccess",Map.class); -//// onConversionDataSuccessMethod.invoke(conversionListener, conversionDataMocked ); -// conversionListener.onConversionDataSuccess(conversionDataMocked); -// -// verify(conversionListener,times(1)).trackInstallAttributed(conversionDataMocked); -//// verify(AppsflyerIntegration.conversionListener,times(1)).onConversion(conversionDataMocked); -// } + @Test + public void testAppsflyerIntegration_ConversionListener_ctor_happyFlow() throws Exception { + Analytics analytics = mock(Analytics.class); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + Assert.assertTrue(conversionListener.analytics==analytics); + } -// @Test -// public void testAppsflyerIntegration_onConversionDataSuccess_happyFlow() throws Exception { -// Analytics analytics = PowerMockito.mock(Analytics.class); -// Map conversionDataMocked = Mockito.mock(Map.class); -// AppsflyerIntegration.ConversionListener conversionListener = PowerMockito.spy(new AppsflyerIntegration.ConversionListener(analytics)); -// conversionListener.onConversionDataSuccess(conversionDataMocked); -// PowerMockito.verifyPrivate(conversionListener).invoke("getFlag",String.class); -// } + @Test + public void testAppsflyerIntegration_ConversionListener_ctor_nullFlow() throws Exception { + Analytics analytics = null; + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + Assert.assertTrue(conversionListener.analytics==analytics); + } @Test - public void testAppsflyerIntegration_onAttributionFailure_happyFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_onConversionDataSuccess_happyFlow() throws Exception { + //I want just to check the conversionListener gets the map. + AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); + Analytics analytics = mock(Analytics.class); + Map conversionData = new ValueMap(); + Application app = mock(Application.class); + Context context = mock(Context.class); + SharedPreferences sharedPreferences = mock(SharedPreferences.class); + when(analytics.getApplication()).thenReturn(app); + when(app.getApplicationContext()).thenReturn(context); + when(context.getSharedPreferences("appsflyer-segment-data",0)).thenReturn(sharedPreferences); + when(sharedPreferences.getBoolean("AF_onConversion_Data",false)).thenReturn(true); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + + conversionListener.onConversionDataSuccess(conversionData); + + verify(AppsflyerIntegration.conversionListener).onConversionDataSuccess(conversionData); + } + + @Test + public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_happyFlow() throws Exception { AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); Analytics analytics = Mockito.mock(Analytics.class); AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); @@ -90,18 +83,20 @@ public void testAppsflyerIntegration_onAttributionFailure_happyFlow() throws Exc reset(analytics,conversionListener); } -// @Test -// public void testAppsflyerIntegration_onAttributionFailure_nullFlow() throws Exception { -//// AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); -// Analytics analytics = Mockito.mock(Analytics.class); -// AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); -// String errorMsg = "error - test"; -// conversionListener.onAttributionFailure(errorMsg); -// verify(AppsflyerIntegration.conversionListener,never()).onAttributionFailure(errorMsg); -// } + @Test + public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_nullFlow() throws Exception { + AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); + Analytics analytics = Mockito.mock(Analytics.class); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + String errorMsg = null; + conversionListener.onAttributionFailure(errorMsg); + verify(AppsflyerIntegration.conversionListener,times(1)).onAttributionFailure(null); + + reset(analytics,conversionListener); + } @Test - public void testAppsflyerIntegration_trackInstallAttributed_happyFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_happyFlow() throws Exception { Analytics analytics =mock(Analytics.class); Map attributionData = new HashMap() { @@ -130,7 +125,7 @@ public void testAppsflyerIntegration_trackInstallAttributed_happyFlow() throws E } @Test - public void testAppsflyerIntegration_trackInstallAttributed_negativeFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_negativeFlow() throws Exception { Analytics analytics =mock(Analytics.class); Map attributionData = new HashMap(); @@ -149,6 +144,7 @@ public void testAppsflyerIntegration_trackInstallAttributed_negativeFlow() throw verify(analytics,times(1)).track("Install Attributed", properties); reset(analytics); } + //This flow breaks because there is no check for attributionData!=null in trackInstallAttributed method. // @Test // public void testAppsflyerIntegration_trackInstallAttributed_nullFlow() throws Exception { @@ -172,21 +168,7 @@ public void testAppsflyerIntegration_trackInstallAttributed_negativeFlow() throw // } @Test - public void testAppsflyerIntegration_getContext_happyFlow() throws Exception { - Analytics analytics = mock(Analytics.class); - Application app = mock(Application.class); - Context context = mock(Context.class); - when(analytics.getApplication()).thenReturn(app); - when(app.getApplicationContext()).thenReturn(context); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - Method getContextMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getContext"); - getContextMethod.setAccessible(true); - Context resContext = (Context) getContextMethod.invoke(conversionListener); - Assert.assertTrue(resContext == context); - } - - @Test - public void testAppsflyerIntegration_getFlag_happyFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_getFlag_happyFlow() throws Exception { String key="key"; Analytics analytics = mock(Analytics.class); Application app = mock(Application.class); @@ -206,24 +188,7 @@ public void testAppsflyerIntegration_getFlag_happyFlow() throws Exception { } @Test - public void testAppsflyerIntegration_getFlag_nullFlow() throws Exception { - String key="key"; - Analytics analytics = mock(Analytics.class); - Application app = mock(Application.class); - Context context = null; - when(analytics.getApplication()).thenReturn(app); - when(app.getApplicationContext()).thenReturn(context); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - - Method getFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getFlag",String.class); - getFlagMethod.setAccessible(true); - boolean resBoolean = (Boolean) getFlagMethod.invoke(conversionListener,key); - - Assert.assertTrue(resBoolean==false); - } - - @Test - public void testAppsflyerIntegration_setFlag_happyFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_setFlag_happyFlow() throws Exception { String key="key"; boolean value=true; Analytics analytics = mock(Analytics.class); @@ -248,4 +213,60 @@ public void testAppsflyerIntegration_setFlag_happyFlow() throws Exception { verify(editor,times(1)).commit(); } } + + @Test + public void testAppsflyerIntegration_ConversionListener_editorCommit_happyFlow() throws Exception { + SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class); + Analytics analytics = mock(Analytics.class); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + Method editorCommitMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("editorCommit",SharedPreferences.Editor.class); + editorCommitMethod.setAccessible(true); + + editorCommitMethod.invoke(conversionListener,editor); + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) { + verify(editor,times(1)).apply(); + } + else{ + verify(editor,times(1)).commit(); + } + } + +// Not checking for editor is null. +// @Test +// public void testAppsflyerIntegration_ConversionListener_editorCommit_nullFlow() throws Exception { +// +// } + + @Test + public void testAppsflyerIntegration_ConversionListener_getContext_happyFlow() throws Exception { + Analytics analytics = mock(Analytics.class); + Application app = mock(Application.class); + Context context = mock(Context.class); + when(analytics.getApplication()).thenReturn(app); + when(app.getApplicationContext()).thenReturn(context); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + Method getContextMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getContext"); + getContextMethod.setAccessible(true); + + Context resContext = (Context) getContextMethod.invoke(conversionListener); + + Assert.assertTrue(resContext==context); + } + + @Test + public void testAppsflyerIntegration_ConversionListener_getContext_nullFlow() throws Exception { + Analytics analytics = mock(Analytics.class); + Application app = mock(Application.class); + Context context = null; + when(analytics.getApplication()).thenReturn(app); + when(app.getApplicationContext()).thenReturn(context); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + Method getContextMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getContext"); + getContextMethod.setAccessible(true); + + Context resContext = (Context) getContextMethod.invoke(conversionListener); + + Assert.assertTrue(resContext==context); + } } From 3ccac30d569972c82290cb0e54a542387a5146ea Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 24 Jan 2023 14:35:12 +0200 Subject: [PATCH 06/30] added a workflow --- .github/workflows/test.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..2810bbd --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,21 @@ +name: CI - Tests +on: + push: + branches-ignore: + - 'main' + - 'releases/**' +jobs: + Tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v1 + with: + java-version: '11' + - name: Setup Android SDK + uses: android-actions/setup-android@v2 + - name: Make gradlew executable + run: chmod +x ./gradlew + - name: Run Tests + run: ./gradlew test \ No newline at end of file From 7167677ea5ecba0e10f822948f757d28e26716a7 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 24 Jan 2023 14:36:25 +0200 Subject: [PATCH 07/30] fixed yml file --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2810bbd..9289f91 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,6 +16,6 @@ jobs: - name: Setup Android SDK uses: android-actions/setup-android@v2 - name: Make gradlew executable - run: chmod +x ./gradlew + run: chmod +x ./gradlew - name: Run Tests run: ./gradlew test \ No newline at end of file From 3b6aeea57ba0b030bd6baf32225be755ca28e89c Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 24 Jan 2023 14:43:15 +0200 Subject: [PATCH 08/30] try for fixing manifest --- app/src/main/AndroidManifest.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d9d6c4e..17cd5a2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,10 @@ - + - + + + \ No newline at end of file From 49ec8eafa9be9f66a32f87554cbba46fcda50fb8 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 24 Jan 2023 16:44:55 +0200 Subject: [PATCH 09/30] fixed some configs --- app/build.gradle | 10 ++++++++++ gradle.properties | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index a74e878..60119fe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -49,4 +49,14 @@ dependencies { // testImplementation 'org.powermock:powermock-classloading-xstream:2.0.9' } +tasks.withType(Test) { + testLogging { + exceptionFormat "full" + events "started", "skipped", "passed", "failed" + showStandardStreams true + } +} + + + //apply from: file('publish.gradle') \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 425918d..97c5b0e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -40,4 +40,4 @@ POM_DEVELOPER_ID=appsflyer POM_DEVELOPER_NAME=AppsFlyer, Inc. android.useAndroidX=true -android.enableJetifier=false \ No newline at end of file +android.enableJetifier=true \ No newline at end of file From 8c51de03b1fc80486b8bbe07f8a5418b6af3a551 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 24 Jan 2023 16:49:16 +0200 Subject: [PATCH 10/30] more configs changed --- app/src/main/AndroidManifest.xml | 10 ++-------- .../src/main/res/layout-v11/activity_main.xml | 5 +++-- segmenttestapp/src/main/res/layout/activity_main.xml | 5 +++-- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 17cd5a2..f49da06 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,10 +1,4 @@ - - - - - - + + \ No newline at end of file diff --git a/segmenttestapp/src/main/res/layout-v11/activity_main.xml b/segmenttestapp/src/main/res/layout-v11/activity_main.xml index 35118c3..2b36d7b 100644 --- a/segmenttestapp/src/main/res/layout-v11/activity_main.xml +++ b/segmenttestapp/src/main/res/layout-v11/activity_main.xml @@ -1,5 +1,6 @@ + app:srcCompat="@drawable/segment_logo" /> + app:srcCompat="@drawable/segment_logo" /> Date: Wed, 25 Jan 2023 11:11:40 +0200 Subject: [PATCH 11/30] refactored the cose added reset to mocks --- .../appsflyer/AppsflyerIntegrationTests.java | 23 ++++++--- ...erIntegration_ConversionListenerTests.java | 48 +++++++++++++------ 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index 82fc03a..c3a585c 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -49,7 +49,9 @@ public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { Assert.assertTrue(appsflyerIntegration.logger == logger); Field field = AppsflyerIntegration.class.getDeclaredField("context"); field.setAccessible(true); + Context contextInappsflyerIntegration = (Context) field.get(appsflyerIntegration); + Assert.assertTrue(contextInappsflyerIntegration == context); // checking the static clause Assert.assertTrue(appsflyerIntegration.MAPPER.get("revenue")== AFInAppEventParameterName.REVENUE); @@ -93,8 +95,11 @@ public void testAppsflyerIntegration_startAppsFlyer_happyFlow() throws Exception AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); Context context = mock(Context.class); + AppsflyerIntegration.startAppsFlyer(context); + verify(appsFlyerLib).start(context); + reset(appsFlyerLib,context); staticAppsFlyerLib.close(); } @@ -104,8 +109,11 @@ public void testAppsflyerIntegration_startAppsFlyer_nilFlow() throws Exception { MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); + AppsflyerIntegration.startAppsFlyer(null); + verify(appsFlyerLib,never()).start(any()); + reset(appsFlyerLib); staticAppsFlyerLib.close(); } @@ -127,6 +135,7 @@ public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception AppsflyerIntegration.deepLinkListener = mock(AppsflyerIntegration.ExternalDeepLinkListener.class); Integration integration= (Integration) AppsflyerIntegration.FACTORY.create(settings,analytics); + verify(appsFlyerLib).setDebugLog(logger.logLevel!=Analytics.LogLevel.NONE); ArgumentCaptor captorListener = ArgumentCaptor.forClass(AppsflyerIntegration.ConversionListener.class); ArgumentCaptor captorDevKey = ArgumentCaptor.forClass(String.class); @@ -137,6 +146,7 @@ public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception Assert.assertTrue(captorDevKey.getValue() == settings.getString("appsFlyerDevKey")); Assert.assertTrue(captorContext.getValue() == app.getApplicationContext()); verify(appsFlyerLib).subscribeForDeepLink(AppsflyerIntegration.deepLinkListener); + reset(appsFlyerLib,analytics,app,AppsflyerIntegration.deepLinkListener); staticAppsFlyerLib.close(); } @@ -190,7 +200,9 @@ public void testAppsflyerIntegration_getUnderlyingInstance_happyFlow() throws Ex AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); Logger logger = new Logger("test", Analytics.LogLevel.INFO); AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(null,logger,appsFlyerLib,null); + Assert.assertTrue(appsflyerIntegration.getUnderlyingInstance().equals(appsFlyerLib)); + reset(appsFlyerLib); } @@ -208,16 +220,15 @@ public void testAppsflyerIntegration_identify_happyFlow() throws Exception { appsflyerIntegration.identify(identifyPayload); verify(logger, never()).verbose(any()); - Field customerUserIdField = AppsflyerIntegration.class.getDeclaredField("customerUserId"); customerUserIdField.setAccessible(true); String customerUserIdInappsflyerIntegration = (String) customerUserIdField.get(appsflyerIntegration); Assert.assertTrue(customerUserIdInappsflyerIntegration.equals("moris")); - Field currencyCodeField = AppsflyerIntegration.class.getDeclaredField("currencyCode"); currencyCodeField.setAccessible(true); String currencyCodeInappsflyerIntegration = (String) currencyCodeField.get(appsflyerIntegration); Assert.assertTrue(currencyCodeInappsflyerIntegration.equals("ILS")); + reset(appsFlyerLib,identifyPayload,traits); } @@ -232,6 +243,7 @@ public void testAppsflyerIntegration_identify_nilflow() throws Exception { appsflyerIntegration.identify(identifyPayload); verify(logger, times(1)).verbose("couldn't update 'Identify' attributes"); + reset(identifyPayload,traits); } @@ -242,7 +254,6 @@ public void testAppsflyerIntegration_updateEndUserAttributes_happyflow() throws AppsflyerIntegration appsflyerIntegration = spy(new AppsflyerIntegration(null,logger,appsFlyerLib,null)); Method updateEndUserAttributes = AppsflyerIntegration.class.getDeclaredMethod("updateEndUserAttributes"); updateEndUserAttributes.setAccessible(true); - Field customerUserIdField = AppsflyerIntegration.class.getDeclaredField("customerUserId"); customerUserIdField.setAccessible(true); customerUserIdField.set(appsflyerIntegration,"Moris"); @@ -255,6 +266,7 @@ public void testAppsflyerIntegration_updateEndUserAttributes_happyflow() throws verify(logger, times(1)).verbose("appsflyer.setCustomerUserId(%s)", "Moris"); verify(logger, times(1)).verbose("appsflyer.setCurrencyCode(%s)", "ILS"); verify(logger, times(1)).verbose("appsflyer.setDebugLog(%s)", true); + reset(appsFlyerLib); } @@ -268,19 +280,18 @@ public void testAppsflyerIntegration_track_happyflow() throws Exception { Properties properties= mock(Properties.class); Map afProperties = mock(Map.class); MockedStatic staticUtils = mockStatic(com.segment.analytics.internal.Utils.class); - when(trackPayload.event()).thenReturn(event); when(trackPayload.properties()).thenReturn(properties); staticUtils.when(()->com.segment.analytics.internal.Utils.transform(any(),any())).thenReturn(afProperties); - appsflyerIntegration.track(trackPayload); - Field contextField = AppsflyerIntegration.class.getDeclaredField("context"); contextField.setAccessible(true); + Context contextInAppsflyerIntegration = (Context) contextField.get(appsflyerIntegration); verify(appsFlyerLib, times(1)).logEvent(contextInAppsflyerIntegration,event,afProperties); verify(logger, times(1)).verbose("appsflyer.logEvent(context, %s, %s)", event, properties); + reset(appsFlyerLib,trackPayload,properties,afProperties); staticUtils.close(); } diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java index d433935..94a65f9 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java @@ -41,14 +41,20 @@ public class AppsflyerIntegration_ConversionListenerTests { public void testAppsflyerIntegration_ConversionListener_ctor_happyFlow() throws Exception { Analytics analytics = mock(Analytics.class); AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + Assert.assertTrue(conversionListener.analytics==analytics); + + reset(analytics,conversionListener); } @Test public void testAppsflyerIntegration_ConversionListener_ctor_nullFlow() throws Exception { Analytics analytics = null; AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + Assert.assertTrue(conversionListener.analytics==analytics); + + reset(conversionListener); } @Test @@ -69,6 +75,8 @@ public void testAppsflyerIntegration_ConversionListener_onConversionDataSuccess_ conversionListener.onConversionDataSuccess(conversionData); verify(AppsflyerIntegration.conversionListener).onConversionDataSuccess(conversionData); + + reset(AppsflyerIntegration.conversionListener,analytics,app,context,sharedPreferences,conversionListener); } @Test @@ -77,10 +85,12 @@ public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_hap Analytics analytics = Mockito.mock(Analytics.class); AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); String errorMsg = "error - test"; + conversionListener.onAttributionFailure(errorMsg); + verify(AppsflyerIntegration.conversionListener,times(1)).onAttributionFailure(errorMsg); - reset(analytics,conversionListener); + reset(analytics,conversionListener,AppsflyerIntegration.conversionListener); } @Test @@ -92,7 +102,7 @@ public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_nul conversionListener.onAttributionFailure(errorMsg); verify(AppsflyerIntegration.conversionListener,times(1)).onAttributionFailure(null); - reset(analytics,conversionListener); + reset(analytics,conversionListener,AppsflyerIntegration.conversionListener); } @Test @@ -106,10 +116,6 @@ public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_h put("adgroup", "adgroup_moris"); } }; - - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - conversionListener.trackInstallAttributed(attributionData); - Map campaign = new ValueMap() // .putValue("source", attributionData.get("media_source")) .putValue("name", attributionData.get("campaign")) @@ -119,19 +125,19 @@ public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_h properties.remove("media_source"); properties.remove("adgroup"); properties.putValue("campaign", campaign); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + + conversionListener.trackInstallAttributed(attributionData); + verify(analytics,times(1)).track("Install Attributed", properties); - reset(analytics); + reset(analytics,conversionListener); } @Test public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_negativeFlow() throws Exception { Analytics analytics =mock(Analytics.class); Map attributionData = new HashMap(); - - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - conversionListener.trackInstallAttributed(attributionData); - Map campaign = new ValueMap() // .putValue("source", "") .putValue("name", "") @@ -141,8 +147,12 @@ public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_n properties.remove("media_source"); properties.remove("adgroup"); properties.putValue("campaign", campaign); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + conversionListener.trackInstallAttributed(attributionData); + verify(analytics,times(1)).track("Install Attributed", properties); - reset(analytics); + + reset(analytics,conversionListener); } //This flow breaks because there is no check for attributionData!=null in trackInstallAttributed method. @@ -179,12 +189,14 @@ public void testAppsflyerIntegration_ConversionListener_getFlag_happyFlow() thro when(context.getSharedPreferences("appsflyer-segment-data",0)).thenReturn(sharedPreferences); when(sharedPreferences.getBoolean(key,false)).thenReturn(true); AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - Method getFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getFlag",String.class); getFlagMethod.setAccessible(true); + boolean resBoolean = (Boolean) getFlagMethod.invoke(conversionListener,key); Assert.assertTrue(resBoolean==true); + + reset(analytics,app,context,sharedPreferences,conversionListener); } @Test @@ -200,10 +212,10 @@ public void testAppsflyerIntegration_ConversionListener_setFlag_happyFlow() thro when(app.getApplicationContext()).thenReturn(context); when(context.getSharedPreferences("appsflyer-segment-data",0)).thenReturn(sharedPreferences); when(sharedPreferences.edit()).thenReturn(editor); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); Method setFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("setFlag",String.class,boolean.class); setFlagMethod.setAccessible(true); + setFlagMethod.invoke(conversionListener,key,value); if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD){ @@ -212,6 +224,8 @@ public void testAppsflyerIntegration_ConversionListener_setFlag_happyFlow() thro else{ verify(editor,times(1)).commit(); } + + reset(analytics,app,context,sharedPreferences,conversionListener); } @Test @@ -230,6 +244,8 @@ public void testAppsflyerIntegration_ConversionListener_editorCommit_happyFlow() else{ verify(editor,times(1)).commit(); } + + reset(analytics,conversionListener); } // Not checking for editor is null. @@ -252,6 +268,8 @@ public void testAppsflyerIntegration_ConversionListener_getContext_happyFlow() t Context resContext = (Context) getContextMethod.invoke(conversionListener); Assert.assertTrue(resContext==context); + + reset(analytics,app,context,conversionListener); } @Test @@ -268,5 +286,7 @@ public void testAppsflyerIntegration_ConversionListener_getContext_nullFlow() th Context resContext = (Context) getContextMethod.invoke(conversionListener); Assert.assertTrue(resContext==context); + + reset(analytics,app,conversionListener); } } From d7a13800fa61fe708c798ac48280685b43162efd Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Wed, 25 Jan 2023 11:11:40 +0200 Subject: [PATCH 12/30] refactored the code added reset to mocks --- .../appsflyer/AppsflyerIntegrationTests.java | 23 ++++++--- ...erIntegration_ConversionListenerTests.java | 48 +++++++++++++------ 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index 82fc03a..c3a585c 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -49,7 +49,9 @@ public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { Assert.assertTrue(appsflyerIntegration.logger == logger); Field field = AppsflyerIntegration.class.getDeclaredField("context"); field.setAccessible(true); + Context contextInappsflyerIntegration = (Context) field.get(appsflyerIntegration); + Assert.assertTrue(contextInappsflyerIntegration == context); // checking the static clause Assert.assertTrue(appsflyerIntegration.MAPPER.get("revenue")== AFInAppEventParameterName.REVENUE); @@ -93,8 +95,11 @@ public void testAppsflyerIntegration_startAppsFlyer_happyFlow() throws Exception AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); Context context = mock(Context.class); + AppsflyerIntegration.startAppsFlyer(context); + verify(appsFlyerLib).start(context); + reset(appsFlyerLib,context); staticAppsFlyerLib.close(); } @@ -104,8 +109,11 @@ public void testAppsflyerIntegration_startAppsFlyer_nilFlow() throws Exception { MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); + AppsflyerIntegration.startAppsFlyer(null); + verify(appsFlyerLib,never()).start(any()); + reset(appsFlyerLib); staticAppsFlyerLib.close(); } @@ -127,6 +135,7 @@ public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception AppsflyerIntegration.deepLinkListener = mock(AppsflyerIntegration.ExternalDeepLinkListener.class); Integration integration= (Integration) AppsflyerIntegration.FACTORY.create(settings,analytics); + verify(appsFlyerLib).setDebugLog(logger.logLevel!=Analytics.LogLevel.NONE); ArgumentCaptor captorListener = ArgumentCaptor.forClass(AppsflyerIntegration.ConversionListener.class); ArgumentCaptor captorDevKey = ArgumentCaptor.forClass(String.class); @@ -137,6 +146,7 @@ public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception Assert.assertTrue(captorDevKey.getValue() == settings.getString("appsFlyerDevKey")); Assert.assertTrue(captorContext.getValue() == app.getApplicationContext()); verify(appsFlyerLib).subscribeForDeepLink(AppsflyerIntegration.deepLinkListener); + reset(appsFlyerLib,analytics,app,AppsflyerIntegration.deepLinkListener); staticAppsFlyerLib.close(); } @@ -190,7 +200,9 @@ public void testAppsflyerIntegration_getUnderlyingInstance_happyFlow() throws Ex AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); Logger logger = new Logger("test", Analytics.LogLevel.INFO); AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(null,logger,appsFlyerLib,null); + Assert.assertTrue(appsflyerIntegration.getUnderlyingInstance().equals(appsFlyerLib)); + reset(appsFlyerLib); } @@ -208,16 +220,15 @@ public void testAppsflyerIntegration_identify_happyFlow() throws Exception { appsflyerIntegration.identify(identifyPayload); verify(logger, never()).verbose(any()); - Field customerUserIdField = AppsflyerIntegration.class.getDeclaredField("customerUserId"); customerUserIdField.setAccessible(true); String customerUserIdInappsflyerIntegration = (String) customerUserIdField.get(appsflyerIntegration); Assert.assertTrue(customerUserIdInappsflyerIntegration.equals("moris")); - Field currencyCodeField = AppsflyerIntegration.class.getDeclaredField("currencyCode"); currencyCodeField.setAccessible(true); String currencyCodeInappsflyerIntegration = (String) currencyCodeField.get(appsflyerIntegration); Assert.assertTrue(currencyCodeInappsflyerIntegration.equals("ILS")); + reset(appsFlyerLib,identifyPayload,traits); } @@ -232,6 +243,7 @@ public void testAppsflyerIntegration_identify_nilflow() throws Exception { appsflyerIntegration.identify(identifyPayload); verify(logger, times(1)).verbose("couldn't update 'Identify' attributes"); + reset(identifyPayload,traits); } @@ -242,7 +254,6 @@ public void testAppsflyerIntegration_updateEndUserAttributes_happyflow() throws AppsflyerIntegration appsflyerIntegration = spy(new AppsflyerIntegration(null,logger,appsFlyerLib,null)); Method updateEndUserAttributes = AppsflyerIntegration.class.getDeclaredMethod("updateEndUserAttributes"); updateEndUserAttributes.setAccessible(true); - Field customerUserIdField = AppsflyerIntegration.class.getDeclaredField("customerUserId"); customerUserIdField.setAccessible(true); customerUserIdField.set(appsflyerIntegration,"Moris"); @@ -255,6 +266,7 @@ public void testAppsflyerIntegration_updateEndUserAttributes_happyflow() throws verify(logger, times(1)).verbose("appsflyer.setCustomerUserId(%s)", "Moris"); verify(logger, times(1)).verbose("appsflyer.setCurrencyCode(%s)", "ILS"); verify(logger, times(1)).verbose("appsflyer.setDebugLog(%s)", true); + reset(appsFlyerLib); } @@ -268,19 +280,18 @@ public void testAppsflyerIntegration_track_happyflow() throws Exception { Properties properties= mock(Properties.class); Map afProperties = mock(Map.class); MockedStatic staticUtils = mockStatic(com.segment.analytics.internal.Utils.class); - when(trackPayload.event()).thenReturn(event); when(trackPayload.properties()).thenReturn(properties); staticUtils.when(()->com.segment.analytics.internal.Utils.transform(any(),any())).thenReturn(afProperties); - appsflyerIntegration.track(trackPayload); - Field contextField = AppsflyerIntegration.class.getDeclaredField("context"); contextField.setAccessible(true); + Context contextInAppsflyerIntegration = (Context) contextField.get(appsflyerIntegration); verify(appsFlyerLib, times(1)).logEvent(contextInAppsflyerIntegration,event,afProperties); verify(logger, times(1)).verbose("appsflyer.logEvent(context, %s, %s)", event, properties); + reset(appsFlyerLib,trackPayload,properties,afProperties); staticUtils.close(); } diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java index d433935..94a65f9 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java @@ -41,14 +41,20 @@ public class AppsflyerIntegration_ConversionListenerTests { public void testAppsflyerIntegration_ConversionListener_ctor_happyFlow() throws Exception { Analytics analytics = mock(Analytics.class); AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + Assert.assertTrue(conversionListener.analytics==analytics); + + reset(analytics,conversionListener); } @Test public void testAppsflyerIntegration_ConversionListener_ctor_nullFlow() throws Exception { Analytics analytics = null; AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + Assert.assertTrue(conversionListener.analytics==analytics); + + reset(conversionListener); } @Test @@ -69,6 +75,8 @@ public void testAppsflyerIntegration_ConversionListener_onConversionDataSuccess_ conversionListener.onConversionDataSuccess(conversionData); verify(AppsflyerIntegration.conversionListener).onConversionDataSuccess(conversionData); + + reset(AppsflyerIntegration.conversionListener,analytics,app,context,sharedPreferences,conversionListener); } @Test @@ -77,10 +85,12 @@ public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_hap Analytics analytics = Mockito.mock(Analytics.class); AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); String errorMsg = "error - test"; + conversionListener.onAttributionFailure(errorMsg); + verify(AppsflyerIntegration.conversionListener,times(1)).onAttributionFailure(errorMsg); - reset(analytics,conversionListener); + reset(analytics,conversionListener,AppsflyerIntegration.conversionListener); } @Test @@ -92,7 +102,7 @@ public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_nul conversionListener.onAttributionFailure(errorMsg); verify(AppsflyerIntegration.conversionListener,times(1)).onAttributionFailure(null); - reset(analytics,conversionListener); + reset(analytics,conversionListener,AppsflyerIntegration.conversionListener); } @Test @@ -106,10 +116,6 @@ public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_h put("adgroup", "adgroup_moris"); } }; - - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - conversionListener.trackInstallAttributed(attributionData); - Map campaign = new ValueMap() // .putValue("source", attributionData.get("media_source")) .putValue("name", attributionData.get("campaign")) @@ -119,19 +125,19 @@ public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_h properties.remove("media_source"); properties.remove("adgroup"); properties.putValue("campaign", campaign); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + + conversionListener.trackInstallAttributed(attributionData); + verify(analytics,times(1)).track("Install Attributed", properties); - reset(analytics); + reset(analytics,conversionListener); } @Test public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_negativeFlow() throws Exception { Analytics analytics =mock(Analytics.class); Map attributionData = new HashMap(); - - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - conversionListener.trackInstallAttributed(attributionData); - Map campaign = new ValueMap() // .putValue("source", "") .putValue("name", "") @@ -141,8 +147,12 @@ public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_n properties.remove("media_source"); properties.remove("adgroup"); properties.putValue("campaign", campaign); + AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + conversionListener.trackInstallAttributed(attributionData); + verify(analytics,times(1)).track("Install Attributed", properties); - reset(analytics); + + reset(analytics,conversionListener); } //This flow breaks because there is no check for attributionData!=null in trackInstallAttributed method. @@ -179,12 +189,14 @@ public void testAppsflyerIntegration_ConversionListener_getFlag_happyFlow() thro when(context.getSharedPreferences("appsflyer-segment-data",0)).thenReturn(sharedPreferences); when(sharedPreferences.getBoolean(key,false)).thenReturn(true); AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - Method getFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getFlag",String.class); getFlagMethod.setAccessible(true); + boolean resBoolean = (Boolean) getFlagMethod.invoke(conversionListener,key); Assert.assertTrue(resBoolean==true); + + reset(analytics,app,context,sharedPreferences,conversionListener); } @Test @@ -200,10 +212,10 @@ public void testAppsflyerIntegration_ConversionListener_setFlag_happyFlow() thro when(app.getApplicationContext()).thenReturn(context); when(context.getSharedPreferences("appsflyer-segment-data",0)).thenReturn(sharedPreferences); when(sharedPreferences.edit()).thenReturn(editor); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); Method setFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("setFlag",String.class,boolean.class); setFlagMethod.setAccessible(true); + setFlagMethod.invoke(conversionListener,key,value); if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD){ @@ -212,6 +224,8 @@ public void testAppsflyerIntegration_ConversionListener_setFlag_happyFlow() thro else{ verify(editor,times(1)).commit(); } + + reset(analytics,app,context,sharedPreferences,conversionListener); } @Test @@ -230,6 +244,8 @@ public void testAppsflyerIntegration_ConversionListener_editorCommit_happyFlow() else{ verify(editor,times(1)).commit(); } + + reset(analytics,conversionListener); } // Not checking for editor is null. @@ -252,6 +268,8 @@ public void testAppsflyerIntegration_ConversionListener_getContext_happyFlow() t Context resContext = (Context) getContextMethod.invoke(conversionListener); Assert.assertTrue(resContext==context); + + reset(analytics,app,context,conversionListener); } @Test @@ -268,5 +286,7 @@ public void testAppsflyerIntegration_ConversionListener_getContext_nullFlow() th Context resContext = (Context) getContextMethod.invoke(conversionListener); Assert.assertTrue(resContext==context); + + reset(analytics,app,conversionListener); } } From 3c8e32f16042950749e14fb8136bbc9c90b1fd39 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Wed, 25 Jan 2023 11:16:29 +0200 Subject: [PATCH 13/30] some more refactor deleted unrelevant imports --- .../appsflyer/AppsflyerIntegrationTests.java | 4 ---- ...yerIntegration_ConversionListenerTests.java | 18 ------------------ 2 files changed, 22 deletions(-) diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index c3a585c..d8cdc90 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -6,12 +6,9 @@ import org.mockito.ArgumentCaptor; import org.mockito.MockedStatic; import org.mockito.Mockito; - import android.app.Application; import android.content.Context; - import androidx.test.ext.junit.runners.AndroidJUnit4; - import com.appsflyer.AFInAppEventParameterName; import com.appsflyer.AppsFlyerLib; import com.segment.analytics.Analytics; @@ -22,7 +19,6 @@ import com.segment.analytics.integrations.Integration; import com.segment.analytics.integrations.Logger; import com.segment.analytics.integrations.TrackPayload; - import static org.mockito.Mockito.*; import java.lang.reflect.Field; import java.lang.reflect.Method; diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java index 94a65f9..d964c0a 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java @@ -3,37 +3,19 @@ import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.MockedStatic; import org.mockito.Mockito; -//import org.powermock.core.classloader.annotations.PrepareForTest; -//import org.powermock.modules.junit4.PowerMockRunner; -//import org.powermock.api.mockito.PowerMockito; import android.app.Application; import android.content.Context; import android.content.SharedPreferences; - import androidx.test.ext.junit.runners.AndroidJUnit4; - -import com.appsflyer.AFInAppEventParameterName; -import com.appsflyer.AppsFlyerLib; import com.segment.analytics.Analytics; import com.segment.analytics.Properties; -import com.segment.analytics.Traits; import com.segment.analytics.ValueMap; -import com.segment.analytics.integrations.IdentifyPayload; -import com.segment.analytics.integrations.Integration; -import com.segment.analytics.integrations.Logger; -import com.segment.analytics.integrations.TrackPayload; - import static org.mockito.Mockito.*; -import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; -//@PrepareForTest(Analytics.class) -//@RunWith(PowerMockRunner.class) @RunWith(AndroidJUnit4.class) public class AppsflyerIntegration_ConversionListenerTests { From e7dcae5c2d57d34e7790c3f6f8a3d4a6d858a5f5 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Sun, 29 Jan 2023 08:55:26 +0200 Subject: [PATCH 14/30] first round changes - merge request --- app/build.gradle | 16 ++--- .../appsflyer/AppsflyerIntegrationTests.java | 61 ++++++------------- ...erIntegration_ConversionListenerTests.java | 10 +-- 3 files changed, 28 insertions(+), 59 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a74e878..3f62bdc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -30,23 +30,15 @@ android { } dependencies { - testImplementation 'androidx.test:core:1.4.0' implementation 'androidx.test.ext:junit:1.1.5' - testImplementation 'junit:junit:4.13.2' - testImplementation 'org.robolectric:robolectric:4.9.2' implementation 'com.appsflyer:af-android-sdk:6.8.2' compileOnly 'com.android.installreferrer:installreferrer:2.1' compileOnly 'com.segment.analytics.android:analytics:4.+' + testImplementation 'androidx.test:core:1.4.0' + testImplementation 'junit:junit:4.13.2' + testImplementation 'org.robolectric:robolectric:4.9.2' testImplementation 'com.android.installreferrer:installreferrer:2.1' testImplementation 'com.segment.analytics.android:analytics:4.+' testImplementation 'org.mockito:mockito-core:4.2.0' testImplementation 'com.segment.analytics.android:analytics-tests:4.+' - -// testImplementation 'junit:junit:4.12' -// testImplementation 'org.powermock:powermock-api-mockito2:2.0.9' -// testImplementation 'org.powermock:powermock-module-junit4:2.0.9' -// testImplementation 'org.powermock:powermock-module-junit4-rule:2.0.9' -// testImplementation 'org.powermock:powermock-classloading-xstream:2.0.9' -} - -//apply from: file('publish.gradle') \ No newline at end of file +} \ No newline at end of file diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index d8cdc90..1ce76c2 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -24,10 +24,6 @@ import java.lang.reflect.Method; import java.util.Map; -/** - * To work on unit tests, switch the Test Artifact in the Build Variants view. - */ - @RunWith(AndroidJUnit4.class) public class AppsflyerIntegrationTests { @@ -39,50 +35,30 @@ public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { String appsflyerDevKey = "appsflyerDevKey"; boolean isDebug = logger.logLevel != Analytics.LogLevel.NONE; AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(context,logger,appsflyer,appsflyerDevKey); - Assert.assertTrue(appsflyerIntegration.isDebug == isDebug); - Assert.assertTrue(appsflyerIntegration.appsFlyerDevKey == appsflyerDevKey); - Assert.assertTrue(appsflyerIntegration.appsflyer == appsflyer); - Assert.assertTrue(appsflyerIntegration.logger == logger); + Assert.assertEquals(appsflyerIntegration.isDebug , isDebug); + Assert.assertEquals(appsflyerIntegration.appsFlyerDevKey, appsflyerDevKey); + Assert.assertEquals(appsflyerIntegration.appsflyer, appsflyer); + Assert.assertEquals(appsflyerIntegration.logger, logger); Field field = AppsflyerIntegration.class.getDeclaredField("context"); field.setAccessible(true); Context contextInappsflyerIntegration = (Context) field.get(appsflyerIntegration); - Assert.assertTrue(contextInappsflyerIntegration == context); + Assert.assertEquals(contextInappsflyerIntegration, context); // checking the static clause - Assert.assertTrue(appsflyerIntegration.MAPPER.get("revenue")== AFInAppEventParameterName.REVENUE); - Assert.assertTrue(appsflyerIntegration.MAPPER.get("currency")== AFInAppEventParameterName.CURRENCY); + Assert.assertEquals(appsflyerIntegration.MAPPER.get("revenue"), AFInAppEventParameterName.REVENUE); + Assert.assertEquals(appsflyerIntegration.MAPPER.get("currency"), AFInAppEventParameterName.CURRENCY); reset(context,appsflyer); } -// @Test -// public void testAppsflyerIntegration_ctor_nullFlow() throws Exception { -// Context context = null; -// Logger logger = null; -// AppsFlyerLib appsflyer = null; -// String appsflyerDevKey = null; -//// the line below is a problem that needs to be sorted. -//// boolean isDebug = logger.logLevel != Analytics.LogLevel.NONE; -// AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(context,logger,appsflyer,appsflyerDevKey); -//// Assert.assertTrue(appsflyerIntegration.isDebug == isDebug); -// Assert.assertTrue(appsflyerIntegration.appsFlyerDevKey == appsflyerDevKey); -// Assert.assertTrue(appsflyerIntegration.appsflyer == appsflyer); -// Assert.assertTrue(appsflyerIntegration.logger == logger); -// Field field = AppsflyerIntegration.class.getDeclaredField("context"); -// field.setAccessible(true); -// Context contextInappsflyerIntegration = (Context) field.get(appsflyerIntegration); -// Assert.assertTrue(contextInappsflyerIntegration == context); -// } - // the issebug line in the ctor is a problem needs to be sorted. - @Test public void testAppsflyerIntegration_setManualMode_happyFlow() throws Exception { - Assert.assertTrue(AppsflyerIntegration.manualMode==false); + Assert.assertFalse(AppsflyerIntegration.manualMode); AppsflyerIntegration.setManualMode(true); - Assert.assertTrue(AppsflyerIntegration.manualMode==true); + Assert.assertTrue(AppsflyerIntegration.manualMode); AppsflyerIntegration.setManualMode(false); - Assert.assertTrue(AppsflyerIntegration.manualMode==false); + Assert.assertFalse(AppsflyerIntegration.manualMode); } @Test @@ -114,7 +90,6 @@ public void testAppsflyerIntegration_startAppsFlyer_nilFlow() throws Exception { staticAppsFlyerLib.close(); } -// @MockitoSession(MockitoSessions.SINGLE_USE) @Test public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception { MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); @@ -137,16 +112,17 @@ public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception ArgumentCaptor captorDevKey = ArgumentCaptor.forClass(String.class); ArgumentCaptor captorContext = ArgumentCaptor.forClass(Context.class); verify(appsFlyerLib).init(captorDevKey.capture(), captorListener.capture() , captorContext.capture()); - Assert.assertTrue(captorListener.getValue()!=null); + Assert.assertNotEquals(captorListener.getValue(), null); Assert.assertTrue(captorListener.getValue() instanceof AppsflyerIntegration.ConversionListener); - Assert.assertTrue(captorDevKey.getValue() == settings.getString("appsFlyerDevKey")); - Assert.assertTrue(captorContext.getValue() == app.getApplicationContext()); + Assert.assertEquals(captorDevKey.getValue(), settings.getString("appsFlyerDevKey")); + Assert.assertEquals(captorContext.getValue(), app.getApplicationContext()); verify(appsFlyerLib).subscribeForDeepLink(AppsflyerIntegration.deepLinkListener); reset(appsFlyerLib,analytics,app,AppsflyerIntegration.deepLinkListener); staticAppsFlyerLib.close(); } +//need to check params values are null // @Test // public void testAppsflyerIntegration_FACTORYCreate_nilFlow() throws Exception { // MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); @@ -177,9 +153,10 @@ public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception @Test public void testAppsflyerIntegration_FACTORYKEY_happyFlow() throws Exception { - Assert.assertTrue(AppsflyerIntegration.FACTORY.key().equals("AppsFlyer")); + Assert.assertEquals(AppsflyerIntegration.FACTORY.key(),"AppsFlyer"); } + //need to check params values are null // @Test // public void testAppsflyerIntegration_onActivityCreated_nilFlow() throws Exception { // MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); @@ -197,7 +174,7 @@ public void testAppsflyerIntegration_getUnderlyingInstance_happyFlow() throws Ex Logger logger = new Logger("test", Analytics.LogLevel.INFO); AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(null,logger,appsFlyerLib,null); - Assert.assertTrue(appsflyerIntegration.getUnderlyingInstance().equals(appsFlyerLib)); + Assert.assertEquals(appsflyerIntegration.getUnderlyingInstance(),appsFlyerLib); reset(appsFlyerLib); } @@ -219,11 +196,11 @@ public void testAppsflyerIntegration_identify_happyFlow() throws Exception { Field customerUserIdField = AppsflyerIntegration.class.getDeclaredField("customerUserId"); customerUserIdField.setAccessible(true); String customerUserIdInappsflyerIntegration = (String) customerUserIdField.get(appsflyerIntegration); - Assert.assertTrue(customerUserIdInappsflyerIntegration.equals("moris")); + Assert.assertEquals(customerUserIdInappsflyerIntegration, "moris"); Field currencyCodeField = AppsflyerIntegration.class.getDeclaredField("currencyCode"); currencyCodeField.setAccessible(true); String currencyCodeInappsflyerIntegration = (String) currencyCodeField.get(appsflyerIntegration); - Assert.assertTrue(currencyCodeInappsflyerIntegration.equals("ILS")); + Assert.assertEquals(currencyCodeInappsflyerIntegration, "ILS"); reset(appsFlyerLib,identifyPayload,traits); } diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java index d964c0a..08b1ca9 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java @@ -24,7 +24,7 @@ public void testAppsflyerIntegration_ConversionListener_ctor_happyFlow() throws Analytics analytics = mock(Analytics.class); AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - Assert.assertTrue(conversionListener.analytics==analytics); + Assert.assertEquals(conversionListener.analytics, analytics); reset(analytics,conversionListener); } @@ -34,7 +34,7 @@ public void testAppsflyerIntegration_ConversionListener_ctor_nullFlow() throws E Analytics analytics = null; AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - Assert.assertTrue(conversionListener.analytics==analytics); + Assert.assertEquals(conversionListener.analytics, analytics); reset(conversionListener); } @@ -176,7 +176,7 @@ public void testAppsflyerIntegration_ConversionListener_getFlag_happyFlow() thro boolean resBoolean = (Boolean) getFlagMethod.invoke(conversionListener,key); - Assert.assertTrue(resBoolean==true); + Assert.assertTrue(resBoolean); reset(analytics,app,context,sharedPreferences,conversionListener); } @@ -249,7 +249,7 @@ public void testAppsflyerIntegration_ConversionListener_getContext_happyFlow() t Context resContext = (Context) getContextMethod.invoke(conversionListener); - Assert.assertTrue(resContext==context); + Assert.assertEquals(resContext, context); reset(analytics,app,context,conversionListener); } @@ -267,7 +267,7 @@ public void testAppsflyerIntegration_ConversionListener_getContext_nullFlow() th Context resContext = (Context) getContextMethod.invoke(conversionListener); - Assert.assertTrue(resContext==context); + Assert.assertEquals(resContext, context); reset(analytics,app,conversionListener); } From ab3407d9177f22f70df128e0db6ddd2c4ad5a864 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Sun, 29 Jan 2023 14:39:04 +0200 Subject: [PATCH 15/30] changes for merge request #2 --- .../appsflyer/ApplicationTest.java | 26 ++++----- .../appsflyer/AppsflyerIntegrationTests.java | 55 ++++++++++--------- ...erIntegration_ConversionListenerTests.java | 16 +++--- 3 files changed, 49 insertions(+), 48 deletions(-) diff --git a/app/src/androidTest/java/com/segment/analytics/android/integrations/appsflyer/ApplicationTest.java b/app/src/androidTest/java/com/segment/analytics/android/integrations/appsflyer/ApplicationTest.java index 56a28c8..5d4cb89 100644 --- a/app/src/androidTest/java/com/segment/analytics/android/integrations/appsflyer/ApplicationTest.java +++ b/app/src/androidTest/java/com/segment/analytics/android/integrations/appsflyer/ApplicationTest.java @@ -1,13 +1,13 @@ -package com.segment.analytics.android.integration.appsflyer; - -import android.app.Application; -import android.test.ApplicationTestCase; - -/** - * Testing Fundamentals - */ -public class ApplicationTest extends ApplicationTestCase { - public ApplicationTest() { - super(Application.class); - } -} \ No newline at end of file +//package com.segment.analytics.android.integration.appsflyer; +// +//import android.app.Application; +//import android.test.ApplicationTestCase; +// +///** +// * Testing Fundamentals +// */ +//public class ApplicationTest extends ApplicationTestCase { +// public ApplicationTest() { +// super(Application.class); +// } +//} \ No newline at end of file diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index 1ce76c2..2a339a9 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -26,6 +26,14 @@ @RunWith(AndroidJUnit4.class) public class AppsflyerIntegrationTests { + MockedStatic staticAppsFlyerLib; + + public AppsFlyerLib mockAppsflyerLib(){ + this.staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); + AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); + this.staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); + return appsFlyerLib; + } @Test public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { @@ -35,25 +43,24 @@ public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { String appsflyerDevKey = "appsflyerDevKey"; boolean isDebug = logger.logLevel != Analytics.LogLevel.NONE; AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(context,logger,appsflyer,appsflyerDevKey); + Assert.assertEquals(appsflyerIntegration.isDebug , isDebug); Assert.assertEquals(appsflyerIntegration.appsFlyerDevKey, appsflyerDevKey); Assert.assertEquals(appsflyerIntegration.appsflyer, appsflyer); Assert.assertEquals(appsflyerIntegration.logger, logger); Field field = AppsflyerIntegration.class.getDeclaredField("context"); field.setAccessible(true); - Context contextInappsflyerIntegration = (Context) field.get(appsflyerIntegration); - Assert.assertEquals(contextInappsflyerIntegration, context); // checking the static clause - Assert.assertEquals(appsflyerIntegration.MAPPER.get("revenue"), AFInAppEventParameterName.REVENUE); - Assert.assertEquals(appsflyerIntegration.MAPPER.get("currency"), AFInAppEventParameterName.CURRENCY); + Assert.assertEquals(AppsflyerIntegration.MAPPER.get("revenue"), AFInAppEventParameterName.REVENUE); + Assert.assertEquals(AppsflyerIntegration.MAPPER.get("currency"), AFInAppEventParameterName.CURRENCY); reset(context,appsflyer); } @Test - public void testAppsflyerIntegration_setManualMode_happyFlow() throws Exception { + public void testAppsflyerIntegration_setManualMode_happyFlow() { Assert.assertFalse(AppsflyerIntegration.manualMode); AppsflyerIntegration.setManualMode(true); Assert.assertTrue(AppsflyerIntegration.manualMode); @@ -62,10 +69,8 @@ public void testAppsflyerIntegration_setManualMode_happyFlow() throws Exception } @Test - public void testAppsflyerIntegration_startAppsFlyer_happyFlow() throws Exception { - MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); - AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); - staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); + public void testAppsflyerIntegration_startAppsFlyer_happyFlow() { + AppsFlyerLib appsFlyerLib = mockAppsflyerLib(); Context context = mock(Context.class); AppsflyerIntegration.startAppsFlyer(context); @@ -77,10 +82,8 @@ public void testAppsflyerIntegration_startAppsFlyer_happyFlow() throws Exception } @Test - public void testAppsflyerIntegration_startAppsFlyer_nilFlow() throws Exception { - MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); - AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); - staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); + public void testAppsflyerIntegration_startAppsFlyer_nilFlow() { + AppsFlyerLib appsFlyerLib = mockAppsflyerLib(); AppsflyerIntegration.startAppsFlyer(null); @@ -91,10 +94,8 @@ public void testAppsflyerIntegration_startAppsFlyer_nilFlow() throws Exception { } @Test - public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception { - MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); - AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); - staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); + public void testAppsflyerIntegration_FACTORYCreate_happyFlow() { + AppsFlyerLib appsFlyerLib = mockAppsflyerLib(); Analytics analytics = mock(Analytics.class); ValueMap settings = new ValueMap(); settings.put("appsFlyerDevKey" , "devKey"); @@ -112,8 +113,7 @@ public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception ArgumentCaptor captorDevKey = ArgumentCaptor.forClass(String.class); ArgumentCaptor captorContext = ArgumentCaptor.forClass(Context.class); verify(appsFlyerLib).init(captorDevKey.capture(), captorListener.capture() , captorContext.capture()); - Assert.assertNotEquals(captorListener.getValue(), null); - Assert.assertTrue(captorListener.getValue() instanceof AppsflyerIntegration.ConversionListener); + Assert.assertNotNull(captorListener.getValue()); Assert.assertEquals(captorDevKey.getValue(), settings.getString("appsFlyerDevKey")); Assert.assertEquals(captorContext.getValue(), app.getApplicationContext()); verify(appsFlyerLib).subscribeForDeepLink(AppsflyerIntegration.deepLinkListener); @@ -124,10 +124,11 @@ public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception //need to check params values are null // @Test -// public void testAppsflyerIntegration_FACTORYCreate_nilFlow() throws Exception { -// MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); -// AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); -// staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); +// public void testAppsflyerIntegration_FACTORYCreate_nilFlow() { +//// MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); +//// AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); +// // staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); +// AppsFlyerLib appsFlyerLib = mockAppsflyerLib(); // Analytics analytics = mock(Analytics.class); // ValueMap settings = new ValueMap(); // settings.put("appsFlyerDevKey_wrong" , "devKey"); @@ -152,13 +153,13 @@ public void testAppsflyerIntegration_FACTORYCreate_happyFlow() throws Exception // verify(appsFlyerLib).subscribeForDeepLink(AppsflyerIntegration.deepLinkListener); @Test - public void testAppsflyerIntegration_FACTORYKEY_happyFlow() throws Exception { + public void testAppsflyerIntegration_FACTORYKEY_happyFlow() { Assert.assertEquals(AppsflyerIntegration.FACTORY.key(),"AppsFlyer"); } //need to check params values are null // @Test -// public void testAppsflyerIntegration_onActivityCreated_nilFlow() throws Exception { +// public void testAppsflyerIntegration_onActivityCreated_nilFlow() { // MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); // AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); // staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); @@ -169,7 +170,7 @@ public void testAppsflyerIntegration_FACTORYKEY_happyFlow() throws Exception { // } @Test - public void testAppsflyerIntegration_getUnderlyingInstance_happyFlow() throws Exception { + public void testAppsflyerIntegration_getUnderlyingInstance_happyFlow() { AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); Logger logger = new Logger("test", Analytics.LogLevel.INFO); AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(null,logger,appsFlyerLib,null); @@ -206,7 +207,7 @@ public void testAppsflyerIntegration_identify_happyFlow() throws Exception { } @Test - public void testAppsflyerIntegration_identify_nilflow() throws Exception { + public void testAppsflyerIntegration_identify_nilflow() { Logger logger = spy(new Logger("test", Analytics.LogLevel.INFO)); AppsflyerIntegration appsflyerIntegration = spy(new AppsflyerIntegration(null,logger,null,null)); IdentifyPayload identifyPayload = mock(IdentifyPayload.class); diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java index 08b1ca9..a8c87ec 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java @@ -20,7 +20,7 @@ public class AppsflyerIntegration_ConversionListenerTests { @Test - public void testAppsflyerIntegration_ConversionListener_ctor_happyFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_ctor_happyFlow() { Analytics analytics = mock(Analytics.class); AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); @@ -30,7 +30,7 @@ public void testAppsflyerIntegration_ConversionListener_ctor_happyFlow() throws } @Test - public void testAppsflyerIntegration_ConversionListener_ctor_nullFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_ctor_nullFlow() { Analytics analytics = null; AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); @@ -40,7 +40,7 @@ public void testAppsflyerIntegration_ConversionListener_ctor_nullFlow() throws E } @Test - public void testAppsflyerIntegration_ConversionListener_onConversionDataSuccess_happyFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_onConversionDataSuccess_happyFlow() { //I want just to check the conversionListener gets the map. AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); Analytics analytics = mock(Analytics.class); @@ -62,7 +62,7 @@ public void testAppsflyerIntegration_ConversionListener_onConversionDataSuccess_ } @Test - public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_happyFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_happyFlow() { AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); Analytics analytics = Mockito.mock(Analytics.class); AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); @@ -76,7 +76,7 @@ public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_hap } @Test - public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_nullFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_nullFlow() { AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); Analytics analytics = Mockito.mock(Analytics.class); AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); @@ -88,7 +88,7 @@ public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_nul } @Test - public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_happyFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_happyFlow() { Analytics analytics =mock(Analytics.class); Map attributionData = new HashMap() { @@ -117,7 +117,7 @@ public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_h } @Test - public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_negativeFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_negativeFlow() { Analytics analytics =mock(Analytics.class); Map attributionData = new HashMap(); Map campaign = new ValueMap() // @@ -255,7 +255,7 @@ public void testAppsflyerIntegration_ConversionListener_getContext_happyFlow() t } @Test - public void testAppsflyerIntegration_ConversionListener_getContext_nullFlow() throws Exception { + public void testAppsflyerIntegration_ConversionListener_getContext_nullFlow() throws Exception{ Analytics analytics = mock(Analytics.class); Application app = mock(Application.class); Context context = null; From 2dc955ce85244ed3ec34375d17533ee98cb9e1c4 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Sun, 29 Jan 2023 16:55:22 +0200 Subject: [PATCH 16/30] Merge request changes #3 --- .../appsflyer/AppsflyerIntegrationTests.java | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index 2a339a9..efd0a9e 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -22,6 +22,7 @@ import static org.mockito.Mockito.*; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.lang.reflect.Type; import java.util.Map; @RunWith(AndroidJUnit4.class) @@ -35,6 +36,18 @@ public AppsFlyerLib mockAppsflyerLib(){ return appsFlyerLib; } + public Object getPrivateFieldForObject(String funcName, Class classObject, Object objToGetValueFrom) throws Exception{ + Field field = classObject.getDeclaredField(funcName); + field.setAccessible(true); + return field.get(classObject.cast(objToGetValueFrom)); + } + + public void setPrivateFieldForObject(String funcName, Class classObject, Object objToGetValueFrom, Class valueClass, Object value) throws Exception{ + Field field = classObject.getDeclaredField(funcName); + field.setAccessible(true); + field.set(objToGetValueFrom,valueClass.cast(value)); + } + @Test public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { Context context = mock(Context.class); @@ -42,15 +55,14 @@ public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { AppsFlyerLib appsflyer = mock(AppsFlyerLib.class); String appsflyerDevKey = "appsflyerDevKey"; boolean isDebug = logger.logLevel != Analytics.LogLevel.NONE; + AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(context,logger,appsflyer,appsflyerDevKey); Assert.assertEquals(appsflyerIntegration.isDebug , isDebug); Assert.assertEquals(appsflyerIntegration.appsFlyerDevKey, appsflyerDevKey); Assert.assertEquals(appsflyerIntegration.appsflyer, appsflyer); Assert.assertEquals(appsflyerIntegration.logger, logger); - Field field = AppsflyerIntegration.class.getDeclaredField("context"); - field.setAccessible(true); - Context contextInappsflyerIntegration = (Context) field.get(appsflyerIntegration); + Context contextInappsflyerIntegration = (Context) getPrivateFieldForObject("context",AppsflyerIntegration.class,appsflyerIntegration); Assert.assertEquals(contextInappsflyerIntegration, context); // checking the static clause Assert.assertEquals(AppsflyerIntegration.MAPPER.get("revenue"), AFInAppEventParameterName.REVENUE); @@ -194,13 +206,9 @@ public void testAppsflyerIntegration_identify_happyFlow() throws Exception { appsflyerIntegration.identify(identifyPayload); verify(logger, never()).verbose(any()); - Field customerUserIdField = AppsflyerIntegration.class.getDeclaredField("customerUserId"); - customerUserIdField.setAccessible(true); - String customerUserIdInappsflyerIntegration = (String) customerUserIdField.get(appsflyerIntegration); + String customerUserIdInappsflyerIntegration = (String)getPrivateFieldForObject("customerUserId",AppsflyerIntegration.class,appsflyerIntegration); Assert.assertEquals(customerUserIdInappsflyerIntegration, "moris"); - Field currencyCodeField = AppsflyerIntegration.class.getDeclaredField("currencyCode"); - currencyCodeField.setAccessible(true); - String currencyCodeInappsflyerIntegration = (String) currencyCodeField.get(appsflyerIntegration); + String currencyCodeInappsflyerIntegration = (String) getPrivateFieldForObject("currencyCode",AppsflyerIntegration.class,appsflyerIntegration); Assert.assertEquals(currencyCodeInappsflyerIntegration, "ILS"); reset(appsFlyerLib,identifyPayload,traits); @@ -228,13 +236,8 @@ public void testAppsflyerIntegration_updateEndUserAttributes_happyflow() throws AppsflyerIntegration appsflyerIntegration = spy(new AppsflyerIntegration(null,logger,appsFlyerLib,null)); Method updateEndUserAttributes = AppsflyerIntegration.class.getDeclaredMethod("updateEndUserAttributes"); updateEndUserAttributes.setAccessible(true); - Field customerUserIdField = AppsflyerIntegration.class.getDeclaredField("customerUserId"); - customerUserIdField.setAccessible(true); - customerUserIdField.set(appsflyerIntegration,"Moris"); - Field currencyCodeField = AppsflyerIntegration.class.getDeclaredField("currencyCode"); - currencyCodeField.setAccessible(true); - currencyCodeField.set(appsflyerIntegration, "ILS"); - + setPrivateFieldForObject("customerUserId",AppsflyerIntegration.class,appsflyerIntegration,String.class,"Moris"); + setPrivateFieldForObject("currencyCode",AppsflyerIntegration.class,appsflyerIntegration,String.class,"ILS"); updateEndUserAttributes.invoke(appsflyerIntegration); verify(logger, times(1)).verbose("appsflyer.setCustomerUserId(%s)", "Moris"); @@ -257,12 +260,10 @@ public void testAppsflyerIntegration_track_happyflow() throws Exception { when(trackPayload.event()).thenReturn(event); when(trackPayload.properties()).thenReturn(properties); staticUtils.when(()->com.segment.analytics.internal.Utils.transform(any(),any())).thenReturn(afProperties); - appsflyerIntegration.track(trackPayload); - Field contextField = AppsflyerIntegration.class.getDeclaredField("context"); - contextField.setAccessible(true); - Context contextInAppsflyerIntegration = (Context) contextField.get(appsflyerIntegration); + appsflyerIntegration.track(trackPayload); + Context contextInAppsflyerIntegration = (Context) getPrivateFieldForObject("context",AppsflyerIntegration.class,appsflyerIntegration); verify(appsFlyerLib, times(1)).logEvent(contextInAppsflyerIntegration,event,afProperties); verify(logger, times(1)).verbose("appsflyer.logEvent(context, %s, %s)", event, properties); From b30cc6c5e2f3db9197f24b61e739feea67daacc5 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Sun, 5 Feb 2023 10:18:12 +0200 Subject: [PATCH 17/30] added Paz's publish.gradle file and changed properties but not sure sample app is working --- app/publish.gradle | 192 ++++++++++++++++++++++++++++++--------------- gradle.properties | 2 +- 2 files changed, 130 insertions(+), 64 deletions(-) diff --git a/app/publish.gradle b/app/publish.gradle index 90ef088..961640c 100644 --- a/app/publish.gradle +++ b/app/publish.gradle @@ -1,63 +1,129 @@ -//apply plugin: 'maven' -//apply plugin: 'signing' -// -//afterEvaluate { project -> -// uploadArchives { -// repositories { -// mavenDeployer { -// beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } -// pom.groupId = GROUP -// pom.artifactId = POM_ARTIFACT_ID -// pom.version = VERSION_NAME -// repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { -// authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) -// } -// pom.project { -// name POM_NAME -// packaging POM_PACKAGING -// description POM_DESCRIPTION -// url POM_URL -// scm { -// url POM_SCM_URL -// connection POM_SCM_CONNECTION -// developerConnection POM_SCM_DEV_CONNECTION -// } -// licenses { -// license { -// name POM_LICENCE_NAME -// url POM_LICENCE_URL -// distribution POM_LICENCE_DIST -// } -// } -// developers { -// developer { -// id POM_DEVELOPER_ID -// name POM_DEVELOPER_NAME -// } -// } -// } -// } -// } -// } -// signing { -// required { gradle.taskGraph.hasTask("uploadArchives") } -// sign configurations.archives -// } -// task androidJavadocs(type: Javadoc) { -// classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) -// if (JavaVersion.current().isJava8Compatible()) { -// allprojects { -// tasks.withType(Javadoc) { options.addStringOption('Xdoclint:none', '-quiet') } -// } -// } -// } -// task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { -// archiveClassifier = 'javadoc' -// from androidJavadocs.destinationDir -// } -// task androidSourcesJar(type: Jar) { -// classifier = 'sources' -// from android.sourceSets.main.java.sourceFiles -// } -// artifacts { archives androidJavadocsJar } -//} \ No newline at end of file +apply plugin: 'maven-publish' +apply plugin: 'signing' + +def isReleaseBuild() { + return !VERSION_NAME.contains("SNAPSHOT") +} + +def getReleaseRepositoryUrl() { + return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL + : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" +} + +def getSnapshotRepositoryUrl() { + return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL + : "https://oss.sonatype.org/content/repositories/snapshots/" +} + +task androidJavadocs(type: Javadoc) { + exclude "**/*.orig" // exclude files created by source control + source = android.sourceSets.main.java.srcDirs + classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) + failOnError false +} + +task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { + archiveClassifier.set("javadoc") + + from androidJavadocs.destinationDir +} + +task androidSourcesJar(type: Jar) { + archiveClassifier.set("sources") + + from android.sourceSets.main.java.source +} + +def logger(log) { + println log +} + +def configurePom(pom) { + logger("configurePom") + pom.name = POM_NAME + pom.packaging = POM_PACKAGING + pom.description = POM_DESCRIPTION + pom.url = POM_URL + + pom.scm { + url = POM_SCM_URL + connection = POM_SCM_CONNECTION + developerConnection = POM_SCM_DEV_CONNECTION + } + + pom.licenses { + license { + name = POM_LICENCE_NAME + url = POM_LICENCE_URL + distribution = POM_LICENCE_DIST + } + } + + pom.developers { + developer { + id = POM_DEVELOPER_ID + name = POM_DEVELOPER_NAME + } + } +} + +afterEvaluate { + publishing { + publications { + release(MavenPublication) { + logger("release") + // The coordinates of the library, being set from variables that + // we'll set up in a moment + groupId GROUP + artifactId POM_ARTIFACT_ID + version VERSION_NAME + + // Two artifacts, the `aar` and the sources + // artifact("$buildDir/outputs/aar/${project.getName()}-release.aar") + artifact bundleReleaseAar + artifact androidSourcesJar + artifact androidJavadocsJar + + // Self-explanatory metadata for the most part + pom { + configurePom(pom) + // A slight fix so that the generated POM will include any transitive dependencies + // that the library builds upon + withXml { + def dependenciesNode = asNode().appendNode('dependencies') + + project.configurations.implementation.allDependencies.each { + def dependencyNode = dependenciesNode.appendNode('dependency') + dependencyNode.appendNode('groupId', it.group) + dependencyNode.appendNode('artifactId', it.name) + dependencyNode.appendNode('version', it.version) + } + } + } + } + } + repositories { + maven { + name = "sonatype" + + // You only need this if you want to publish snapshots, otherwise just set the URL + // to the release repo directly + url = isReleaseBuild() ? getReleaseRepositoryUrl() : getSnapshotRepositoryUrl() + + credentials(PasswordCredentials) { + username = getRepositoryUsername() + password = getRepositoryPassword() + } + } + } + } +} + +signing { + logger("signing") + sign publishing.publications +} + + +publish.dependsOn build +publishToMavenLocal.dependsOn build \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 425918d..97c5b0e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -40,4 +40,4 @@ POM_DEVELOPER_ID=appsflyer POM_DEVELOPER_NAME=AppsFlyer, Inc. android.useAndroidX=true -android.enableJetifier=false \ No newline at end of file +android.enableJetifier=true \ No newline at end of file From 02aed62c28617f53c67a2547945cd4798ccf146f Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 7 Feb 2023 11:52:50 +0200 Subject: [PATCH 18/30] build.gradle change --- app/build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 3f62bdc..3cff191 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,4 +41,6 @@ dependencies { testImplementation 'com.segment.analytics.android:analytics:4.+' testImplementation 'org.mockito:mockito-core:4.2.0' testImplementation 'com.segment.analytics.android:analytics-tests:4.+' -} \ No newline at end of file +} + +apply from:file("publish.gradle") \ No newline at end of file From bded5228f9f8fdab45d1998ef4317da27cb796e9 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 7 Feb 2023 11:56:29 +0200 Subject: [PATCH 19/30] Changes following Paz's review --- ...erIntegrationConversionListenerTests.java} | 103 ++++++------------ .../appsflyer/AppsflyerIntegrationTests.java | 53 +++------ .../integrations/appsflyer/TestHelper.java | 42 +++++++ 3 files changed, 91 insertions(+), 107 deletions(-) rename app/src/test/java/com/segment/analytics/android/integrations/appsflyer/{AppsflyerIntegration_ConversionListenerTests.java => AppsflyerIntegrationConversionListenerTests.java} (70%) create mode 100644 app/src/test/java/com/segment/analytics/android/integrations/appsflyer/TestHelper.java diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationConversionListenerTests.java similarity index 70% rename from app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java rename to app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationConversionListenerTests.java index a8c87ec..417a2ae 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration_ConversionListenerTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationConversionListenerTests.java @@ -17,26 +17,24 @@ import java.util.Map; @RunWith(AndroidJUnit4.class) -public class AppsflyerIntegration_ConversionListenerTests { +public class AppsflyerIntegrationConversionListenerTests { @Test public void testAppsflyerIntegration_ConversionListener_ctor_happyFlow() { Analytics analytics = mock(Analytics.class); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + AppsflyerIntegration.ConversionListener conversionListener = new AppsflyerIntegration.ConversionListener(analytics); Assert.assertEquals(conversionListener.analytics, analytics); - reset(analytics,conversionListener); + reset(analytics); } @Test public void testAppsflyerIntegration_ConversionListener_ctor_nullFlow() { Analytics analytics = null; - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + AppsflyerIntegration.ConversionListener conversionListener = new AppsflyerIntegration.ConversionListener(analytics); Assert.assertEquals(conversionListener.analytics, analytics); - - reset(conversionListener); } @Test @@ -52,53 +50,50 @@ public void testAppsflyerIntegration_ConversionListener_onConversionDataSuccess_ when(app.getApplicationContext()).thenReturn(context); when(context.getSharedPreferences("appsflyer-segment-data",0)).thenReturn(sharedPreferences); when(sharedPreferences.getBoolean("AF_onConversion_Data",false)).thenReturn(true); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + AppsflyerIntegration.ConversionListener conversionListener = new AppsflyerIntegration.ConversionListener(analytics); conversionListener.onConversionDataSuccess(conversionData); verify(AppsflyerIntegration.conversionListener).onConversionDataSuccess(conversionData); - reset(AppsflyerIntegration.conversionListener,analytics,app,context,sharedPreferences,conversionListener); + reset(AppsflyerIntegration.conversionListener,analytics,app,context,sharedPreferences); } @Test public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_happyFlow() { AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); Analytics analytics = Mockito.mock(Analytics.class); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + AppsflyerIntegration.ConversionListener conversionListener = new AppsflyerIntegration.ConversionListener(analytics); String errorMsg = "error - test"; conversionListener.onAttributionFailure(errorMsg); verify(AppsflyerIntegration.conversionListener,times(1)).onAttributionFailure(errorMsg); - reset(analytics,conversionListener,AppsflyerIntegration.conversionListener); + reset(analytics,AppsflyerIntegration.conversionListener); } @Test public void testAppsflyerIntegration_ConversionListener_onAttributionFailure_nullFlow() { AppsflyerIntegration.conversionListener = mock(AppsflyerIntegration.ExternalAppsFlyerConversionListener.class); Analytics analytics = Mockito.mock(Analytics.class); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + AppsflyerIntegration.ConversionListener conversionListener = new AppsflyerIntegration.ConversionListener(analytics); String errorMsg = null; conversionListener.onAttributionFailure(errorMsg); verify(AppsflyerIntegration.conversionListener,times(1)).onAttributionFailure(null); - reset(analytics,conversionListener,AppsflyerIntegration.conversionListener); + reset(analytics,AppsflyerIntegration.conversionListener); } @Test public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_happyFlow() { Analytics analytics =mock(Analytics.class); - Map attributionData = new HashMap() - { - { - put("media_source", "media_source_moris"); - put("campaign", "campaign_moris"); - put("adgroup", "adgroup_moris"); - } - }; - Map campaign = new ValueMap() // + Map attributionData = new HashMap<>(); + attributionData.put("media_source", "media_source_moris"); + attributionData.put("campaign", "campaign_moris"); + attributionData.put("adgroup", "adgroup_moris"); + + Map campaign = new ValueMap() .putValue("source", attributionData.get("media_source")) .putValue("name", attributionData.get("campaign")) .putValue("ad_group", attributionData.get("adgroup")); @@ -107,13 +102,13 @@ public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_h properties.remove("media_source"); properties.remove("adgroup"); properties.putValue("campaign", campaign); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + AppsflyerIntegration.ConversionListener conversionListener = new AppsflyerIntegration.ConversionListener(analytics); conversionListener.trackInstallAttributed(attributionData); verify(analytics,times(1)).track("Install Attributed", properties); - reset(analytics,conversionListener); + reset(analytics); } @Test @@ -129,12 +124,12 @@ public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_n properties.remove("media_source"); properties.remove("adgroup"); properties.putValue("campaign", campaign); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); + AppsflyerIntegration.ConversionListener conversionListener = new AppsflyerIntegration.ConversionListener(analytics); conversionListener.trackInstallAttributed(attributionData); verify(analytics,times(1)).track("Install Attributed", properties); - reset(analytics,conversionListener); + reset(analytics); } //This flow breaks because there is no check for attributionData!=null in trackInstallAttributed method. @@ -170,15 +165,13 @@ public void testAppsflyerIntegration_ConversionListener_getFlag_happyFlow() thro when(app.getApplicationContext()).thenReturn(context); when(context.getSharedPreferences("appsflyer-segment-data",0)).thenReturn(sharedPreferences); when(sharedPreferences.getBoolean(key,false)).thenReturn(true); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - Method getFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getFlag",String.class); - getFlagMethod.setAccessible(true); + AppsflyerIntegration.ConversionListener conversionListener = new AppsflyerIntegration.ConversionListener(analytics); - boolean resBoolean = (Boolean) getFlagMethod.invoke(conversionListener,key); + boolean resBoolean = (Boolean) TestHelper.getPrivateMethodForObjectReadyToInvoke("getFlag",String.class).invoke(conversionListener,key); Assert.assertTrue(resBoolean); - reset(analytics,app,context,sharedPreferences,conversionListener); + reset(analytics,app,context,sharedPreferences); } @Test @@ -194,11 +187,9 @@ public void testAppsflyerIntegration_ConversionListener_setFlag_happyFlow() thro when(app.getApplicationContext()).thenReturn(context); when(context.getSharedPreferences("appsflyer-segment-data",0)).thenReturn(sharedPreferences); when(sharedPreferences.edit()).thenReturn(editor); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - Method setFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("setFlag",String.class,boolean.class); - setFlagMethod.setAccessible(true); + AppsflyerIntegration.ConversionListener conversionListener = new AppsflyerIntegration.ConversionListener(analytics); - setFlagMethod.invoke(conversionListener,key,value); + TestHelper.getPrivateMethodForObjectReadyToInvoke("setFlag",String.class,boolean.class).invoke(conversionListener,key,value); if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD){ verify(editor,times(1)).apply(); @@ -207,35 +198,9 @@ public void testAppsflyerIntegration_ConversionListener_setFlag_happyFlow() thro verify(editor,times(1)).commit(); } - reset(analytics,app,context,sharedPreferences,conversionListener); - } - - @Test - public void testAppsflyerIntegration_ConversionListener_editorCommit_happyFlow() throws Exception { - SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class); - Analytics analytics = mock(Analytics.class); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - Method editorCommitMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("editorCommit",SharedPreferences.Editor.class); - editorCommitMethod.setAccessible(true); - - editorCommitMethod.invoke(conversionListener,editor); - - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) { - verify(editor,times(1)).apply(); - } - else{ - verify(editor,times(1)).commit(); - } - - reset(analytics,conversionListener); + reset(analytics,app,context,sharedPreferences); } -// Not checking for editor is null. -// @Test -// public void testAppsflyerIntegration_ConversionListener_editorCommit_nullFlow() throws Exception { -// -// } - @Test public void testAppsflyerIntegration_ConversionListener_getContext_happyFlow() throws Exception { Analytics analytics = mock(Analytics.class); @@ -243,15 +208,13 @@ public void testAppsflyerIntegration_ConversionListener_getContext_happyFlow() t Context context = mock(Context.class); when(analytics.getApplication()).thenReturn(app); when(app.getApplicationContext()).thenReturn(context); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - Method getContextMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getContext"); - getContextMethod.setAccessible(true); + AppsflyerIntegration.ConversionListener conversionListener = new AppsflyerIntegration.ConversionListener(analytics); - Context resContext = (Context) getContextMethod.invoke(conversionListener); + Context resContext = (Context) TestHelper.getPrivateMethodForObjectReadyToInvoke("getContext").invoke(conversionListener); Assert.assertEquals(resContext, context); - reset(analytics,app,context,conversionListener); + reset(analytics,app,context); } @Test @@ -261,14 +224,12 @@ public void testAppsflyerIntegration_ConversionListener_getContext_nullFlow() th Context context = null; when(analytics.getApplication()).thenReturn(app); when(app.getApplicationContext()).thenReturn(context); - AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); - Method getContextMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod("getContext"); - getContextMethod.setAccessible(true); + AppsflyerIntegration.ConversionListener conversionListener = new AppsflyerIntegration.ConversionListener(analytics); - Context resContext = (Context) getContextMethod.invoke(conversionListener); + Context resContext = (Context) TestHelper.getPrivateMethodForObjectReadyToInvoke("getContext").invoke(conversionListener); Assert.assertEquals(resContext, context); - reset(analytics,app,conversionListener); + reset(analytics,app); } } diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index efd0a9e..72acf88 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -27,26 +27,7 @@ @RunWith(AndroidJUnit4.class) public class AppsflyerIntegrationTests { - MockedStatic staticAppsFlyerLib; - - public AppsFlyerLib mockAppsflyerLib(){ - this.staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); - AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); - this.staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); - return appsFlyerLib; - } - - public Object getPrivateFieldForObject(String funcName, Class classObject, Object objToGetValueFrom) throws Exception{ - Field field = classObject.getDeclaredField(funcName); - field.setAccessible(true); - return field.get(classObject.cast(objToGetValueFrom)); - } - - public void setPrivateFieldForObject(String funcName, Class classObject, Object objToGetValueFrom, Class valueClass, Object value) throws Exception{ - Field field = classObject.getDeclaredField(funcName); - field.setAccessible(true); - field.set(objToGetValueFrom,valueClass.cast(value)); - } + private TestHelper testHelper = new TestHelper(); @Test public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { @@ -62,7 +43,7 @@ public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { Assert.assertEquals(appsflyerIntegration.appsFlyerDevKey, appsflyerDevKey); Assert.assertEquals(appsflyerIntegration.appsflyer, appsflyer); Assert.assertEquals(appsflyerIntegration.logger, logger); - Context contextInappsflyerIntegration = (Context) getPrivateFieldForObject("context",AppsflyerIntegration.class,appsflyerIntegration); + Context contextInappsflyerIntegration = (Context) TestHelper.getPrivateFieldForObject("context",AppsflyerIntegration.class,appsflyerIntegration); Assert.assertEquals(contextInappsflyerIntegration, context); // checking the static clause Assert.assertEquals(AppsflyerIntegration.MAPPER.get("revenue"), AFInAppEventParameterName.REVENUE); @@ -82,7 +63,7 @@ public void testAppsflyerIntegration_setManualMode_happyFlow() { @Test public void testAppsflyerIntegration_startAppsFlyer_happyFlow() { - AppsFlyerLib appsFlyerLib = mockAppsflyerLib(); + AppsFlyerLib appsFlyerLib = testHelper.mockAppsflyerLib(); Context context = mock(Context.class); AppsflyerIntegration.startAppsFlyer(context); @@ -90,24 +71,24 @@ public void testAppsflyerIntegration_startAppsFlyer_happyFlow() { verify(appsFlyerLib).start(context); reset(appsFlyerLib,context); - staticAppsFlyerLib.close(); + testHelper.closeMockAppsflyerLib(); } @Test public void testAppsflyerIntegration_startAppsFlyer_nilFlow() { - AppsFlyerLib appsFlyerLib = mockAppsflyerLib(); + AppsFlyerLib appsFlyerLib = testHelper.mockAppsflyerLib(); AppsflyerIntegration.startAppsFlyer(null); verify(appsFlyerLib,never()).start(any()); reset(appsFlyerLib); - staticAppsFlyerLib.close(); + testHelper.closeMockAppsflyerLib(); } @Test public void testAppsflyerIntegration_FACTORYCreate_happyFlow() { - AppsFlyerLib appsFlyerLib = mockAppsflyerLib(); + AppsFlyerLib appsFlyerLib = testHelper.mockAppsflyerLib(); Analytics analytics = mock(Analytics.class); ValueMap settings = new ValueMap(); settings.put("appsFlyerDevKey" , "devKey"); @@ -131,7 +112,7 @@ public void testAppsflyerIntegration_FACTORYCreate_happyFlow() { verify(appsFlyerLib).subscribeForDeepLink(AppsflyerIntegration.deepLinkListener); reset(appsFlyerLib,analytics,app,AppsflyerIntegration.deepLinkListener); - staticAppsFlyerLib.close(); + testHelper.closeMockAppsflyerLib(); } //need to check params values are null @@ -196,7 +177,7 @@ public void testAppsflyerIntegration_getUnderlyingInstance_happyFlow() { public void testAppsflyerIntegration_identify_happyFlow() throws Exception { AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); Logger logger = spy(new Logger("test", Analytics.LogLevel.INFO)); - AppsflyerIntegration appsflyerIntegration = spy(new AppsflyerIntegration(null,logger,appsFlyerLib,null)); + AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(null,logger,appsFlyerLib,null); IdentifyPayload identifyPayload = mock(IdentifyPayload.class); Traits traits = mock(Traits.class); when(identifyPayload.userId()).thenReturn("moris"); @@ -206,9 +187,9 @@ public void testAppsflyerIntegration_identify_happyFlow() throws Exception { appsflyerIntegration.identify(identifyPayload); verify(logger, never()).verbose(any()); - String customerUserIdInappsflyerIntegration = (String)getPrivateFieldForObject("customerUserId",AppsflyerIntegration.class,appsflyerIntegration); + String customerUserIdInappsflyerIntegration = (String) TestHelper.getPrivateFieldForObject("customerUserId",AppsflyerIntegration.class,appsflyerIntegration); Assert.assertEquals(customerUserIdInappsflyerIntegration, "moris"); - String currencyCodeInappsflyerIntegration = (String) getPrivateFieldForObject("currencyCode",AppsflyerIntegration.class,appsflyerIntegration); + String currencyCodeInappsflyerIntegration = (String) TestHelper.getPrivateFieldForObject("currencyCode",AppsflyerIntegration.class,appsflyerIntegration); Assert.assertEquals(currencyCodeInappsflyerIntegration, "ILS"); reset(appsFlyerLib,identifyPayload,traits); @@ -217,7 +198,7 @@ public void testAppsflyerIntegration_identify_happyFlow() throws Exception { @Test public void testAppsflyerIntegration_identify_nilflow() { Logger logger = spy(new Logger("test", Analytics.LogLevel.INFO)); - AppsflyerIntegration appsflyerIntegration = spy(new AppsflyerIntegration(null,logger,null,null)); + AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(null,logger,null,null); IdentifyPayload identifyPayload = mock(IdentifyPayload.class); Traits traits = mock(Traits.class); when(identifyPayload.traits()).thenReturn(traits); @@ -233,11 +214,11 @@ public void testAppsflyerIntegration_identify_nilflow() { public void testAppsflyerIntegration_updateEndUserAttributes_happyflow() throws Exception { AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); Logger logger = spy(new Logger("test", Analytics.LogLevel.INFO)); - AppsflyerIntegration appsflyerIntegration = spy(new AppsflyerIntegration(null,logger,appsFlyerLib,null)); + AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(null,logger,appsFlyerLib,null); Method updateEndUserAttributes = AppsflyerIntegration.class.getDeclaredMethod("updateEndUserAttributes"); updateEndUserAttributes.setAccessible(true); - setPrivateFieldForObject("customerUserId",AppsflyerIntegration.class,appsflyerIntegration,String.class,"Moris"); - setPrivateFieldForObject("currencyCode",AppsflyerIntegration.class,appsflyerIntegration,String.class,"ILS"); + TestHelper.setPrivateFieldForObject("customerUserId",AppsflyerIntegration.class,appsflyerIntegration,String.class,"Moris"); + TestHelper.setPrivateFieldForObject("currencyCode",AppsflyerIntegration.class,appsflyerIntegration,String.class,"ILS"); updateEndUserAttributes.invoke(appsflyerIntegration); verify(logger, times(1)).verbose("appsflyer.setCustomerUserId(%s)", "Moris"); @@ -251,7 +232,7 @@ public void testAppsflyerIntegration_updateEndUserAttributes_happyflow() throws public void testAppsflyerIntegration_track_happyflow() throws Exception { AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); Logger logger = spy(new Logger("test", Analytics.LogLevel.INFO)); - AppsflyerIntegration appsflyerIntegration = spy(new AppsflyerIntegration(null,logger,appsFlyerLib,null)); + AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(null,logger,appsFlyerLib,null); TrackPayload trackPayload = mock(TrackPayload.class); String event = "event"; Properties properties= mock(Properties.class); @@ -263,7 +244,7 @@ public void testAppsflyerIntegration_track_happyflow() throws Exception { appsflyerIntegration.track(trackPayload); - Context contextInAppsflyerIntegration = (Context) getPrivateFieldForObject("context",AppsflyerIntegration.class,appsflyerIntegration); + Context contextInAppsflyerIntegration = (Context) TestHelper.getPrivateFieldForObject("context",AppsflyerIntegration.class,appsflyerIntegration); verify(appsFlyerLib, times(1)).logEvent(contextInAppsflyerIntegration,event,afProperties); verify(logger, times(1)).verbose("appsflyer.logEvent(context, %s, %s)", event, properties); diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/TestHelper.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/TestHelper.java new file mode 100644 index 0000000..15f3ff0 --- /dev/null +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/TestHelper.java @@ -0,0 +1,42 @@ +package com.segment.analytics.android.integrations.appsflyer; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; + +import com.appsflyer.AppsFlyerLib; + +import org.mockito.MockedStatic; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public class TestHelper { + MockedStatic staticAppsFlyerLib; + public AppsFlyerLib mockAppsflyerLib(){ + this.staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); + AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); + this.staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); + return appsFlyerLib; + } + public void closeMockAppsflyerLib(){ + this.staticAppsFlyerLib.close(); + } + + public static Object getPrivateFieldForObject(String fieldName, Class classObject, Object objToGetValueFrom) throws Exception{ + Field field = classObject.getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(classObject.cast(objToGetValueFrom)); + } + + public static void setPrivateFieldForObject(String fieldName, Class classObject, Object objToGetValueFrom, Class valueClass, Object value) throws Exception{ + Field field = classObject.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(objToGetValueFrom,valueClass.cast(value)); + } + + public static Method getPrivateMethodForObjectReadyToInvoke(String funcName,Class... parameterTypesForMethod) throws Exception{ + Method getFlagMethod = AppsflyerIntegration.ConversionListener.class.getDeclaredMethod(funcName,parameterTypesForMethod); + getFlagMethod.setAccessible(true); + return getFlagMethod; + } +} From 96e1c3148dba1f382f6e2ae84bc8d4dd5c6dcc3d Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 7 Feb 2023 12:17:56 +0200 Subject: [PATCH 20/30] removed comments --- ...yerIntegrationConversionListenerTests.java | 22 ------------------- .../appsflyer/AppsflyerIntegrationTests.java | 12 ---------- 2 files changed, 34 deletions(-) diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationConversionListenerTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationConversionListenerTests.java index 417a2ae..32f2378 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationConversionListenerTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationConversionListenerTests.java @@ -132,28 +132,6 @@ public void testAppsflyerIntegration_ConversionListener_trackInstallAttributed_n reset(analytics); } -//This flow breaks because there is no check for attributionData!=null in trackInstallAttributed method. -// @Test -// public void testAppsflyerIntegration_trackInstallAttributed_nullFlow() throws Exception { -// Analytics analytics =mock(Analytics.class); -// Map attributionData = null; -// -// AppsflyerIntegration.ConversionListener conversionListener = spy(new AppsflyerIntegration.ConversionListener(analytics)); -// conversionListener.trackInstallAttributed(attributionData); -// -// Map campaign = new ValueMap() // -// .putValue("source", "") -// .putValue("name", "") -// .putValue("ad_group", ""); -// Properties properties = new Properties().putValue("provider", "AppsFlyer"); -// properties.putAll(attributionData); -// properties.remove("media_source"); -// properties.remove("adgroup"); -// properties.putValue("campaign", campaign); -// verify(analytics,times(1)).track("Install Attributed", properties); -// reset(analytics); -// } - @Test public void testAppsflyerIntegration_ConversionListener_getFlag_happyFlow() throws Exception { String key="key"; diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index 72acf88..f80796d 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -150,18 +150,6 @@ public void testAppsflyerIntegration_FACTORYKEY_happyFlow() { Assert.assertEquals(AppsflyerIntegration.FACTORY.key(),"AppsFlyer"); } - //need to check params values are null -// @Test -// public void testAppsflyerIntegration_onActivityCreated_nilFlow() { -// MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); -// AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); -// staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); -// AppsflyerIntegration.manualMode=false; -// AppsflyerIntegration appsflyerIntegration = mock(AppsflyerIntegration.class); -// appsflyerIntegration.onActivityCreated(mock(Activity.class), mock(Bundle.class)); -// verify(appsFlyerLib).start(any()); -// } - @Test public void testAppsflyerIntegration_getUnderlyingInstance_happyFlow() { AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); From 4543ab685bb2d5ffd5666adebfe7a6957307dbab Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 7 Feb 2023 12:19:25 +0200 Subject: [PATCH 21/30] small refactor checked if a param is a null value - create method --- .../android/integrations/appsflyer/AppsflyerIntegration.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration.java b/app/src/main/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration.java index 22e10cf..0bdcc02 100644 --- a/app/src/main/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration.java +++ b/app/src/main/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration.java @@ -80,6 +80,9 @@ public static void startAppsFlyer(@NonNull Context context){ public static final Factory FACTORY = new Integration.Factory() { @Override public Integration create(ValueMap settings, Analytics analytics) { + if(settings==null || analytics==null){ + return null; + } Logger logger = analytics.logger(APPSFLYER_KEY); AppsFlyerLib afLib = AppsFlyerLib.getInstance(); From 98acc6244647d020c653ba44c99619fe3bcd4e00 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Mon, 27 Feb 2023 09:17:12 +0200 Subject: [PATCH 22/30] added spaces --- .../android/integrations/appsflyer/AppsflyerIntegration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration.java b/app/src/main/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration.java index 0bdcc02..145961b 100644 --- a/app/src/main/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration.java +++ b/app/src/main/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegration.java @@ -80,7 +80,7 @@ public static void startAppsFlyer(@NonNull Context context){ public static final Factory FACTORY = new Integration.Factory() { @Override public Integration create(ValueMap settings, Analytics analytics) { - if(settings==null || analytics==null){ + if(settings == null || analytics == null){ return null; } Logger logger = analytics.logger(APPSFLYER_KEY); From f7d54e320d08d19bf4cc1964bd19b8e4289b4a82 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 28 Feb 2023 11:27:31 +0200 Subject: [PATCH 23/30] sanity check --- .../integrations/appsflyer/AppsflyerIntegrationTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index f80796d..820839c 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -38,7 +38,7 @@ public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { boolean isDebug = logger.logLevel != Analytics.LogLevel.NONE; AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(context,logger,appsflyer,appsflyerDevKey); - + Assert.assertEquals(4,5); Assert.assertEquals(appsflyerIntegration.isDebug , isDebug); Assert.assertEquals(appsflyerIntegration.appsFlyerDevKey, appsflyerDevKey); Assert.assertEquals(appsflyerIntegration.appsflyer, appsflyer); From cf687c9fa65ec56d834d52ece08508c97d0d5099 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 28 Feb 2023 11:32:41 +0200 Subject: [PATCH 24/30] added verbose to testing --- app/build.gradle | 8 ++++++++ .../integrations/appsflyer/AppsflyerIntegrationTests.java | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 3cff191..741bdf7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -43,4 +43,12 @@ dependencies { testImplementation 'com.segment.analytics.android:analytics-tests:4.+' } +tasks.withType(Test) { + testLogging { + exceptionFormat "full" + events "started", "skipped", "passed", "failed" + showStandardStreams true + } +} + apply from:file("publish.gradle") \ No newline at end of file diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index 820839c..60e71f8 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -38,7 +38,6 @@ public void testAppsflyerIntegration_ctor_happyFlow() throws Exception { boolean isDebug = logger.logLevel != Analytics.LogLevel.NONE; AppsflyerIntegration appsflyerIntegration = new AppsflyerIntegration(context,logger,appsflyer,appsflyerDevKey); - Assert.assertEquals(4,5); Assert.assertEquals(appsflyerIntegration.isDebug , isDebug); Assert.assertEquals(appsflyerIntegration.appsFlyerDevKey, appsflyerDevKey); Assert.assertEquals(appsflyerIntegration.appsflyer, appsflyer); From 6b2c9660de550d6e28f7a7ef66ac9d91a7a4146b Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 28 Feb 2023 15:56:19 +0200 Subject: [PATCH 25/30] added nil flow check --- .../appsflyer/AppsflyerIntegrationTests.java | 38 +++++-------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java index 60e71f8..823b26b 100644 --- a/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java +++ b/app/src/test/java/com/segment/analytics/android/integrations/appsflyer/AppsflyerIntegrationTests.java @@ -114,35 +114,15 @@ public void testAppsflyerIntegration_FACTORYCreate_happyFlow() { testHelper.closeMockAppsflyerLib(); } -//need to check params values are null -// @Test -// public void testAppsflyerIntegration_FACTORYCreate_nilFlow() { -//// MockedStatic staticAppsFlyerLib = mockStatic(AppsFlyerLib.class); -//// AppsFlyerLib appsFlyerLib = mock(AppsFlyerLib.class); -// // staticAppsFlyerLib.when(AppsFlyerLib::getInstance).thenReturn(appsFlyerLib); -// AppsFlyerLib appsFlyerLib = mockAppsflyerLib(); -// Analytics analytics = mock(Analytics.class); -// ValueMap settings = new ValueMap(); -// settings.put("appsFlyerDevKey_wrong" , "devKey"); -// settings.put("trackAttributionData_wrong" , true); -// Logger logger = new Logger("test", Analytics.LogLevel.INFO); -// Mockito.when(analytics.logger("AppsFlyer")).thenReturn(logger); -// Application app = mock(Application.class); -// Mockito.when(analytics.getApplication()).thenReturn(app); -// AppsflyerIntegration.deepLinkListener = mock(AppsflyerIntegration.ExternalDeepLinkListener.class); -// -// Integration integration = -// (Integration) AppsflyerIntegration.FACTORY.create(settings,analytics); -// verify(appsFlyerLib).setDebugLog(logger.logLevel!=Analytics.LogLevel.NONE); -// ArgumentCaptor captorListener = ArgumentCaptor.forClass(AppsflyerIntegration.ConversionListener.class); -// ArgumentCaptor captorDevKey = ArgumentCaptor.forClass(String.class); -// ArgumentCaptor captorContext = ArgumentCaptor.forClass(Context.class); -// verify(appsFlyerLib).init(captorDevKey.capture(), captorListener.capture() , captorContext.capture()); -// Assert.assertTrue(captorListener.getValue()!=null); -// Assert.assertTrue(captorListener.getValue() instanceof AppsflyerIntegration.ConversionListener); -// Assert.assertTrue(captorDevKey.getValue() == settings.getString("appsFlyerDevKey")); -// Assert.assertTrue(captorContext.getValue() == app.getApplicationContext()); -// verify(appsFlyerLib).subscribeForDeepLink(AppsflyerIntegration.deepLinkListener); + @Test + public void testAppsflyerIntegration_FACTORYCreate_nilFlow() { + Analytics analytics = null; + ValueMap settings = null; + + Integration integration= (Integration) AppsflyerIntegration.FACTORY.create(settings,analytics); + + Assert.assertNull(integration); + } @Test public void testAppsflyerIntegration_FACTORYKEY_happyFlow() { From 8aada7a2450b0575fbc5c438bccca941b3ec1e27 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 28 Feb 2023 16:21:39 +0200 Subject: [PATCH 26/30] CI yaml change - added reporter --- .github/workflows/test.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9289f91..cdf1431 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up JDK - uses: actions/setup-java@v1 + uses: actions/setup-java@v3.4.0 with: java-version: '11' - name: Setup Android SDK @@ -18,4 +18,12 @@ jobs: - name: Make gradlew executable run: chmod +x ./gradlew - name: Run Tests - run: ./gradlew test \ No newline at end of file + run: ./gradlew test + - name: Test Report + uses: dorny/test-reporter@v1 + if: always() + with: + name: Test Results + path: test-reports/TEST-*.xml # Path to test results + reporter: java-junit # Format of test results + fail-on-error: true \ No newline at end of file From 4f6f0a0b146ebbe1e7cec867dd5be43a1294a2de Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 28 Feb 2023 16:22:54 +0200 Subject: [PATCH 27/30] yaml syntax fix --- .github/workflows/test.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cdf1431..b8787ae 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,10 +20,10 @@ jobs: - name: Run Tests run: ./gradlew test - name: Test Report - uses: dorny/test-reporter@v1 - if: always() - with: - name: Test Results - path: test-reports/TEST-*.xml # Path to test results - reporter: java-junit # Format of test results - fail-on-error: true \ No newline at end of file + uses: dorny/test-reporter@v1 + if: always() + with: + name: Test Results + path: test-reports/TEST-*.xml # Path to test results + reporter: java-junit # Format of test results + fail-on-error: true \ No newline at end of file From 5f43ea0b50983b61dd3b36cb8d55605c5cea0403 Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 28 Feb 2023 16:36:17 +0200 Subject: [PATCH 28/30] ci tests fixes --- .github/workflows/test.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b8787ae..bb409d3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up JDK - uses: actions/setup-java@v3.4.0 + uses: actions/setup-java@v1 with: java-version: '11' - name: Setup Android SDK @@ -19,11 +19,14 @@ jobs: run: chmod +x ./gradlew - name: Run Tests run: ./gradlew test - - name: Test Report - uses: dorny/test-reporter@v1 - if: always() + - uses: actions/upload-artifact@v2 # upload test results + if: success() || failure() # run this step even if previous step failed with: - name: Test Results - path: test-reports/TEST-*.xml # Path to test results - reporter: java-junit # Format of test results - fail-on-error: true \ No newline at end of file + name: test-results + path: java-junit.xml + - uses: dorny/test-reporter@v1 + with: + artifact: test-results # artifact name + name: java Tests # Name of the check run which will be created + path: '*.xml' # Path to test results (inside artifact .zip) + reporter: java-junit # Format of test results \ No newline at end of file From 74d1ee6d1a6d3d8d89207cd6fab3185eaa8b1f8a Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Tue, 28 Feb 2023 16:50:01 +0200 Subject: [PATCH 29/30] CI flows --- .github/workflows/test.yml | 17 +++++++---------- app/build.gradle | 8 ++++++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bb409d3..977ded4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,14 +19,11 @@ jobs: run: chmod +x ./gradlew - name: Run Tests run: ./gradlew test - - uses: actions/upload-artifact@v2 # upload test results - if: success() || failure() # run this step even if previous step failed + - name: Test Report + uses: dorny/test-reporter@v1 + if: always() with: - name: test-results - path: java-junit.xml - - uses: dorny/test-reporter@v1 - with: - artifact: test-results # artifact name - name: java Tests # Name of the check run which will be created - path: '*.xml' # Path to test results (inside artifact .zip) - reporter: java-junit # Format of test results \ No newline at end of file + name: Test Results + path: app/build/test-results/testDebugUnitTest/TEST-*.xml # Path to test results + reporter: java-junit # Format of test results + fail-on-error: true \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 741bdf7..d05537d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -24,7 +24,15 @@ android { testOptions { unitTests { + all { + testLogging { + exceptionFormat = "full" + events "PASSED", "FAILED", "SKIPPED" + } + forkEvery 1 + } includeAndroidResources = true + returnDefaultValues = true } } } From 33623f9522cdc22b66b0ea45b5f1c5f4088fdbcb Mon Sep 17 00:00:00 2001 From: Moris Gateno Date: Wed, 1 Mar 2023 17:38:24 +0200 Subject: [PATCH 30/30] release configuration changes --- RELEASENOTES.md | 5 +++++ Readme.md | 2 +- app/build.gradle | 2 +- gradle.properties | 4 ++-- segmenttestapp/build.gradle | 9 ++------- .../com/appsflyer/segment/app/SampleApplication.java | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c9d1714..3add3e3 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,5 +1,10 @@ # Release Notes +### 6.10.1 +* Update Android SDK to v6.10.1 +* Added unit tests. +* Added github workflows. + ### 6.8.2 * Update Android SDK to v6.8.2 diff --git a/Readme.md b/Readme.md index 5eb1ef6..034a0a8 100644 --- a/Readme.md +++ b/Readme.md @@ -21,7 +21,7 @@ You can track installs, updates and sessions and also track additional in-app ev --- -Built with AppsFlyer Android SDK `v6.8.2` +Built with AppsFlyer Android SDK `v6.10.1` ## Table of content diff --git a/app/build.gradle b/app/build.gradle index d05537d..01ce7b8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,7 +39,7 @@ android { dependencies { implementation 'androidx.test.ext:junit:1.1.5' - implementation 'com.appsflyer:af-android-sdk:6.8.2' + implementation 'com.appsflyer:af-android-sdk:6.10.1' compileOnly 'com.android.installreferrer:installreferrer:2.1' compileOnly 'com.segment.analytics.android:analytics:4.+' testImplementation 'androidx.test:core:1.4.0' diff --git a/gradle.properties b/gradle.properties index 97c5b0e..394d461 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,8 +19,8 @@ GROUP=com.appsflyer -VERSION_CODE=10 -VERSION_NAME=6.8.2 +VERSION_CODE=11 +VERSION_NAME=6.10.1 POM_ARTIFACT_ID=segment-android-integration POM_PACKAGING=aar diff --git a/segmenttestapp/build.gradle b/segmenttestapp/build.gradle index 0736c1d..5d50692 100644 --- a/segmenttestapp/build.gradle +++ b/segmenttestapp/build.gradle @@ -27,12 +27,7 @@ dependencies { implementation project(path: ':app') testImplementation 'junit:junit:4.12' implementation 'com.android.support:appcompat-v7:28.0.0' - implementation 'com.appsflyer:af-android-sdk:6.8.2' - //noinspection GradleDynamicVersion + implementation 'com.appsflyer:af-android-sdk:6.10.1' implementation 'com.segment.analytics.android:analytics:4.+' -// compile 'com.appsflyer:segment-android-integration:6.8.2' implementation 'com.android.installreferrer:installreferrer:2.1' - //compile project(':app') - // compile 'com.google.firebase:firebase-crash:9.4.0' -} -//apply plugin: 'com.google.gms.google-services' \ No newline at end of file +} \ No newline at end of file diff --git a/segmenttestapp/src/main/java/com/appsflyer/segment/app/SampleApplication.java b/segmenttestapp/src/main/java/com/appsflyer/segment/app/SampleApplication.java index 4fdc1f4..998dc15 100644 --- a/segmenttestapp/src/main/java/com/appsflyer/segment/app/SampleApplication.java +++ b/segmenttestapp/src/main/java/com/appsflyer/segment/app/SampleApplication.java @@ -15,7 +15,7 @@ public class SampleApplication extends Application { - static final String SEGMENT_WRITE_KEY = ""; + static final String SEGMENT_WRITE_KEY = ""; static final String TAG = "SEG_AF"; @Override public void onCreate() {