1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.settingslib.spa.screenshot.util
18
19 import android.os.Build
20 import androidx.activity.ComponentActivity
21 import androidx.compose.material3.MaterialTheme
22 import androidx.compose.material3.Surface
23 import androidx.compose.runtime.Composable
24 import androidx.compose.ui.platform.ViewRootForTest
25 import androidx.compose.ui.test.junit4.createAndroidComposeRule
26 import androidx.compose.ui.test.onRoot
27 import com.android.settingslib.spa.framework.theme.SettingsTheme
28 import org.junit.rules.RuleChain
29 import org.junit.rules.TestRule
30 import org.junit.runner.Description
31 import org.junit.runners.model.Statement
32 import platform.test.screenshot.DeviceEmulationRule
33 import platform.test.screenshot.DeviceEmulationSpec
34 import platform.test.screenshot.MaterialYouColorsRule
35 import platform.test.screenshot.ScreenshotTestRule
36 import platform.test.screenshot.getEmulatedDevicePathConfig
37
38 /** A rule for Settings screenshot diff tests. */
39 class SettingsScreenshotTestRule(
40 emulationSpec: DeviceEmulationSpec,
41 assetsPathRelativeToBuildRoot: String
42 ) : TestRule {
43 private val colorsRule = MaterialYouColorsRule()
44 private val deviceEmulationRule = DeviceEmulationRule(emulationSpec)
45 private val screenshotRule =
46 ScreenshotTestRule(
47 SettingsGoldenPathManager(
48 getEmulatedDevicePathConfig(emulationSpec),
49 assetsPathRelativeToBuildRoot
50 )
51 )
52 private val composeRule = createAndroidComposeRule<ComponentActivity>()
53 private val delegateRule =
54 RuleChain.outerRule(colorsRule)
55 .around(deviceEmulationRule)
56 .around(screenshotRule)
57 .around(composeRule)
58 private val matcher = UnitTestBitmapMatcher
59
applynull60 override fun apply(base: Statement, description: Description): Statement {
61 return delegateRule.apply(base, description)
62 }
63
64 /**
65 * Compare [content] with the golden image identified by [goldenIdentifier] in the context of
66 * [testSpec].
67 */
screenshotTestnull68 fun screenshotTest(
69 goldenIdentifier: String,
70 content: @Composable () -> Unit,
71 ) {
72 // Make sure that the activity draws full screen and fits the whole display.
73 val activity = composeRule.activity
74 activity.mainExecutor.execute { activity.window.setDecorFitsSystemWindows(false) }
75
76 // Set the content using the AndroidComposeRule to make sure that the Activity is set up
77 // correctly.
78 composeRule.setContent {
79 SettingsTheme {
80 Surface(
81 color = MaterialTheme.colorScheme.background,
82 ) {
83 content()
84 }
85 }
86 }
87 composeRule.waitForIdle()
88
89 val view = (composeRule.onRoot().fetchSemanticsNode().root as ViewRootForTest).view
90 screenshotRule.assertBitmapAgainstGolden(view.drawIntoBitmap(), goldenIdentifier, matcher)
91 }
92 }
93
94 /** Create a [SettingsScreenshotTestRule] for settings screenshot tests. */
settingsScreenshotTestRulenull95 fun settingsScreenshotTestRule(
96 emulationSpec: DeviceEmulationSpec,
97 ): SettingsScreenshotTestRule {
98 val assetPath = if (Build.FINGERPRINT.contains("robolectric")) {
99 "frameworks/base/packages/SettingsLib/Spa/screenshot/robotests/assets"
100 } else {
101 "frameworks/base/packages/SettingsLib/Spa/screenshot/assets"
102 }
103 return SettingsScreenshotTestRule(
104 emulationSpec,
105 assetPath
106 )
107 }
108