"""Tests for the artifacts package.""" from __future__ import annotations from artifacts import hash_bytes, next_version, render_cover_letter, render_cv_pdf SAMPLE_PROFILE = { "full_name": "Joakim Morling", "headline": "Full-stack Engineer & Architect", "email": "jcamorling@gmail.com", "phone": "+46 76 006 7335", "location": "Malmo, Sweden", "summary": ( "Full-stack engineer with a passion for building robust systems. " "Experienced in government platforms and embedded ML. " "Swedish characters: å ä ö Å Ä Ö are important." ), } SAMPLE_SECTIONS = [ { "kind": "experience", "title": "Co-founder & Partner", "org": "Pro Firmitas ApS", "location": "Copenhagen, DK", "start_date": "2026-02", "end_date": None, "bullets": [ "Co-founded a consulting company building AI-enhanced software", "Responsible for technical architecture and client delivery", ], }, { "kind": "education", "title": "M.Sc. Computer Science & Engineering", "org": "Lund University (LTH)", "location": "Lund, SE", "start_date": "2018", "end_date": "2023", "bullets": [ "Master Thesis: optimized DBSCAN clustering for radar processing", ], }, ] SWEDISH_PROFILE = { "full_name": "Åke Öberg", "headline": "Mjukvaruingenjör - Full Stack", "email": "ake.oberg@example.se", "phone": "+46 70 123 4567", "location": "Malmö, Sverige", "summary": "Erfaren utvecklare med fokus på å ä ö Å Ä Ö i alla texter.", } SWEDISH_SECTIONS = [ { "kind": "experience", "title": "Senior Utvecklare", "org": "Företag AB", "location": "Göteborg", "start_date": "2020", "end_date": None, "bullets": [ "Byggde system med ångervektor och översättningsmotor", "Ansvarig för säkerhetsgranskning av ärendehantering", ], }, ] class TestRenderCvPdf: def test_returns_valid_pdf_bytes(self) -> None: result = render_cv_pdf(SAMPLE_PROFILE, SAMPLE_SECTIONS) assert isinstance(result, (bytes, bytearray)) assert bytes(result).startswith(b"%PDF") def test_swedish_characters_render(self) -> None: """Swedish characters must not raise an encoding error.""" result = render_cv_pdf(SWEDISH_PROFILE, SWEDISH_SECTIONS) assert bytes(result).startswith(b"%PDF") def test_content_hash_stable(self) -> None: """Same input should produce the same content hash.""" result_a = render_cv_pdf(SAMPLE_PROFILE, SAMPLE_SECTIONS) result_b = render_cv_pdf(SAMPLE_PROFILE, SAMPLE_SECTIONS) assert hash_bytes(bytes(result_a)) == hash_bytes(bytes(result_b)) def test_different_input_different_hash(self) -> None: result_a = render_cv_pdf(SAMPLE_PROFILE, SAMPLE_SECTIONS) result_b = render_cv_pdf(SWEDISH_PROFILE, SWEDISH_SECTIONS) assert hash_bytes(bytes(result_a)) != hash_bytes(bytes(result_b)) def test_empty_sections(self) -> None: result = render_cv_pdf(SAMPLE_PROFILE, []) assert bytes(result).startswith(b"%PDF") def test_minimal_profile(self) -> None: result = render_cv_pdf({"full_name": "Test Person"}, []) assert bytes(result).startswith(b"%PDF") class TestRenderCoverLetter: def test_returns_valid_pdf_bytes(self) -> None: result = render_cover_letter("Dear Hiring Manager,\n\nI am applying...", SAMPLE_PROFILE) assert bytes(result).startswith(b"%PDF") def test_swedish_text(self) -> None: text = "Hej! Jag söker jobbet. Mvh Åke Öberg." result = render_cover_letter(text, SWEDISH_PROFILE) assert bytes(result).startswith(b"%PDF") def test_content_hash_stable(self) -> None: text = "Cover letter body text." result_a = render_cover_letter(text, SAMPLE_PROFILE) result_b = render_cover_letter(text, SAMPLE_PROFILE) assert hash_bytes(bytes(result_a)) == hash_bytes(bytes(result_b)) class TestHashBytes: def test_known_value(self) -> None: assert hash_bytes(b"hello") == ( "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824" ) def test_empty_bytes(self) -> None: assert hash_bytes(b"") == ( "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" ) def test_different_input_different_hash(self) -> None: assert hash_bytes(b"a") != hash_bytes(b"b") class TestNextVersion: def test_empty_list(self) -> None: assert next_version([]) == 1 def test_sequential(self) -> None: assert next_version([1, 2, 3]) == 4 def test_gaps(self) -> None: assert next_version([1, 3]) == 4 def test_single(self) -> None: assert next_version([5]) == 6