Skip to content

Commit 384677f

Browse files
cortinicofacebook-github-bot
authored andcommitted
Add tests for DisplayMetricsHolder (#52946)
Summary: Pull Request resolved: #52946 This just add a set of unit tests for `DisplayMetricsHolder` as I'm working on this class recently. Changelog: [Internal] [Changed] - Reviewed By: rshest, mdvacca Differential Revision: D78981753 fbshipit-source-id: 5800d44d3131a58770a0049eb2d08306874b7183
1 parent 2e76fc8 commit 384677f

2 files changed

Lines changed: 175 additions & 1 deletion

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,6 @@ public object DisplayMetricsHolder {
168168
(checkNotNull(screenDisplayMetrics).heightPixels - verticalInsets).toFloat().pxToDp())
169169
}
170170

171-
private fun encodeFloatsToLong(width: Float, height: Float): Long =
171+
internal fun encodeFloatsToLong(width: Float, height: Float): Long =
172172
(width.toRawBits().toLong()) shl 32 or (height.toRawBits().toLong())
173173
}
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.react.uimanager
9+
10+
import android.annotation.TargetApi
11+
import android.app.Activity
12+
import android.content.Context
13+
import android.util.DisplayMetrics
14+
import android.view.View
15+
import android.view.Window
16+
import android.view.WindowInsets
17+
import com.facebook.react.bridge.WritableMap
18+
import com.facebook.testutils.shadows.ShadowNativeLoader
19+
import com.facebook.testutils.shadows.ShadowNativeMap
20+
import com.facebook.testutils.shadows.ShadowReadableNativeMap
21+
import com.facebook.testutils.shadows.ShadowSoLoader
22+
import com.facebook.testutils.shadows.ShadowWritableNativeMap
23+
import org.assertj.core.api.Assertions.assertThat
24+
import org.junit.Before
25+
import org.junit.Test
26+
import org.junit.runner.RunWith
27+
import org.mockito.ArgumentMatchers.anyInt
28+
import org.mockito.kotlin.mock
29+
import org.mockito.kotlin.whenever
30+
import org.robolectric.RobolectricTestRunner
31+
import org.robolectric.RuntimeEnvironment
32+
import org.robolectric.annotation.Config
33+
34+
@RunWith(RobolectricTestRunner::class)
35+
@Config(
36+
shadows =
37+
[
38+
ShadowSoLoader::class,
39+
ShadowNativeLoader::class,
40+
ShadowNativeMap::class,
41+
ShadowWritableNativeMap::class,
42+
ShadowReadableNativeMap::class,
43+
])
44+
class DisplayMetricsHolderTest {
45+
46+
private lateinit var context: Context
47+
private lateinit var displayMetrics: DisplayMetrics
48+
49+
@Before
50+
fun setUp() {
51+
context = RuntimeEnvironment.getApplication()
52+
displayMetrics = context.resources.displayMetrics
53+
DisplayMetricsHolder.setWindowDisplayMetrics(null)
54+
DisplayMetricsHolder.setScreenDisplayMetrics(null)
55+
}
56+
57+
@Test(expected = IllegalStateException::class)
58+
fun getWindowDisplayMetrics_failsIfDisplayMetricsIsNotInitialized() {
59+
DisplayMetricsHolder.getWindowDisplayMetrics()
60+
}
61+
62+
@Test(expected = IllegalStateException::class)
63+
fun getScreenDisplayMetrics_failsIfDisplayMetricsIsNotInitialized() {
64+
DisplayMetricsHolder.getScreenDisplayMetrics()
65+
}
66+
67+
@Test
68+
fun setAndGetWindowDisplayMetrics_returnsSetValue() {
69+
DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics)
70+
val result = DisplayMetricsHolder.getWindowDisplayMetrics()
71+
assertThat(result).isEqualTo(displayMetrics)
72+
}
73+
74+
@Test
75+
fun setAndGetScreenDisplayMetrics_returnsSetValue() {
76+
DisplayMetricsHolder.setScreenDisplayMetrics(displayMetrics)
77+
val result = DisplayMetricsHolder.getScreenDisplayMetrics()
78+
assertThat(result).isEqualTo(displayMetrics)
79+
}
80+
81+
@Test
82+
fun initScreenDisplayMetrics_setsMetrics() {
83+
DisplayMetricsHolder.initScreenDisplayMetrics(context)
84+
assertThat(DisplayMetricsHolder.getScreenDisplayMetrics()).isNotNull()
85+
}
86+
87+
@Test
88+
fun initWindowDisplayMetrics_setsMetrics() {
89+
DisplayMetricsHolder.initWindowDisplayMetrics(context)
90+
assertThat(DisplayMetricsHolder.getWindowDisplayMetrics()).isNotNull()
91+
}
92+
93+
@Test
94+
fun initWindowMetricsIfNotInitialized_onlyInitializesOnce() {
95+
DisplayMetricsHolder.initWindowDisplayMetrics(context)
96+
val firstWindow = DisplayMetricsHolder.getWindowDisplayMetrics()
97+
// Should not reinitialize
98+
DisplayMetricsHolder.initWindowDisplayMetrics(context)
99+
val secondWindow = DisplayMetricsHolder.getWindowDisplayMetrics()
100+
assertThat(secondWindow).isEqualTo(firstWindow)
101+
}
102+
103+
@Test
104+
fun initScreenMetricsIfNotInitialized_onlyInitializesOnce() {
105+
DisplayMetricsHolder.initScreenDisplayMetrics(context)
106+
val firstScreen = DisplayMetricsHolder.getScreenDisplayMetrics()
107+
// Should not reinitialize
108+
DisplayMetricsHolder.initScreenDisplayMetrics(context)
109+
val secondScreen = DisplayMetricsHolder.getScreenDisplayMetrics()
110+
assertThat(secondScreen).isEqualTo(firstScreen)
111+
}
112+
113+
@Test(expected = IllegalStateException::class)
114+
fun getDisplayMetricsWritableMap_failsIfNotInitialized() {
115+
DisplayMetricsHolder.getDisplayMetricsWritableMap(1.0)
116+
}
117+
118+
@Test
119+
fun getDisplayMetricsWritableMap_returnsCorrectMap() {
120+
// Use the official initialization method to ensure both metrics are set
121+
DisplayMetricsHolder.initWindowDisplayMetrics(context)
122+
DisplayMetricsHolder.initScreenDisplayMetrics(context)
123+
val map: WritableMap = DisplayMetricsHolder.getDisplayMetricsWritableMap(1.0)
124+
assertThat(map.hasKey("windowPhysicalPixels")).isTrue()
125+
assertThat(map.hasKey("screenPhysicalPixels")).isTrue()
126+
val windowMap = map.getMap("windowPhysicalPixels")
127+
val screenMap = map.getMap("screenPhysicalPixels")
128+
checkNotNull(windowMap)
129+
checkNotNull(screenMap)
130+
assertThat(windowMap.hasKey("width")).isTrue()
131+
assertThat(windowMap.hasKey("height")).isTrue()
132+
assertThat(windowMap.hasKey("scale")).isTrue()
133+
assertThat(windowMap.hasKey("fontScale")).isTrue()
134+
assertThat(windowMap.hasKey("densityDpi")).isTrue()
135+
}
136+
137+
@Test
138+
@TargetApi(30)
139+
fun getEncodedScreenSizeWithoutVerticalInsets_returnsEncodedValue() {
140+
DisplayMetricsHolder.initScreenDisplayMetrics(context)
141+
142+
val activity: Activity = mock()
143+
val window: Window = mock()
144+
val decorView: View = mock()
145+
val windowInsets: WindowInsets = mock()
146+
whenever(activity.window).thenReturn(window)
147+
whenever(window.decorView).thenReturn(decorView)
148+
149+
whenever(decorView.rootWindowInsets).thenReturn(windowInsets)
150+
whenever(windowInsets.getInsets(anyInt()))
151+
.thenReturn(android.graphics.Insets.of(10, 20, 10, 20))
152+
153+
// Should return a non-zero encoded value
154+
val encoded = DisplayMetricsHolder.getEncodedScreenSizeWithoutVerticalInsets(activity)
155+
assertThat(encoded).isNotZero()
156+
}
157+
158+
@Test
159+
fun getEncodedScreenSizeWithoutVerticalInsets_returnsZeroIfActivityIsNull() {
160+
val encoded = DisplayMetricsHolder.getEncodedScreenSizeWithoutVerticalInsets(null)
161+
assertThat(encoded).isZero()
162+
}
163+
164+
@Test
165+
fun encodeFloatsToLong_encodesWidthAndHeightCorrectly() {
166+
val width = 123.45f
167+
val height = 67.89f
168+
val encoded = DisplayMetricsHolder.encodeFloatsToLong(width, height)
169+
val decodedWidth = Float.fromBits((encoded shr 32).toInt())
170+
val decodedHeight = Float.fromBits(encoded.toInt())
171+
assertThat(decodedWidth).isEqualTo(width)
172+
assertThat(decodedHeight).isEqualTo(height)
173+
}
174+
}

0 commit comments

Comments
 (0)