Skip to content

Commit cab324e

Browse files
committed
Add instrumentation tests for AEPPresentable
1 parent 47bb4e7 commit cab324e

File tree

3 files changed

+182
-6
lines changed

3 files changed

+182
-6
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*
2+
Copyright 2025 Adobe. All rights reserved.
3+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License. You may obtain a copy
5+
of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
Unless required by applicable law or agreed to in writing, software distributed under
7+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8+
OF ANY KIND, either express or implied. See the License for the specific language
9+
governing permissions and limitations under the License.
10+
*/
11+
12+
package com.adobe.marketing.mobile.services.ui.common
13+
14+
import android.content.Context
15+
import android.view.ContextThemeWrapper
16+
import androidx.compose.ui.platform.ComposeView
17+
import androidx.test.core.app.ApplicationProvider
18+
import com.adobe.marketing.mobile.internal.util.ActivityCompatOwnerUtils
19+
import com.adobe.marketing.mobile.services.ui.InAppMessage
20+
import com.adobe.marketing.mobile.services.ui.Presentation
21+
import com.adobe.marketing.mobile.services.ui.PresentationDelegate
22+
import com.adobe.marketing.mobile.services.ui.PresentationUtilityProvider
23+
import junit.framework.TestCase.assertEquals
24+
import junit.framework.TestCase.assertFalse
25+
import junit.framework.TestCase.assertTrue
26+
import kotlinx.coroutines.CoroutineScope
27+
import org.junit.Test
28+
import org.mockito.ArgumentMatchers.anyInt
29+
import org.mockito.ArgumentMatchers.eq
30+
import org.mockito.Mockito.mock
31+
import org.mockito.Mockito.`when`
32+
33+
class AEPPresentableTests {
34+
35+
@Test
36+
fun test_getThemedContextWhenNewThemeCreationFails() {
37+
// setup
38+
val context = mock(Context::class.java)
39+
val presentationUtilityProvider = mock(PresentationUtilityProvider::class.java)
40+
val presentationDelegate = mock(PresentationDelegate::class.java)
41+
val appLifecycleProvider = mock(AppLifecycleProvider::class.java)
42+
val presentationStateManager = mock(PresentationStateManager::class.java)
43+
val activityCompatOwnerUtils = mock(ActivityCompatOwnerUtils::class.java)
44+
val mainScope = mock(CoroutineScope::class.java)
45+
val presentationObserver = mock(PresentationObserver::class.java)
46+
val presentation = mock(InAppMessage::class.java)
47+
48+
val presentable = SampleAEPPresentable(
49+
presentation,
50+
presentationUtilityProvider,
51+
presentationDelegate,
52+
appLifecycleProvider,
53+
presentationStateManager,
54+
activityCompatOwnerUtils,
55+
mainScope,
56+
presentationObserver
57+
)
58+
59+
val resources = mock(android.content.res.Resources::class.java)
60+
`when`(context.resources).thenReturn(resources)
61+
`when`(resources.newTheme()).thenThrow(RuntimeException("Resources.newTheme() invocation failure."))
62+
63+
// test
64+
val themedContext = presentable.getThemedContext(context)
65+
66+
// verify
67+
assertFalse(themedContext is ContextThemeWrapper)
68+
assertEquals(context, themedContext) // No wrapping should occur if theme creation fails
69+
}
70+
71+
@Test
72+
fun test_getThemedContextWhenApplyStyleFails() {
73+
// setup
74+
val context = mock(Context::class.java)
75+
val presentationUtilityProvider = mock(PresentationUtilityProvider::class.java)
76+
val presentationDelegate = mock(PresentationDelegate::class.java)
77+
val appLifecycleProvider = mock(AppLifecycleProvider::class.java)
78+
val presentationStateManager = mock(PresentationStateManager::class.java)
79+
val activityCompatOwnerUtils = mock(ActivityCompatOwnerUtils::class.java)
80+
val mainScope = mock(CoroutineScope::class.java)
81+
val presentationObserver = mock(PresentationObserver::class.java)
82+
val presentation = mock(InAppMessage::class.java)
83+
84+
val presentable = SampleAEPPresentable(
85+
presentation,
86+
presentationUtilityProvider,
87+
presentationDelegate,
88+
appLifecycleProvider,
89+
presentationStateManager,
90+
activityCompatOwnerUtils,
91+
mainScope,
92+
presentationObserver
93+
)
94+
95+
val resources = mock(android.content.res.Resources::class.java)
96+
`when`(context.resources).thenReturn(resources)
97+
val theme = mock(android.content.res.Resources.Theme::class.java)
98+
`when`(resources.newTheme()).thenReturn(theme)
99+
100+
`when`(theme.applyStyle(anyInt(), eq(true))).thenThrow(RuntimeException("Theme.applyStyle() invocation failure."))
101+
102+
// test
103+
val themedContext = presentable.getThemedContext(context)
104+
assertFalse(themedContext is ContextThemeWrapper)
105+
assertEquals(context, themedContext) // No wrapping should occur if theme creation fails
106+
}
107+
108+
@Test
109+
fun test_getThemedContextSucceedsWithThemeOverride() {
110+
// setup
111+
val context = ApplicationProvider.getApplicationContext<Context>()
112+
val presentationUtilityProvider = mock(PresentationUtilityProvider::class.java)
113+
val presentationDelegate = mock(PresentationDelegate::class.java)
114+
val appLifecycleProvider = mock(AppLifecycleProvider::class.java)
115+
val presentationStateManager = mock(PresentationStateManager::class.java)
116+
val activityCompatOwnerUtils = mock(ActivityCompatOwnerUtils::class.java)
117+
val mainScope = mock(CoroutineScope::class.java)
118+
val presentationObserver = mock(PresentationObserver::class.java)
119+
val presentation = mock(InAppMessage::class.java)
120+
121+
val presentable = SampleAEPPresentable(
122+
presentation,
123+
presentationUtilityProvider,
124+
presentationDelegate,
125+
appLifecycleProvider,
126+
presentationStateManager,
127+
activityCompatOwnerUtils,
128+
mainScope,
129+
presentationObserver
130+
)
131+
132+
// test
133+
val themedContext = presentable.getThemedContext(context)
134+
assertTrue(themedContext is ContextThemeWrapper)
135+
val themedContextWrapper = themedContext as ContextThemeWrapper
136+
val background = themedContextWrapper.theme.obtainStyledAttributes(intArrayOf(android.R.attr.background))
137+
assertTrue(background.hasValue(0))
138+
assertTrue(background.peekValue(0).resourceId == android.R.color.transparent)
139+
}
140+
141+
internal class SampleAEPPresentable(
142+
private val presentation: InAppMessage,
143+
presentationUtilityProvider: PresentationUtilityProvider,
144+
presentationDelegate: PresentationDelegate?,
145+
appLifecycleProvider: AppLifecycleProvider,
146+
presentationStateManager: PresentationStateManager,
147+
activityCompatOwnerUtils: ActivityCompatOwnerUtils,
148+
mainScope: CoroutineScope,
149+
presentationObserver: PresentationObserver,
150+
) : AEPPresentable<InAppMessage>(
151+
presentation,
152+
presentationUtilityProvider,
153+
presentationDelegate,
154+
appLifecycleProvider,
155+
presentationStateManager,
156+
activityCompatOwnerUtils,
157+
mainScope,
158+
presentationObserver
159+
) {
160+
override fun getPresentation(): InAppMessage {
161+
return presentation
162+
}
163+
164+
override fun getContent(activityContext: Context): ComposeView {
165+
return ComposeView(activityContext)
166+
}
167+
168+
override fun gateDisplay(): Boolean {
169+
return true
170+
}
171+
172+
override fun hasConflicts(visiblePresentations: List<Presentation<*>>): Boolean {
173+
return false
174+
}
175+
}
176+
}

code/core/src/androidTest/java/com/adobe/marketing/mobile/services/ui/floatingbutton/FloatingButtonPresentableTests.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import android.content.Context
1313
import android.view.ContextThemeWrapper
1414
import androidx.test.core.app.ApplicationProvider
15-
import com.adobe.marketing.mobile.core.R
1615
import com.adobe.marketing.mobile.services.ui.FloatingButton
1716
import com.adobe.marketing.mobile.services.ui.PresentationDelegate
1817
import com.adobe.marketing.mobile.services.ui.PresentationUtilityProvider
@@ -75,9 +74,9 @@ class FloatingButtonPresentableTests {
7574
val theme = themedContext.theme
7675
// get android.background from the theme
7776
val background = theme.obtainStyledAttributes(intArrayOf(android.R.attr.background))
78-
assertTrue(
79-
background.hasValue(0) &&
80-
background.peekValue(0).resourceId == android.R.color.transparent
81-
)
77+
// Verify that the background attribute is added
78+
assertTrue(background.hasValue(0))
79+
// Verify that the background attribute is transparent
80+
assertTrue(background.peekValue(0).resourceId == android.R.color.transparent)
8281
}
8382
}

code/core/src/phone/java/com/adobe/marketing/mobile/services/ui/common/AEPPresentable.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,8 @@ internal abstract class AEPPresentable<T : Presentation<T>> :
298298
* to ensure that the presentable UI is consistent with the rest of the application while
299299
* ensuring that specific attributes like view background are not inherited from the base theme.
300300
*/
301-
protected fun getThemedContext(context: Context): Context {
301+
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
302+
internal fun getThemedContext(context: Context): Context {
302303
// Theme overrides are supported only for API level 23 and above. For lower API levels,
303304
// return the base context as is.
304305
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {

0 commit comments

Comments
 (0)