retronews

a featureful fork of the luke8086/retronews hn+lobste.rs tui
Log | Files | Refs | README | LICENSE

commit f105819d0291c6dddf433d976286c199261069a1
parent bc43f8adfec5d6d4797adb0bc82a3647f19f354e
Author: luke8086 <55237178+luke8086@users.noreply.github.com>
Date:   Wed, 14 Jun 2023 14:12:27 +0000

Extract testcases to separate files, support dumping current msg

Diffstat:
Mretronews.py | 13+++++++++++++
Mtests.py | 132+++++++++++++++----------------------------------------------------------------
Atests/test_01.html | 2++
Atests/test_01.out | 6++++++
Atests/test_02.html | 1+
Atests/test_02.out | 8++++++++
Atests/test_03.html | 1+
Atests/test_03.out | 1+
Atests/test_04.html | 1+
Atests/test_04.out | 7+++++++
Atests/test_05.html | 9+++++++++
Atests/test_05.out | 16++++++++++++++++
Atests/test_06.html | 2++
Atests/test_06.out | 5+++++
14 files changed, 96 insertions(+), 108 deletions(-)

diff --git a/retronews.py b/retronews.py @@ -49,6 +49,7 @@ KEY_BINDINGS: dict[int, Callable[["AppState"], None]] = { ord("x"): lambda app: cmd_close(app), ord("s"): lambda app: cmd_star(app), ord("S"): lambda app: cmd_star_thread(app), + ord("D"): lambda app: cmd_dump(app), ord("r"): lambda app: cmd_toggle_raw_mode(app), ord("k"): lambda app: cmd_up(app), ord("j"): lambda app: cmd_down(app), @@ -544,6 +545,18 @@ def cmd_star_thread(app: AppState) -> None: cmd_next(app) +def cmd_dump(app: AppState) -> None: + if (msg := app.selected_message) is None: + return + + filename = f"{msg.msg_id}.html" + + with open(filename, "w") as fp: + fp.write(msg.body or "") + + app_show_flash(app, f"Message body dumped to {filename}") + + def cmd_toggle_raw_mode(app: AppState) -> None: app.raw_mode = not app.raw_mode app_select_message(app, app.selected_message) diff --git a/tests.py b/tests.py @@ -1,127 +1,43 @@ +import os import unittest import retronews +TC_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "tests") + class TestHtmlParser(unittest.TestCase): maxDiff = None - def test_paragraphs(self): - html = ( - "<p>Lorem ipsum dolor sit amet, pro eu soleat civibus. " - + "Mel quas sensibus te. Noster nominati recteque no has.</p>" - + "<p>Lorem ipsum dolor sit amet, pro eu soleat civibus. " - + "Mel quas sensibus te. Noster nominati recteque no has.</p>" - ) - lines = [ - "Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus", - "te. Noster nominati recteque no has.", - "", - "Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus", - "te. Noster nominati recteque no has.", - ] - self.assertLines(html, lines) + def checkFormatting(self, name: str): + html_path = os.path.join(TC_DIR, f"{name}.html") + out_path = os.path.join(TC_DIR, f"{name}.out") + + with open(html_path) as fp: + html = fp.read() - def test_quotes(self): - html = ( - "<p>&gt;&gt;Lorem ipsum dolor sit amet, pro eu soleat civibus. " - + "Mel quas sensibus te. Noster nominati recteque no has.</p>" - + "<p>&gt; Lorem ipsum dolor sit amet, pro eu soleat civibus. " - + "Mel quas sensibus te. Noster nominati recteque no has.</p>" - + "<p>Lorem ipsum dolor sit amet, pro eu soleat civibus. " - + "Mel quas sensibus te. Noster nominati recteque no has.</p>" - ) - lines = [ - ">>Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus", - ">>te. Noster nominati recteque no has.", - "", - "> Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus", - "> te. Noster nominati recteque no has.", - "", - "Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus", - "te. Noster nominati recteque no has.", - ] - self.assertLines(html, lines) + actual = "\n".join(retronews.parse_html(html)).strip() - def test_expanding_links(self): - # Ensure links shortened with ellipsis are rendered in full - html = '<a href="https://example.com/foo/bar">https://example.com/foo...</a>' - lines = ["https://example.com/foo/bar"] - self.assertLines(html, lines) + if not os.path.exists(out_path): + with open(out_path, "w") as fp: + fp.write(actual) - def test_link_references(self): - # Ensure links in numbered references are not shifted to the next line - html = ( - "<p>Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus</p>" - + "<p>[0]: <a>https://long.long.long.long.long.long.long.long.long.long.long.example.com</a></p>" - + "<p>[1] - <a>https://long.long.long.long.long.long.long.long.long.long.long.example.com</a></p>" - + "<p>[2] <a>https://long.long.long.long.long.long.long.long.long.long.long.example.com</a></p>" - ) - lines = [ - "Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus", - "", - "[0]: https://long.long.long.long.long.long.long.long.long.long.long.example.com", - "", - "[1] - https://long.long.long.long.long.long.long.long.long.long.long.example.com", - "", - "[2] https://long.long.long.long.long.long.long.long.long.long.long.example.com", - ] + with open(out_path) as fp: + expected = fp.read().strip() - self.assertLines(html, lines) + if actual != expected: + sep = "\n" + "-" * 64 + "\n" + msg = f"\n\nExpected:{sep}{expected}{sep}\n\nActual:{sep}{actual}{sep}" + self.fail(msg) - def test_code_blocks(self): - # This HTML is not particularly correct, but it's how HN renders code blocks - html = ( - "<p>Lorem ipsum dolor sit amet, pro eu soleat civibus. " - + "Mel quas sensibus te. Noster nominati recteque no has.</p>" - + "<p><pre><code> def hello():\n print('Hello World')\n return None\n</code></pre>\n" - + "Lorem ipsum dolor sit amet, pro eu soleat civibus. " - + "Mel quas sensibus te. Noster nominati recteque no has.</p>" - + "<p><pre><code> def hello():\n print('Hello World')\n return None\n</code></pre>\n" - + "Lorem ipsum dolor sit amet, pro eu soleat civibus. " - + "Mel quas sensibus te. Noster nominati recteque no has.</p>" - ) - lines = [ - "Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus", - "te. Noster nominati recteque no has.", - "", - " def hello():", - " print('Hello World')", - " return None", - "", - "Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus", - "te. Noster nominati recteque no has.", - "", - " def hello():", - " print('Hello World')", - " return None", - "", - "Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus", - "te. Noster nominati recteque no has.", - ] - self.assertLines(html, lines) - def test_long_code_blocks(self): - # Make sure long code doesn't get wrapped - html = ( - "<p>Lorem ipsum dolor sit amet, pro eu soleat civibus.</p>" - + "<p><pre><code> lambda L: [] if L==[] else qsort([x for x in L[1:] " - + "if x< L[0]]) + L[0:1] + qsort([x for x in L[1:] if x>=L[0]])\n</code></pre>\n" - + "Mel quas sensibus te. Noster nominati recteque no has.</p>" - ) - lines = [ - "Lorem ipsum dolor sit amet, pro eu soleat civibus.", - "", - " lambda L: [] if L==[] else qsort([x for x in L[1:] if x< L[0]]) + L[0:1] " - + "+ qsort([x for x in L[1:] if x>=L[0]])", - "", - "Mel quas sensibus te. Noster nominati recteque no has.", - ] - self.assertLines(html, lines) +def setup_test_cases(): + tcs = [x.split(".")[0] for x in sorted(os.listdir(TC_DIR)) if x.endswith(".html")] - def assertLines(self, html: str, lines: list[str]) -> None: - self.assertListEqual(retronews.parse_html(html), lines) + for tc in tcs: + setattr(TestHtmlParser, tc, lambda self, tc=tc: self.checkFormatting(tc)) if __name__ == "__main__": + setup_test_cases() unittest.main() diff --git a/tests/test_01.html b/tests/test_01.html @@ -0,0 +1 @@ +<p>Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus te. Noster nominati recteque no has.</p><p>Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus te. Noster nominati recteque no has.</p> +\ No newline at end of file diff --git a/tests/test_01.out b/tests/test_01.out @@ -0,0 +1,5 @@ +Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus +te. Noster nominati recteque no has. + +Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus +te. Noster nominati recteque no has. +\ No newline at end of file diff --git a/tests/test_02.html b/tests/test_02.html @@ -0,0 +1 @@ +<p>&gt;&gt;Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus te. Noster nominati recteque no has.</p><p>&gt; Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus te. Noster nominati recteque no has.</p><p>Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus te. Noster nominati recteque no has.</p> diff --git a/tests/test_02.out b/tests/test_02.out @@ -0,0 +1,8 @@ +>>Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus +>>te. Noster nominati recteque no has. + +> Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus +> te. Noster nominati recteque no has. + +Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus +te. Noster nominati recteque no has. diff --git a/tests/test_03.html b/tests/test_03.html @@ -0,0 +1 @@ +<a href="https://example.com/foo/bar">https://example.com/foo...</a> diff --git a/tests/test_03.out b/tests/test_03.out @@ -0,0 +1 @@ +https://example.com/foo/bar diff --git a/tests/test_04.html b/tests/test_04.html @@ -0,0 +1 @@ +<p>Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus</p><p>[0]: <a>https://long.long.long.long.long.long.long.long.long.long.long.example.com</a></p><p>[1] - <a>https://long.long.long.long.long.long.long.long.long.long.long.example.com</a></p><p>[2] <a>https://long.long.long.long.long.long.long.long.long.long.long.example.com</a></p> diff --git a/tests/test_04.out b/tests/test_04.out @@ -0,0 +1,7 @@ +Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus + +[0]: https://long.long.long.long.long.long.long.long.long.long.long.example.com + +[1] - https://long.long.long.long.long.long.long.long.long.long.long.example.com + +[2] https://long.long.long.long.long.long.long.long.long.long.long.example.com diff --git a/tests/test_05.html b/tests/test_05.html @@ -0,0 +1,9 @@ +<p>Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus te. Noster nominati recteque no has.</p><p><pre><code> def hello(): + print('Hello World') + return None +</code></pre> +Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus te. Noster nominati recteque no has.</p><p><pre><code> def hello(): + print('Hello World') + return None +</code></pre> +Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus te. Noster nominati recteque no has.</p> diff --git a/tests/test_05.out b/tests/test_05.out @@ -0,0 +1,16 @@ +Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus +te. Noster nominati recteque no has. + + def hello(): + print('Hello World') + return None + +Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus +te. Noster nominati recteque no has. + + def hello(): + print('Hello World') + return None + +Lorem ipsum dolor sit amet, pro eu soleat civibus. Mel quas sensibus +te. Noster nominati recteque no has. diff --git a/tests/test_06.html b/tests/test_06.html @@ -0,0 +1,2 @@ +<p>Lorem ipsum dolor sit amet, pro eu soleat civibus.</p><p><pre><code> lambda L: [] if L==[] else qsort([x for x in L[1:] if x< L[0]]) + L[0:1] + qsort([x for x in L[1:] if x>=L[0]]) +</code></pre>Mel quas sensibus te. Noster nominati recteque no has.</p> diff --git a/tests/test_06.out b/tests/test_06.out @@ -0,0 +1,5 @@ +Lorem ipsum dolor sit amet, pro eu soleat civibus. + + lambda L: [] if L==[] else qsort([x for x in L[1:] if x< L[0]]) + L[0:1] + qsort([x for x in L[1:] if x>=L[0]]) + +Mel quas sensibus te. Noster nominati recteque no has.