import sys import re from loguru import logger from rl_string_helper import ( RLStringHelper, UTF16Handler, StringAssignmentMixin, quote_html, split_overlapping_ranges, ) class TestRLStringHelper: def setup_method(self): logger.remove() logger.add(sys.stdout, level="TRACE") def test_html_quote(self): quoted_string_1 = [i for i in quote_html("", "full")] assert quoted_string_1 == [((0, 1), "<"), ((12, 13), ">")] # Test with standard HTML characters html = '
Hello & World
' result = list(quote_html(html, "full")) expected = [ ((0, 1), "<"), ((11, 12), """), ((16, 17), """), ((17, 18), ">"), ((24, 25), "&"), ((31, 32), "<"), ((36, 37), ">"), ] assert sorted(result) == sorted(expected) # Test with extra characters html = '
\nHello & World
' result = list(quote_html(html, "extra")) expected = [ ((0, 1), "<"), ((11, 12), """), ((16, 17), """), ((17, 18), ">"), ((25, 26), "&"), ((32, 33), "<"), ((37, 38), ">"), ((18, 19), "
"), ] assert sorted(result) == sorted(expected) # Test with quote characters html = "
Hello & 'World'
" result = list(quote_html(html, "full")) expected = [ ((0, 1), "<"), ((11, 12), """), ((16, 17), """), ((17, 18), ">"), ((24, 25), "&"), ((26, 27), "'"), ((32, 33), "'"), ((33, 34), "<"), ((38, 39), ">"), ] assert sorted(result) == sorted(expected) def test_basic_template(self): helper = RLStringHelper("Hello world") helper.set_template(0, 5, "{{text}}") assert str(helper) == "Hello world" helper.set_template(6, 11, "{{text}}") assert str(helper) == "Hello world" helper.set_template(0, 11, "{{text}}") assert str(helper) == "Hello world" def test_super_duper_overlapsing(self): text = "Note: The patterns and ideas discussed in this post are broadly applicable." helper = RLStringHelper(text) markups = [ {"start": 0, "end": 5, "type": "code", "template": "{{text}}"}, { "start": 0, "end": 6, "type": "strong", "template": "{{text}}", }, {"start": 0, "end": 6, "type": "em", "template": "{{text}}"}, ] parsed_markups = split_overlapping_ranges(markups) for markup in parsed_markups: helper.set_template(markup["start"], markup["end"], markup["template"]) expected_pattern = r"Note: The patterns and ideas discussed in this post are broadly applicable\." result = str(helper) assert re.match(expected_pattern, result) def test_complex_overlapping_tags(self): text = "The quick (brown) fox jumps over 13 lazy dogs!" helper = RLStringHelper(text) markups = [ { "start": 0, "end": 46, "type": "span", "template": "{{text}}", }, {"start": 4, "end": 17, "type": "bold", "template": "{{text}}"}, {"start": 10, "end": 21, "type": "italic", "template": "{{text}}"}, { "start": 18, "end": 27, "type": "underline", "template": "{{text}}", }, { "start": 33, "end": 41, "type": "code", "template": "{{text}}", }, { "start": 40, "end": 46, "type": "link", "template": '{{text}}', }, ] parsed_markups = split_overlapping_ranges(markups) for markup in parsed_markups: helper.set_template(markup["start"], markup["end"], markup["template"]) expected_output = """The quick (brown) fox jumps over 13 lazy dogs!""" assert str(helper) == expected_output def test_nmultibyte_emoji(self): text = "Noah dragged his two printers out from Settings โš™๏ธ < Printers & Scanners ๐Ÿ–จ๏ธ and dropped them in Dock or Desktop, I donโ€™t remember โ€” but you can drag to both the places." string_helper = StringAssignmentMixin(text) utf_handler = UTF16Handler() string_pos_matrix = list(range(len(text))) updated_text, string_pos_matrix, utf_16_bang_list = utf_handler.pre_utf_16_bang( string_helper, string_pos_matrix ) updated_text, string_pos_matrix = utf_handler.post_utf_16_bang( updated_text, string_pos_matrix, utf_16_bang_list ) assert str(updated_text) == text from icecream import ic string_helper = RLStringHelper(text, None) string_helper.set_template(0, 100000, "{{text}}") assert str(string_helper) == f"{text}".replace("โ€™", "'") string_helper = RLStringHelper(text, ["None"]) string_helper.set_template(39, 76, "{{text}}") with open("test.txt", "w") as f: f.write(str(string_helper) + "\n") assert str( string_helper ) == f"{text[:39]}Settings โš™๏ธ < Printers & Scanners ๐Ÿ–จ๏ธ{text[76:]}".replace( "โ€™", "'" ) def test_basic_replace(self): # Replace A to B - ONE to ONE char helper = RLStringHelper("ABC") helper.set_replace(0, 1, "B") assert str(helper) == "BBC" # Replace first B to AA - ONE to TWO chars helper.set_replace(0, 1, "AA") assert str(helper) == "AABC" # Replace C to D - ONE to ONE char helper.set_replace(2, 3, "D") assert str(helper) == "AABD" # Replace BD to R - TWO to ONE char helper.set_replace(1, 3, "R") assert str(helper) == "AAR" # Replace AA to CD helper.set_replace(0, 2, "CD") assert str(helper) == "CD" def test_multibyte_replace(self): helper = RLStringHelper("TESERT - ๐Ÿ“Š - ABC") helper.set_replace(0, 6, "B") assert helper.get_text() == "B - ๐Ÿ“Š - ABC" helper = RLStringHelper( "Your support means the world to me. If you found this article valuable and insightful, please consider giving it a round of applause by clicking the clapping hands icon ๐Ÿ‘." ) helper.set_template(0, 200, "{{text}}") helper.set_template(0, 200, "{{text}}") assert ( helper.get_text() == "Your support means the world to me. If you found this article valuable and insightful, please consider giving it a round of applause by clicking the clapping hands icon ๐Ÿ‘." ) helper = RLStringHelper("TESERT ALMACOM - ๐Ÿ“Š - ABC") helper.set_replace(0, 14, "B") assert helper.get_text() == "B - ๐Ÿ“Š - ABC" helper = RLStringHelper("hello - ๐Ÿ“Š - ABC") helper.set_template(0, 5, "{{text}}") assert helper.get_text() == "hello - ๐Ÿ“Š - ABC" helper = RLStringHelper("ABC ๐Ÿ“Š - How are you?") helper.set_template(4, 6, "{{text}}") assert str(helper) == "ABC ๐Ÿ“Š - How are you?" helper = RLStringHelper("We have a ๐Ÿ“Š, a ๐Ÿ“Š and a ๐Ÿ“Š.") helper.set_template(0, 30, "{{text}}") assert helper.get_text() == "We have a ๐Ÿ“Š, a ๐Ÿ“Š and a ๐Ÿ“Š." def test_romano(self): issue_text = "Whilst academic research papers have highlighted performance issues with the prophet since 2017, the propagation of package popularity through the data science community has been fueled by ๐™—๐™ค๐™ฉ๐™ ๐™š๐™ญ๐™˜๐™š๐™จ๐™จ๐™ž๐™ซ๐™š ๐™˜๐™ก๐™–๐™ž๐™ข๐™จ ๐™›๐™ง๐™ค๐™ข ๐™ฉ๐™๐™š ๐™ค๐™ง๐™ž๐™œ๐™ž๐™ฃ๐™–๐™ก ๐™™๐™š๐™ซ๐™š๐™ก๐™ค๐™ฅ๐™ข๐™š๐™ฃ๐™ฉ ๐™ฉ๐™š๐™–๐™ข ๐™—๐™ช๐™ฉ ๐™ข๐™ค๐™ง๐™š ๐™ž๐™ข๐™ฅ๐™ค๐™ง๐™ฉ๐™–๐™ฃ๐™ฉ๐™ก๐™ฎ ๐™—๐™ฎ ๐™ข๐™–๐™ง๐™ ๐™š๐™ฉ๐™ž๐™ฃ๐™œ ๐™ค๐™› ๐™ฉ๐™๐™š ๐™ฃ๐™ค๐™ฃ-๐™ฅ๐™š๐™ง๐™›๐™ค๐™ง๐™ข๐™ž๐™ฃ๐™œ ๐™ฅ๐™–๐™˜๐™ ๐™–๐™œ๐™š ๐™ซ๐™ž๐™– ๐™–๐™ง๐™ฉ๐™ž๐™˜๐™ก๐™š๐™จ ๐™ค๐™ฃ ๐™ˆ๐™š๐™™๐™ž๐™ช๐™ข ๐™–๐™ฃ๐™™ ๐™จ๐™ค๐™˜๐™ž๐™–๐™ก ๐™ข๐™š๐™™๐™ž๐™–." helper = RLStringHelper(issue_text) assert helper.get_text() == issue_text def test_markup_parser(self): href_markup = { "start": 0, "end": 12, "type": "a", "template": '{{ text }}', } helper = RLStringHelper("Hello world") parsed_markups = split_overlapping_ranges([href_markup]) for markup in parsed_markups: helper.set_template(markup["start"], markup["end"], markup["template"]) assert ( helper.get_text() == 'Hello world' ) def test_medium_all(self): helper = RLStringHelper("ABC Hello world") helper.set_replace(0, 1, "B") assert str(helper) == "BBC Hello world" helper.set_template(4, 9, "{{text}}") assert str(helper) == "BBC Hello world" helper.set_template(10, 15, "{{text}}") assert str(helper) == "BBC Hello world"