Ctrl K
ComunidadGuías…

tests/test_star_history.py

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
from __future__ import annotations

from datetime import UTC, datetime, timedelta
import importlib.util
from pathlib import Path
import re
import sys
import unittest
import xml.etree.ElementTree as ET

ROOT = Path(__file__).resolve().parents[1]
spec = importlib.util.spec_from_file_location("render_star_history", ROOT / "scripts" / "render_star_history.py")
star = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = star
spec.loader.exec_module(star)

SUNDAY = datetime(2026, 10, 11, tzinfo=UTC)


def week(start: datetime, days: list[int]) -> dict:
    return {"week": int(start.timestamp()), "total": sum(days), "days": days}


class DailyPointsTests(unittest.TestCase):
    def test_the_line_starts_at_zero_on_the_first_starred_day_and_ends_at_generation_time(self):
        as_of = SUNDAY + timedelta(days=9, hours=6)
        weeks = [week(SUNDAY - timedelta(days=7), [0] * 7),
                 week(SUNDAY + timedelta(days=7), [3, 4, 0, 0, 0, 0, 0]),
                 week(SUNDAY, [0, 0, 5, 0, 1, 0, 0])]

        points = star.daily_points(weeks, as_of)

        self.assertEqual(points[0], (SUNDAY + timedelta(days=2), 0))
        self.assertEqual(points[1], (SUNDAY + timedelta(days=3), 5))
        self.assertEqual(points[-1], (as_of, 13))
        self.assertEqual(len(points), 1 + 8)

    def test_days_after_generation_time_in_the_current_week_are_not_drawn(self):
        as_of = SUNDAY + timedelta(days=1, hours=1)

        points = star.daily_points([week(SUNDAY, [2, 1, 0, 0, 0, 0, 0])], as_of)

        self.assertEqual([value for _, value in points], [0, 2, 3])
        self.assertLessEqual(max(moment for moment, _ in points), as_of)

    def test_a_history_without_any_star_is_refused_instead_of_publishing_an_empty_chart(self):
        with self.assertRaises(ValueError):
            star.daily_points([week(SUNDAY, [0] * 7)], SUNDAY + timedelta(days=8))


class CurveTests(unittest.TestCase):
    def test_every_curve_segment_stays_between_its_two_daily_values(self):
        values = [0, 0, 2, 2, 180, 3700, 8500, 10400, 11000, 11700, 12300]
        points = [(56 + 40 * index, 456 - value / 40) for index, value in enumerate(values)]

        path = star.monotone_path(points)

        segments = re.findall(r"C([-\d.]+),([-\d.]+),([-\d.]+),([-\d.]+),([-\d.]+),([-\d.]+)", path)
        self.assertEqual(len(segments), len(points) - 1)
        for (_, y0), segment in zip(points, segments):
            y1 = float(segment[5])
            low, high = sorted((y0, y1))
            for control in (float(segment[1]), float(segment[3])):
                self.assertGreaterEqual(control, low - 0.01)
                self.assertLessEqual(control, high + 0.01)


class RenderTests(unittest.TestCase):
    def test_both_themes_are_valid_svg_and_differ_only_in_colours(self):
        points = star.daily_points([week(SUNDAY, [1, 40, 900, 300, 50, 0, 0])], SUNDAY + timedelta(days=6))

        light = star.render(points, "owner/repo", "light")
        dark = star.render(points, "owner/repo", "dark")

        for svg in (light, dark):
            root = ET.fromstring(svg)
            self.assertEqual(root.get("width"), "900")
            self.assertIn("1,291", "".join(root.itertext()))
        strip = re.compile(r"#[0-9a-f]{6}")
        self.assertNotEqual(light, dark)
        self.assertEqual(strip.sub("", light), strip.sub("", dark))

    def test_value_ticks_cover_the_total_with_a_round_step(self):
        self.assertEqual(star.value_ticks(13071), [0, 5000, 10000])
        self.assertEqual(star.value_ticks(7), [0, 2, 4, 6])


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