* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <algorithm>
#include "gtest/gtest.h"
#include "test/mock/frameworks/core/common/mock_container.h"
#include "test/mock/frameworks/core/pipeline/mock_pipeline_context.h"
#include "core/common/ace_application_info.h"
#include "core/components/common/properties/shadow.h"
#include "core/interfaces/native/utility/converter.h"
#include "core/interfaces/native/utility/reverse_converter.h"
using namespace testing;
using namespace testing::ext;
namespace OHOS::Ace::NG {
namespace {
void SetApiVersion(int32_t version)
{
MockContainer::Current()->SetApiTargetVersion(version);
MockPipelineContext::GetCurrent()->SetMinPlatformVersion(version);
AceApplicationInfo::GetInstance().SetApiTargetVersion(version);
}
Ark_ShadowOptions MakeEmptyShadowOptions()
{
Ark_ShadowOptions src = {};
src.radius = Converter::ArkValue<Opt_Union_F64_Resource>(Ark_Empty());
src.type = Converter::ArkValue<Opt_ShadowType>(Ark_Empty());
src.color =
Converter::ArkValue<Opt_Union_arkui_component_enums_Color_String_Resource_ColoringStrategy>(Ark_Empty());
src.offsetX = Converter::ArkValue<Opt_Union_F64_Resource>(Ark_Empty());
src.offsetY = Converter::ArkValue<Opt_Union_F64_Resource>(Ark_Empty());
src.fill = Converter::ArkValue<Opt_Boolean>(Ark_Empty());
return src;
}
}
class ConvertorTextShadowTest : public testing::Test {
public:
static void SetUpTestSuite()
{
MockPipelineContext::SetUp();
MockContainer::SetUp(MockPipelineContext::GetCurrent());
SetApiVersion(static_cast<int32_t>(PlatformVersion::VERSION_TWELVE));
}
static void TearDownTestSuite()
{
MockContainer::TearDown();
MockPipelineContext::TearDown();
}
void TearDown() override
{
SetApiVersion(static_cast<int32_t>(PlatformVersion::VERSION_TWELVE));
}
};
* @tc.name: DefaultShadowBlurRadiusRAIITest
* @tc.desc: Verify DefaultShadowBlurRadius RAII saves and restores state correctly
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, DefaultShadowBlurRadiusRAIITest, TestSize.Level1)
{
EXPECT_DOUBLE_EQ(Converter::ConverterState::defShadowBlurRadius, -1.0);
{
Converter::DefaultShadowBlurRadius defaultRadius(0.0);
EXPECT_DOUBLE_EQ(Converter::ConverterState::defShadowBlurRadius, 0.0);
}
EXPECT_DOUBLE_EQ(Converter::ConverterState::defShadowBlurRadius, -1.0);
}
* @tc.name: ConvertTextShadowDefaultBlurRadiusTest
* @tc.desc: Verify Convert<Shadow> with DefaultShadowBlurRadius returns Shadow with blurRadius=0.0
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertTextShadowDefaultBlurRadiusTest, TestSize.Level1)
{
Ark_ShadowOptions src = {};
Converter::DefaultShadowBlurRadius defaultBlurRadius(0.0);
auto result = Converter::Convert<Shadow>(src);
EXPECT_DOUBLE_EQ(result.GetBlurRadius(), 0.0);
}
* @tc.name: ConvertShadowWithoutRAIILowAPITest
* @tc.desc: API < 26, no RAII. SetBlurRadius clamps -1.0 to 0.0 internally, result is 0.0
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertShadowWithoutRAIILowAPITest, TestSize.Level1)
{
SetApiVersion(static_cast<int32_t>(PlatformVersion::VERSION_TWELVE));
auto src = MakeEmptyShadowOptions();
auto result = Converter::Convert<Shadow>(src);
EXPECT_DOUBLE_EQ(result.GetBlurRadius(), 0.0);
}
* @tc.name: ConvertShadowWithoutRAIIHighAPITest
* @tc.desc: API >= 26, no RAII. SetBlurRadius keeps -1.0, result is -1.0
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertShadowWithoutRAIIHighAPITest, TestSize.Level1)
{
SetApiVersion(static_cast<int32_t>(PlatformVersion::VERSION_TWENTY_SIX));
auto src = MakeEmptyShadowOptions();
auto result = Converter::Convert<Shadow>(src);
EXPECT_DOUBLE_EQ(result.GetBlurRadius(), -1.0);
}
* @tc.name: ConvertShadowWithRAIIHighAPITest
* @tc.desc: API >= 26, with RAII(0.0). Shadow(0.0) -> blurRadius is 0.0, RAII takes effect
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertShadowWithRAIIHighAPITest, TestSize.Level1)
{
SetApiVersion(static_cast<int32_t>(PlatformVersion::VERSION_TWENTY_SIX));
auto src = MakeEmptyShadowOptions();
Converter::DefaultShadowBlurRadius defaultBlurRadius(0.0);
auto result = Converter::Convert<Shadow>(src);
EXPECT_DOUBLE_EQ(result.GetBlurRadius(), 0.0);
}
* @tc.name: ConvertTextShadowExplicitRadiusTest
* @tc.desc: Verify Convert<Shadow> sets blurRadius when radius is explicitly provided
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertTextShadowExplicitRadiusTest, TestSize.Level1)
{
Ark_ShadowOptions src = {};
src.radius = Converter::ArkUnion<Opt_Union_F64_Resource, Ark_Float64>(10.5);
Converter::DefaultShadowBlurRadius defaultBlurRadius(0.0);
auto result = Converter::Convert<Shadow>(src);
EXPECT_DOUBLE_EQ(result.GetBlurRadius(), 10.5);
}
* @tc.name: ConvertTextShadowOffsetTest
* @tc.desc: Verify Convert<Shadow> correctly sets offsetX and offsetY
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertTextShadowOffsetTest, TestSize.Level1)
{
Ark_ShadowOptions src = {};
src.offsetX = Converter::ArkUnion<Opt_Union_F64_Resource, Ark_Float64>(3.0);
src.offsetY = Converter::ArkUnion<Opt_Union_F64_Resource, Ark_Float64>(4.0);
Converter::DefaultShadowBlurRadius defaultBlurRadius(0.0);
auto result = Converter::Convert<Shadow>(src);
EXPECT_DOUBLE_EQ(result.GetOffset().GetX(), 3.0);
EXPECT_DOUBLE_EQ(result.GetOffset().GetY(), 4.0);
}
* @tc.name: ConvertTextShadowTypeTest
* @tc.desc: Verify Convert<Shadow> correctly sets ShadowType
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertTextShadowTypeTest, TestSize.Level1)
{
Ark_ShadowOptions src = {};
src.type = Converter::ArkValue<Opt_ShadowType>(ARK_SHADOW_TYPE_BLUR);
Converter::DefaultShadowBlurRadius defaultBlurRadius(0.0);
auto result = Converter::Convert<Shadow>(src);
EXPECT_EQ(result.GetShadowType(), ShadowType::BLUR);
}
* @tc.name: ConvertTextShadowColorTest
* @tc.desc: Verify Convert<Shadow> correctly sets color
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertTextShadowColorTest, TestSize.Level1)
{
Ark_ShadowOptions src = {};
src.color = Converter::ArkUnion<Opt_Union_arkui_component_enums_Color_String_Resource_ColoringStrategy,
Ark_arkui_component_enums_Color>(ARK_ARKUI_COMPONENT_ENUMS_COLOR_RED);
Converter::DefaultShadowBlurRadius defaultBlurRadius(0.0);
auto result = Converter::Convert<Shadow>(src);
EXPECT_EQ(result.GetColor(), Color::RED);
}
* @tc.name: ConvertTextShadowFillTest
* @tc.desc: Verify Convert<Shadow> correctly sets isFilled
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertTextShadowFillTest, TestSize.Level1)
{
Ark_ShadowOptions src = {};
src.fill = Converter::ArkValue<Opt_Boolean>(true);
Converter::DefaultShadowBlurRadius defaultBlurRadius(0.0);
auto result = Converter::Convert<Shadow>(src);
EXPECT_TRUE(result.GetIsFilled());
}
* @tc.name: ConvertTextShadowAllFieldsTest
* @tc.desc: Verify Convert<Shadow> with all fields set
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertTextShadowAllFieldsTest, TestSize.Level1)
{
Ark_ShadowOptions src = {};
src.radius = Converter::ArkUnion<Opt_Union_F64_Resource, Ark_Float64>(5.0);
src.type = Converter::ArkValue<Opt_ShadowType>(ARK_SHADOW_TYPE_COLOR);
src.color = Converter::ArkUnion<Opt_Union_arkui_component_enums_Color_String_Resource_ColoringStrategy,
Ark_arkui_component_enums_Color>(ARK_ARKUI_COMPONENT_ENUMS_COLOR_BLUE);
src.offsetX = Converter::ArkUnion<Opt_Union_F64_Resource, Ark_Float64>(1.0);
src.offsetY = Converter::ArkUnion<Opt_Union_F64_Resource, Ark_Float64>(2.0);
src.fill = Converter::ArkValue<Opt_Boolean>(true);
Converter::DefaultShadowBlurRadius defaultBlurRadius(0.0);
auto result = Converter::Convert<Shadow>(src);
EXPECT_DOUBLE_EQ(result.GetBlurRadius(), 5.0);
EXPECT_EQ(result.GetShadowType(), ShadowType::COLOR);
EXPECT_EQ(result.GetColor(), Color::BLUE);
EXPECT_DOUBLE_EQ(result.GetOffset().GetX(), 1.0);
EXPECT_DOUBLE_EQ(result.GetOffset().GetY(), 2.0);
EXPECT_TRUE(result.GetIsFilled());
}
* @tc.name: ConvertTextShadowVectorTest
* @tc.desc: Verify Convert<vector<Shadow>> with DefaultShadowBlurRadius returns a vector with a single element
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertTextShadowVectorTest, TestSize.Level1)
{
Ark_ShadowOptions src = {};
src.radius = Converter::ArkUnion<Opt_Union_F64_Resource, Ark_Float64>(8.0);
Converter::DefaultShadowBlurRadius defaultBlurRadius(0.0);
auto result = Converter::Convert<std::vector<Shadow>>(src);
EXPECT_EQ(result.size(), 1u);
EXPECT_DOUBLE_EQ(result[0].GetBlurRadius(), 8.0);
}
* @tc.name: ConvertTextShadowVectorDefaultBlurRadiusTest
* @tc.desc: Verify Convert<vector<Shadow>> returns Shadow with blurRadius=0.0 by default
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertTextShadowVectorDefaultBlurRadiusTest, TestSize.Level1)
{
Ark_ShadowOptions src = {};
Converter::DefaultShadowBlurRadius defaultBlurRadius(0.0);
auto result = Converter::Convert<std::vector<Shadow>>(src);
ASSERT_EQ(result.size(), 1u);
EXPECT_DOUBLE_EQ(result[0].GetBlurRadius(), 0.0);
}
* @tc.name: ShadowConstructorWithBlurRadiusTest
* @tc.desc: Verify Shadow(double) constructor sets blurRadius correctly
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ShadowConstructorWithBlurRadiusTest, TestSize.Level1)
{
Shadow shadow(0.0);
EXPECT_DOUBLE_EQ(shadow.GetBlurRadius(), 0.0);
Shadow shadowPositive(5.5);
EXPECT_DOUBLE_EQ(shadowPositive.GetBlurRadius(), 5.5);
}
* @tc.name: ShadowDefaultConstructorHighAPITest
* @tc.desc: API >= 26, Shadow() default constructor keeps blurRadius=-1.0
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ShadowDefaultConstructorHighAPITest, TestSize.Level1)
{
SetApiVersion(static_cast<int32_t>(PlatformVersion::VERSION_TWENTY_SIX));
Shadow shadow;
EXPECT_DOUBLE_EQ(shadow.GetBlurRadius(), -1.0);
}
* @tc.name: ConvertTextShadowColorStrategyTest
* @tc.desc: Verify Convert<Shadow> correctly sets ShadowColorStrategy
* @tc.type: FUNC
*/
HWTEST_F(ConvertorTextShadowTest, ConvertTextShadowColorStrategyTest, TestSize.Level1)
{
Ark_ShadowOptions src = {};
src.color = Converter::ArkUnion<Opt_Union_arkui_component_enums_Color_String_Resource_ColoringStrategy,
Ark_ColoringStrategy>(ARK_COLORING_STRATEGY_AVERAGE);
Converter::DefaultShadowBlurRadius defaultBlurRadius(0.0);
auto result = Converter::Convert<Shadow>(src);
EXPECT_EQ(result.GetShadowColorStrategy(), ShadowColorStrategy::AVERAGE);
}
}