blob: 3209c8bb1f8ac0bb8a12ff9bd93e287470709eb5 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.testing.screenshot
import android.app.Activity
import android.app.Dialog
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams
import androidx.test.ext.junit.rules.ActivityScenarioRule
import org.junit.Assert.assertEquals
import org.junit.rules.RuleChain
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
import platform.test.screenshot.DeviceEmulationRule
import platform.test.screenshot.DeviceEmulationSpec
import platform.test.screenshot.MaterialYouColorsRule
import platform.test.screenshot.ScreenshotTestRule
import platform.test.screenshot.getEmulatedDevicePathConfig
/** A rule for View screenshot diff unit tests. */
class ViewScreenshotTestRule(emulationSpec: DeviceEmulationSpec) : TestRule {
private val colorsRule = MaterialYouColorsRule()
private val deviceEmulationRule = DeviceEmulationRule(emulationSpec)
private val screenshotRule =
ScreenshotTestRule(
SystemUIGoldenImagePathManager(getEmulatedDevicePathConfig(emulationSpec))
)
private val activityRule = ActivityScenarioRule(ScreenshotActivity::class.java)
private val delegateRule =
RuleChain.outerRule(colorsRule)
.around(deviceEmulationRule)
.around(screenshotRule)
.around(activityRule)
private val matcher = UnitTestBitmapMatcher
override fun apply(base: Statement, description: Description): Statement {
return delegateRule.apply(base, description)
}
/**
* Compare the content of the view provided by [viewProvider] with the golden image identified
* by [goldenIdentifier] in the context of [emulationSpec].
*/
fun screenshotTest(
goldenIdentifier: String,
layoutParams: LayoutParams =
LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT),
viewProvider: (Activity) -> View,
) {
activityRule.scenario.onActivity { activity ->
// Make sure that the activity draws full screen and fits the whole display instead of
// the system bars.
activity.window.setDecorFitsSystemWindows(false)
activity.setContentView(viewProvider(activity), layoutParams)
}
// We call onActivity again because it will make sure that our Activity is done measuring,
// laying out and drawing its content (that we set in the previous onActivity lambda).
activityRule.scenario.onActivity { activity ->
// Check that the content is what we expected.
val content = activity.requireViewById<ViewGroup>(android.R.id.content)
assertEquals(1, content.childCount)
screenshotRule.assertBitmapAgainstGolden(
content.getChildAt(0).drawIntoBitmap(),
goldenIdentifier,
matcher
)
}
}
/**
* Compare the content of the dialog provided by [dialogProvider] with the golden image
* identified by [goldenIdentifier] in the context of [emulationSpec].
*/
fun dialogScreenshotTest(
goldenIdentifier: String,
dialogProvider: (Activity) -> Dialog,
) {
var dialog: Dialog? = null
activityRule.scenario.onActivity { activity ->
dialog =
dialogProvider(activity).apply {
// Make sure that the dialog draws full screen and fits the whole display
// instead of the system bars.
window.setDecorFitsSystemWindows(false)
// Disable enter/exit animations.
create()
window.setWindowAnimations(0)
// Show the dialog.
show()
}
}
// We call onActivity again because it will make sure that our Dialog is done measuring,
// laying out and drawing its content (that we set in the previous onActivity lambda).
activityRule.scenario.onActivity {
// Check that the content is what we expected.
val dialog = dialog ?: error("dialog is null")
try {
screenshotRule.assertBitmapAgainstGolden(
dialog.window.decorView.drawIntoBitmap(),
goldenIdentifier,
matcher,
)
} finally {
dialog.dismiss()
}
}
}
}