diff --git a/core/test/utils/html_utils_test.dart b/core/test/utils/html_utils_test.dart index 58d3353d7..567c8e8ba 100644 --- a/core/test/utils/html_utils_test.dart +++ b/core/test/utils/html_utils_test.dart @@ -232,7 +232,6 @@ void main() { expect(HtmlUtils.extractPlainText(html), 'Before Hello After'); }); - test('handles emoji correctly', () { const html = '''

Hello 🌍🚀

@@ -318,8 +317,203 @@ void main() { }); test('keeps unknown tags as plain text', () { + // Unknown HTML tags should be keep as html text, + // not stripped or removed by the extractor. const html = 'dab'; - expect(HtmlUtils.extractPlainText(html), 'dab'); + expect( + HtmlUtils.extractPlainText(html), + 'dab', + ); + }); + + test('removes deeply nested blockquotes with mixed content', () { + const html = ''' +

Intro

+
+
Level1
+
+

Level2

+
+ Level3 +
+ Level4 +
+
+
+
+

Outro

+ '''; + expect(HtmlUtils.extractPlainText(html), 'Intro Outro'); + }); + + test('removes adjacent blockquotes and preserves surrounding text', () { + const html = ''' +
Top
+

Q1

+

Q2

+

Q3

+
Bottom
+ '''; + expect(HtmlUtils.extractPlainText(html), 'Top Bottom'); + }); + + test('removes blockquote with attributes and cite', () { + const html = ''' +

Start

+
+ On Nov 10 ... +
Quoted text
+
+

End

+ '''; + expect(HtmlUtils.extractPlainText(html), 'Start End'); + }); + + test('keeps content when removeQuotes=false', () { + const html = ''' +

A

+

B inside quote

+

C

+ '''; + expect( + HtmlUtils.extractPlainText(html, removeQuotes: false), + 'A B inside quote C', + ); + }); + + test('keeps content of encoded blockquotes since they are not real tags', () { + const html = ''' +

Before

+ <blockquote>Inner from encoded quote</blockquote> +

After

+ '''; + expect(HtmlUtils.extractPlainText(html), 'Before Inner from encoded quote After'); + }); + + test('handles multiple encoded tags that become real tags then stripped', () { + const html = ''' + <div>A</div><span>B</span> + '''; + // After decoding twice:
A
B → "A B" + expect(HtmlUtils.extractPlainText(html), 'A B'); + }); + + test('removes style and script tags when enabled', () { + const html = ''' +

Keep

+ + +

Me

+ '''; + expect(HtmlUtils.extractPlainText(html), 'Keep Me'); + }); + + test('keeps style content when removeStyle=false', () { + const html = ''' +

Top

+ +

Bottom

+ '''; + // When removeStyle=false, style content remains after tag stripping. + expect( + HtmlUtils.extractPlainText(html, removeStyle: false), + 'Top Bottom', + ); + }); + + test('keeps script content when removeScript=false', () { + const html = ''' +

Hello

+ +

World

+ '''; + expect( + HtmlUtils.extractPlainText(html, removeScript: false), + 'Hello World', + ); + }); + + test('collapses multiple
tags into a single space', () { + const html = ''' + Hello


World + '''; + expect(HtmlUtils.extractPlainText(html), 'Hello World'); + }); + + test('handles mixed languages inside and outside quotes', () { + const html = ''' +

Xin chào

+

Bonjour (quoted)

+

こんにちは

+ '''; + expect(HtmlUtils.extractPlainText(html), 'Xin chào こんにちは'); + }); + + test('handles messy whitespace around quotes and tags', () { + const html = ''' +
A
+
+

should be gone

+
+ B + '''; + expect(HtmlUtils.extractPlainText(html), 'A B'); + }); + + test('ignores disclaimers when wrapped inside blockquotes', () { + const html = ''' +

Keep

+
+
+ Ce message et les éventuels documents joints... +
+
+

Text

+ '''; + expect(HtmlUtils.extractPlainText(html), 'Keep Text'); + }); + + test('keeps disclaimers that are not wrapped in blockquotes', () { + const html = ''' +

Top

+
Ce message et les éventuels documents joints...
+

Bottom

+ '''; + expect(HtmlUtils.extractPlainText(html), + 'Top Ce message et les éventuels documents joints... Bottom'); + }); + + test('removes malformed nested blockquotes completely', () { + const html = ''' +

Intro

+
+
Q1 +
Q2 +
Q3
+
+
+

Outro

+ '''; + expect(HtmlUtils.extractPlainText(html), 'Intro Outro'); + }); + + test('leaves unknown entities untouched while decoding known ones', () { + const html = ''' +

© 2025 &unknown; & <tag>

+ '''; + // © → ©, & → &, <tag> → , unknown entities stay as-is + expect(HtmlUtils.extractPlainText(html), '© 2025 &unknown; & '); + }); + + test('keeps unknown tags as html text even when adjacent', () { + const html = 'ab'; + expect(HtmlUtils.extractPlainText(html), 'ab'); + }); + + test('handles encoded unknown tags that become html text after decoding', () { + const html = '&lt;weird&gt;X&lt;/weird&gt;Y'; + expect(HtmlUtils.extractPlainText(html), 'XY'); }); });