]> git.scottworley.com Git - paperdoorknob/blobdiff - glowfic_test.py
Handle Unicode characters ≈ and ◁
[paperdoorknob] / glowfic_test.py
index ed32945d50f1bcce42f507346146761c9a029468..d3fb2ddb9d627720dff02c86a01d099ae19dc985 100644 (file)
@@ -4,46 +4,66 @@
 # under the terms of the GNU General Public License as published by the
 # Free Software Foundation, version 3.
 
-
+import dataclasses
+from io import BytesIO
+from sys import stderr
 import unittest
 
-from bs4 import BeautifulSoup
+from typing import Optional
 
+from fetch import FakeFetcher
 from images import FakeImageStore
 from glowfic import makeChunk, Thread
+from spec import Spec
 from texify import PandocTexifier
 
 
+def spec_for_testing(html: bytes, outbuf: Optional[BytesIO] = None) -> Spec:
+    return Spec('https://fake/test',
+                FakeFetcher({'https://fake/test': html,
+                             'https://fake/test?view=flat': html}),
+                FakeImageStore(),
+                lambda x: x,
+                lambda x: None,
+                PandocTexifier('pandoc'),
+                lambda x: x,
+                20,
+                b'',
+                None,
+                stderr.buffer if outbuf is None else outbuf,
+                lambda x: None)
+
+
 class TestSplit(unittest.TestCase):
 
     def testSplit1(self) -> None:
-        t = Thread(BeautifulSoup(b'''
+        t = Thread(spec_for_testing(b'''
             <html><body><div class="post-container post-post">
               The "post"
-            </div></body></html>''', 'html.parser'))
+            </div></body></html>'''))
         self.assertEqual([list(t.stripped_strings) for t in t.chunkDOMs()],
                          [['The "post"']])
 
     def testSplit2(self) -> None:
-        t = Thread(BeautifulSoup(b'''
+        t = Thread(spec_for_testing(b'''
             <html><body>
               <div class="post-container post-post">The "post"</div>
               <div class="flat-post-replies">
                 <div class="post-container post-reply">The "reply"</div>
               </div>
-            </body></html>''', 'html.parser'))
+            </body></html>'''))
         self.assertEqual([list(t.stripped_strings) for t in t.chunkDOMs()],
                          [['The "post"'], ['The "reply"']])
 
     def testSplit3(self) -> None:
-        t = Thread(BeautifulSoup(b'''
+        t = Thread(spec_for_testing(b'''
             <html><body>
               <div class="post-container post-post">The "post"</div>
               <div class="flat-post-replies">
                 <div class="post-container post-reply">1st reply</div>
                 <div class="post-container post-reply">2nd reply</div>
               </div>
-            </body></html>''', 'html.parser'))
+            </body></html>'''))
         self.assertEqual([list(t.stripped_strings) for t in t.chunkDOMs()],
                          [['The "post"'], ['1st reply'], ['2nd reply']])
 
@@ -52,7 +72,7 @@ class TestMakeChunk(unittest.TestCase):
 
     def testEmptyContent(self) -> None:
         with open('testdata/empty-content.html', 'rb') as f:
-            t = Thread(BeautifulSoup(f, 'html.parser'))
+            t = Thread(spec_for_testing(f.read((9999))))
         c = makeChunk(next(iter(t.chunkDOMs())), FakeImageStore())
         self.assertEqual(
             c.icon,
@@ -71,6 +91,110 @@ class TestMakeChunk(unittest.TestCase):
         self.assertEqual(
             PandocTexifier("pandoc").texify(c.character), b'{Keltham}\n')
 
+    def testMinimal(self) -> None:
+        t = Thread(spec_for_testing(b'''
+            <html><body>
+              <div class="post-container post-post">
+                <div class="post-content">Just content</div>
+              </div>
+            </body></html>'''))
+        c = makeChunk(next(iter(t.chunkDOMs())), FakeImageStore())
+        self.assertIsNone(c.icon)
+        self.assertIsNone(c.character)
+        self.assertIsNone(c.screen_name)
+        self.assertIsNone(c.author)
+        self.assertEqual(str(c.content),
+                         '<div class="post-content">Just content</div>')
+
+
+class TestThread(unittest.TestCase):
+
+    def testTitle(self) -> None:
+        t = Thread(spec_for_testing(b'''
+            <html><body>
+              <div class="content-header">
+                <span id="post-title">
+                  <a href="/posts/1234">Teh Story!</a>
+                </span>
+              </div>
+              <div class="post-container post-post">The "post"</div>
+            </body></html>'''))
+        self.assertEqual(t.title(), 'Teh Story!')
+
+    def testNextThreadRelative(self) -> None:
+        t = Thread(spec_for_testing(b'''
+            <html><body>
+              <div class="post-navheader">
+                <a class="view-button-link" href="/posts/4567"><div class="view-button">Next Post &raquo;</div>
+                </a><a class="view-button-link" href="/posts/4321"><div class="view-button float-none">&laquo; Previous Post</div>
+                </a>
+              </div>
+              <div class="post-container post-post">The "post"</div>
+            </body></html>'''))
+        self.assertEqual(t.next_thread(), 'https://fake/posts/4567')
+
+    def testNextThreadAbsolute(self) -> None:
+        t = Thread(spec_for_testing(b'''
+            <html><body>
+              <div class="post-navheader">
+                <a class="view-button-link" href="https://elsewhere/posts/4567"><div class="view-button">Next Post &raquo;</div>
+                </a><a class="view-button-link" href="https://elsewhere/posts/4321"><div class="view-button float-none">&laquo; Previous Post</div>
+                </a>
+              </div>
+              <div class="post-container post-post">The "post"</div>
+            </body></html>'''))
+        self.assertEqual(t.next_thread(), 'https://elsewhere/posts/4567')
+
+
+class TestEmit(unittest.TestCase):
+
+    def testEmit(self) -> None:
+        buf = BytesIO()
+        Thread(spec_for_testing(b'''
+            <html><body>
+              <div class="post-container post-post">
+                <div class="post-content">A</div>
+              </div>
+              <div class="flat-post-replies">
+                <div class="post-container post-reply">
+                  <div class="post-content">B</div>
+                </div>
+              </div>
+            </body></html>''', buf)).emit()
+        self.assertEqual(buf.getvalue(), rb'''\glowhead{}{}{}{}A
+\glowhead{}{}{}{}B
+''')
+
+    def testEmitTwoThreads(self) -> None:
+        buf = BytesIO()
+        spec = dataclasses.replace(spec_for_testing(b'', buf), fetcher=FakeFetcher({
+            'https://fake/test': b'''<html><body>
+              <div class="post-navheader">
+                <a class="view-button-link" href="/page2"><div class="view-button">Next Post &raquo;</div></a>
+              </div></body></html>''',
+            'https://fake/test?view=flat': b'''<html><body>
+              <div class="post-container post-post"><div class="post-content">A</div></div>
+              <div class="flat-post-replies">
+                <div class="post-container post-reply"><div class="post-content">B</div></div>
+              </div>
+            </body></html>''',
+            'https://fake/page2': b'''<html><body></body></html>''',
+            'https://fake/page2?view=flat': b'''<html><body>
+              <div class="post-container post-post"><div class="post-content">C</div></div>
+              <div class="flat-post-replies">
+                <div class="post-container post-reply"><div class="post-content">D</div></div>
+                <div class="post-container post-reply"><div class="post-content">E</div></div>
+              </div>
+            </body></html>''',
+        }))
+        Thread(spec).emit()
+        self.assertEqual(buf.getvalue(), rb'''\glowhead{}{}{}{}A
+\glowhead{}{}{}{}B
+\glowhead{}{}{}{}C
+\glowhead{}{}{}{}D
+\glowhead{}{}{}{}E
+''')
+
 
 if __name__ == '__main__':
     unittest.main()