1 /* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "test/unittest/adapter/ohos/capability/convert_test_tools.h" 17 18 #undef private 19 #undef protected 20 21 using namespace testing; 22 using namespace testing::ext; 23 namespace OHOS::Ace::NG { 24 25 namespace { 26 std::string testStr[] = { "hello", "world", "this", "find", "gank", "pink", "that", "when", "how", "cpp" }; 27 Font testFont1 { OHOS::Ace::FontWeight::BOLD, Dimension(29.0, DimensionUnit::PX), OHOS::Ace::FontStyle::ITALIC, 28 std::vector<std::string>(testStr, testStr + 10), OHOS::Ace::Color::BLUE }; 29 Font testFont2 { OHOS::Ace::FontWeight::LIGHTER, Dimension(19.0, DimensionUnit::PX), OHOS::Ace::FontStyle::ITALIC, 30 std::vector<std::string>(testStr, testStr + 10), OHOS::Ace::Color::GRAY }; 31 Font testEmptyFont {}; 32 } 33 34 /** 35 * @tc.name: SpanStringConvert000 36 * @tc.desc: This test case checks the conversion of a SpanString containing a mixture of different 37 * spans including font, letter spacing, baseline offset, text decoration, text shadow, 38 * and paragraph styles. It ensures that all styles are applied correctly and the conversion 39 * between HTML and SpanString is accurate. 40 * @tc.level: 1 41 */ 42 HWTEST_F(HtmlConvertTestNg, SpanStringConvert000, TestSize.Level1) 43 { 44 /** 45 * @tc.steps1: Initialize a mutable SpanString with an image option and create a SpanString with 46 * mixed styles (font, letter spacing, baseline offset, text decoration, etc.). 47 * @tc.expected: The SpanString should properly handle different types of spans and apply them correctly. 48 */ 49 auto imageOption = GetImageOption("src/icon-1.png"); 50 auto mutableStr = AceType::MakeRefPtr<MutableSpanString>(imageOption); 51 auto spanString3 = AceType::MakeRefPtr<SpanString>(u"012345678\n9"); 52 53 // Add font spans with different font styles 54 spanString3->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont1, 0, 3)); 55 spanString3->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont2, 3, 5)); 56 spanString3->AddSpan(AceType::MakeRefPtr<FontSpan>(testEmptyFont, 5, 8)); 57 58 // Add baseline offset span 59 spanString3->AddSpan(AceType::MakeRefPtr<BaselineOffsetSpan>(Dimension(4), 0, 2)); 60 61 // Add letter spacing span 62 spanString3->AddSpan(AceType::MakeRefPtr<LetterSpacingSpan>(Dimension(5), 5, 8)); 63 64 // Add text decoration (line through) span 65 // change Test by search MakeRefPtr<DecorationSpan> 66 spanString3->AddSpan(AceType::MakeRefPtr<DecorationSpan>( 67 std::vector<TextDecoration>({TextDecoration::LINE_THROUGH}), Color::BLUE, 68 TextDecorationStyle::WAVY, std::optional<TextDecorationOptions>(), 0, 1)); 69 70 // Add paragraph style span 71 auto spanParagraphStyle = GetDefaultParagraphStyle(); 72 auto paraSpan = AceType::MakeRefPtr<ParagraphStyleSpan>(spanParagraphStyle, 2, 5); 73 spanString3->AddSpan(paraSpan); 74 75 // Add text shadow spans 76 Shadow textShadow; 77 textShadow.SetBlurRadius(0.0); 78 textShadow.SetColor(Color::BLUE); 79 textShadow.SetOffsetX(5.0); 80 textShadow.SetOffsetY(5.0); 81 82 Shadow textShadow1; 83 textShadow1.SetBlurRadius(1.0); 84 textShadow1.SetColor(Color::BLUE); 85 textShadow1.SetOffsetX(10.0); 86 textShadow1.SetOffsetY(10.0); 87 88 vector<Shadow> textShadows { textShadow, textShadow1 }; 89 spanString3->AddSpan(AceType::MakeRefPtr<TextShadowSpan>(textShadows, 3, 6)); 90 91 // Insert the span string into the mutable string 92 mutableStr->InsertSpanString(1, spanString3); 93 94 /** 95 * @tc.steps2: Create another SpanString with Chinese text, add font spans, letter spacing, 96 * and insert it into the mutable string. 97 * @tc.expected: The second span string should be properly inserted and apply the added styles correctly. 98 */ 99 auto spanString2 = AceType::MakeRefPtr<SpanString>(u"测试一下中文,\n看看是什么情况"); 100 spanString2->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont1, 0, 5)); 101 spanString2->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont2, 6, 10)); 102 spanString2->AddSpan(AceType::MakeRefPtr<LetterSpacingSpan>(Dimension(10), 12, 14)); 103 104 // Insert this new SpanString into the mutable string 105 mutableStr->InsertSpanString(5, spanString2); 106 107 /** 108 * @tc.steps3: Convert the mutable SpanString to HTML using the SpanToHtml converter. 109 * @tc.expected: The HTML conversion should preserve all the added spans and their properties. 110 */ 111 SpanToHtml convert; 112 auto out = convert.ToHtml(*mutableStr); 113 114 /** 115 * @tc.steps4: Convert the resulting HTML back to a SpanString and validate the number of span items. 116 * @tc.expected: The number of span items should match the total number of spans added. 117 */ 118 HtmlToSpan toSpan; 119 auto dstSpan = toSpan.ToSpanString(out); 120 EXPECT_NE(dstSpan, nullptr); 121 auto items = dstSpan->GetSpanItems(); 122 EXPECT_EQ(items.size(), 17); 123 } 124 125 /** 126 * @tc.name: SpanStringConvert001 127 * @tc.desc: This test case verifies the conversion of a `SpanString` object to HTML and 128 * back from HTML to `SpanString`. 129 * It ensures that the content and structure are preserved during the entire conversion process. 130 * @tc.level: 1 131 */ 132 HWTEST_F(HtmlConvertTestNg, SpanStringConvert001, TestSize.Level1) 133 { 134 /** 135 * @tc.steps1: Initialize parameters and create a `SpanString` object, adding different font style spans. 136 * Each span represents a substring with a specific style (e.g., font, size, etc.). 137 * @tc.expected: The `SpanString` object should be correctly initialized with the given content and spans. 138 */ 139 auto spanString = AceType::MakeRefPtr<SpanString>(u"0123456789"); 140 141 // Adding FontSpans with different fonts to the spanString 142 spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont1, 0, 3)); 143 spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont2, 3, 5)); 144 spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testEmptyFont, 5, 8)); 145 146 /** 147 * @tc.steps2: Call the `ToHtml` function to convert the `SpanString` object to an HTML string. 148 * First, use `EncodeTlv` method to convert the content into a byte buffer. 149 * @tc.expected: `u8ToHtml` should be a non-empty string representing the successful HTML conversion. 150 */ 151 std::vector<uint8_t> buffer; 152 spanString->EncodeTlv(buffer); 153 154 SpanToHtml convert; 155 auto u8ToHtml = convert.ToHtml(buffer); 156 EXPECT_NE(u8ToHtml.empty(), true); 157 158 // Directly convert `SpanString` to HTML string 159 auto out = convert.ToHtml(*spanString); 160 EXPECT_NE(out.empty(), true); 161 EXPECT_EQ(out, u8ToHtml); 162 163 /** 164 * @tc.steps3: Call the `ToSpanString` function to convert the HTML string back to a `SpanString` object. 165 * @tc.expected: The `ToSpanString` function should successfully convert the HTML back to a `SpanString`. 166 */ 167 HtmlToSpan toSpan; 168 auto dstSpan = toSpan.ToSpanString(out); // Convert the HTML string back to a SpanString 169 EXPECT_NE(dstSpan, nullptr); // Expect the returned SpanString to be non-null 170 171 // Get the SpanItems from the converted `SpanString` 172 auto items = dstSpan->GetSpanItems(); 173 EXPECT_EQ(items.size(), 4); // Expect the number of SpanItems to be 4, as there were 4 FontSpans added 174 175 /** 176 * @tc.steps4: Verify that the number of SpanItems in the original `SpanString` matches the converted `SpanString`. 177 * @tc.expected: The number of SpanItems in the original `SpanString` and the converted `SpanString` be the same. 178 */ 179 EXPECT_EQ(items.size(), spanString->GetSpanItems().size()); 180 } 181 182 /** 183 * @tc.name: SpanStringConvert002 184 * @tc.desc: This test case checks the HTML conversion when special HTML tags like `<strong>`, `<del>`, 185 * and inline styles are used. It verifies that these elements are correctly converted to 186 * `SpanString` and back to HTML. 187 * @tc.level: 1 188 */ 189 HWTEST_F(HtmlConvertTestNg, SpanStringConvert002, TestSize.Level1) 190 { 191 /** 192 * @tc.steps1: Initialize HTML string containing special tags and inline styles. 193 * @tc.expected: The HTML should be properly formatted and support special tags like `<strong>`, `<del>`, etc. 194 */ 195 const std::string fontHtml = 196 "<html>\n" 197 "<body>\n" 198 "<p>\n" 199 "<strong>Important Text</strong>\n" 200 "<del>Deleted Text</del>\n" 201 "</p>\n" 202 "</body>\n" 203 "</html>\n"; 204 205 /** 206 * @tc.steps2: Convert the HTML string to `SpanString`. 207 * @tc.expected: The conversion should result in a valid `SpanString` with correct `SpanItems` for the tags. 208 */ 209 HtmlToSpan toSpan; 210 auto dstSpan = toSpan.ToSpanString(fontHtml); 211 EXPECT_NE(dstSpan, nullptr); 212 auto items = dstSpan->GetSpanItems(); 213 EXPECT_GT(items.size(), 0); 214 215 /** 216 * @tc.steps3: Convert the `SpanString` back to HTML and verify the result matches the original HTML. 217 * @tc.expected: Verify that the outHtml's size is not empty. 218 */ 219 SpanToHtml convert; 220 auto outHtml = convert.ToHtml(*dstSpan); 221 EXPECT_GT(outHtml.size(), 0); 222 } 223 224 /** 225 * @tc.name: SpanStringConvert003 226 * @tc.desc: This test case checks the conversion when complex inline styles are applied to text. 227 * It ensures that the font styles, color, and size are properly handled during the conversion. 228 * @tc.level: 1 229 */ 230 HWTEST_F(HtmlConvertTestNg, SpanStringConvert003, TestSize.Level1) 231 { 232 /** 233 * @tc.steps1: Initialize HTML string with complex inline styles (font size, color, and weight). 234 * @tc.expected: The HTML should contain the correct inline styles for each text element. 235 */ 236 const std::string complexHtml = 237 "<html>\n" 238 "<body>\n" 239 "<p style=\"font-size:20px; color:red; font-weight:bold;\">\n" 240 "Styled Text\n" 241 "</p>\n" 242 "</body>\n" 243 "</html>\n"; 244 245 /** 246 * @tc.steps2: Convert the HTML string to `SpanString`. 247 * @tc.expected: The conversion should parse the inline styles correctly and convert them into `FontSpan` objects. 248 */ 249 HtmlToSpan toSpan; 250 auto dstSpan = toSpan.ToSpanString(complexHtml); 251 EXPECT_NE(dstSpan, nullptr); 252 253 // Verify that the SpanItems reflect the correct styles (e.g., size, color, and weight) 254 auto items = dstSpan->GetSpanItems(); 255 EXPECT_GT(items.size(), 0); 256 257 /** 258 * @tc.steps3: Convert the `SpanString` back to HTML and ensure the inline styles are retained. 259 * @tc.expected: Verify that the outHtml's size is not empty. 260 */ 261 SpanToHtml convert; 262 auto outHtml = convert.ToHtml(*dstSpan); 263 EXPECT_GT(outHtml.size(), 0); 264 } 265 266 /** 267 * @tc.name: SpanStringConvert004 268 * @tc.desc: This test case verifies the behavior when converting HTML with embedded spans and complex inline elements. 269 * It ensures that nested HTML elements like `<span>` are handled correctly during the conversion process. 270 * @tc.level: 1 271 */ 272 HWTEST_F(HtmlConvertTestNg, SpanStringConvert004, TestSize.Level1) 273 { 274 /** 275 * @tc.steps1: Initialize HTML string with nested `<span>` tags and inline styles. 276 * @tc.expected: The HTML should contain nested spans with different styles. 277 */ 278 const std::string nestedHtml = "<html>\n" 279 "<body>\n" 280 "<p>\n" 281 "<span style=\"color:blue;\">Blue Text</span>\n" 282 "<span style=\"color:red;\">Red Text</span>\n" 283 "</p>\n" 284 "</body>\n" 285 "</html>"; 286 /** 287 * @tc.steps2: Convert the HTML string to `SpanString`. 288 * @tc.expected: The conversion should properly handle nested spans and inline styles. 289 */ 290 HtmlToSpan toSpan; 291 auto dstSpan = toSpan.ToSpanString(nestedHtml); 292 EXPECT_NE(dstSpan, nullptr); 293 294 // Verify that the SpanItems reflect the correct styles for each span 295 auto items = dstSpan->GetSpanItems(); 296 EXPECT_GT(items.size(), 0); 297 298 /** 299 * @tc.steps3: Convert the `SpanString` back to HTML and ensure that nested spans are correctly retained. 300 * @tc.expected: Verify that the outHtml's size is not empty. 301 */ 302 SpanToHtml convert; 303 auto outHtml = convert.ToHtml(*dstSpan); 304 EXPECT_GT(outHtml.size(), 0); 305 } 306 307 /** 308 * @tc.name: SpanStringConvert005 309 * @tc.desc: This test case checks the behavior when HTML contains elements with different text alignment properties. 310 * It verifies that text alignment properties like `text-align` are properly converted and maintained. 311 * @tc.level: 1 312 */ 313 HWTEST_F(HtmlConvertTestNg, SpanStringConvert005, TestSize.Level1) 314 { 315 /** 316 * @tc.steps1: Initialize HTML string with different text alignments (center, left, right). 317 * @tc.expected: The HTML should contain proper alignment properties for each element. 318 */ 319 const std::string alignmentHtml = "<html>\n" 320 "<body>\n" 321 "<p style=\"text-align:center;\">Centered Text</p>\n" 322 "<p style=\"text-align:left;\">Left Aligned Text</p>\n" 323 "<p style=\"text-align:right;\">Right Aligned Text</p>\n" 324 "</body>\n" 325 "</html>"; 326 /** 327 * @tc.steps2: Convert the HTML string to `SpanString`. 328 * @tc.expected: The conversion should properly handle text alignment properties for each text block. 329 */ 330 HtmlToSpan toSpan; 331 auto dstSpan = toSpan.ToSpanString(alignmentHtml); 332 EXPECT_NE(dstSpan, nullptr); 333 334 // Verify that the SpanItems reflect the correct alignment for each paragraph 335 auto items = dstSpan->GetSpanItems(); 336 EXPECT_GT(items.size(), 0); 337 338 /** 339 * @tc.steps3: Convert the `SpanString` back to HTML and ensure that text alignment properties are preserved. 340 * @tc.expected: Verify that the outHtml's size is not empty. 341 */ 342 SpanToHtml convert; 343 auto outHtml = convert.ToHtml(*dstSpan); 344 EXPECT_GT(outHtml.size(), 0); 345 } 346 347 /** 348 * @tc.name: SpanStringConvert006 349 * @tc.desc: This test case checks the conversion of a SpanString with multiple font spans and the 350 * encoding/decoding of the span string into HTML and back. It verifies that the correct number 351 * of span items is maintained and that the conversion preserves the span data. 352 * @tc.level: 1 353 */ 354 HWTEST_F(HtmlConvertTestNg, SpanStringConvert006, TestSize.Level1) 355 { 356 /** 357 * @tc.steps1: Initialize a SpanString with a series of font spans (testFont1, testFont2, and testEmptyFont), 358 * each covering different ranges of the string "0123456789". 359 * @tc.expected: Each span should correctly apply its respective font style to the 360 * corresponding range in the string. 361 */ 362 auto spanString = AceType::MakeRefPtr<SpanString>(u"0123456789"); 363 spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont1, 0, 3)); 364 spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont2, 3, 5)); 365 spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testEmptyFont, 5, 8)); 366 367 /** 368 * @tc.steps2: Encode the SpanString into a TLV (Type-Length-Value) format and convert it to HTML. 369 * Check that the resulting HTML is not empty and is properly generated. 370 * @tc.expected: The conversion to HTML should produce a valid output, and the generated HTML should 371 * match the encoded TLV version. 372 */ 373 std::vector<uint8_t> buffer; 374 spanString->EncodeTlv(buffer); 375 SpanToHtml convert; 376 auto u8ToHtml = convert.ToHtml(buffer); 377 EXPECT_NE(u8ToHtml.empty(), true); 378 379 auto out = convert.ToHtml(*spanString); 380 EXPECT_NE(out.empty(), true); 381 EXPECT_EQ(out, u8ToHtml); 382 383 /** 384 * @tc.steps3: Convert the HTML back to a SpanString and validate that the number of span items is correct. 385 * @tc.expected: The number of span items in the resulting SpanString should match the original SpanString. 386 */ 387 HtmlToSpan toSpan; 388 auto dstSpan = toSpan.ToSpanString(out); 389 EXPECT_NE(dstSpan, nullptr); 390 auto items = dstSpan->GetSpanItems(); 391 EXPECT_EQ(items.size(), 4); 392 393 /** 394 * @tc.steps4: Verify that the number of span items in the resulting SpanString matches the original. 395 * @tc.expected: The number of span items in the original SpanString should be the same as in 396 * the converted SpanString. 397 */ 398 EXPECT_EQ(items.size(), spanString->GetSpanItems().size()); 399 } 400 401 /** 402 * @tc.name: SpanStringConvert007 403 * @tc.desc: This test case checks the conversion of a MutableSpanString containing an image span and text. 404 * It tests the handling of image spans during encoding and decoding to ensure proper HTML conversion. 405 * @tc.level: 1 406 */ 407 HWTEST_F(HtmlConvertTestNg, SpanStringConvert007, TestSize.Level1) 408 { 409 /** 410 * @tc.steps1: Create a MutableSpanString with an image span and a text span, and encode the 411 * MutableSpanString to a buffer. 412 * @tc.expected: The image span should be correctly encoded, and the HTML conversion hould match 413 * the expected result. 414 */ 415 auto imageOption = GetImageOption("src/icon-1.png"); 416 auto imageSpan = AceType::MakeRefPtr<MutableSpanString>(imageOption); 417 auto mutableStr2 = AceType::MakeRefPtr<MutableSpanString>(u"123456"); 418 imageSpan->AppendSpanString(mutableStr2); 419 420 std::vector<uint8_t> buffer; 421 imageSpan->EncodeTlv(buffer); 422 423 SpanToHtml convert; 424 auto u8ToHtml = convert.ToHtml(buffer); 425 EXPECT_NE(u8ToHtml.empty(), true); 426 427 auto out = convert.ToHtml(*imageSpan); 428 EXPECT_NE(out.empty(), true); 429 EXPECT_EQ(out, u8ToHtml); 430 431 HtmlToSpan toSpan; 432 auto dstSpan = toSpan.ToSpanString(out); 433 EXPECT_NE(dstSpan, nullptr); 434 435 auto dstHtml = convert.ToHtml(*dstSpan); 436 EXPECT_EQ(out, dstHtml); 437 438 // image is invalid,to html discart image the first char is not black space 439 auto spans = dstSpan->GetSpans(0, 6); 440 EXPECT_EQ(spans.size(), 2); 441 } 442 443 /** 444 * @tc.name: SpanStringConvert008 445 * @tc.desc: This test case checks the conversion of a simple SpanString with basic text color and font size. 446 * It ensures that the span string is correctly converted to HTML with the specified styles. 447 * @tc.level: 1 448 */ 449 HWTEST_F(HtmlConvertTestNg, SpanStringConvert008, TestSize.Level1) 450 { 451 /** 452 * @tc.steps1: Create a SpanString with the text "简单的文本" and apply basic paragraph styles 453 * including text alignment (left), text indent (0), word break (break_word), 454 * and text overflow (clip). 455 * @tc.expected: The generated HTML should include basic font color and size styles. 456 */ 457 auto spanString = AceType::MakeRefPtr<SpanString>(u"this is a normal text Hello WORLD"); 458 SpanParagraphStyle spanParagraphStyle; 459 spanParagraphStyle.align = TextAlign::LEFT; 460 spanParagraphStyle.textIndent = Dimension(0.0_vp); 461 spanParagraphStyle.wordBreak = WordBreak::BREAK_WORD; 462 spanParagraphStyle.textOverflow = TextOverflow::CLIP; 463 spanParagraphStyle.leadingMargin = LeadingMargin(); 464 spanParagraphStyle.leadingMargin->size = LeadingMarginSize(Dimension(10.0_vp), Dimension(12.0)); 465 auto paragraphStyle = AceType::MakeRefPtr<ParagraphStyleSpan>(spanParagraphStyle, 0, 2); 466 spanString->AddSpan(paragraphStyle); 467 468 /** 469 * @tc.steps2: Convert the SpanString to HTML using the SpanToHtml converter. 470 * @tc.expected: The resulting HTML should match the specified span and paragraph styles. 471 */ 472 SpanToHtml convert; 473 auto out = convert.ToHtml(*spanString); 474 std::string result = 475 "<div ><p style=\"word-break: break_word;text-overflow: clip;\"><span style=\"font-size: 16.00px;" 476 "font-style: normal;font-weight: normal;color: #000000FF;font-family: HarmonyOS Sans;" 477 "stroke-width: 0.00px;stroke-color: #000000FF;font-superscript: normal;\">th</span><span " 478 "style=\"font-size: 16.00px;font-style: normal;font-weight: normal;color: #000000FF;font-family: " 479 "HarmonyOS Sans;stroke-width: 0.00px;stroke-color: #000000FF;font-superscript: normal;\">" 480 "is is a normal text Hello WORLD</span></p></div>"; 481 EXPECT_EQ(out, result); 482 } 483 484 /** 485 * @tc.name: SpanStringConvert009 486 * @tc.desc: This test case checks the conversion of a SpanString with text that is aligned to the center 487 * and has an indentation applied. It ensures the HTML conversion reflects the correct text alignment 488 * and indentation. 489 * @tc.level: 1 490 */ 491 HWTEST_F(HtmlConvertTestNg, SpanStringConvert009, TestSize.Level1) 492 { 493 /** 494 * @tc.steps1: Create a SpanString with the text "居中的文本" and apply paragraph styles such as 495 * center alignment, text indentation (20px), word break (break_word), 496 * and text overflow (clip). 497 * @tc.expected: The generated HTML should reflect the correct text alignment (center) and indentation (20px). 498 */ 499 auto spanString = AceType::MakeRefPtr<SpanString>(u"this text with CENTER BREAK_ALL textIndent property"); 500 SpanParagraphStyle spanParagraphStyle; 501 spanParagraphStyle.align = TextAlign::CENTER; 502 spanParagraphStyle.textIndent = Dimension(20.0_vp); 503 spanParagraphStyle.wordBreak = WordBreak::BREAK_ALL; 504 spanParagraphStyle.textOverflow = TextOverflow::CLIP; 505 spanParagraphStyle.leadingMargin = LeadingMargin(); 506 spanParagraphStyle.leadingMargin->size = LeadingMarginSize(Dimension(12.0_vp), Dimension(14.0)); 507 auto paragraphStyle = AceType::MakeRefPtr<ParagraphStyleSpan>(spanParagraphStyle, 0, 5); 508 spanString->AddSpan(paragraphStyle); 509 510 /** 511 * @tc.steps2: Convert the SpanString to HTML using the SpanToHtml converter. 512 * @tc.expected: The resulting HTML should match the specified paragraph and span styles. 513 */ 514 SpanToHtml convert; 515 auto out = convert.ToHtml(*spanString); 516 std::string result = 517 "<div ><p style=\"text-align: center;text-indent: 20.00px;word-break: break_all;text-overflow: clip;\">" 518 "<span style=\"font-size: 16.00px;font-style: normal;font-weight: normal;color: #000000FF;" 519 "font-family: HarmonyOS Sans;stroke-width: 0.00px;stroke-color: #000000FF;font-superscript: normal;\">" 520 "this </span><span style=\"font-size: 16.00px;font-style: normal;font-weight: normal;color: #000000FF;" 521 "font-family: HarmonyOS Sans;stroke-width: 0.00px;stroke-color: #000000FF;font-superscript: normal;\">" 522 "text with CENTER BREAK_ALL textIndent property</span></p></div>"; 523 EXPECT_EQ(out, result); 524 } 525 526 /** 527 * @tc.name: SpanStringConvert010 528 * @tc.desc: This test case checks the conversion of a SpanString with mixed font sizes in the text, 529 * verifying that the HTML conversion applies the correct font sizes to different spans within the same text. 530 * @tc.level: 1 531 */ 532 HWTEST_F(HtmlConvertTestNg, SpanStringConvert010, TestSize.Level1) 533 { 534 /** 535 * @tc.steps1: Create a SpanString with the text "大<span style=\"font-size: 50px;\">小</span>的文本" 536 * and apply appropriate font styles for each span element. 537 * @tc.expected: The HTML should reflect the correct font sizes for each part of the text. 538 */ 539 auto spanString = AceType::MakeRefPtr<SpanString>(u"big 中文混排情况 text"); 540 SpanParagraphStyle spanParagraphStyle; 541 spanParagraphStyle.align = TextAlign::LEFT; 542 spanParagraphStyle.textIndent = Dimension(0.0_vp); 543 spanParagraphStyle.wordBreak = WordBreak::BREAK_WORD; 544 spanParagraphStyle.textOverflow = TextOverflow::CLIP; 545 spanParagraphStyle.leadingMargin = LeadingMargin(); 546 spanParagraphStyle.leadingMargin->size = LeadingMarginSize(Dimension(10.0_vp), Dimension(12.0)); 547 auto paragraphStyle = AceType::MakeRefPtr<ParagraphStyleSpan>(spanParagraphStyle, 0, 7); 548 spanString->AddSpan(paragraphStyle); 549 550 /** 551 * @tc.steps2: Convert the SpanString to HTML using the SpanToHtml converter. 552 * @tc.expected: The HTML should reflect the correct font sizes, with the word "小" being 50px, 553 * while others remain 16px. 554 */ 555 SpanToHtml convert; 556 auto out = convert.ToHtml(*spanString); 557 std::string result = 558 "<div ><p style=\"word-break: break_word;text-overflow: clip;\"><span style=\"font-size: 16.00px;" 559 "font-style: normal;font-weight: normal;color: #000000FF;font-family: HarmonyOS Sans;" 560 "stroke-width: 0.00px;stroke-color: #000000FF;font-superscript: normal;\">big " 561 "\xE4\xB8\xAD\xE6\x96\x87\xE6\xB7\xB7</span><span style=\"font-size: 16.00px;font-style: normal;" 562 "font-weight: normal;color: #000000FF;font-family: HarmonyOS Sans;stroke-width: 0.00px;" 563 "stroke-color: #000000FF;font-superscript: normal;\">\xE6\x8E\x92\xE6\x83\x85\xE5\x86\xB5 text" 564 "</span></p></div>"; // xE4 etc is corresponding Chinese 565 EXPECT_EQ(out, result); 566 } 567 568 /** 569 * @tc.name: SpanStringConvert011 570 * @tc.desc: This test case checks the conversion of a SpanString with mixed text styles including font size, 571 * text shadow, and alignment. It ensures that the HTML conversion applies the correct styles 572 * for both the paragraph and the individual spans. 573 * @tc.level: 1 574 */ 575 HWTEST_F(HtmlConvertTestNg, SpanStringConvert011, TestSize.Level1) 576 { 577 /** 578 * @tc.steps1: Create a SpanString and apply complex paragraph styles and nested text shadow within the span. 579 * @tc.expected: The HTML should reflect the correct styles including text shadow for the nested span. 580 */ 581 auto spanString = AceType::MakeRefPtr<SpanString> 582 (u"complext text span style= font size: 40px;text shadow: 0 0 3px red; shadow span "); 583 SpanParagraphStyle spanParagraphStyle; 584 spanParagraphStyle.align = TextAlign::START; 585 spanParagraphStyle.textIndent = Dimension(10.0_vp); 586 spanParagraphStyle.wordBreak = WordBreak::HYPHENATION; 587 spanParagraphStyle.textOverflow = TextOverflow::DEFAULT; 588 spanParagraphStyle.leadingMargin = LeadingMargin(); 589 spanParagraphStyle.leadingMargin->size = LeadingMarginSize(Dimension(20.0_vp), Dimension(30.0)); 590 auto paragraphStyle = AceType::MakeRefPtr<ParagraphStyleSpan>(spanParagraphStyle, 0, 7); 591 spanString->AddSpan(paragraphStyle); 592 593 /** 594 * @tc.steps2: Convert the SpanString to HTML using the SpanToHtml converter. 595 * @tc.expected: The resulting HTML should include the correct text shadow and font size styles. 596 */ 597 SpanToHtml convert; 598 auto out = convert.ToHtml(*spanString); 599 std::string result = 600 "<div ><p style=\"text-align: start;text-indent: 10.00px;\"><span style=\"font-size: 16.00px;" 601 "font-style: normal;font-weight: normal;color: #000000FF;font-family: HarmonyOS Sans;" 602 "stroke-width: 0.00px;stroke-color: #000000FF;font-superscript: normal;\">complex</span>" 603 "<span style=\"font-size: 16.00px;font-style: normal;font-weight: normal;color: #000000FF;" 604 "font-family: HarmonyOS Sans;stroke-width: 0.00px;stroke-color: #000000FF;font-superscript: " 605 "normal;\">t text span style= font size: 40px;text shadow: 0 0 3px red; shadow span </span></p></div>"; 606 EXPECT_EQ(out, result); 607 } 608 609 /** 610 * @tc.name: SpanStringConvert012 611 * @tc.desc: This test case checks the conversion of a complex HTML string with various font styles, 612 * including colors, font-family, font-size, and nested elements like strong and del tags. 613 * It verifies that the HTML is correctly parsed and converted back to a SpanString. 614 * @tc.level: 1 615 */ 616 HWTEST_F(HtmlConvertTestNg, SpanStringConvert012, TestSize.Level1) 617 { 618 /** 619 * @tc.steps1: Create a complex HTML string with various font styles and elements. Convert it to SpanString. 620 * @tc.expected: The SpanString should correctly represent the HTML content and its styles. 621 */ 622 const std::string fontHtml = "<!DOCTYPE html>" 623 "<html>" 624 "<body>" 625 "<p>我是正常的</p>" 626 "<p style=\"COLOR:red;\">我是红色的</p>" 627 "<p style=\"font-family: 'Times New Roman', serif; font-size: 14px; font-weight: " 628 "normal; color: red; color: blue;\">我是蓝色的<strong style=\"color:blue; " 629 "font-size:100px;\">这段文字很重要!</strong><del>蓝色</del></p>" 630 "<p style=\"font-size:50px;\">我是50的</p>" 631 "</body>" 632 "</html>"; 633 HtmlToSpan toSpan; 634 auto dstSpan = toSpan.ToSpanString(fontHtml); 635 EXPECT_NE(dstSpan, nullptr); 636 637 SpanToHtml convert; 638 auto dstHtml = convert.ToHtml(*dstSpan); 639 HtmlToSpan toSpan1; 640 auto dstSpan1 = toSpan1.ToSpanString(dstHtml); 641 EXPECT_EQ(IsSpanItemSame(dstSpan->GetSpanItems(), dstSpan1->GetSpanItems()), true); 642 auto secondHtml = convert.ToHtml(*dstSpan1); 643 EXPECT_EQ(secondHtml, dstHtml); 644 } 645 646 /** 647 * @tc.name: SpanStringConvert013 648 * @tc.desc: This test case checks the encoding and decoding of a simple SpanString with both English and Chinese. 649 * It verifies that no information is lost during the encoding and decoding process. 650 * @tc.level: 1 651 */ 652 HWTEST_F(HtmlConvertTestNg, SpanStringConvert013, TestSize.Level1) 653 { 654 /** 655 * @tc.steps1: Create a SpanString with mixed English and Chinese characters, and encode it to a buffer. 656 * Convert the buffer to HTML and then convert it back to SpanString. 657 * Finally, compare the original SpanString with the decoded SpanString. 658 * @tc.expected: The original SpanString and the decoded SpanString should be identical. 659 */ 660 auto spanString = AceType::MakeRefPtr<SpanString>(u"01234中文56789"); 661 std::vector<uint8_t> buff; 662 spanString->EncodeTlv(buff); 663 EXPECT_EQ(buff.size() > 0, true); 664 SpanToHtml toHtml; 665 auto htmlFromU8 = toHtml.ToHtml(buff); 666 auto htmlFromSpan = toHtml.ToHtml(*spanString); // 如果一致,说明编码和解码过程中没有丢失信息。 667 EXPECT_EQ(htmlFromU8, htmlFromSpan); 668 669 HtmlToSpan toSpan; 670 auto spanFromHtml = toSpan.ToSpanString(htmlFromU8); 671 EXPECT_EQ(IsSpanItemSame(spanFromHtml->GetSpanItems(), spanString->GetSpanItems()), true); 672 673 SpanToHtml toHtml1; 674 auto hmtlString = toHtml1.ToHtml(*spanFromHtml); 675 EXPECT_EQ(hmtlString, htmlFromSpan); 676 } 677 678 /** 679 * @tc.name: SpanStringConvert014 680 * @tc.desc: This test case checks the conversion of a SpanString with multiple styles, including font spans, 681 * letter spacing, and text decoration. It verifies that all styles are correctly applied and 682 * preserved during conversion. 683 * @tc.level: 1 684 */ 685 HWTEST_F(HtmlConvertTestNg, SpanStringConvert014, TestSize.Level1) 686 { 687 /** 688 * @tc.steps1: Create a SpanString with multiple spans, including font styles, letter spacing, and text decoration. 689 * Convert it to HTML and then back to a SpanString. 690 * Compare the span items to ensure no information is lost during the conversion process. 691 * @tc.expected: The converted SpanString should match the original SpanString with all styles applied correctly. 692 */ 693 auto spanString = AceType::MakeRefPtr<SpanString>(u"0123456789"); 694 spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont1, 0, 3)); 695 spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont2, 3, 5)); 696 spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testEmptyFont, 5, 8)); 697 spanString->AddSpan(AceType::MakeRefPtr<LetterSpacingSpan>(Dimension(5), 5, 8)); 698 spanString->AddSpan(AceType::MakeRefPtr<DecorationSpan>( 699 std::vector<TextDecoration>({TextDecoration::LINE_THROUGH}), Color::BLUE, 700 TextDecorationStyle::WAVY, std::optional<TextDecorationOptions>(), 0, 1)); 701 702 SpanToHtml convert; 703 auto out = convert.ToHtml(*spanString); 704 HtmlToSpan toSpan; 705 auto dstSpan = toSpan.ToSpanString(out); 706 EXPECT_EQ(IsSpanItemSame(dstSpan->GetSpanItems(), spanString->GetSpanItems()), true); 707 } 708 709 /** 710 * @tc.name: HTMLLineThicknessScaleTest001 711 * @tc.desc: This test case checks the conversion of a SpanString containing a mixture of 712 * spans. It ensures that all styles are applied correctly and the conversion 713 * between HTML and SpanString is accurate. 714 * @tc.level: 1 715 */ 716 HWTEST_F(HtmlConvertTestNg, HTMLLineThicknessScaleTest001, TestSize.Level1) 717 { 718 /** 719 * @tc.steps1: Initialize a mutable SpanString with an image option and create a SpanString with 720 * mixed styles (font, letter spacing, baseline offset, text decoration, etc.). 721 * @tc.expected: The SpanString should properly handle different types of spans and apply them correctly. 722 */ 723 auto imageOption = GetImageOption("src/appIcon-1.png"); 724 auto mutableStr = AceType::MakeRefPtr<MutableSpanString>(imageOption); 725 auto spanString = AceType::MakeRefPtr<SpanString>(u"testNewDecoration\n123"); 726 727 // Add text decoration (line through) span 728 // change Test by search MakeRefPtr<DecorationSpan> 729 spanString->AddSpan(AceType::MakeRefPtr<DecorationSpan>( 730 std::vector<TextDecoration>({TextDecoration::UNDERLINE}), Color::BLACK, 731 TextDecorationStyle::SOLID, 1.0f, std::optional<TextDecorationOptions>(), 0, 1)); 732 spanString->AddSpan(AceType::MakeRefPtr<DecorationSpan>( 733 std::vector<TextDecoration>({TextDecoration::UNDERLINE}), Color::BLACK, 734 TextDecorationStyle::WAVY, 5.0f, std::optional<TextDecorationOptions>(), 0, 1)); 735 spanString->AddSpan(AceType::MakeRefPtr<DecorationSpan>( 736 std::vector<TextDecoration>({TextDecoration::LINE_THROUGH}), Color::BLACK, 737 TextDecorationStyle::DASHED, -5.0f, std::optional<TextDecorationOptions>(), 0, 1)); 738 spanString->AddSpan(AceType::MakeRefPtr<DecorationSpan>( 739 std::vector<TextDecoration>({TextDecoration::LINE_THROUGH}), Color::BLACK, 740 TextDecorationStyle::DOTTED, 0, std::optional<TextDecorationOptions>(), 0, 1)); 741 742 // Add paragraph style span 743 auto spanParagraphStyle = GetDefaultParagraphStyle(); 744 auto paragraphSpan = AceType::MakeRefPtr<ParagraphStyleSpan>(spanParagraphStyle, 4, 7); 745 spanString->AddSpan(paragraphSpan); 746 747 // Insert the span string into the mutable string 748 mutableStr->InsertSpanString(2, spanString); 749 750 /** 751 * @tc.steps3: Convert the mutable SpanString to HTML using the SpanToHtml converter. 752 * @tc.expected: The HTML conversion should preserve all the added spans and their properties. 753 */ 754 SpanToHtml convert; 755 auto out = convert.ToHtml(*mutableStr); 756 757 /** 758 * @tc.steps4: Convert the resulting HTML back to a SpanString and validate the number of span items. 759 * @tc.expected: The number of span items should match the total number of spans added. 760 */ 761 HtmlToSpan toSpan; 762 auto dstSpan = toSpan.ToSpanString(out); 763 EXPECT_NE(dstSpan, nullptr); 764 auto items = dstSpan->GetSpanItems(); 765 EXPECT_NE(items.size(), 0); 766 } 767 768 /** 769 * @tc.name: HTMLLineThicknessScaleTest002 770 * @tc.desc: This test case checks the conversion of a SpanString with multiple styles, 771 * It verifies that all styles are correctly applied and preserved during conversion. 772 * @tc.level: 1 773 */ 774 HWTEST_F(HtmlConvertTestNg, HTMLLineThicknessScaleTest002, TestSize.Level1) 775 { 776 /** 777 * @tc.steps1: Create a SpanString with multiple spans 778 */ 779 auto spanString = AceType::MakeRefPtr<SpanString>(u"testNewDecoration123"); 780 spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont1, 0, 6)); 781 spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testFont2, 6, 10)); 782 spanString->AddSpan(AceType::MakeRefPtr<FontSpan>(testEmptyFont, 10, 12)); 783 spanString->AddSpan(AceType::MakeRefPtr<LetterSpacingSpan>(Dimension(10), 5, 8)); 784 /** 785 * @tc.steps2: Create a SpanString with multiple spans. 786 */ 787 spanString->AddSpan(AceType::MakeRefPtr<DecorationSpan>( 788 std::vector<TextDecoration>({TextDecoration::UNDERLINE}), Color::BLACK, 789 TextDecorationStyle::SOLID, 1.0f, std::optional<TextDecorationOptions>(), 0, 1)); 790 spanString->AddSpan(AceType::MakeRefPtr<DecorationSpan>( 791 std::vector<TextDecoration>({TextDecoration::LINE_THROUGH}), Color::BLACK, 792 TextDecorationStyle::SOLID, 5.0f, std::optional<TextDecorationOptions>(), 2, 6)); 793 spanString->AddSpan(AceType::MakeRefPtr<DecorationSpan>( 794 std::vector<TextDecoration>({TextDecoration::OVERLINE}), Color::BLACK, 795 TextDecorationStyle::SOLID, -1.0f, std::optional<TextDecorationOptions>(), 7, 9)); 796 /** 797 * @tc.steps3: Create a SpanString with multiple spans, including font styles, etc. 798 */ 799 SpanToHtml convert; 800 auto out = convert.ToHtml(*spanString); 801 HtmlToSpan toSpan; 802 auto dstSpan = toSpan.ToSpanString(out); 803 EXPECT_EQ(IsSpanItemSame(dstSpan->GetSpanItems(), spanString->GetSpanItems()), true); 804 } 805 806 } // namespace OHOS::Ace::NG