1 /* <lambda>null2 * Copyright (C) 2022 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.compose.theme 18 19 import android.content.Context 20 import androidx.annotation.AttrRes 21 import androidx.compose.material3.ColorScheme 22 import androidx.compose.material3.MaterialTheme 23 import androidx.compose.material3.Text 24 import androidx.compose.runtime.LaunchedEffect 25 import androidx.compose.ui.graphics.Color 26 import androidx.compose.ui.platform.LocalContext 27 import androidx.compose.ui.test.assertIsDisplayed 28 import androidx.compose.ui.test.junit4.createComposeRule 29 import androidx.compose.ui.test.onNodeWithText 30 import androidx.test.ext.junit.runners.AndroidJUnit4 31 import com.android.internal.R 32 import com.google.common.truth.Truth.assertThat 33 import com.google.common.truth.Truth.assertWithMessage 34 import org.junit.Assert.assertThrows 35 import org.junit.Rule 36 import org.junit.Test 37 import org.junit.runner.RunWith 38 39 @RunWith(AndroidJUnit4::class) 40 class PlatformThemeTest { 41 @get:Rule val composeRule = createComposeRule() 42 43 @Test 44 fun testThemeShowsContent() { 45 composeRule.setContent { PlatformTheme { Text("foo") } } 46 47 composeRule.onNodeWithText("foo").assertIsDisplayed() 48 } 49 50 @Test 51 fun testAndroidColorsAreAvailableInsideTheme() { 52 composeRule.setContent { 53 PlatformTheme { Text("foo", color = LocalAndroidColorScheme.current.primaryFixed) } 54 } 55 56 composeRule.onNodeWithText("foo").assertIsDisplayed() 57 } 58 59 @Test 60 fun testAccessingAndroidColorsWithoutThemeThrows() { 61 assertThrows(IllegalStateException::class.java) { 62 composeRule.setContent { 63 Text("foo", color = LocalAndroidColorScheme.current.primaryFixed) 64 } 65 } 66 } 67 68 @Test 69 fun testMaterialColorsMatchAttributeValue() { 70 val colorValues = mutableListOf<ColorValue>() 71 72 fun onLaunch(colorScheme: ColorScheme, context: Context) { 73 fun addValue(name: String, materialValue: Color, @AttrRes attr: Int) { 74 colorValues.add(ColorValue(name, materialValue, colorAttr(context, attr))) 75 } 76 77 addValue("primary", colorScheme.primary, R.attr.materialColorPrimary) 78 addValue("onPrimary", colorScheme.onPrimary, R.attr.materialColorOnPrimary) 79 addValue( 80 "primaryContainer", 81 colorScheme.primaryContainer, 82 R.attr.materialColorPrimaryContainer, 83 ) 84 addValue( 85 "onPrimaryContainer", 86 colorScheme.onPrimaryContainer, 87 R.attr.materialColorOnPrimaryContainer, 88 ) 89 addValue( 90 "inversePrimary", 91 colorScheme.inversePrimary, 92 R.attr.materialColorInversePrimary, 93 ) 94 addValue("secondary", colorScheme.secondary, R.attr.materialColorSecondary) 95 addValue("onSecondary", colorScheme.onSecondary, R.attr.materialColorOnSecondary) 96 addValue( 97 "secondaryContainer", 98 colorScheme.secondaryContainer, 99 R.attr.materialColorSecondaryContainer, 100 ) 101 addValue( 102 "onSecondaryContainer", 103 colorScheme.onSecondaryContainer, 104 R.attr.materialColorOnSecondaryContainer, 105 ) 106 addValue("tertiary", colorScheme.tertiary, R.attr.materialColorTertiary) 107 addValue("onTertiary", colorScheme.onTertiary, R.attr.materialColorOnTertiary) 108 addValue( 109 "tertiaryContainer", 110 colorScheme.tertiaryContainer, 111 R.attr.materialColorTertiaryContainer, 112 ) 113 addValue( 114 "onTertiaryContainer", 115 colorScheme.onTertiaryContainer, 116 R.attr.materialColorOnTertiaryContainer, 117 ) 118 addValue("onBackground", colorScheme.onBackground, R.attr.materialColorOnBackground) 119 addValue("surface", colorScheme.surface, R.attr.materialColorSurface) 120 addValue("onSurface", colorScheme.onSurface, R.attr.materialColorOnSurface) 121 addValue( 122 "surfaceVariant", 123 colorScheme.surfaceVariant, 124 R.attr.materialColorSurfaceVariant, 125 ) 126 addValue( 127 "onSurfaceVariant", 128 colorScheme.onSurfaceVariant, 129 R.attr.materialColorOnSurfaceVariant, 130 ) 131 addValue( 132 "inverseSurface", 133 colorScheme.inverseSurface, 134 R.attr.materialColorInverseSurface, 135 ) 136 addValue( 137 "inverseOnSurface", 138 colorScheme.inverseOnSurface, 139 R.attr.materialColorInverseOnSurface, 140 ) 141 addValue("error", colorScheme.error, R.attr.materialColorError) 142 addValue("onError", colorScheme.onError, R.attr.materialColorOnError) 143 addValue( 144 "errorContainer", 145 colorScheme.errorContainer, 146 R.attr.materialColorErrorContainer, 147 ) 148 addValue( 149 "onErrorContainer", 150 colorScheme.onErrorContainer, 151 R.attr.materialColorOnErrorContainer, 152 ) 153 addValue("outline", colorScheme.outline, R.attr.materialColorOutline) 154 addValue( 155 "outlineVariant", 156 colorScheme.outlineVariant, 157 R.attr.materialColorOutlineVariant, 158 ) 159 addValue("surfaceBright", colorScheme.surfaceBright, R.attr.materialColorSurfaceBright) 160 addValue("surfaceDim", colorScheme.surfaceDim, R.attr.materialColorSurfaceDim) 161 addValue( 162 "surfaceContainer", 163 colorScheme.surfaceContainer, 164 R.attr.materialColorSurfaceContainer, 165 ) 166 addValue( 167 "surfaceContainerHigh", 168 colorScheme.surfaceContainerHigh, 169 R.attr.materialColorSurfaceContainerHigh, 170 ) 171 addValue( 172 "surfaceContainerHighest", 173 colorScheme.surfaceContainerHighest, 174 R.attr.materialColorSurfaceContainerHighest, 175 ) 176 addValue( 177 "surfaceContainerLow", 178 colorScheme.surfaceContainerLow, 179 R.attr.materialColorSurfaceContainerLow, 180 ) 181 addValue( 182 "surfaceContainerLowest", 183 colorScheme.surfaceContainerLowest, 184 R.attr.materialColorSurfaceContainerLowest, 185 ) 186 } 187 188 composeRule.setContent { 189 PlatformTheme { 190 val colorScheme = MaterialTheme.colorScheme 191 val context = LocalContext.current 192 193 LaunchedEffect(Unit) { onLaunch(colorScheme, context) } 194 } 195 } 196 197 assertThat(colorValues).hasSize(33) 198 colorValues.forEach { colorValue -> 199 assertWithMessage( 200 "MaterialTheme.colorScheme.${colorValue.name} matches attribute color" 201 ) 202 .that(colorValue.materialValue) 203 .isEqualTo(colorValue.attrValue) 204 } 205 } 206 207 private data class ColorValue(val name: String, val materialValue: Color, val attrValue: Color) 208 } 209