aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_webpage.py
blob: 97abb910e39249f0f9136b1580d059a5df6e04f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import json
import os
import re
import tempfile
import unittest

from claude_logbook import webpage

PAYLOAD_RE = re.compile(
    r'<script id="payload" type="application/json">(.*?)</script>', re.S)

REGISTRO = {"id": "abc", "p": "/proj", "u": 1, "c": [{"r": "u", "x": "hola"}]}


class TestPayload(unittest.TestCase):
    def test_escapa_el_cierre_de_etiqueta(self):
        raw = webpage.encode_payload({"s": [{"x": "mirá este </script> de acá"}]})
        self.assertNotIn("</", raw)
        self.assertEqual(json.loads(raw)["s"][0]["x"], "mirá este </script> de acá")

    def test_no_escapa_a_ascii(self):
        self.assertIn("ñ", webpage.encode_payload({"s": [{"x": "año"}]}))

    def test_separa_sesiones_de_memorias(self):
        payload = webpage.build_payload([REGISTRO], [{"name": "algo"}])
        self.assertEqual(payload["s"], [REGISTRO])
        self.assertEqual(payload["m"], [{"name": "algo"}])

    def test_sin_memorias_igual_trae_la_clave(self):
        self.assertEqual(webpage.build_payload([REGISTRO])["m"], [])


class TestRender(unittest.TestCase):
    def test_reemplaza_el_marcador(self):
        html = webpage.render([REGISTRO], template="<b>__DATA__</b>")
        self.assertNotIn("__DATA__", html)
        self.assertIn('"id":"abc"', html)

    def test_falla_si_el_template_no_tiene_marcador(self):
        with self.assertRaises(webpage.TemplateError):
            webpage.render([REGISTRO], template="<b>sin marcador</b>")

    def test_falla_si_el_marcador_esta_repetido(self):
        with self.assertRaises(webpage.TemplateError):
            webpage.render([REGISTRO], template="__DATA__ y __DATA__")

    def test_una_transcripcion_con_html_no_corta_el_script(self):
        # El caso que motiva el escape: una sesión donde se habló de este mismo
        # generador tiene "</script>" y "__DATA__" adentro del texto.
        peligrosa = dict(REGISTRO, c=[{"r": "u", "x": "poné </script><img> y __DATA__"}])
        html = webpage.render([peligrosa])

        bloques = PAYLOAD_RE.findall(html)
        self.assertEqual(len(bloques), 1)
        vuelta = json.loads(bloques[0])
        self.assertEqual(vuelta["s"][0]["c"][0]["x"],
                         "poné </script><img> y __DATA__")


class TestTemplate(unittest.TestCase):
    def setUp(self):
        self.html = webpage.template_text()

    def test_el_template_del_paquete_tiene_un_solo_marcador(self):
        self.assertEqual(self.html.count(webpage.MARKER), 1)

    def test_es_un_documento_completo(self):
        # Sin doctype ni charset, un file:// se abre en quirks mode y con la
        # codificación del sistema: los acentos salen rotos.
        self.assertTrue(self.html.lstrip().startswith("<!doctype html>"))
        self.assertIn('<meta charset="utf-8">', self.html)
        self.assertIn('name="viewport"', self.html)
        self.assertTrue(self.html.rstrip().endswith("</html>"))

    def test_no_pide_nada_por_red(self):
        for atributo in ("src=\"http", "href=\"http", "@import"):
            self.assertNotIn(atributo, self.html)

    def test_se_puede_pasar_otro_template(self):
        with tempfile.NamedTemporaryFile("w", suffix=".html", delete=False,
                                         encoding="utf-8") as f:
            f.write("propio __DATA__")
            ruta = f.name
        self.addCleanup(os.unlink, ruta)
        self.assertTrue(webpage.template_text(ruta).startswith("propio"))


class TestWrite(unittest.TestCase):
    def test_escribe_y_resume(self):
        with tempfile.TemporaryDirectory() as d:
            out = os.path.join(d, "s.html")
            stats = webpage.write(
                [REGISTRO, dict(REGISTRO, id="def", p="/otro", u=2)], out)
            self.assertEqual(stats, {"sesiones": 2, "proyectos": 2,
                                     "mensajes": 3, "bloques": 2,
                                     "memorias": 0})
            with open(out, encoding="utf-8") as f:
                self.assertEqual(len(PAYLOAD_RE.findall(f.read())), 1)


if __name__ == "__main__":
    unittest.main()