Skip to content

Commit 51cea0a

Browse files
committed
implemented onboarding
1 parent 0b94d26 commit 51cea0a

29 files changed

+849
-174
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Nextcloud - Android Client
3+
*
4+
* SPDX-FileCopyrightText: 2025 TSI-mc <surinder.kumar@t-systems.com>
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*/
7+
8+
package com.nmc.android
9+
10+
import android.content.Context
11+
import android.content.res.Configuration
12+
import android.util.DisplayMetrics
13+
import androidx.test.core.app.ApplicationProvider
14+
import androidx.test.ext.junit.runners.AndroidJUnit4
15+
import com.owncloud.android.R
16+
import junit.framework.TestCase.assertEquals
17+
import org.junit.Test
18+
import org.junit.runner.RunWith
19+
import java.util.Locale
20+
21+
/**
22+
* Test class to verify the strings and dimens customized in this branch PR for NMC
23+
*/
24+
@RunWith(AndroidJUnit4::class)
25+
class OnboardingResourceTest {
26+
27+
private val baseContext = ApplicationProvider.getApplicationContext<Context>()
28+
29+
private val localizedStringMap = mapOf(
30+
R.string.common_login to ExpectedLocalizedString(
31+
translations = mapOf(
32+
Locale.ENGLISH to "Login",
33+
Locale.GERMAN to "Anmelden"
34+
)
35+
),
36+
)
37+
38+
@Test
39+
fun verifyLocalizedStrings() {
40+
localizedStringMap.forEach { (stringRes, expected) ->
41+
expected.translations.forEach { (locale, expectedText) ->
42+
43+
val config = Configuration(baseContext.resources.configuration)
44+
config.setLocale(locale)
45+
46+
val localizedContext = baseContext.createConfigurationContext(config)
47+
val actualText = localizedContext.getString(stringRes)
48+
49+
assertEquals(
50+
"Mismatch for ${baseContext.resources.getResourceEntryName(stringRes)} in $locale",
51+
expectedText,
52+
actualText
53+
)
54+
}
55+
}
56+
}
57+
58+
data class ExpectedLocalizedString(val translations: Map<Locale, String>)
59+
60+
private val expectedDimenMap = mapOf(
61+
R.dimen.login_btn_bottom_margin to ExpectedDimen(
62+
default = 48f,
63+
unit = DimenUnit.DP,
64+
alt = 96f
65+
),
66+
R.dimen.alternate_double_margin to ExpectedDimen(
67+
default = 20f,
68+
unit = DimenUnit.DP
69+
),
70+
)
71+
72+
@Test
73+
fun validateDefaultDimens() {
74+
validateDimens(
75+
configModifier = { it }, // no change → default values
76+
) { it.default to it.unit }
77+
}
78+
79+
@Test
80+
fun validate_sw600dp_Dimens() {
81+
validateDimens(configModifier = { config ->
82+
config.smallestScreenWidthDp = 600
83+
config
84+
}) { it.alt to it.unit }
85+
}
86+
87+
private fun validateDimens(
88+
configModifier: (Configuration) -> Configuration,
89+
selector: (ExpectedDimen) -> Pair<Float?, DimenUnit>
90+
) {
91+
val baseConfig = Configuration(baseContext.resources.configuration)
92+
val testConfig = configModifier(baseConfig)
93+
val testContext = baseContext.createConfigurationContext(testConfig)
94+
val dm = testContext.resources.displayMetrics
95+
val config = testContext.resources.configuration
96+
expectedDimenMap.forEach { (resId, entry) ->
97+
val (value, unit) = selector(entry)
98+
val actualPx = testContext.resources.getDimension(resId)
99+
value?.let {
100+
val expectedPx = convertToPx(value, unit, dm, config)
101+
assertEquals(
102+
"Mismatch for ${testContext.resources.getResourceEntryName(resId)} ($unit)",
103+
expectedPx,
104+
actualPx,
105+
0.01f
106+
)
107+
}
108+
}
109+
}
110+
111+
private fun convertToPx(
112+
value: Float,
113+
unit: DimenUnit,
114+
dm: DisplayMetrics,
115+
config: Configuration
116+
): Float {
117+
return when (unit) {
118+
DimenUnit.DP -> value * dm.density
119+
DimenUnit.SP -> value * dm.density * config.fontScale
120+
DimenUnit.PX -> value
121+
}
122+
}
123+
124+
data class ExpectedDimen(
125+
val default: Float,
126+
val alt: Float? = null,
127+
val unit: DimenUnit,
128+
)
129+
130+
enum class DimenUnit { DP, SP, PX }
131+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.nmc.android.onboarding
2+
3+
import androidx.test.espresso.Espresso.*
4+
import androidx.test.espresso.action.ViewActions.swipeLeft
5+
import androidx.test.espresso.action.ViewActions.swipeRight
6+
import androidx.test.espresso.assertion.ViewAssertions.matches
7+
import androidx.test.espresso.matcher.ViewMatchers.isClickable
8+
import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed
9+
import androidx.test.espresso.matcher.ViewMatchers.withId
10+
import androidx.test.ext.junit.rules.ActivityScenarioRule
11+
import androidx.test.ext.junit.runners.AndroidJUnit4
12+
import com.nextcloud.client.onboarding.FirstRunActivity
13+
import com.owncloud.android.AbstractIT
14+
import com.owncloud.android.R
15+
import org.junit.Rule
16+
import org.junit.Test
17+
import org.junit.runner.RunWith
18+
19+
@RunWith(AndroidJUnit4::class)
20+
class OnBoardingIT : AbstractIT() {
21+
22+
@get:Rule
23+
var activityRule = ActivityScenarioRule(FirstRunActivity::class.java)
24+
25+
@Test
26+
fun runAllOnboardingTests() {
27+
verifyUIElements()
28+
29+
shortSleep()
30+
31+
verifyOnBoardingSwipe()
32+
}
33+
34+
private fun verifyUIElements() {
35+
onView(withId(R.id.contentPanel)).check(matches(isCompletelyDisplayed()))
36+
onView(withId(R.id.progressIndicator)).check(matches(isCompletelyDisplayed()))
37+
onView(withId(R.id.login)).check(matches(isCompletelyDisplayed()))
38+
onView(withId(R.id.login)).check(matches(isClickable()))
39+
}
40+
41+
private fun verifyOnBoardingSwipe() {
42+
onView(withId(R.id.contentPanel)).perform(swipeLeft())
43+
onView(withId(R.id.contentPanel)).perform(swipeLeft())
44+
onView(withId(R.id.contentPanel)).perform(swipeLeft())
45+
46+
onView(withId(R.id.contentPanel)).perform(swipeRight())
47+
onView(withId(R.id.contentPanel)).perform(swipeRight())
48+
}
49+
}

0 commit comments

Comments
 (0)