From a1ad3cedd47e19e451b7b611410f381f9efa749c Mon Sep 17 00:00:00 2001 From: Andrew Datsenko Date: Tue, 26 Nov 2024 11:43:07 -0800 Subject: [PATCH] Add `toMatchRenderedOutput()` API Summary: Changelog: [Internal] Differential Revision: D65617491 --- jest/integration/config/metro.config.js | 1 - jest/integration/runtime/setup.js | 21 ++++ .../attributedstring/ParagraphAttributes.cpp | 40 +++++-- .../attributedstring/TextAttributes.cpp | 106 +++++++++++++----- .../debug/debugStringConvertibleUtils.h | 13 +++ 5 files changed, 142 insertions(+), 39 deletions(-) diff --git a/jest/integration/config/metro.config.js b/jest/integration/config/metro.config.js index bff07bde93a524..f345ae82f8f514 100644 --- a/jest/integration/config/metro.config.js +++ b/jest/integration/config/metro.config.js @@ -44,7 +44,6 @@ const config = { ? [ path.join(JS_DIR, 'RKJSModules', 'vendor', 'react'), path.join(JS_DIR, 'tools', 'metro'), - path.join(JS_DIR, 'node_modules'), path.join(JS_DIR, 'public', 'node_modules'), ] : [], diff --git a/jest/integration/runtime/setup.js b/jest/integration/runtime/setup.js index 67106278bbea16..15fc755f88526a 100644 --- a/jest/integration/runtime/setup.js +++ b/jest/integration/runtime/setup.js @@ -9,8 +9,12 @@ * @oncall react_native */ +import type {RenderOutputConfig} from 'react-native/src/private/__tests__/ReactNativeTester.fb'; + import deepEqual from 'deep-equal'; import nullthrows from 'nullthrows'; +import {maybeRoot} from 'react-native/src/private/__tests__/ReactNativeTester.fb'; +import {toMatchRenderedOutput} from 'react-native/src/private/__tests__/RenderOutputMatcher.fb'; export type TestCaseResult = { ancestorTitles: Array, @@ -275,6 +279,23 @@ class Expect { } } + toMatchRenderedOutput( + expected: React.Node, + config: RenderOutputConfig = {}, + ): void { + const root = maybeRoot(this.#received); + if (root == null) { + throw new Error( + `Expected ${String(this.#received)}${this.#maybeNotLabel()} to be a ReactTestRenderer`, + ); + } + + const result = toMatchRenderedOutput(root, expected, config); + if (!result.pass) { + throw new Error(`Mismatch in rendered output:\n${result.reason}`); + } + } + #isExpectedResult(pass: boolean): boolean { return this.#isNot ? !pass : pass; } diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp b/packages/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp index f2317ba080f202..c60fe918bebcf7 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp @@ -41,16 +41,38 @@ bool ParagraphAttributes::operator!=(const ParagraphAttributes& rhs) const { #if RN_DEBUG_STRING_CONVERTIBLE SharedDebugStringConvertibleList ParagraphAttributes::getDebugProps() const { + auto paragraphAttributes = ParagraphAttributes{}; return { - debugStringConvertibleItem("maximumNumberOfLines", maximumNumberOfLines), - debugStringConvertibleItem("ellipsizeMode", ellipsizeMode), - debugStringConvertibleItem("textBreakStrategy", textBreakStrategy), - debugStringConvertibleItem("adjustsFontSizeToFit", adjustsFontSizeToFit), - debugStringConvertibleItem("minimumFontSize", minimumFontSize), - debugStringConvertibleItem("maximumFontSize", maximumFontSize), - debugStringConvertibleItem("includeFontPadding", includeFontPadding), - debugStringConvertibleItem( - "android_hyphenationFrequency", android_hyphenationFrequency)}; + debugStringConvertibleItem( + "maximumNumberOfLines", + maximumNumberOfLines, + paragraphAttributes.maximumNumberOfLines), + debugStringConvertibleItem( + "ellipsizeMode", ellipsizeMode, paragraphAttributes.ellipsizeMode), + debugStringConvertibleItem( + "textBreakStrategy", + textBreakStrategy, + paragraphAttributes.textBreakStrategy), + debugStringConvertibleItem( + "adjustsFontSizeToFit", + adjustsFontSizeToFit, + paragraphAttributes.adjustsFontSizeToFit), + debugStringConvertibleItem( + "minimumFontSize", + minimumFontSize, + paragraphAttributes.minimumFontSize), + debugStringConvertibleItem( + "maximumFontSize", + maximumFontSize, + paragraphAttributes.maximumFontSize), + debugStringConvertibleItem( + "includeFontPadding", + includeFontPadding, + paragraphAttributes.includeFontPadding), + debugStringConvertibleItem( + "android_hyphenationFrequency", + android_hyphenationFrequency, + paragraphAttributes.android_hyphenationFrequency)}; } #endif diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp index 9b06f12948a654..c039c90ee90977 100644 --- a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp +++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp @@ -197,49 +197,97 @@ TextAttributes TextAttributes::defaultTextAttributes() { #if RN_DEBUG_STRING_CONVERTIBLE SharedDebugStringConvertibleList TextAttributes::getDebugProps() const { + auto textAttributes = TextAttributes::defaultTextAttributes(); return { // Color - debugStringConvertibleItem("backgroundColor", backgroundColor), - debugStringConvertibleItem("foregroundColor", foregroundColor), - debugStringConvertibleItem("opacity", opacity), + debugStringConvertibleItem( + "backgroundColor", backgroundColor, textAttributes.backgroundColor), + debugStringConvertibleItem( + "foregroundColor", foregroundColor, textAttributes.foregroundColor), + debugStringConvertibleItem("opacity", opacity, textAttributes.opacity), // Font - debugStringConvertibleItem("fontFamily", fontFamily), - debugStringConvertibleItem("fontSize", fontSize), - debugStringConvertibleItem("fontSizeMultiplier", fontSizeMultiplier), - debugStringConvertibleItem("fontWeight", fontWeight), - debugStringConvertibleItem("fontStyle", fontStyle), - debugStringConvertibleItem("fontVariant", fontVariant), - debugStringConvertibleItem("allowFontScaling", allowFontScaling), - debugStringConvertibleItem("dynamicTypeRamp", dynamicTypeRamp), - debugStringConvertibleItem("letterSpacing", letterSpacing), + debugStringConvertibleItem( + "fontFamily", fontFamily, textAttributes.fontFamily), + debugStringConvertibleItem("fontSize", fontSize, textAttributes.fontSize), + debugStringConvertibleItem( + "fontSizeMultiplier", + fontSizeMultiplier, + textAttributes.fontSizeMultiplier), + debugStringConvertibleItem( + "fontWeight", fontWeight, textAttributes.fontWeight), + debugStringConvertibleItem( + "fontStyle", fontStyle, textAttributes.fontStyle), + debugStringConvertibleItem( + "fontVariant", fontVariant, textAttributes.fontVariant), + debugStringConvertibleItem( + "allowFontScaling", + allowFontScaling, + textAttributes.allowFontScaling), + debugStringConvertibleItem( + "dynamicTypeRamp", dynamicTypeRamp, textAttributes.dynamicTypeRamp), + debugStringConvertibleItem( + "letterSpacing", letterSpacing, textAttributes.letterSpacing), // Paragraph Styles - debugStringConvertibleItem("lineHeight", lineHeight), - debugStringConvertibleItem("alignment", alignment), - debugStringConvertibleItem("baseWritingDirection", baseWritingDirection), - debugStringConvertibleItem("lineBreakStrategyIOS", lineBreakStrategy), - debugStringConvertibleItem("lineBreakModeIOS", lineBreakMode), + debugStringConvertibleItem( + "lineHeight", lineHeight, textAttributes.lineHeight), + debugStringConvertibleItem( + "alignment", alignment, textAttributes.alignment), + debugStringConvertibleItem( + "baseWritingDirection", + baseWritingDirection, + textAttributes.baseWritingDirection), + debugStringConvertibleItem( + "lineBreakStrategyIOS", + lineBreakStrategy, + textAttributes.lineBreakStrategy), + debugStringConvertibleItem( + "lineBreakModeIOS", lineBreakMode, textAttributes.lineBreakMode), // Decoration - debugStringConvertibleItem("textDecorationColor", textDecorationColor), debugStringConvertibleItem( - "textDecorationLineType", textDecorationLineType), - debugStringConvertibleItem("textDecorationStyle", textDecorationStyle), + "textDecorationColor", + textDecorationColor, + textAttributes.textDecorationColor), + debugStringConvertibleItem( + "textDecorationLineType", + textDecorationLineType, + textAttributes.textDecorationLineType), + debugStringConvertibleItem( + "textDecorationStyle", + textDecorationStyle, + textAttributes.textDecorationStyle), // Shadow - debugStringConvertibleItem("textShadowOffset", textShadowOffset), - debugStringConvertibleItem("textShadowRadius", textShadowRadius), - debugStringConvertibleItem("textShadowColor", textShadowColor), + debugStringConvertibleItem( + "textShadowOffset", + textShadowOffset, + textAttributes.textShadowOffset), + debugStringConvertibleItem( + "textShadowRadius", + textShadowRadius, + textAttributes.textShadowRadius), + debugStringConvertibleItem( + "textShadowColor", textShadowColor, textAttributes.textShadowColor), // Special - debugStringConvertibleItem("isHighlighted", isHighlighted), - debugStringConvertibleItem("isPressable", isPressable), - debugStringConvertibleItem("layoutDirection", layoutDirection), - debugStringConvertibleItem("accessibilityRole", accessibilityRole), - debugStringConvertibleItem("role", role), + debugStringConvertibleItem( + "isHighlighted", isHighlighted, textAttributes.isHighlighted), + debugStringConvertibleItem( + "isPressable", isPressable, textAttributes.isPressable), + debugStringConvertibleItem( + "layoutDirection", layoutDirection, textAttributes.layoutDirection), + debugStringConvertibleItem( + "accessibilityRole", + accessibilityRole, + textAttributes.accessibilityRole), + debugStringConvertibleItem("role", role, textAttributes.role), - debugStringConvertibleItem("textAlignVertical", textAlignVertical), + debugStringConvertibleItem( + "textAlignVertical", + textAlignVertical, + textAttributes.textAlignVertical), }; } #endif diff --git a/packages/react-native/ReactCommon/react/renderer/debug/debugStringConvertibleUtils.h b/packages/react-native/ReactCommon/react/renderer/debug/debugStringConvertibleUtils.h index 9a3c28731cde16..1a1c567440b920 100644 --- a/packages/react-native/ReactCommon/react/renderer/debug/debugStringConvertibleUtils.h +++ b/packages/react-native/ReactCommon/react/renderer/debug/debugStringConvertibleUtils.h @@ -15,11 +15,24 @@ #include #include +#include namespace facebook::react { #if RN_DEBUG_STRING_CONVERTIBLE +inline SharedDebugStringConvertible debugStringConvertibleItem( + std::string name, + float value, + float defaultValue = {}) { + if (floatEquality(value, defaultValue)) { + return nullptr; + } + + return std::make_shared( + name, facebook::react::toString(value)); +} + template inline SharedDebugStringConvertible debugStringConvertibleItem(std::string name, T value, T defaultValue = {}) {