Skip to content

Commit 6484335

Browse files
committed
feat: initial automated screenshots
1 parent 9b5b1f9 commit 6484335

2 files changed

Lines changed: 118 additions & 12 deletions

File tree

app/build.gradle.kts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,10 @@ dependencies {
8080
implementation("io.coil-kt:coil-video:2.4.0")
8181
implementation("androidx.gridlayout:gridlayout:1.0.0")
8282
implementation("io.noties.markwon:core:4.6.2")
83-
testImplementation("junit:junit:4.13.2")
84-
testImplementation("androidx.test.ext:junit:1.1.5")
85-
testImplementation("androidx.test.espresso:espresso-core:3.5.1")
83+
androidTestImplementation("junit:junit:4.13.2")
84+
androidTestImplementation("androidx.test:core:1.5.0")
85+
androidTestImplementation("androidx.test.ext:junit:1.1.5")
86+
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
8687
}
8788

8889
ktlint {
Lines changed: 114 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,127 @@
11
package com.fredhappyface.ewesticker
22

3+
import android.content.ContentValues
4+
import android.content.Context
5+
import android.graphics.Bitmap
6+
import android.os.Environment
7+
import android.provider.MediaStore
8+
import androidx.test.core.app.ActivityScenario
9+
import androidx.test.core.app.takeScreenshot
10+
import android.app.UiModeManager
11+
import android.content.res.Configuration
312
import androidx.test.ext.junit.runners.AndroidJUnit4
413
import androidx.test.platform.app.InstrumentationRegistry
5-
import org.junit.Assert.assertEquals
14+
import org.junit.Before
15+
import org.junit.Rule
616
import org.junit.Test
17+
import org.junit.rules.TestName
718
import org.junit.runner.RunWith
19+
import java.io.OutputStream
20+
import java.util.Locale
821

9-
/**
10-
* Instrumented test, which will execute on an Android device.
22+
/*
23+
* Illustrates usage of APIs to capture a bitmap from view and saving it to test storage.
1124
*
12-
* See [testing documentation](http://d.android.com/tools/testing).
25+
* When this test is executed via gradle managed devices, the saved image files will be stored at
26+
* build/outputs/managed_device_android_test_additional_output/debugAndroidTest/managedDevice/nexusOneApi30/
1327
*/
1428
@RunWith(AndroidJUnit4::class)
15-
class ExampleInstrumentedTest {
29+
class ScreenshotTest {
30+
31+
// a handy JUnit rule that stores the method name, so it can be used to generate unique
32+
// screenshot files per test method
33+
@get:Rule
34+
var nameRule: TestName = TestName()
35+
36+
private val appContext: Context = InstrumentationRegistry.getInstrumentation().targetContext
37+
private lateinit var activityScenario: ActivityScenario<MainActivity>
38+
39+
@Before
40+
fun setUp() {
41+
// Launch the main activity of your app
42+
activityScenario = ActivityScenario.launch(MainActivity::class.java)
43+
}
44+
45+
46+
/**
47+
* Captures and saves an image of the entire device screen to storage.
48+
*/
49+
@Test
50+
fun mainActivityLight() {
51+
val bitmap = takeScreenshot()
52+
saveBitmapToMediaStore(appContext, bitmap, nameRule.methodName)
53+
assert(true)
54+
}
55+
1656
@Test
17-
fun useAppContext() {
18-
// Context of the app under test.
19-
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20-
assertEquals("com.fredhappyface.ewesticker", appContext.packageName)
57+
fun mainActivityDark() {
58+
val uiModeManager = appContext.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager
59+
uiModeManager.nightMode = UiModeManager.MODE_NIGHT_YES
60+
activityScenario.recreate()
61+
62+
val bitmap = takeScreenshot()
63+
saveBitmapToMediaStore(appContext, bitmap, nameRule.methodName)
64+
65+
66+
uiModeManager.nightMode = UiModeManager.MODE_NIGHT_NO
67+
68+
assert(true)
69+
}
70+
71+
@Test
72+
fun mainActivityFr() {
73+
setLocale("fr")
74+
val bitmap = takeScreenshot()
75+
saveBitmapToMediaStore(appContext, bitmap, nameRule.methodName)
76+
assert(true)
77+
}
78+
79+
80+
private fun setLocale(languageCode: String) {
81+
val locale = Locale(languageCode)
82+
val config = Configuration()
83+
config.setLocale(locale)
84+
InstrumentationRegistry.getInstrumentation().targetContext.resources.updateConfiguration(
85+
config,
86+
null
87+
)
88+
}
89+
90+
private fun saveBitmapToMediaStore(context: Context, bitmap: Bitmap, fileName: String) {
91+
// Define the subdirectory where the image will be saved (e.g., "Screenshots")
92+
val subdirectory = "Screenshots/"
93+
94+
// Prepare the content values for the MediaStore
95+
val values = ContentValues()
96+
values.put(MediaStore.Images.Media.DISPLAY_NAME, "screenshot_$fileName")
97+
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
98+
values.put(
99+
MediaStore.MediaColumns.RELATIVE_PATH,
100+
"${Environment.DIRECTORY_DCIM}/$subdirectory"
101+
)
102+
values.put(MediaStore.Images.Media.IS_PENDING, 1) // Mark the image as pending
103+
104+
// Insert the image into the MediaStore
105+
val uri =
106+
context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
107+
uri?.let {
108+
try {
109+
// Open an OutputStream to the newly created image
110+
val os: OutputStream? = context.contentResolver.openOutputStream(uri)
111+
112+
// Compress and save the bitmap to the OutputStream
113+
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os)
114+
os?.close()
115+
116+
// Mark the image as non-pending
117+
values.clear()
118+
values.put(MediaStore.Images.Media.IS_PENDING, 0)
119+
context.contentResolver.update(uri, values, null, null)
120+
} catch (e: Exception) {
121+
e.printStackTrace()
122+
}
123+
}
21124
}
22125
}
126+
127+

0 commit comments

Comments
 (0)