From 6964b061f86386a10a897b46f922fdf0413915e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98rjan=20Helstr=C3=B8m?= Date: Thu, 26 Feb 2026 12:15:06 +0100 Subject: [PATCH] * Verify that variableValue['@media (prefers-color-scheme: dark)'] is defined before using it as defaultValue * Added test for css.defineVars --- .../src/native/css/customProperties.js | 5 +- .../tests/css/css-define-vars-test.native.js | 105 ++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 packages/react-strict-dom/tests/css/css-define-vars-test.native.js diff --git a/packages/react-strict-dom/src/native/css/customProperties.js b/packages/react-strict-dom/src/native/css/customProperties.js index c59b5a90..b920cb4a 100644 --- a/packages/react-strict-dom/src/native/css/customProperties.js +++ b/packages/react-strict-dom/src/native/css/customProperties.js @@ -68,7 +68,10 @@ function resolveVariableReferenceValue( if (variableValue != null) { if (typeof variableValue === 'object' && variableValue.default != null) { let defaultValue = variableValue.default; - if (colorScheme === 'dark') { + if ( + colorScheme === 'dark' && + variableValue['@media (prefers-color-scheme: dark)'] != null + ) { defaultValue = variableValue['@media (prefers-color-scheme: dark)']; } return defaultValue; diff --git a/packages/react-strict-dom/tests/css/css-define-vars-test.native.js b/packages/react-strict-dom/tests/css/css-define-vars-test.native.js new file mode 100644 index 00000000..84df94af --- /dev/null +++ b/packages/react-strict-dom/tests/css/css-define-vars-test.native.js @@ -0,0 +1,105 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import * as React from 'react'; +import { css, html } from 'react-strict-dom'; +import { act, create } from 'react-test-renderer'; + +describe('css.defineVars(): @media', () => { + const ReactNative = require('../../src/native/react-native'); + + beforeEach(() => { + ReactNative.useWindowDimensions.mockReturnValue({ + height: 1000, + width: 2000 + }); + ReactNative.useColorScheme.mockReturnValue('light'); + + // avoid console messages for these tests + jest.spyOn(console, 'error'); + console.error.mockImplementation(() => {}); + jest.spyOn(console, 'warn'); + console.warn.mockImplementation(() => {}); + }); + + afterEach(() => { + ReactNative.useWindowDimensions.mockReturnValue({ + height: 1000, + width: 2000 + }); + ReactNative.useColorScheme.mockReturnValue('light'); + + console.error.mockRestore(); + console.warn.mockRestore(); + jest.clearAllMocks(); + }); + + const tokens = css.defineVars({ + prefersColor: { + default: 'blue', + '@media (prefers-color-scheme: dark)': 'darkblue' + }, + maxHeight: { + default: 100, + '@media (max-height: 400px)': 300 + } + }); + + const styles = css.create({ + root: { + backgroundColor: tokens.prefersColor, + maxHeight: tokens.maxHeight + } + }); + + describe('@media (prefers-color-scheme)', () => { + test('color-scheme: light - returns default', () => { + let root; + act(() => { + root = create(); + }); + expect(root.toJSON().props.style.backgroundColor).toBe('blue'); + }); + + test('color-scheme: dark - returns media query value)', () => { + ReactNative.useColorScheme.mockReturnValue('dark'); + let root; + act(() => { + root = create(); + }); + expect(root.toJSON().props.style.backgroundColor).toBe('darkblue'); + }); + }); + + describe('other media queries', () => { + test('matches (max-height: 400px) - returns default', () => { + ReactNative.useWindowDimensions.mockReturnValue({ height: 100 }); + let root; + act(() => { + root = create(); + }); + expect(root.toJSON().props.style.maxHeight).toBe(100); + }); + test('matches (max-height: 400px) with color-scheme: dark - returns default', () => { + ReactNative.useColorScheme.mockReturnValue('dark'); + ReactNative.useWindowDimensions.mockReturnValue({ height: 100 }); + let root; + act(() => { + root = create(); + }); + expect(root.toJSON().props.style.maxHeight).toBe(100); + }); + test('does not match (max-height: 400px) - returns default', () => { + ReactNative.useWindowDimensions.mockReturnValue({ height: 1000 }); + let root; + act(() => { + root = create(); + }); + expect(root.toJSON().props.style.maxHeight).toBe(100); + }); + }); +});