/* * 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. */ #include #include namespace facebook::react { TEST(CSSParser, keyword_values) { auto emptyValue = parseCSSComponentValue(""); EXPECT_EQ(emptyValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(emptyValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto autoValue = parseCSSComponentValue("auto"); EXPECT_EQ(autoValue.type(), CSSValueType::Keyword); EXPECT_EQ(autoValue.getKeyword(), CSSKeyword::Auto); auto autoCapsValue = parseCSSComponentValue("AuTO"); EXPECT_EQ(autoCapsValue.type(), CSSValueType::Keyword); EXPECT_EQ(autoCapsValue.getKeyword(), CSSKeyword::Auto); auto autoDisallowedValue = parseCSSComponentValue("auto"); EXPECT_EQ(autoDisallowedValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(autoDisallowedValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto whitespaceValue = parseCSSComponentValue(" flex-start "); EXPECT_EQ(whitespaceValue.type(), CSSValueType::Keyword); EXPECT_EQ(whitespaceValue.getKeyword(), CSSKeyword::FlexStart); auto badIdentValue = parseCSSComponentValue("bad"); EXPECT_EQ(badIdentValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(badIdentValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto pxValue = parseCSSComponentValue("20px"); EXPECT_EQ(pxValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(pxValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto multiValue = parseCSSComponentValue("auto flex-start"); EXPECT_EQ(multiValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(multiValue.getCSSWideKeyword(), CSSWideKeyword::Unset); } TEST(CSSParser, length_values) { auto emptyValue = parseCSSComponentValue(""); EXPECT_EQ(emptyValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(emptyValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto autoValue = parseCSSComponentValue("auto"); EXPECT_EQ(autoValue.type(), CSSValueType::Keyword); EXPECT_EQ(autoValue.getKeyword(), CSSKeyword::Auto); auto pxValue = parseCSSComponentValue("20px"); EXPECT_EQ(pxValue.type(), CSSValueType::Length); EXPECT_EQ(pxValue.getLength().value, 20.0f); EXPECT_EQ(pxValue.getLength().unit, CSSLengthUnit::Px); auto cmValue = parseCSSComponentValue("453cm"); EXPECT_EQ(cmValue.type(), CSSValueType::Length); EXPECT_EQ(cmValue.getLength().value, 453.0f); EXPECT_EQ(cmValue.getLength().unit, CSSLengthUnit::Cm); auto unitlessZeroValue = parseCSSComponentValue("0"); EXPECT_EQ(unitlessZeroValue.type(), CSSValueType::Length); EXPECT_EQ(unitlessZeroValue.getLength().value, 0.0f); EXPECT_EQ(unitlessZeroValue.getLength().unit, CSSLengthUnit::Px); auto unitlessNonzeroValue = parseCSSComponentValue("123"); EXPECT_EQ(unitlessNonzeroValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(unitlessNonzeroValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto pctValue = parseCSSComponentValue("-40%"); EXPECT_EQ(pctValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(pctValue.getCSSWideKeyword(), CSSWideKeyword::Unset); } TEST(CSSParser, length_percentage_values) { auto emptyValue = parseCSSComponentValue(""); EXPECT_EQ(emptyValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(emptyValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto autoValue = parseCSSComponentValue< CSSWideKeyword, CSSKeyword, CSSLength, CSSPercentage>("auto"); EXPECT_EQ(autoValue.type(), CSSValueType::Keyword); EXPECT_EQ(autoValue.getKeyword(), CSSKeyword::Auto); auto pxValue = parseCSSComponentValue("20px"); EXPECT_EQ(pxValue.type(), CSSValueType::Length); EXPECT_EQ(pxValue.getLength().value, 20.0f); EXPECT_EQ(pxValue.getLength().unit, CSSLengthUnit::Px); auto pctValue = parseCSSComponentValue("-40%"); EXPECT_EQ(pctValue.type(), CSSValueType::Percentage); EXPECT_EQ(pctValue.getPercentage().value, -40.0f); } TEST(CSSParser, number_values) { auto emptyValue = parseCSSComponentValue(""); EXPECT_EQ(emptyValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(emptyValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto inheritValue = parseCSSComponentValue("inherit"); EXPECT_EQ(inheritValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(inheritValue.getCSSWideKeyword(), CSSWideKeyword::Inherit); auto pxValue = parseCSSComponentValue("20px"); EXPECT_EQ(pxValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(pxValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto numberValue = parseCSSComponentValue("123.456"); EXPECT_EQ(numberValue.type(), CSSValueType::Number); EXPECT_EQ(numberValue.getNumber().value, 123.456f); auto unitlessZeroValue = parseCSSComponentValue("0"); EXPECT_EQ(unitlessZeroValue.type(), CSSValueType::Number); EXPECT_EQ(unitlessZeroValue.getNumber().value, 0.0f); } TEST(CSSParser, ratio_values) { auto emptyValue = parseCSSComponentValue(""); EXPECT_EQ(emptyValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(emptyValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto validRatio = parseCSSComponentValue("16/9"); EXPECT_EQ(validRatio.type(), CSSValueType::Ratio); EXPECT_EQ(validRatio.getRatio().numerator, 16.0f); EXPECT_EQ(validRatio.getRatio().denominator, 9.0f); auto validRatioWithWhitespace = parseCSSComponentValue("16 / 9"); EXPECT_EQ(validRatioWithWhitespace.type(), CSSValueType::Ratio); EXPECT_EQ(validRatioWithWhitespace.getRatio().numerator, 16.0f); EXPECT_EQ(validRatioWithWhitespace.getRatio().denominator, 9.0f); auto singleNumberRatio = parseCSSComponentValue("16"); EXPECT_EQ(singleNumberRatio.type(), CSSValueType::Ratio); EXPECT_EQ(singleNumberRatio.getRatio().numerator, 16.0f); EXPECT_EQ(singleNumberRatio.getRatio().denominator, 1.0f); auto fractionalNumber = parseCSSComponentValue("16.5"); EXPECT_EQ(fractionalNumber.type(), CSSValueType::Ratio); EXPECT_EQ(fractionalNumber.getRatio().numerator, 16.5f); EXPECT_EQ(fractionalNumber.getRatio().denominator, 1.0f); auto negativeNumber = parseCSSComponentValue("-16"); EXPECT_EQ(negativeNumber.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(negativeNumber.getCSSWideKeyword(), CSSWideKeyword::Unset); auto missingDenominator = parseCSSComponentValue("16/"); EXPECT_EQ(missingDenominator.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(missingDenominator.getCSSWideKeyword(), CSSWideKeyword::Unset); auto negativeNumerator = parseCSSComponentValue("-16/9"); EXPECT_EQ(negativeNumerator.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(negativeNumerator.getCSSWideKeyword(), CSSWideKeyword::Unset); auto negativeDenominator = parseCSSComponentValue("16/-9"); EXPECT_EQ(negativeDenominator.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(negativeDenominator.getCSSWideKeyword(), CSSWideKeyword::Unset); auto fractionalNumerator = parseCSSComponentValue("16.5/9"); EXPECT_EQ(fractionalNumerator.type(), CSSValueType::Ratio); EXPECT_EQ(fractionalNumerator.getRatio().numerator, 16.5f); EXPECT_EQ(fractionalNumerator.getRatio().denominator, 9.0f); auto fractionalDenominator = parseCSSComponentValue("16/9.5"); EXPECT_EQ(fractionalDenominator.type(), CSSValueType::Ratio); EXPECT_EQ(fractionalDenominator.getRatio().numerator, 16.0f); EXPECT_EQ(fractionalDenominator.getRatio().denominator, 9.5f); auto degenerateRatio = parseCSSComponentValue("0"); EXPECT_EQ(degenerateRatio.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(degenerateRatio.getCSSWideKeyword(), CSSWideKeyword::Unset); } TEST(CSSParser, number_ratio_values) { auto emptyValue = parseCSSComponentValue(""); EXPECT_EQ(emptyValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(emptyValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto validRatio = parseCSSComponentValue("16/9"); EXPECT_EQ(validRatio.type(), CSSValueType::Ratio); EXPECT_EQ(validRatio.getRatio().numerator, 16.0f); EXPECT_EQ(validRatio.getRatio().denominator, 9.0f); auto validRatioWithWhitespace = parseCSSComponentValue("16 / 9"); EXPECT_EQ(validRatioWithWhitespace.type(), CSSValueType::Ratio); EXPECT_EQ(validRatioWithWhitespace.getRatio().numerator, 16.0f); EXPECT_EQ(validRatioWithWhitespace.getRatio().denominator, 9.0f); auto singleNumberRatio = parseCSSComponentValue("16"); EXPECT_EQ(singleNumberRatio.type(), CSSValueType::Ratio); EXPECT_EQ(singleNumberRatio.getRatio().numerator, 16.0f); EXPECT_EQ(singleNumberRatio.getRatio().denominator, 1.0f); auto fractionalNumber = parseCSSComponentValue("16.5"); EXPECT_EQ(fractionalNumber.type(), CSSValueType::Ratio); EXPECT_EQ(fractionalNumber.getRatio().numerator, 16.5f); EXPECT_EQ(singleNumberRatio.getRatio().denominator, 1.0f); auto negativeNumber = parseCSSComponentValue("-16"); EXPECT_EQ(negativeNumber.type(), CSSValueType::Number); EXPECT_EQ(negativeNumber.getNumber().value, -16.0f); auto missingDenominator = parseCSSComponentValue("16/"); EXPECT_EQ(missingDenominator.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(missingDenominator.getCSSWideKeyword(), CSSWideKeyword::Unset); auto negativeNumerator = parseCSSComponentValue("-16/9"); EXPECT_EQ(negativeNumerator.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(negativeNumerator.getCSSWideKeyword(), CSSWideKeyword::Unset); auto negativeDenominator = parseCSSComponentValue("16/-9"); EXPECT_EQ(negativeDenominator.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(negativeDenominator.getCSSWideKeyword(), CSSWideKeyword::Unset); auto fractionalNumerator = parseCSSComponentValue("16.5/9"); EXPECT_EQ(fractionalNumerator.type(), CSSValueType::Ratio); EXPECT_EQ(fractionalNumerator.getRatio().numerator, 16.5f); EXPECT_EQ(fractionalNumerator.getRatio().denominator, 9.0f); auto fractionalDenominator = parseCSSComponentValue("16/9.5"); EXPECT_EQ(fractionalDenominator.type(), CSSValueType::Ratio); EXPECT_EQ(fractionalDenominator.getRatio().numerator, 16.0f); EXPECT_EQ(fractionalDenominator.getRatio().denominator, 9.5f); auto degenerateRatio = parseCSSComponentValue("0"); EXPECT_EQ(degenerateRatio.type(), CSSValueType::Number); EXPECT_EQ(degenerateRatio.getNumber().value, 0.0f); } TEST(CSSParser, parse_prop) { auto emptyValue = parseCSSProp(""); EXPECT_EQ(emptyValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(emptyValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto numberWidthValue = parseCSSProp("50px"); EXPECT_EQ(numberWidthValue.type(), CSSValueType::Length); EXPECT_EQ(numberWidthValue.getLength().value, 50.0f); EXPECT_EQ(numberWidthValue.getLength().unit, CSSLengthUnit::Px); auto percentWidthValue = parseCSSProp("50%"); EXPECT_EQ(percentWidthValue.type(), CSSValueType::Percentage); EXPECT_EQ(percentWidthValue.getPercentage().value, 50.0f); auto autoWidthValue = parseCSSProp("auto"); EXPECT_EQ(autoWidthValue.type(), CSSValueType::Keyword); EXPECT_EQ( autoWidthValue.getKeyword(), CSSAllowedKeywords::Auto); auto invalidWidthValue = parseCSSProp("50"); EXPECT_EQ(invalidWidthValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(invalidWidthValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto invalidKeywordValue = parseCSSProp("flex-start"); EXPECT_EQ(invalidKeywordValue.type(), CSSValueType::CSSWideKeyword); EXPECT_EQ(invalidKeywordValue.getCSSWideKeyword(), CSSWideKeyword::Unset); auto keywordlessValue = parseCSSProp("50px"); EXPECT_EQ(keywordlessValue.type(), CSSValueType::Length); EXPECT_EQ(keywordlessValue.getLength().value, 50.0f); EXPECT_EQ(keywordlessValue.getLength().unit, CSSLengthUnit::Px); } TEST(CSSParser, parse_keyword_prop_constexpr) { constexpr auto rowValue = parseCSSProp("row"); EXPECT_EQ(rowValue.type(), CSSValueType::Keyword); EXPECT_EQ( rowValue.getKeyword(), CSSAllowedKeywords::Row); } TEST(CSSParser, parse_length_prop_constexpr) { constexpr auto pxValue = parseCSSProp("2px"); EXPECT_EQ(pxValue.type(), CSSValueType::Length); EXPECT_EQ(pxValue.getLength().value, 2.0f); EXPECT_EQ(pxValue.getLength().unit, CSSLengthUnit::Px); } } // namespace facebook::react