krz/crumb

A local alternative to your browser's history.

clone: git clone https://gitbay.org/krz/crumb.git

main: tests/test_server.py · raw

 1import json
 2import os
 3import tempfile
 4import unittest
 5from unittest.mock import patch
 6
 7from server import app
 8
 9
10class TestServer(unittest.TestCase):
11    """The POST handler appends to LOG_PATH, which defaults to the developer's
12    own ~/.crumb/history.org. Every test here patches it at a temporary file:
13    without that, running the suite writes into real browsing history."""
14
15    def setUp(self):
16        self.client = app.test_client()
17        handle, self.log_path = tempfile.mkstemp(suffix=".org")
18        os.close(handle)
19
20    def tearDown(self):
21        os.unlink(self.log_path)
22
23    def test_log_visit_post_writes_an_entry(self):
24        data = {
25            "title": "Test Visit",
26            "url": "https://test.com",
27            "hostname": "test.com",
28            "path": "/",
29            "query": "test",
30            "tabId": 123,
31            "windowId": 456,
32            "favIconUrl": "https://example.com/favicon.ico",
33        }
34
35        # json=, not data=: with data= Flask sends it form-encoded regardless of
36        # content_type, request.json comes back empty and the handler 400s.
37        with patch("server.LOG_PATH", self.log_path):
38            response = self.client.post("/", json=data)
39
40        self.assertEqual(response.status_code, 204)
41
42        with open(self.log_path) as f:
43            written = f.read()
44        self.assertIn("* Test Visit", written)
45        self.assertIn(":URL:       https://test.com", written)
46        self.assertIn(":QUERY:     test", written)
47        self.assertIn(":END:", written)
48
49    def test_optional_fields_are_omitted_when_empty(self):
50        with patch("server.LOG_PATH", self.log_path):
51            response = self.client.post("/", json={"title": "Bare", "url": "https://x"})
52
53        self.assertEqual(response.status_code, 204)
54        with open(self.log_path) as f:
55            written = f.read()
56        self.assertNotIn(":QUERY:", written)
57        self.assertNotIn(":FAVICON:", written)
58
59    def test_log_visit_options(self):
60        response = self.client.options("/")
61        self.assertEqual(response.status_code, 204)
62
63    def test_cors_headers_are_present(self):
64        response = self.client.options("/")
65        self.assertEqual(response.headers["Access-Control-Allow-Origin"], "*")
66        self.assertEqual(response.headers["Access-Control-Allow-Headers"], "Content-Type")