diff --git a/test/unittest/core/pattern/rich_editor/rich_editor_change_reason_test.cpp b/test/unittest/core/pattern/rich_editor/rich_editor_change_reason_test.cpp index b94c4eacb26b16a807657062aba5b51bd931f8ec..541c671fcd4c6121274a588dd3fe2d701328085e 100644 --- a/test/unittest/core/pattern/rich_editor/rich_editor_change_reason_test.cpp +++ b/test/unittest/core/pattern/rich_editor/rich_editor_change_reason_test.cpp @@ -237,4 +237,100 @@ HWTEST_F(RichEditorChangeReasonTest, DeleteBackwardForward001, TestSize.Level1) EXPECT_EQ(changeReason, TextChangeReason::INPUT); } +/** + * @tc.name: ControllerAddPlaceholder + * @tc.desc: test AddPlaceholder + * @tc.type: FUNC + */ +HWTEST_F(RichEditorChangeReasonTest, AddPlaceholder001, TestSize.Level1) +{ + RichEditorModelNG richEditorModel; + richEditorModel.Create(); + auto host = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + ASSERT_NE(host, nullptr); + auto richEditorPattern = host->GetPattern(); + ASSERT_NE(richEditorPattern, nullptr); + auto richEditorController = richEditorPattern->GetRichEditorController(); + ASSERT_NE(richEditorController, nullptr); + + auto changeReason = TextChangeReason::UNKNOWN; + auto onWillChange = [&changeReason](const RichEditorChangeValue& changeValue) { + changeReason = changeValue.changeReason_; + return true; + }; + richEditorModel.SetOnWillChange(std::move(onWillChange)); + + richEditorController->AddImageSpan(IMAGE_SPAN_OPTIONS_1); + EXPECT_EQ(changeReason, TextChangeReason::CONTROLLER); + + changeReason = TextChangeReason::UNKNOWN; + auto builderId = ElementRegister::GetInstance()->MakeUniqueId(); + auto builderNode = FrameNode::GetOrCreateFrameNode( + V2::ROW_ETS_TAG, builderId, []() { return AceType::MakeRefPtr(false); }); + richEditorController->AddPlaceholderSpan(builderNode, PLACEHOLDER_SPAN_OPTIONS_1); + EXPECT_EQ(changeReason, TextChangeReason::UNKNOWN); +} + +/** + * @tc.name: ControllerAddAndDeleteSpans + * @tc.desc: test DeleteSpans + * @tc.type: FUNC + */ +HWTEST_F(RichEditorChangeReasonTest, rAddAndDeleteSpans001, TestSize.Level1) +{ + RichEditorModelNG richEditorModel; + richEditorModel.Create(); + auto host = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + ASSERT_NE(host, nullptr); + auto richEditorPattern = host->GetPattern(); + ASSERT_NE(richEditorPattern, nullptr); + auto richEditorController = richEditorPattern->GetRichEditorController(); + ASSERT_NE(richEditorController, nullptr); + + auto changeReason = TextChangeReason::UNKNOWN; + auto onWillChange = [&changeReason](const RichEditorChangeValue& changeValue) { + changeReason = changeValue.changeReason_; + return true; + }; + richEditorModel.SetOnWillChange(std::move(onWillChange)); + + richEditorController->AddImageSpan(IMAGE_SPAN_OPTIONS_1); + EXPECT_EQ(changeReason, TextChangeReason::CONTROLLER); + + changeReason = TextChangeReason::UNKNOWN; + richEditorController->AddSymbolSpan(SYMBOL_SPAN_OPTIONS_1); + EXPECT_EQ(changeReason, TextChangeReason::CONTROLLER); + + changeReason = TextChangeReason::UNKNOWN; + richEditorPattern->DeleteBackward(2); + EXPECT_EQ(changeReason, TextChangeReason::INPUT); + + changeReason = TextChangeReason::UNKNOWN; + richEditorController->AddTextSpan(TEXT_SPAN_OPTIONS_1); + EXPECT_EQ(changeReason, TextChangeReason::CONTROLLER); + + changeReason = TextChangeReason::UNKNOWN; + richEditorController->AddTextSpan(TEXT_SPAN_OPTIONS_2); + EXPECT_EQ(changeReason, TextChangeReason::CONTROLLER); + + changeReason = TextChangeReason::UNKNOWN; + auto builderId = ElementRegister::GetInstance()->MakeUniqueId(); + auto builderNode = FrameNode::GetOrCreateFrameNode( + V2::ROW_ETS_TAG, builderId, []() { return AceType::MakeRefPtr(false); }); + richEditorController->AddPlaceholderSpan(builderNode, PLACEHOLDER_SPAN_OPTIONS_1); + EXPECT_EQ(changeReason, TextChangeReason::UNKNOWN); + + changeReason = TextChangeReason::UNKNOWN; + richEditorPattern->DeleteRange(0, 1, true); + EXPECT_EQ(changeReason, TextChangeReason::INPUT); + + richEditorModel.SetOnWillChange(std::move(onWillChange)); + changeReason = TextChangeReason::UNKNOWN; + richEditorPattern->HandleOnDelete(false); + EXPECT_EQ(changeReason, TextChangeReason::INPUT); + + changeReason = TextChangeReason::UNKNOWN; + richEditorPattern->DeleteForward(1); + EXPECT_EQ(changeReason, TextChangeReason::INPUT); +} } \ No newline at end of file diff --git a/test/unittest/core/pattern/rich_editor/rich_editor_common_test_ng.h b/test/unittest/core/pattern/rich_editor/rich_editor_common_test_ng.h index f5b4a892e818098522dd3cfd493c033a54094deb..b14a7eef52015cb266ba4b1608181d03bdb68e0b 100644 --- a/test/unittest/core/pattern/rich_editor/rich_editor_common_test_ng.h +++ b/test/unittest/core/pattern/rich_editor/rich_editor_common_test_ng.h @@ -99,6 +99,7 @@ const TextStyle TEXT_STYLE_1(10.0); const TextStyle TEXT_STYLE_2(20.0); const TextStyle TEXT_STYLE_3(30.0); const TextSpanOptions TEXT_SPAN_OPTIONS_1 = { .value = INIT_VALUE_1, .style = TEXT_STYLE_1 }; +const TextSpanOptions TEXT_SPAN_OPTIONS_2 = { .value = INIT_VALUE_2, .style = TEXT_STYLE_2 }; const float LINE_THICKNESS_SCALE = 1.5f; const ImageSpanAttribute IMAGE_SPAN_ATTRIBUTE_1 = { .size = ImageSpanSize{ .width = 200.0_px, .height = 100.0_px }, @@ -122,6 +123,12 @@ const SymbolSpanOptions SYMBOL_SPAN_OPTIONS_1 = { .style = TEXT_STYLE_1, .resourceObject = nullptr }; +const SpanOptionBase PLACEHOLDER_SPAN_OPTIONS_1 = { + .offset = std::nullopt, + .dragBackgroundColor = Color::BLACK, + .isDragShadowNeeded = false, + .optionSource = OptionSource::UNDO_REDO +}; } // namespace struct TestCursorItem { diff --git a/test/unittest/core/pattern/rich_editor/rich_editor_layout_test_ng.cpp b/test/unittest/core/pattern/rich_editor/rich_editor_layout_test_ng.cpp index ecaf83edb3f9fae08c73232868430c5eb36055f0..329b85d94735e50489f71b0c09e24cee453b2ee1 100644 --- a/test/unittest/core/pattern/rich_editor/rich_editor_layout_test_ng.cpp +++ b/test/unittest/core/pattern/rich_editor/rich_editor_layout_test_ng.cpp @@ -661,5 +661,164 @@ HWTEST_F(RichEditorLayoutTestNg, OnDirtyLayoutWrapperSwap001, TestSize.Level1) auto ret = richEditorPattern->OnDirtyLayoutWrapperSwap(layoutWrapper, config); EXPECT_FALSE(ret); } + +/** + * @tc.name: HandleAISpanTest002 + * @tc.desc: test call HandleAISpanTest for double times + * @tc.type: FUNC + */ +HWTEST_F(RichEditorLayoutTestNg, HandleAISpanTest002, TestSize.Level1) +{ + ASSERT_NE(richEditorNode_, nullptr); + auto richEditorPattern = richEditorNode_->GetPattern(); + ASSERT_NE(richEditorPattern, nullptr); + auto layoutAlgorithm = AceType::DynamicCast(richEditorPattern->CreateLayoutAlgorithm()); + ASSERT_NE(layoutAlgorithm, nullptr); + std::list> spans; + auto spanItem1 = AceType::MakeRefPtr(); + spanItem1->rangeStart = 0; + spanItem1->position = 5; + + auto spanItem2 = AceType::MakeRefPtr(); + spanItem2->rangeStart = 5; + spanItem2->position = 10; + + auto spanItem3 = AceType::MakeRefPtr(); + spanItem3->rangeStart = 10; + spanItem3->position = 15; + + auto spanItem4 = AceType::MakeRefPtr(); + spanItem4->rangeStart = 15; + spanItem4->position = 20; + + spans.push_back(spanItem1); + spans.push_back(spanItem2); + spans.push_back(spanItem3); + spans.push_back(spanItem4); + + std::map aiSpanMap1 = { { 8, { 8, 12 } } }; + std::map aiSpanMap2 = { { 4, { 4, 7 } } }; + AISpanLayoutInfo aiSpanLayoutInfo1{ aiSpanMap1, true }; + AISpanLayoutInfo aiSpanLayoutInfo2{ aiSpanMap2, true }; + // span:[0-5][5-10][10-15][15-20] + layoutAlgorithm->HandleAISpan(spans, aiSpanLayoutInfo1); + EXPECT_EQ(spanItem1->aiSpanResultCount, 0); + EXPECT_EQ(spanItem2->aiSpanResultCount, 1); + EXPECT_EQ(spanItem3->aiSpanResultCount, 1); + EXPECT_EQ(spanItem4->aiSpanResultCount, 0); + + EXPECT_EQ(spanItem1->needReLayout, false); + EXPECT_EQ(spanItem2->needReLayout, true); + EXPECT_EQ(spanItem3->needReLayout, true); + EXPECT_EQ(spanItem4->needReLayout, false); + + layoutAlgorithm->HandleAISpan(spans, aiSpanLayoutInfo2); + EXPECT_EQ(spanItem1->aiSpanResultCount, 1); + EXPECT_EQ(spanItem2->aiSpanResultCount, 1); + EXPECT_EQ(spanItem3->aiSpanResultCount, 0); + EXPECT_EQ(spanItem4->aiSpanResultCount, 0); + + EXPECT_EQ(spanItem1->needReLayout, true); + EXPECT_EQ(spanItem2->needReLayout, true); + EXPECT_EQ(spanItem3->needReLayout, true); + EXPECT_EQ(spanItem4->needReLayout, false); +} + +/** + * @tc.name: HandleAISpanTest003 + * @tc.desc: test call HandleAISpanTest several times + * @tc.type: FUNC + */ +HWTEST_F(RichEditorLayoutTestNg, HandleAISpanTest003, TestSize.Level1) +{ + ASSERT_NE(richEditorNode_, nullptr); + auto richEditorPattern = richEditorNode_->GetPattern(); + ASSERT_NE(richEditorPattern, nullptr); + auto layoutAlgorithm = AceType::DynamicCast(richEditorPattern->CreateLayoutAlgorithm()); + ASSERT_NE(layoutAlgorithm, nullptr); + std::list> spans; + auto spanItem1 = AceType::MakeRefPtr(); + spanItem1->rangeStart = 0; + spanItem1->position = 5; + + auto spanItem2 = AceType::MakeRefPtr(); + spanItem2->rangeStart = 5; + spanItem2->position = 10; + + auto spanItem3 = AceType::MakeRefPtr(); + spanItem3->rangeStart = 10; + spanItem3->position = 15; + + auto spanItem4 = AceType::MakeRefPtr(); + spanItem4->rangeStart = 15; + spanItem4->position = 20; + + spans.push_back(spanItem1); + spans.push_back(spanItem2); + spans.push_back(spanItem3); + spans.push_back(spanItem4); + + std::map aiSpanMap1 = { { 4, { 4, 14 } } }; + std::map aiSpanMap2 = { { 14, { 14, 18 } } }; + std::map aiSpanMap3 = { { 7, { 7, 9 } } }; + AISpanLayoutInfo aiSpanLayoutInfo1{ aiSpanMap1, true }; + AISpanLayoutInfo aiSpanLayoutInfo2{ aiSpanMap2, true }; + AISpanLayoutInfo aiSpanLayoutInfo3{ aiSpanMap3, true }; + // span:[0-5][5-10][10-15][15-20] + layoutAlgorithm->HandleAISpan(spans, aiSpanLayoutInfo1); + layoutAlgorithm->HandleAISpan(spans, aiSpanLayoutInfo2); + layoutAlgorithm->HandleAISpan(spans, aiSpanLayoutInfo3); + EXPECT_EQ(spanItem1->aiSpanResultCount, 0); + EXPECT_EQ(spanItem2->aiSpanResultCount, 1); + EXPECT_EQ(spanItem3->aiSpanResultCount, 0); + EXPECT_EQ(spanItem4->aiSpanResultCount, 0); + + EXPECT_EQ(spanItem1->needReLayout, true); + EXPECT_EQ(spanItem2->needReLayout, true); + EXPECT_EQ(spanItem3->needReLayout, true); + EXPECT_EQ(spanItem4->needReLayout, true); +} + +/** + * @tc.name: HandleAISpanTest004 + * @tc.desc: test HandleAISpanTest + * @tc.type: FUNC + */ +HWTEST_F(RichEditorLayoutTestNg, HandleAISpanTest004, TestSize.Level1) +{ + ASSERT_NE(richEditorNode_, nullptr); + auto richEditorPattern = richEditorNode_->GetPattern(); + ASSERT_NE(richEditorPattern, nullptr); + auto layoutAlgorithm = AceType::DynamicCast(richEditorPattern->CreateLayoutAlgorithm()); + ASSERT_NE(layoutAlgorithm, nullptr); + std::list> spans; + auto spanItem1 = AceType::MakeRefPtr(); + spanItem1->rangeStart = 0; + spanItem1->position = 10; + + auto spanItem2 = AceType::MakeRefPtr(); + spanItem2->rangeStart = 10; + spanItem2->position = 20; + + auto spanItem3 = AceType::MakeRefPtr(); + spanItem3->rangeStart = 20; + spanItem3->position = 30; + + spans.push_back(spanItem1); + spans.push_back(spanItem2); + spans.push_back(spanItem3); + + std::map aiSpanMap = { { 8, { 8, 12 } } }; + AISpanLayoutInfo aiSpanLayoutInfo{ aiSpanMap, false }; + // span:[0-10][10-20][20-30] + layoutAlgorithm->HandleAISpan(spans, aiSpanLayoutInfo); + EXPECT_EQ(spanItem1->aiSpanResultCount, 0); + EXPECT_EQ(spanItem2->aiSpanResultCount, 0); + EXPECT_EQ(spanItem3->aiSpanResultCount, 0); + + EXPECT_EQ(spanItem1->needReLayout, false); + EXPECT_EQ(spanItem2->needReLayout, false); + EXPECT_EQ(spanItem3->needReLayout, false); +} } // namespace OHOS::Ace::NG diff --git a/test/unittest/core/pattern/text/text_testten_ng.cpp b/test/unittest/core/pattern/text/text_testten_ng.cpp index 249e34e802eaee188e1635b605c55e6594a0c159..4d02f374a84dfc0f6d82ec9103a68013c87361ea 100644 --- a/test/unittest/core/pattern/text/text_testten_ng.cpp +++ b/test/unittest/core/pattern/text/text_testten_ng.cpp @@ -1969,6 +1969,58 @@ HWTEST_F(TextFieldTenPatternNg, CreateTextDragInfo001, TestSize.Level1) EXPECT_NE(ret.secondHandle, paintRect2); } +/** + * @tc.name: CreateTextDragInfo002 + * @tc.desc: test CreateTextDragInfo when ai is not selected + * @tc.type: FUNC + */ +HWTEST_F(TextFieldTenPatternNg, CreateTextDragInfo002, TestSize.Level1) { + auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXTINPUT_ETS_TAG, + ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr(); }); + RefPtr pattern = textNode->GetPattern(); + auto frameNode = FrameNode::CreateFrameNode("Test", 1, pattern); + RefPtr mockBase = AIWriteAdapter::MakeRefPtr(); + WeakPtr textBase = mockBase; + pattern->selectOverlay_ = AceType::MakeRefPtr(textBase); + + auto manager = AceType::MakeRefPtr(textNode); + pattern->selectOverlay_->OnBind(manager); + pattern->selectOverlay_->ToggleMenu(); + pattern->AttachToFrameNode(frameNode); + pattern->textSelector_.aiStart = std::nullopt; + pattern->textSelector_.aiEnd = std::nullopt; + + auto info = pattern->CreateTextDragInfo(); + EXPECT_EQ(info.isFirstHandleAnimation, true); + EXPECT_EQ(info.isSecondHandleAnimation, true); +} + +/** + * @tc.name: CreateTextDragInfo003 + * @tc.desc: test CreateTextDragInfo when ai is selected + * @tc.type: FUNC + */ +HWTEST_F(TextFieldTenPatternNg, CreateTextDragInfo003, TestSize.Level1) { + auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXTINPUT_ETS_TAG, + ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr(); }); + RefPtr pattern = textNode->GetPattern(); + auto frameNode = FrameNode::CreateFrameNode("Test", 1, pattern); + RefPtr mockBase = AIWriteAdapter::MakeRefPtr(); + WeakPtr textBase = mockBase; + pattern->selectOverlay_ = AceType::MakeRefPtr(textBase); + + auto manager = AceType::MakeRefPtr(textNode); + pattern->selectOverlay_->OnBind(manager); + pattern->selectOverlay_->ToggleMenu(); + pattern->AttachToFrameNode(frameNode); + pattern->textSelector_.aiStart = 1; + pattern->textSelector_.aiEnd = 2; + + auto info = pattern->CreateTextDragInfo(); + EXPECT_EQ(info.isFirstHandleAnimation, false); + EXPECT_EQ(info.isSecondHandleAnimation, false); +} + /** * @tc.name: GetUrlSpanColor001 * @tc.desc: test GetUrlSpanColor