diff --git a/frameworks/bridge/declarative_frontend/style_string/js_span_string.cpp b/frameworks/bridge/declarative_frontend/style_string/js_span_string.cpp index f7302bb120830cf563d58c4e4626fd97c57a387c..59caa2360a13f36df1f8257710d201d7143a2b58 100644 --- a/frameworks/bridge/declarative_frontend/style_string/js_span_string.cpp +++ b/frameworks/bridge/declarative_frontend/style_string/js_span_string.cpp @@ -281,7 +281,6 @@ void JSMutableSpanString::Constructor(const JSCallbackInfo& args) auto spanBases = JSSpanString::ParseJsSpanBaseVector(args[1], StringUtils::ToWstring(data).length()); spanString = AceType::MakeRefPtr(data, spanBases); } - LOGE("jyj string value %s", data.c_str()); jsSpanString->SetController(spanString); jsSpanString->SetMutableController(spanString); args.SetReturnValue(Referenced::RawPtr(jsSpanString)); diff --git a/frameworks/core/components_ng/pattern/text_field/text_field_model.h b/frameworks/core/components_ng/pattern/text_field/text_field_model.h index 7aedbba563e764fc4d4de3c0ac88ffc8532d8966..9470b1ccf2801373f6147c26c049c3af01b8bb78 100644 --- a/frameworks/core/components_ng/pattern/text_field/text_field_model.h +++ b/frameworks/core/components_ng/pattern/text_field/text_field_model.h @@ -67,6 +67,11 @@ struct Font { } return flag; } + + std::string GetFontColor() const + { + return fontColor.has_value() ? fontColor.value().ColorToString() : ""; + } }; struct CaretStyle { diff --git a/test/unittest/core/pattern/text/BUILD.gn b/test/unittest/core/pattern/text/BUILD.gn index 1bb4e7dd0bf13b3420aff6af275d4220c790dd0c..9dca56000a8239b518bb1f4eb493d0f3c5d22b6a 100644 --- a/test/unittest/core/pattern/text/BUILD.gn +++ b/test/unittest/core/pattern/text/BUILD.gn @@ -16,6 +16,7 @@ import("//foundation/arkui/ace_engine/test/unittest/ace_unittest.gni") ace_unittest("text_test_ng") { type = "new" sources = [ + "span_string_test_ng.cpp", "span_test_ng.cpp", "text_test_ng.cpp", ] diff --git a/test/unittest/core/pattern/text/span_string_test_ng.cpp b/test/unittest/core/pattern/text/span_string_test_ng.cpp new file mode 100644 index 0000000000000000000000000000000000000000..822090f9746912e9d66393477effd78eb0e30c95 --- /dev/null +++ b/test/unittest/core/pattern/text/span_string_test_ng.cpp @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2024 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 +#include +#include +#include + +#include "gtest/gtest.h" + +#include "core/components/common/properties/color.h" +#define private public +#define protected public +#include "test/mock/core/common/mock_theme_manager.h" +#include "test/mock/core/pipeline/mock_pipeline_context.h" +#include "test/mock/core/render/mock_paragraph.h" + +#include "base/geometry/dimension.h" +#include "base/memory/ace_type.h" +#include "base/memory/referenced.h" +#include "core/components/common/properties/text_style.h" +#include "core/components/text/text_theme.h" +#include "core/components_ng/pattern/text/span/mutable_span_string.h" +#include "core/components_ng/pattern/text/span/span_object.h" +#include "core/components_ng/pattern/text/span/span_string.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS::Ace::NG { + +class SpanStringTestNg : public testing::Test { +public: + static void SetUpTestSuite(); + static void TearDownTestSuite(); +}; + +void SpanStringTestNg::SetUpTestSuite() +{ + MockPipelineContext::SetUp(); + auto themeManager = AceType::MakeRefPtr(); + MockPipelineContext::GetCurrent()->SetThemeManager(themeManager); + EXPECT_CALL(*themeManager, GetTheme(_)).WillRepeatedly(Return(AceType::MakeRefPtr())); + RefPtr stageNode = AceType::MakeRefPtr("STAGE", -1, AceType::MakeRefPtr()); + auto stageManager = AceType::MakeRefPtr(stageNode); + MockPipelineContext::GetCurrent()->stageManager_ = stageManager; +} + +void SpanStringTestNg::TearDownTestSuite() +{ + MockPipelineContext::TearDown(); +} + +class TestNode : public UINode { + DECLARE_ACE_TYPE(TestNode, UINode); + +public: + static RefPtr CreateTestNode(int32_t nodeId) + { + auto spanNode = MakeRefPtr(nodeId); + return spanNode; + }; + + bool IsAtomicNode() const override + { + return true; + } + + explicit TestNode(int32_t nodeId) : UINode("TestNode", nodeId) {} + ~TestNode() override = default; +}; +std::string test_str[] = { "hello", "world", "this", "find", "gank", "pink", "that", "when", "how", "cpp" }; +Font testFont1 { OHOS::Ace::FontWeight::BOLD, Dimension(29.0, DimensionUnit::PX), OHOS::Ace::FontStyle::ITALIC, + std::vector(test_str, test_str + 10), OHOS::Ace::Color::RED }; +Font testFont2 { OHOS::Ace::FontWeight::LIGHTER, Dimension(19.0, DimensionUnit::PX), OHOS::Ace::FontStyle::ITALIC, + std::vector(test_str, test_str + 10), OHOS::Ace::Color::WHITE }; +Font testEmptyFont {}; +/** + * @tc.name: SpanStringTest001 + * @tc.desc: Test basic function of GetString/GetLength/GetIndex + * @tc.type: FUNC + */ +HWTEST_F(SpanStringTestNg, SpanString001, TestSize.Level1) +{ + auto spanString = AceType::MakeRefPtr("0123456789"); + EXPECT_EQ(spanString->GetString(), "0123456789"); + EXPECT_EQ(spanString->GetLength(), 10); + + auto spanString1 = AceType::MakeRefPtr("中0123456789"); + EXPECT_EQ(spanString1->GetString(), "中0123456789"); + EXPECT_EQ(spanString1->GetLength(), 11); + + auto spanString2 = AceType::MakeRefPtr("0123456"); + EXPECT_EQ(spanString2->GetString(), "0123456"); + EXPECT_EQ(spanString2->GetLength(), 7); + + auto spanString3 = AceType::MakeRefPtr("你好"); + EXPECT_EQ(spanString3->GetString(), "你好"); + EXPECT_EQ(spanString3->GetLength(), 2); +} +/** + * @tc.name: SpanStringTest002 + * @tc.desc: Test basic function of IsEqualToSpanString/GetSubSpanString + * @tc.type: FUNC + */ +HWTEST_F(SpanStringTestNg, SpanString002, TestSize.Level1) +{ + auto spanString1 = AceType::MakeRefPtr("01234中56789"); + auto spanString2 = AceType::MakeRefPtr("01234中56789"); + auto spanString3 = AceType::MakeRefPtr("01234567891"); + EXPECT_TRUE(spanString1->IsEqualToSpanString(spanString2)); + EXPECT_FALSE(spanString1->IsEqualToSpanString(spanString3)); + std::vector> spans; + spans.push_back(AceType::MakeRefPtr(testFont2, 0, 3)); + spans.push_back(AceType::MakeRefPtr(testEmptyFont, 5, 8)); + auto spanStringWithSpans1 = AceType::MakeRefPtr("01234567891", spans); + auto spanStringWithSpans2 = AceType::MakeRefPtr("01234567891", spans); + EXPECT_TRUE(spanStringWithSpans1->IsEqualToSpanString(spanStringWithSpans2)); + std::vector> spans1; + spans1.push_back(AceType::MakeRefPtr(testFont2, 0, 3)); + spans1.push_back(AceType::MakeRefPtr(testEmptyFont, 5, 7)); + auto spanStringWithSpans3 = AceType::MakeRefPtr("01234567891", spans1); + EXPECT_FALSE(spanStringWithSpans3->IsEqualToSpanString(spanStringWithSpans2)); + auto subSpanStringWithSpans2 = spanStringWithSpans2->GetSubSpanString(0, 7); + auto subSpanStringWithSpans3 = spanStringWithSpans3->GetSubSpanString(0, 7); + auto map2 = subSpanStringWithSpans2->GetSpansMap(); + EXPECT_TRUE(subSpanStringWithSpans2->IsEqualToSpanString(subSpanStringWithSpans3)); + auto emptySpanString = spanStringWithSpans2->GetSubSpanString(1, 0); + EXPECT_TRUE(emptySpanString->IsEqualToSpanString(AceType::MakeRefPtr(""))); +} + +/** + * @tc.name: SpanStringTest003 + * @tc.desc: Test basic function of GetSpans/GetFontColor/GetFontSize/GetFontWeight/GetFontFamily/GetFontStyle + * @tc.type: FUNC + */ +HWTEST_F(SpanStringTestNg, SpanString003, TestSize.Level1) +{ + auto spanString3 = AceType::MakeRefPtr("0123456789"); + spanString3->AddSpan(AceType::MakeRefPtr(testFont1, 0, 3)); + spanString3->AddSpan(AceType::MakeRefPtr(testFont2, 3, 5)); + spanString3->AddSpan(AceType::MakeRefPtr(testEmptyFont, 5, 8)); + auto firstSpans = spanString3->GetSpans(5, 2); + EXPECT_EQ(firstSpans.size(), 1); + auto firstFontSpan = AceType::DynamicCast(firstSpans[0]); + EXPECT_NE(firstFontSpan, nullptr); + EXPECT_EQ(firstFontSpan->GetStartIndex(), 5); + EXPECT_EQ(firstFontSpan->GetEndIndex(), 7); + EXPECT_EQ(firstFontSpan->GetFont().GetFontColor(), ""); + + auto secondString3 = spanString3->GetSpans(0, 3); + EXPECT_EQ(secondString3.size(), 1); + auto secondFontSpan = AceType::DynamicCast(secondString3[0]); + EXPECT_NE(secondFontSpan, nullptr); + EXPECT_EQ(secondFontSpan->GetStartIndex(), 0); + EXPECT_EQ(secondFontSpan->GetEndIndex(), 3); + EXPECT_EQ(secondFontSpan->GetFont().GetFontColor(), OHOS::Ace::Color::RED.ColorToString()); + + auto thirdString3 = spanString3->GetSpans(3, 1); + EXPECT_EQ(thirdString3.size(), 1); + auto thirdFontSpan = AceType::DynamicCast(thirdString3[0]); + EXPECT_NE(thirdFontSpan, nullptr); + EXPECT_EQ(thirdFontSpan->GetStartIndex(), 3); + EXPECT_EQ(thirdFontSpan->GetEndIndex(), 4); + EXPECT_EQ(thirdFontSpan->GetFont().GetFontColor(), OHOS::Ace::Color::WHITE.ColorToString()); +} +/** + * @tc.name: SpanStringTest004 + * @tc.desc: Test basic function of GetString/GetLength/GetIndex + * @tc.type: FUNC + */ +HWTEST_F(SpanStringTestNg, SpanString004, TestSize.Level1) +{ + auto spanString3 = AceType::MakeRefPtr("0123456789"); + spanString3->AddSpan(AceType::MakeRefPtr(testEmptyFont, 0, 3)); + spanString3->AddSpan(AceType::MakeRefPtr(testFont1, 3, 5)); + spanString3->AddSpan(AceType::MakeRefPtr(testFont2, 5, 8)); + auto spans = spanString3->GetSpans(1, 7); + EXPECT_EQ(spans.size(), 3); + auto firstFontSpan = AceType::DynamicCast(spans[0]); + EXPECT_NE(firstFontSpan, nullptr); + EXPECT_EQ(firstFontSpan->GetStartIndex(), 1); + EXPECT_EQ(firstFontSpan->GetEndIndex(), 3); + EXPECT_EQ(firstFontSpan->GetFont().GetFontColor(), ""); + + auto secondFontSpan = AceType::DynamicCast(spans[1]); + EXPECT_NE(secondFontSpan, nullptr); + EXPECT_EQ(secondFontSpan->GetStartIndex(), 3); + EXPECT_EQ(secondFontSpan->GetEndIndex(), 5); + EXPECT_EQ(secondFontSpan->GetFont().GetFontColor(), OHOS::Ace::Color::RED.ColorToString()); + + auto thirdFontSpan = AceType::DynamicCast(spans[2]); + EXPECT_NE(thirdFontSpan, nullptr); + EXPECT_EQ(thirdFontSpan->GetStartIndex(), 5); + EXPECT_EQ(thirdFontSpan->GetEndIndex(), 8); + EXPECT_EQ(thirdFontSpan->GetFont().GetFontColor(), OHOS::Ace::Color::WHITE.ColorToString()); +} + +/** + * @tc.name: SpanStringTest001 + * @tc.desc: Test basic function of ReplaceString/InsertString/RemoveString + * @tc.type: FUNC + */ +HWTEST_F(SpanStringTestNg, MutableSpanString001, TestSize.Level1) +{ + auto a = AceType::MakeRefPtr("0123456789"); + EXPECT_EQ(a->GetString(), "0123456789"); + a->ReplaceString(0, 1, "abcd"); + EXPECT_EQ(a->GetString(), "abcd123456789"); + a->InsertString(0, "abcd"); + EXPECT_EQ(a->GetString(), "abcdabcd123456789"); + a->RemoveString(3, 3); + EXPECT_EQ(a->GetString(), "abccd123456789"); + a->InsertString(4, "中文插入测试"); + EXPECT_EQ(a->GetString(), "abcc中文插入测试d123456789"); + a->RemoveString(4, 6); + EXPECT_EQ(a->GetString(), "abccd123456789"); + a->ReplaceString(5, 9, "中文替换测试"); + EXPECT_EQ(a->GetString(), "abccd中文替换测试"); +} + +bool CompareSpanList(const std::list>& a, const std::list>& b) +{ + if (a.size() != b.size()) { + std::cout << "size not match" << a.size() << " " << b.size() << std::endl; + return false; + } + auto ita = a.begin(); + auto itb = b.begin(); + while (ita != a.end()) { + if (!(*ita)->IsAttributesEqual(*itb)) { + std::cout << (*ita)->ToString() << " " << (*itb)->ToString() << std::endl; + return false; + } + ++ita; + ++itb; + } + return true; +} + +/** + * @tc.name: SpanStringTest001 + * @tc.desc: Test if span is right after addSpan/replaceSpan/removeSpan + * @tc.type: FUNC + */ +HWTEST_F(SpanStringTestNg, MutableSpanString002, TestSize.Level1) +{ + auto a = AceType::MakeRefPtr("0123456789"); + + std::string test_str[] = { "hello", "world", "this", "find", "gank", "pink", "that", "when", "how", "cpp" }; + a->AddSpan(AceType::MakeRefPtr(testFont1, 0, 10)); + EXPECT_EQ(a->GetString(), "0123456789"); + std::list> resultList1 = { AceType::MakeRefPtr(testFont1, 0, 10) }; + auto aSpansMap = a->GetSpansMap(); + EXPECT_TRUE(CompareSpanList(aSpansMap[SpanType::Font], resultList1)); + std::list> resultList2 = { AceType::MakeRefPtr(testFont2, 0, 3), + AceType::MakeRefPtr(testFont1, 3, 10) }; + a->ReplaceSpan(0, 3, AceType::MakeRefPtr(testFont2, 0, 10)); + aSpansMap = a->GetSpansMap(); + EXPECT_EQ(a->GetString(), "0123456789"); + EXPECT_TRUE(CompareSpanList(aSpansMap[SpanType::Font], resultList2)); + std::list> resultList3 = { AceType::MakeRefPtr(testFont1, 3, 10) }; + a->RemoveSpan(0, 3, SpanType::Font); + aSpansMap = a->GetSpansMap(); + EXPECT_EQ(a->GetString(), "0123456789"); + EXPECT_TRUE(CompareSpanList(aSpansMap[SpanType::Font], resultList3)); + + // 用中文再测一次 + auto b = MutableSpanString("零一二三四五六七八九"); + b.AddSpan(AceType::MakeRefPtr(testFont1, 0, 10)); + EXPECT_EQ(b.GetString(), "零一二三四五六七八九"); + std::list> resultList4 = { AceType::MakeRefPtr(testFont1, 0, 10) }; + auto bSpansMap = b.GetSpansMap(); + EXPECT_TRUE(CompareSpanList(bSpansMap[SpanType::Font], resultList4)); + std::list> resultList5 = { AceType::MakeRefPtr(testFont2, 0, 3), + AceType::MakeRefPtr(testFont1, 3, 10) }; + b.ReplaceSpan(0, 3, AceType::MakeRefPtr(testFont2, 0, 10)); + bSpansMap = b.GetSpansMap(); + EXPECT_EQ(b.GetString(), "零一二三四五六七八九"); + EXPECT_TRUE(CompareSpanList(bSpansMap[SpanType::Font], resultList5)); + std::list> resultList6 = { AceType::MakeRefPtr(testFont1, 3, 10) }; + b.RemoveSpan(0, 3, SpanType::Font); + bSpansMap = b.GetSpansMap(); + EXPECT_EQ(b.GetString(), "零一二三四五六七八九"); + EXPECT_TRUE(CompareSpanList(bSpansMap[SpanType::Font], resultList6)); +} + +/** + * @tc.name: MutableSpanString003 + * @tc.desc: Test if span is right after addSpan + * @tc.type: FUNC + */ +HWTEST_F(SpanStringTestNg, MutableSpanString003, TestSize.Level1) +{ + auto mutableSpan = AceType::MakeRefPtr("0123456789"); + + Font fontOne { .fontColor = OHOS::Ace::Color::RED }; + Font fontTwo { .fontColor = OHOS::Ace::Color::WHITE }; + Font fontThree { .fontColor = OHOS::Ace::Color::BLACK }; + + mutableSpan->AddSpan(AceType::MakeRefPtr(fontOne, 0, 10)); + auto spansMap = mutableSpan->GetSpansMap(); + auto spanItems = mutableSpan->GetSpanItems(); + EXPECT_EQ(spansMap.size(), 1); + EXPECT_EQ(spanItems.size(), 1); + + mutableSpan->AddSpan(AceType::MakeRefPtr(fontTwo, 3, 7)); + spansMap = mutableSpan->GetSpansMap(); + auto fontSpans = spansMap[SpanType::Font]; + spanItems = mutableSpan->GetSpanItems(); + EXPECT_EQ(fontSpans.size(), 3); + EXPECT_EQ(spanItems.size(), 3); + std::list> resultList = { AceType::MakeRefPtr(fontOne, 0, 3), + AceType::MakeRefPtr(fontTwo, 3, 7), AceType::MakeRefPtr(fontOne, 7, 10) }; + EXPECT_EQ(CompareSpanList(fontSpans, resultList), true); + + mutableSpan->AddSpan(AceType::MakeRefPtr(fontThree, 2, 5)); + spansMap = mutableSpan->GetSpansMap(); + fontSpans = spansMap[SpanType::Font]; + spanItems = mutableSpan->GetSpanItems(); + EXPECT_EQ(fontSpans.size(), 4); + EXPECT_EQ(spanItems.size(), 5); + resultList = { AceType::MakeRefPtr(fontOne, 0, 2), AceType::MakeRefPtr(fontThree, 2, 5), + AceType::MakeRefPtr(fontTwo, 5, 7), AceType::MakeRefPtr(fontOne, 7, 10) }; + EXPECT_EQ(CompareSpanList(fontSpans, resultList), true); +} + +/** + * @tc.name: MutableSpanString004 + * @tc.desc: Test if span is right after removeSpan + * @tc.type: FUNC + */ +HWTEST_F(SpanStringTestNg, MutableSpanString004, TestSize.Level1) +{ + auto mutableSpan = AceType::MakeRefPtr("0123456789"); + + Font fontOne { .fontColor = OHOS::Ace::Color::RED }; + Font fontTwo { .fontColor = OHOS::Ace::Color::WHITE }; + Font fontThree { .fontColor = OHOS::Ace::Color::BLACK }; + + mutableSpan->AddSpan(AceType::MakeRefPtr(fontOne, 0, 10)); + mutableSpan->AddSpan(AceType::MakeRefPtr(fontTwo, 3, 7)); + mutableSpan->AddSpan(AceType::MakeRefPtr(fontThree, 2, 5)); + + mutableSpan->RemoveSpan(2, 3, SpanType::Font); + auto spansMap = mutableSpan->GetSpansMap(); + auto fontSpans = spansMap[SpanType::Font]; + EXPECT_EQ(fontSpans.size(), 3); + std::list> resultList = { AceType::MakeRefPtr(fontOne, 0, 2), + AceType::MakeRefPtr(fontTwo, 5, 7), AceType::MakeRefPtr(fontOne, 7, 10) }; + EXPECT_EQ(CompareSpanList(fontSpans, resultList), true); + + mutableSpan->RemoveSpan(2, 5, SpanType::Font); + spansMap = mutableSpan->GetSpansMap(); + fontSpans = spansMap[SpanType::Font]; + EXPECT_EQ(fontSpans.size(), 2); + resultList = { AceType::MakeRefPtr(fontOne, 0, 2), AceType::MakeRefPtr(fontOne, 7, 10) }; + EXPECT_EQ(CompareSpanList(fontSpans, resultList), true); + + mutableSpan->RemoveSpan(0, 10, SpanType::Font); + spansMap = mutableSpan->GetSpansMap(); + fontSpans = spansMap[SpanType::Font]; + EXPECT_EQ(fontSpans.size(), 0); +} + +/** + * @tc.name: MutableSpanString005 + * @tc.desc: Test for outliers + * @tc.type: FUNC + */ +HWTEST_F(SpanStringTestNg, MutableSpanString005, TestSize.Level1) +{ + auto mutableSpan = AceType::MakeRefPtr("0123456789"); + + Font fontOne { .fontColor = OHOS::Ace::Color::RED }; + Font fontTwo { .fontColor = OHOS::Ace::Color::WHITE }; + Font fontThree { .fontColor = OHOS::Ace::Color::BLACK }; + + mutableSpan->AddSpan(AceType::MakeRefPtr(fontOne, -1, 10)); + mutableSpan->AddSpan(AceType::MakeRefPtr(fontTwo, 3, 100)); + mutableSpan->AddSpan(AceType::MakeRefPtr(fontThree, -100, 100)); + + auto spansMap = mutableSpan->GetSpansMap(); + EXPECT_EQ(spansMap.size(), 0); + + mutableSpan->AddSpan(AceType::MakeRefPtr(fontOne, 0, 10)); + mutableSpan->AddSpan(AceType::MakeRefPtr(fontTwo, 3, 7)); + mutableSpan->AddSpan(AceType::MakeRefPtr(fontThree, 2, 5)); + spansMap = mutableSpan->GetSpansMap(); + auto fontSpans = spansMap[SpanType::Font]; + EXPECT_EQ(fontSpans.size(), 4); + mutableSpan->RemoveSpan(-1, 10, SpanType::Font); + mutableSpan->RemoveSpan(3, 100, SpanType::Font); + mutableSpan->RemoveSpan(-100, 100, SpanType::Font); + spansMap = mutableSpan->GetSpansMap(); + fontSpans = spansMap[SpanType::Font]; + EXPECT_EQ(fontSpans.size(), 4); +} + +/** + * @tc.name: MutableSpanString006 + * @tc.desc: Test combination of IsEqualToSpanString/GetSubSpanString/GetSpans/GetSpan + * @tc.type: FUNC + */ +HWTEST_F(SpanStringTestNg, MutableSpanString006, TestSize.Level1) +{ + Font fontOne { .fontColor = OHOS::Ace::Color::RED }; + Font fontTwo { .fontColor = OHOS::Ace::Color::WHITE }; + auto spanString1 = AceType::MakeRefPtr("0123456789"); + spanString1->AddSpan(AceType::MakeRefPtr(fontOne, 0, 3)); + auto mutableSpanString1 = AceType::MakeRefPtr("0123456789"); + EXPECT_FALSE(spanString1->IsEqualToSpanString(mutableSpanString1)); + mutableSpanString1->AddSpan(AceType::MakeRefPtr(fontOne, 0, 3)); + EXPECT_TRUE(spanString1->IsEqualToSpanString(mutableSpanString1)); + mutableSpanString1->AddSpan(AceType::MakeRefPtr(fontOne, 3, 7)); + auto mutableSpanString2 = AceType::MakeRefPtr("0123456789"); + mutableSpanString2->AddSpan(AceType::MakeRefPtr(fontOne, 0, 7)); + EXPECT_TRUE(mutableSpanString2->IsEqualToSpanString(mutableSpanString1)); + EXPECT_TRUE(spanString1->GetSubSpanString(0, 3)->IsEqualToSpanString(mutableSpanString2->GetSubSpanString(0, 3))); + mutableSpanString2->AddSpan(AceType::MakeRefPtr(fontTwo, 7, 8)); + mutableSpanString2->AddSpan(AceType::MakeRefPtr(fontOne, 8, 9)); + auto spanArr = mutableSpanString2->GetSpans(0, 9); + EXPECT_EQ(spanArr.size(), 3); +} + +/** + * @tc.name: MutableSpanString007 + * @tc.desc: Test some edge case of InsertString/ReplaceString/RemoveString + * @tc.type: FUNC + */ +HWTEST_F(SpanStringTestNg, MutableSpanString007, TestSize.Level1) +{ + vector colors = { Color::RED, Color::BLACK, Color::GREEN, Color::GRAY, Color::BLUE }; + vector fonts; + auto spanString1 = AceType::MakeRefPtr("01234"); + for (int i = 0; i < colors.size(); i++) { + Font f; + f.fontColor = colors[i]; + fonts.emplace_back(f); + spanString1->AddSpan(AceType::MakeRefPtr(f, i, i + 1)); + } + auto spanArr = spanString1->GetSpans(0, spanString1->GetLength()); + EXPECT_EQ(spanArr.size(), colors.size()); + + auto spanString2 = spanString1->GetSubSpanString(0, spanString1->GetLength()); + EXPECT_TRUE(spanString2->IsEqualToSpanString(spanString1)); + std::list> resultList1 = { AceType::MakeRefPtr(fonts[0], 0, 6), + AceType::MakeRefPtr(fonts[1], 6, 7), AceType::MakeRefPtr(fonts[2], 7, 8), + AceType::MakeRefPtr(fonts[3], 8, 9), AceType::MakeRefPtr(fonts[4], 9, 10) }; + spanString1->InsertString(0, "一二三四五"); + auto spanMap = spanString1->GetSpansMap(); + EXPECT_TRUE(CompareSpanList(spanMap[SpanType::Font], resultList1)); + spanString1->InsertString(6, "红红火火"); + std::list> resultList2 = { AceType::MakeRefPtr(fonts[0], 0, 10), + AceType::MakeRefPtr(fonts[1], 10, 11), AceType::MakeRefPtr(fonts[2], 11, 12), + AceType::MakeRefPtr(fonts[3], 12, 13), AceType::MakeRefPtr(fonts[4], 13, 14) }; + spanMap = spanString1->GetSpansMap(); + EXPECT_TRUE(CompareSpanList(spanMap[SpanType::Font], resultList2)); + spanString1->InsertString(11, "abcdefg"); + spanString1->ReplaceString(8, 8, "A"); + std::list> resultList3 = { AceType::MakeRefPtr(fonts[0], 0, 9), + AceType::MakeRefPtr(fonts[1], 9, 11), AceType::MakeRefPtr(fonts[2], 11, 12), + AceType::MakeRefPtr(fonts[3], 12, 13), AceType::MakeRefPtr(fonts[4], 13, 14) }; + spanMap = spanString1->GetSpansMap(); + EXPECT_TRUE(CompareSpanList(spanMap[SpanType::Font], resultList3)); + EXPECT_EQ(spanString1->GetString(), "一二三四五0红红Afg234"); + spanString1->RemoveString(1, 10); + std::list> resultList4 = { AceType::MakeRefPtr(fonts[0], 0, 1), + AceType::MakeRefPtr(fonts[2], 1, 2), AceType::MakeRefPtr(fonts[3], 2, 3), + AceType::MakeRefPtr(fonts[4], 3, 4) }; + spanMap = spanString1->GetSpansMap(); + EXPECT_TRUE(CompareSpanList(spanMap[SpanType::Font], resultList4)); +} + +/** + * @tc.name: MutableSpanString008 + * @tc.desc: Test some edge case of InsertSpanString/ReplaceSpanString/AppendSpanString + * @tc.type: FUNC + */ +HWTEST_F(SpanStringTestNg, MutableSpanString008, TestSize.Level1) +{ + vector colors = { Color::RED, Color::BLACK, Color::GREEN, Color::GRAY, Color::BLUE }; + vector fonts; + auto spanString1 = AceType::MakeRefPtr("0123"); + for (int i = 0; i < 5; i++) { + Font f; + f.fontColor = colors[i]; + fonts.emplace_back(f); + if (i != 4) { + spanString1->AddSpan(AceType::MakeRefPtr(f, i, i + 1)); + } + } + auto spanArr = spanString1->GetSpans(0, spanString1->GetLength()); + auto spanString2 = AceType::MakeRefPtr("abc"); + Font f; + f.fontColor = colors[4]; + spanString2->AddSpan(AceType::MakeRefPtr(f, 0, 3)); + spanString1->InsertSpanString(1, spanString2); + std::list> resultList1 = { AceType::MakeRefPtr(fonts[0], 0, 1), + AceType::MakeRefPtr(fonts[4], 1, 4), AceType::MakeRefPtr(fonts[1], 4, 5), + AceType::MakeRefPtr(fonts[2], 5, 6), AceType::MakeRefPtr(fonts[3], 6, 7) }; + auto spanMap = spanString1->GetSpansMap(); + EXPECT_TRUE(CompareSpanList(spanMap[SpanType::Font], resultList1)); + + spanString1->InsertSpanString(0, spanString2); + std::list> resultList2 = { AceType::MakeRefPtr(fonts[4], 0, 3), + AceType::MakeRefPtr(fonts[0], 3, 4), AceType::MakeRefPtr(fonts[4], 4, 7), + AceType::MakeRefPtr(fonts[1], 7, 8), AceType::MakeRefPtr(fonts[2], 8, 9), + AceType::MakeRefPtr(fonts[3], 9, 10) }; + spanMap = spanString1->GetSpansMap(); + EXPECT_TRUE(CompareSpanList(spanMap[SpanType::Font], resultList2)); + + spanString1->ReplaceSpanString(0, 7, spanString2); + std::list> resultList3 = { AceType::MakeRefPtr(fonts[4], 0, 3), + AceType::MakeRefPtr(fonts[1], 3, 4), AceType::MakeRefPtr(fonts[2], 4, 5), + AceType::MakeRefPtr(fonts[3], 5, 6) }; + spanMap = spanString1->GetSpansMap(); + EXPECT_TRUE(CompareSpanList(spanMap[SpanType::Font], resultList3)); + + spanString1->AppendSpanString(spanString2); + std::list> resultList4 = { AceType::MakeRefPtr(fonts[4], 0, 3), + AceType::MakeRefPtr(fonts[1], 3, 4), AceType::MakeRefPtr(fonts[2], 4, 5), + AceType::MakeRefPtr(fonts[3], 5, 6), AceType::MakeRefPtr(fonts[4], 6, 9) }; + spanMap = spanString1->GetSpansMap(); + EXPECT_TRUE(CompareSpanList(spanMap[SpanType::Font], resultList4)); +} +} // namespace OHOS::Ace::NG \ No newline at end of file