From bf4e8d55c7ab9893439c2e7917aa8a3972275092 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 11 Feb 2026 10:56:50 +0000
Subject: [PATCH 1/5] Initial plan
From 2fa8481a24042dd05d4b0c07aa2e418d1f6af300 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 11 Feb 2026 11:06:49 +0000
Subject: [PATCH 2/5] Extract inline Python from workflow into scripts with
tests and fix bugs
- Move inline Python from sync-tag-definitions.yml into scripts/fetch_tag_types.py
and scripts/generate_tag_types.py for easier debugging and change tracking
- Fix re.sub() crash on Unicode escape sequences (e.g. \u2010) by using string
slicing instead of regex replacement
- Fix string vs integer key type mismatch when comparing JSON data
- Fix lexicographic sorting of type IDs
- Use ensure_ascii=False to preserve Unicode characters in output
- Add 28 tests covering all script functions
Co-authored-by: Misiu <1741838+Misiu@users.noreply.github.com>
---
.github/workflows/sync-tag-definitions.yml | 160 +--------
scripts/fetch_tag_types.py | 85 +++++
scripts/generate_tag_types.py | 157 +++++++++
tests/scripts/test_sync_tag_types.py | 377 +++++++++++++++++++++
4 files changed, 621 insertions(+), 158 deletions(-)
create mode 100644 scripts/fetch_tag_types.py
create mode 100644 scripts/generate_tag_types.py
create mode 100644 tests/scripts/test_sync_tag_types.py
diff --git a/.github/workflows/sync-tag-definitions.yml b/.github/workflows/sync-tag-definitions.yml
index d48fef3..c8ff2d2 100644
--- a/.github/workflows/sync-tag-definitions.yml
+++ b/.github/workflows/sync-tag-definitions.yml
@@ -29,167 +29,11 @@ jobs:
- name: Fetch tag type definitions from OpenEPaperLink
id: fetch
- run: |
- python3 << 'PYEOF'
- import urllib.request
- import json
- import re
-
- print("Fetching tag type files from OpenEPaperLink repository...")
-
- # Fetch the directory listing
- url = "https://github.com/OpenEPaperLink/OpenEPaperLink/tree/master/resources/tagtypes"
- headers = {'User-Agent': 'Mozilla/5.0'}
- req = urllib.request.Request(url, headers=headers)
-
- try:
- with urllib.request.urlopen(req, timeout=30) as response:
- html = response.read().decode('utf-8')
- json_files = re.findall(r'([0-9a-fA-F]+\.json)', html)
- json_files = sorted(set(json_files))
- print(f"Found {len(json_files)} tag type files")
- except Exception as e:
- print(f"Error fetching file list: {e}")
- exit(1)
-
- # Fetch all tag type definitions
- tag_types = {}
- errors = []
-
- for filename in json_files:
- url = f"https://raw.githubusercontent.com/OpenEPaperLink/OpenEPaperLink/master/resources/tagtypes/{filename}"
- try:
- with urllib.request.urlopen(url, timeout=10) as response:
- data = json.loads(response.read().decode('utf-8'))
- type_id = int(filename.replace('.json', ''), 16)
-
- # Extract only required fields
- tag_types[type_id] = {
- 'version': data.get('version'),
- 'name': data.get('name'),
- 'width': data.get('width'),
- 'height': data.get('height'),
- }
- except Exception as e:
- errors.append(f"Error fetching {filename}: {e}")
-
- if errors:
- for error in errors:
- print(error)
-
- print(f"Successfully fetched {len(tag_types)} tag type definitions")
-
- # Save to file for next step
- with open('new_tag_types.json', 'w') as f:
- json.dump(tag_types, f, indent=2)
-
- print("Tag types saved to new_tag_types.json")
- PYEOF
+ run: python3 scripts/fetch_tag_types.py new_tag_types.json
- name: Generate updated tag_types.py
id: generate
- run: |
- python3 << 'PYEOF'
- import json
- import re
-
- # Load new tag types
- with open('new_tag_types.json', 'r') as f:
- new_tag_types = json.load(f)
-
- # Read current tag_types.py
- with open('custom_components/opendisplay/tag_types.py', 'r') as f:
- content = f.read()
-
- # Extract current fallback definitions
- match = re.search(r'fallback_definitions = \{(.*?)\n \}', content, re.DOTALL)
- if not match:
- print("Error: Could not find fallback_definitions in tag_types.py")
- exit(1)
-
- current_definitions = match.group(1)
-
- # Parse current definitions to dict
- current_types = {}
- for line in current_definitions.split('\n'):
- match = re.match(r'\s+(\d+):', line)
- if match:
- type_id = int(match.group(1))
- current_types[type_id] = line.strip()
-
- print(f"Current definitions: {len(current_types)} types")
- print(f"New definitions: {len(new_tag_types)} types")
-
- # Check if there are differences
- changed = False
- added = []
- removed = []
- modified = []
-
- # Find added and modified
- for type_id in sorted(new_tag_types.keys()):
- if type_id not in current_types:
- added.append(type_id)
- changed = True
- else:
- # Compare values
- new_line = f'{type_id}: {json.dumps(new_tag_types[str(type_id)])}'
- if new_line not in current_types[type_id]:
- modified.append(type_id)
- changed = True
-
- # Find removed
- for type_id in current_types:
- if str(type_id) not in new_tag_types and type_id not in [int(k) for k in new_tag_types.keys()]:
- removed.append(type_id)
- changed = True
-
- # Generate new fallback_definitions content
- lines = []
- for type_id in sorted([int(k) for k in new_tag_types.keys()]):
- type_data = new_tag_types[str(type_id)]
- line = f' {type_id}: {json.dumps(type_data)},'
- lines.append(line)
-
- new_fallback = '\n'.join(lines)
-
- # Replace in content
- new_content = re.sub(
- r'(fallback_definitions = \{)\n.*?\n( \})',
- r'\1\n' + new_fallback + '\n\2',
- content,
- flags=re.DOTALL
- )
-
- # Write updated file
- with open('custom_components/opendisplay/tag_types.py', 'w') as f:
- f.write(new_content)
-
- # Create summary
- summary = []
- if added:
- summary.append(f"Added: {len(added)} types ({', '.join(map(str, added[:5]))}{'...' if len(added) > 5 else ''})")
- if removed:
- summary.append(f"Removed: {len(removed)} types ({', '.join(map(str, removed[:5]))}{'...' if len(removed) > 5 else ''})")
- if modified:
- summary.append(f"Modified: {len(modified)} types ({', '.join(map(str, modified[:5]))}{'...' if len(modified) > 5 else ''})")
-
- if changed:
- print("CHANGED=true")
- print(f"SUMMARY={'|'.join(summary)}")
- with open('CHANGES_SUMMARY.txt', 'w') as f:
- f.write('\n'.join(summary))
- else:
- print("CHANGED=false")
- print("No changes detected")
-
- # Set output for GitHub Actions
- import os
- with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
- f.write(f"changed={'true' if changed else 'false'}\n")
- if summary:
- f.write(f"summary={'|'.join(summary)}\n")
- PYEOF
+ run: python3 scripts/generate_tag_types.py new_tag_types.json
- name: Create Pull Request
if: steps.generate.outputs.changed == 'true'
diff --git a/scripts/fetch_tag_types.py b/scripts/fetch_tag_types.py
new file mode 100644
index 0000000..b891cc8
--- /dev/null
+++ b/scripts/fetch_tag_types.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python3
+"""Fetch tag type definitions from the OpenEPaperLink repository.
+
+Downloads all tag type JSON files from the OpenEPaperLink GitHub repository
+and saves them as a consolidated JSON file for further processing.
+"""
+
+import json
+import re
+import sys
+import urllib.request
+
+
+GITHUB_TREE_URL = (
+ "https://github.com/OpenEPaperLink/OpenEPaperLink/tree/master/resources/tagtypes"
+)
+GITHUB_RAW_URL = (
+ "https://raw.githubusercontent.com/OpenEPaperLink/OpenEPaperLink"
+ "/master/resources/tagtypes"
+)
+
+
+def fetch_file_list():
+ """Fetch the list of tag type JSON files from the repository."""
+ print("Fetching tag type files from OpenEPaperLink repository...")
+ headers = {"User-Agent": "Mozilla/5.0"}
+ req = urllib.request.Request(GITHUB_TREE_URL, headers=headers)
+
+ with urllib.request.urlopen(req, timeout=30) as response:
+ html = response.read().decode("utf-8")
+ json_files = re.findall(r"([0-9a-fA-F]+\.json)", html)
+ json_files = sorted(set(json_files))
+ print(f"Found {len(json_files)} tag type files")
+ return json_files
+
+
+def fetch_tag_types(json_files):
+ """Fetch and parse all tag type definitions."""
+ tag_types = {}
+ errors = []
+
+ for filename in json_files:
+ url = f"{GITHUB_RAW_URL}/{filename}"
+ try:
+ with urllib.request.urlopen(url, timeout=10) as response:
+ data = json.loads(response.read().decode("utf-8"))
+ type_id = int(filename.replace(".json", ""), 16)
+
+ tag_types[type_id] = {
+ "version": data.get("version"),
+ "name": data.get("name"),
+ "width": data.get("width"),
+ "height": data.get("height"),
+ }
+ except Exception as e:
+ errors.append(f"Error fetching {filename}: {e}")
+
+ if errors:
+ for error in errors:
+ print(error)
+
+ print(f"Successfully fetched {len(tag_types)} tag type definitions")
+ return tag_types
+
+
+def main():
+ """Fetch tag type definitions and save to a JSON file."""
+ output_file = sys.argv[1] if len(sys.argv) > 1 else "new_tag_types.json"
+
+ try:
+ json_files = fetch_file_list()
+ except Exception as e:
+ print(f"Error fetching file list: {e}")
+ sys.exit(1)
+
+ tag_types = fetch_tag_types(json_files)
+
+ with open(output_file, "w") as f:
+ json.dump(tag_types, f, indent=2)
+
+ print(f"Tag types saved to {output_file}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/generate_tag_types.py b/scripts/generate_tag_types.py
new file mode 100644
index 0000000..a467bb3
--- /dev/null
+++ b/scripts/generate_tag_types.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python3
+"""Generate updated tag_types.py from fetched tag type definitions.
+
+Reads a JSON file of tag type definitions (produced by fetch_tag_types.py),
+compares them against the current fallback definitions in tag_types.py,
+and updates the file if there are changes.
+
+Sets GitHub Actions outputs for downstream workflow steps.
+"""
+
+import json
+import os
+import re
+import sys
+
+
+TAG_TYPES_PATH = "custom_components/opendisplay/tag_types.py"
+FALLBACK_PATTERN = re.compile(
+ r"( fallback_definitions = \{)\n(.*?)\n( \})", re.DOTALL
+)
+ENTRY_PATTERN = re.compile(r"\s+(\d+):")
+
+
+def load_new_tag_types(input_file):
+ """Load new tag types from JSON, converting keys to integers."""
+ with open(input_file, "r") as f:
+ raw = json.load(f)
+ return {int(k): v for k, v in raw.items()}
+
+
+def parse_current_definitions(content):
+ """Extract current fallback definitions from tag_types.py content."""
+ match = FALLBACK_PATTERN.search(content)
+ if not match:
+ print("Error: Could not find fallback_definitions in tag_types.py")
+ sys.exit(1)
+
+ current_types = {}
+ for line in match.group(2).split("\n"):
+ m = ENTRY_PATTERN.match(line)
+ if m:
+ type_id = int(m.group(1))
+ current_types[type_id] = line.strip()
+
+ return current_types
+
+
+def compute_changes(current_types, new_tag_types):
+ """Compute added, removed, and modified tag types."""
+ added = []
+ removed = []
+ modified = []
+
+ for type_id in sorted(new_tag_types.keys()):
+ if type_id not in current_types:
+ added.append(type_id)
+ else:
+ new_line = f"{type_id}: {json.dumps(new_tag_types[type_id], ensure_ascii=False)},"
+ if new_line != current_types[type_id]:
+ modified.append(type_id)
+
+ for type_id in sorted(current_types.keys()):
+ if type_id not in new_tag_types:
+ removed.append(type_id)
+
+ return added, removed, modified
+
+
+def generate_fallback_content(new_tag_types):
+ """Generate the new fallback_definitions dict content."""
+ lines = []
+ for type_id in sorted(new_tag_types.keys()):
+ type_data = new_tag_types[type_id]
+ line = f" {type_id}: {json.dumps(type_data, ensure_ascii=False)},"
+ lines.append(line)
+ return "\n".join(lines)
+
+
+def update_tag_types_file(content, new_fallback):
+ """Replace fallback_definitions content in tag_types.py."""
+ match = FALLBACK_PATTERN.search(content)
+ if not match:
+ print("Error: Could not find fallback_definitions in tag_types.py")
+ sys.exit(1)
+
+ start = match.start(2)
+ end = match.end(2)
+ return content[:start] + new_fallback + content[end:]
+
+
+def build_summary(added, removed, modified):
+ """Build a human-readable summary of changes."""
+ summary = []
+ if added:
+ ids = ", ".join(map(str, added[:5]))
+ suffix = "..." if len(added) > 5 else ""
+ summary.append(f"Added: {len(added)} types ({ids}{suffix})")
+ if removed:
+ ids = ", ".join(map(str, removed[:5]))
+ suffix = "..." if len(removed) > 5 else ""
+ summary.append(f"Removed: {len(removed)} types ({ids}{suffix})")
+ if modified:
+ ids = ", ".join(map(str, modified[:5]))
+ suffix = "..." if len(modified) > 5 else ""
+ summary.append(f"Modified: {len(modified)} types ({ids}{suffix})")
+ return summary
+
+
+def set_github_output(changed, summary):
+ """Set GitHub Actions step outputs."""
+ github_output = os.environ.get("GITHUB_OUTPUT")
+ if not github_output:
+ return
+
+ with open(github_output, "a") as f:
+ f.write(f"changed={'true' if changed else 'false'}\n")
+ if summary:
+ f.write(f"summary={'|'.join(summary)}\n")
+
+
+def main():
+ """Generate updated tag_types.py from fetched definitions."""
+ input_file = sys.argv[1] if len(sys.argv) > 1 else "new_tag_types.json"
+
+ new_tag_types = load_new_tag_types(input_file)
+
+ with open(TAG_TYPES_PATH, "r") as f:
+ content = f.read()
+
+ current_types = parse_current_definitions(content)
+
+ print(f"Current definitions: {len(current_types)} types")
+ print(f"New definitions: {len(new_tag_types)} types")
+
+ added, removed, modified = compute_changes(current_types, new_tag_types)
+ changed = bool(added or removed or modified)
+
+ new_fallback = generate_fallback_content(new_tag_types)
+ new_content = update_tag_types_file(content, new_fallback)
+
+ with open(TAG_TYPES_PATH, "w") as f:
+ f.write(new_content)
+
+ summary = build_summary(added, removed, modified)
+
+ if changed:
+ print("CHANGED=true")
+ print(f"SUMMARY={'|'.join(summary)}")
+ else:
+ print("CHANGED=false")
+ print("No changes detected")
+
+ set_github_output(changed, summary)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/scripts/test_sync_tag_types.py b/tests/scripts/test_sync_tag_types.py
new file mode 100644
index 0000000..446d904
--- /dev/null
+++ b/tests/scripts/test_sync_tag_types.py
@@ -0,0 +1,377 @@
+"""Tests for the tag type sync scripts."""
+
+import json
+import os
+import re
+import textwrap
+from unittest.mock import MagicMock, patch
+
+import pytest
+
+# Add scripts directory to path so we can import the modules
+import sys
+
+REPO_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+sys.path.insert(0, os.path.join(REPO_ROOT, "scripts"))
+
+import fetch_tag_types
+import generate_tag_types
+
+
+# ---------------------------------------------------------------------------
+# Fixtures
+# ---------------------------------------------------------------------------
+
+SAMPLE_TAG_TYPES_PY = textwrap.dedent("""\
+ class Foo:
+ def _load_fallback_types(self):
+ fallback_definitions = {
+ 0: {"version": 4, "name": "M2 1.54\\"", "width": 152, "height": 152},
+ 1: {"version": 5, "name": "M2 2.9\\"", "width": 296, "height": 128},
+ 240: {"version": 2, "name": "SLT\u2010EM007 Segmented", "width": 0, "height": 0},
+ 250: {"version": 1, "name": "ConfigMode", "width": 0, "height": 0},
+ }
+ self._tag_types = {
+ type_id: TagType(type_id, data) for type_id, data in fallback_definitions.items()
+ }
+""")
+
+
+@pytest.fixture
+def tag_types_file(tmp_path):
+ """Write a minimal tag_types.py and return its path."""
+ p = tmp_path / "tag_types.py"
+ p.write_text(SAMPLE_TAG_TYPES_PY)
+ return p
+
+
+@pytest.fixture
+def new_types_json(tmp_path):
+ """Write a new_tag_types.json and return its path."""
+ data = {
+ 0: {"version": 4, "name": 'M2 1.54"', "width": 152, "height": 152},
+ 1: {"version": 5, "name": 'M2 2.9"', "width": 296, "height": 128},
+ 240: {"version": 2, "name": "SLT\u2010EM007 Segmented", "width": 0, "height": 0},
+ 250: {"version": 1, "name": "ConfigMode", "width": 0, "height": 0},
+ }
+ p = tmp_path / "new_tag_types.json"
+ p.write_text(json.dumps(data, indent=2))
+ return p
+
+
+# ---------------------------------------------------------------------------
+# Tests for generate_tag_types – load_new_tag_types
+# ---------------------------------------------------------------------------
+
+class TestLoadNewTagTypes:
+ """Tests for loading and converting JSON tag types."""
+
+ def test_keys_are_integers(self, new_types_json):
+ """JSON string keys must be converted to integers."""
+ result = generate_tag_types.load_new_tag_types(str(new_types_json))
+ assert all(isinstance(k, int) for k in result.keys())
+
+ def test_values_preserved(self, new_types_json):
+ """Tag type data values must be preserved after loading."""
+ result = generate_tag_types.load_new_tag_types(str(new_types_json))
+ assert result[0]["name"] == 'M2 1.54"'
+ assert result[250]["width"] == 0
+
+
+# ---------------------------------------------------------------------------
+# Tests for generate_tag_types – parse_current_definitions
+# ---------------------------------------------------------------------------
+
+class TestParseCurrentDefinitions:
+ """Tests for parsing fallback_definitions from tag_types.py."""
+
+ def test_parses_all_entries(self, tag_types_file):
+ """Should parse all entries from the fallback_definitions block."""
+ content = tag_types_file.read_text()
+ result = generate_tag_types.parse_current_definitions(content)
+ assert len(result) == 4
+ assert set(result.keys()) == {0, 1, 240, 250}
+
+ def test_keys_are_integers(self, tag_types_file):
+ """Parsed keys must be integers."""
+ content = tag_types_file.read_text()
+ result = generate_tag_types.parse_current_definitions(content)
+ assert all(isinstance(k, int) for k in result.keys())
+
+ def test_exits_on_missing_block(self):
+ """Should exit if fallback_definitions block is not found."""
+ with pytest.raises(SystemExit):
+ generate_tag_types.parse_current_definitions("no such block here")
+
+
+# ---------------------------------------------------------------------------
+# Tests for generate_tag_types – compute_changes
+# ---------------------------------------------------------------------------
+
+class TestComputeChanges:
+ """Tests for computing diffs between current and new definitions."""
+
+ def test_no_changes(self):
+ """Identical data should produce no changes."""
+ current = {
+ 0: '0: {"version": 4, "name": "Tag0", "width": 100, "height": 100},',
+ }
+ new = {0: {"version": 4, "name": "Tag0", "width": 100, "height": 100}}
+ added, removed, modified = generate_tag_types.compute_changes(current, new)
+ assert added == []
+ assert removed == []
+ assert modified == []
+
+ def test_added(self):
+ """New type IDs should be detected as added."""
+ current = {}
+ new = {5: {"version": 1, "name": "New", "width": 10, "height": 10}}
+ added, removed, modified = generate_tag_types.compute_changes(current, new)
+ assert added == [5]
+ assert removed == []
+
+ def test_removed(self):
+ """Missing type IDs should be detected as removed."""
+ current = {
+ 5: '5: {"version": 1, "name": "Old", "width": 10, "height": 10},',
+ }
+ new = {}
+ added, removed, modified = generate_tag_types.compute_changes(current, new)
+ assert removed == [5]
+ assert added == []
+
+ def test_modified(self):
+ """Changed values should be detected as modified."""
+ current = {
+ 0: '0: {"version": 1, "name": "Tag0", "width": 100, "height": 100},',
+ }
+ new = {0: {"version": 2, "name": "Tag0", "width": 100, "height": 100}}
+ added, removed, modified = generate_tag_types.compute_changes(current, new)
+ assert modified == [0]
+
+ def test_sorting(self):
+ """Results should be sorted numerically, not lexicographically."""
+ current = {}
+ new = {
+ 100: {"version": 1, "name": "A", "width": 1, "height": 1},
+ 2: {"version": 1, "name": "B", "width": 1, "height": 1},
+ 17: {"version": 1, "name": "C", "width": 1, "height": 1},
+ }
+ added, _, _ = generate_tag_types.compute_changes(current, new)
+ assert added == [2, 17, 100]
+
+
+# ---------------------------------------------------------------------------
+# Tests for generate_tag_types – generate_fallback_content
+# ---------------------------------------------------------------------------
+
+class TestGenerateFallbackContent:
+ """Tests for generating the fallback_definitions dict content."""
+
+ def test_format(self):
+ """Each line should have 12-space indent, type_id, JSON data, and trailing comma."""
+ data = {0: {"version": 1, "name": "Tag", "width": 10, "height": 20}}
+ content = generate_tag_types.generate_fallback_content(data)
+ assert content.startswith(" 0:")
+ assert content.endswith(",")
+
+ def test_sorted_numerically(self):
+ """Entries should be sorted by numeric type_id."""
+ data = {
+ 100: {"version": 1, "name": "A", "width": 1, "height": 1},
+ 2: {"version": 1, "name": "B", "width": 1, "height": 1},
+ 17: {"version": 1, "name": "C", "width": 1, "height": 1},
+ }
+ content = generate_tag_types.generate_fallback_content(data)
+ ids = [int(re.match(r"\s+(\d+):", line).group(1)) for line in content.split("\n")]
+ assert ids == [2, 17, 100]
+
+ def test_unicode_chars(self):
+ """Unicode characters in names should be handled without errors."""
+ data = {240: {"version": 2, "name": "SLT\u2010EM007", "width": 0, "height": 0}}
+ content = generate_tag_types.generate_fallback_content(data)
+ # Should contain the json-escaped unicode
+ assert "\\u2010" in content or "\u2010" in content
+
+
+# ---------------------------------------------------------------------------
+# Tests for generate_tag_types – update_tag_types_file
+# ---------------------------------------------------------------------------
+
+class TestUpdateTagTypesFile:
+ """Tests for replacing fallback_definitions in file content."""
+
+ def test_replaces_content(self, tag_types_file):
+ """The fallback block should be replaced with new content."""
+ content = tag_types_file.read_text()
+ new_fallback = ' 999: {"version": 1, "name": "New", "width": 1, "height": 1},'
+ result = generate_tag_types.update_tag_types_file(content, new_fallback)
+ assert "999:" in result
+ # Old entries removed
+ assert "250:" not in result
+
+ def test_preserves_surrounding_code(self, tag_types_file):
+ """Code around fallback_definitions should be unchanged."""
+ content = tag_types_file.read_text()
+ new_fallback = ' 999: {"version": 1, "name": "New", "width": 1, "height": 1},'
+ result = generate_tag_types.update_tag_types_file(content, new_fallback)
+ assert "class Foo:" in result
+ assert "self._tag_types" in result
+
+ def test_unicode_in_replacement(self, tag_types_file):
+ """Unicode escape sequences in replacement must not cause regex errors.
+
+ This is the primary bug that was fixed: json.dumps() produces \\uXXXX
+ sequences which re.sub() would interpret as bad regex escapes.
+ """
+ content = tag_types_file.read_text()
+ # This would fail with re.sub() because \u2010 is a bad regex escape
+ new_fallback = ' 240: {"version": 2, "name": "SLT\\u2010EM007", "width": 0, "height": 0},'
+ result = generate_tag_types.update_tag_types_file(content, new_fallback)
+ assert "\\u2010" in result
+
+ def test_exits_on_missing_block(self):
+ """Should exit if fallback_definitions block is not found."""
+ with pytest.raises(SystemExit):
+ generate_tag_types.update_tag_types_file("no such block", "replacement")
+
+
+# ---------------------------------------------------------------------------
+# Tests for generate_tag_types – build_summary
+# ---------------------------------------------------------------------------
+
+class TestBuildSummary:
+ """Tests for the human-readable change summary."""
+
+ def test_empty_on_no_changes(self):
+ assert generate_tag_types.build_summary([], [], []) == []
+
+ def test_added(self):
+ result = generate_tag_types.build_summary([1, 2], [], [])
+ assert len(result) == 1
+ assert "Added: 2" in result[0]
+
+ def test_truncated(self):
+ result = generate_tag_types.build_summary(list(range(10)), [], [])
+ assert "..." in result[0]
+
+
+# ---------------------------------------------------------------------------
+# Tests for generate_tag_types – set_github_output
+# ---------------------------------------------------------------------------
+
+class TestSetGithubOutput:
+ """Tests for writing GitHub Actions outputs."""
+
+ def test_writes_changed(self, tmp_path):
+ output_file = tmp_path / "output.txt"
+ output_file.write_text("")
+ with patch.dict(os.environ, {"GITHUB_OUTPUT": str(output_file)}):
+ generate_tag_types.set_github_output(True, ["Added: 1 types (5)"])
+ content = output_file.read_text()
+ assert "changed=true" in content
+ assert "summary=" in content
+
+ def test_no_op_without_env(self, tmp_path):
+ """Should not crash when GITHUB_OUTPUT is not set."""
+ with patch.dict(os.environ, {}, clear=True):
+ generate_tag_types.set_github_output(False, []) # should not raise
+
+
+# ---------------------------------------------------------------------------
+# Tests for generate_tag_types – full main() integration
+# ---------------------------------------------------------------------------
+
+class TestMainIntegration:
+ """Integration tests for the full generate_tag_types.main() flow."""
+
+ def test_no_change_run(self, tag_types_file, new_types_json, tmp_path):
+ """When data matches, output changed=false."""
+ output_file = tmp_path / "output.txt"
+ output_file.write_text("")
+ with patch.object(generate_tag_types, "TAG_TYPES_PATH", str(tag_types_file)), \
+ patch.dict(os.environ, {"GITHUB_OUTPUT": str(output_file)}), \
+ patch("sys.argv", ["prog", str(new_types_json)]):
+ generate_tag_types.main()
+ assert "changed=false" in output_file.read_text()
+
+ def test_added_type_run(self, tag_types_file, tmp_path):
+ """When a new type is added, output changed=true and file is updated."""
+ data = {
+ 0: {"version": 4, "name": 'M2 1.54"', "width": 152, "height": 152},
+ 1: {"version": 5, "name": 'M2 2.9"', "width": 296, "height": 128},
+ 240: {"version": 2, "name": "SLT\u2010EM007 Segmented", "width": 0, "height": 0},
+ 250: {"version": 1, "name": "ConfigMode", "width": 0, "height": 0},
+ 999: {"version": 1, "name": "Brand New", "width": 100, "height": 200},
+ }
+ json_file = tmp_path / "new.json"
+ json_file.write_text(json.dumps(data, indent=2))
+
+ output_file = tmp_path / "output.txt"
+ output_file.write_text("")
+ with patch.object(generate_tag_types, "TAG_TYPES_PATH", str(tag_types_file)), \
+ patch.dict(os.environ, {"GITHUB_OUTPUT": str(output_file)}), \
+ patch("sys.argv", ["prog", str(json_file)]):
+ generate_tag_types.main()
+ assert "changed=true" in output_file.read_text()
+ updated = tag_types_file.read_text()
+ assert "999:" in updated
+ assert "Brand New" in updated
+
+
+# ---------------------------------------------------------------------------
+# Tests for fetch_tag_types
+# ---------------------------------------------------------------------------
+
+class TestFetchTagTypes:
+ """Tests for the fetch_tag_types module."""
+
+ def test_fetch_file_list(self):
+ """fetch_file_list should parse JSON filenames from HTML."""
+ fake_html = '00.json 0A.json other.txt'
+ mock_response = MagicMock()
+ mock_response.read.return_value = fake_html.encode("utf-8")
+ mock_response.__enter__ = MagicMock(return_value=mock_response)
+ mock_response.__exit__ = MagicMock(return_value=False)
+
+ with patch("urllib.request.urlopen", return_value=mock_response):
+ result = fetch_tag_types.fetch_file_list()
+ assert result == ["00.json", "0A.json"]
+
+ def test_fetch_tag_types_parses_hex_ids(self):
+ """Filenames should be converted from hex to decimal type IDs."""
+ fake_json = json.dumps({
+ "version": 1, "name": "Test", "width": 100, "height": 50
+ }).encode("utf-8")
+
+ mock_response = MagicMock()
+ mock_response.read.return_value = fake_json
+ mock_response.__enter__ = MagicMock(return_value=mock_response)
+ mock_response.__exit__ = MagicMock(return_value=False)
+
+ with patch("urllib.request.urlopen", return_value=mock_response):
+ result = fetch_tag_types.fetch_tag_types(["0A.json"])
+ # 0x0A = 10
+ assert 10 in result
+ assert result[10]["name"] == "Test"
+
+ def test_fetch_tag_types_handles_errors(self):
+ """Errors fetching individual files should not crash the whole run."""
+ with patch("urllib.request.urlopen", side_effect=Exception("Network error")):
+ result = fetch_tag_types.fetch_tag_types(["00.json"])
+ assert result == {}
+
+ def test_main_writes_json(self, tmp_path):
+ """main() should write fetched data to the output JSON file."""
+ output = tmp_path / "out.json"
+
+ with patch.object(fetch_tag_types, "fetch_file_list", return_value=["01.json"]), \
+ patch.object(fetch_tag_types, "fetch_tag_types", return_value={
+ 1: {"version": 1, "name": "X", "width": 10, "height": 10}
+ }), \
+ patch("sys.argv", ["prog", str(output)]):
+ fetch_tag_types.main()
+
+ data = json.loads(output.read_text())
+ assert "1" in data # JSON keys are strings
+ assert data["1"]["name"] == "X"
From c5c6e528a0f10d84d9f1cb2630519f7636844b85 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 11 Feb 2026 11:07:47 +0000
Subject: [PATCH 3/5] Address code review: fix list comprehension safety and
tighten unicode assertion
Co-authored-by: Misiu <1741838+Misiu@users.noreply.github.com>
---
tests/scripts/test_sync_tag_types.py | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/tests/scripts/test_sync_tag_types.py b/tests/scripts/test_sync_tag_types.py
index 446d904..f35eeff 100644
--- a/tests/scripts/test_sync_tag_types.py
+++ b/tests/scripts/test_sync_tag_types.py
@@ -183,15 +183,19 @@ def test_sorted_numerically(self):
17: {"version": 1, "name": "C", "width": 1, "height": 1},
}
content = generate_tag_types.generate_fallback_content(data)
- ids = [int(re.match(r"\s+(\d+):", line).group(1)) for line in content.split("\n")]
+ ids = [
+ int(m.group(1))
+ for line in content.split("\n")
+ if (m := re.match(r"\s+(\d+):", line))
+ ]
assert ids == [2, 17, 100]
- def test_unicode_chars(self):
- """Unicode characters in names should be handled without errors."""
+ def test_unicode_chars_preserved(self):
+ """Unicode characters should be preserved (not escaped) with ensure_ascii=False."""
data = {240: {"version": 2, "name": "SLT\u2010EM007", "width": 0, "height": 0}}
content = generate_tag_types.generate_fallback_content(data)
- # Should contain the json-escaped unicode
- assert "\\u2010" in content or "\u2010" in content
+ # ensure_ascii=False preserves the actual Unicode character
+ assert "\u2010" in content
# ---------------------------------------------------------------------------
From 0d5e1db1d3375e08f9263c41b93a0c33ba838896 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 11 Feb 2026 11:42:19 +0000
Subject: [PATCH 4/5] Fix test_overlapping_elements: regenerate reference image
as JPEG
The reference image overlapping_elements.png was saved as a real PNG
while the image generator produces JPEG output. All other reference
images are JPEG data (with .png extension). This mismatch caused the
pixel-exact comparison to fail. Regenerated the reference from the
current image generator output.
Co-authored-by: Misiu <1741838+Misiu@users.noreply.github.com>
---
.../common/overlapping_elements.png | Bin 9172 -> 9224 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/tests/drawcustom/test_images/common/overlapping_elements.png b/tests/drawcustom/test_images/common/overlapping_elements.png
index 4c213b4ec6071bd1eda91feed566f95f0881a004..a8eab05fd554ecd0eaa3d32a2516f0ca0128a68f 100644
GIT binary patch
delta 6107
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
From ca6c29ee072c89f9f09fac70d429716d4b9087c7 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 11 Feb 2026 11:57:00 +0000
Subject: [PATCH 5/5] Rename JPEG test reference images from .png to .jpg
All 52 test reference images contain JPEG data (confirmed by FFD8FF
magic bytes) but had incorrect .png extensions. The image generator
(core.py:411) explicitly outputs JPEG format.
- Rename all 52 reference images from .png to .jpg
- Update all 15 test files to reference .jpg instead of .png
- Verified all 82 tests pass
Co-authored-by: Misiu <1741838+Misiu@users.noreply.github.com>
---
tests/drawcustom/arc_test.py | 4 +--
tests/drawcustom/circle_test.py | 6 ++--
tests/drawcustom/common_test.py | 10 +++----
tests/drawcustom/conftest.py | 2 +-
tests/drawcustom/debug_grid_test.py | 8 ++---
tests/drawcustom/ellipse_test.py | 4 +--
tests/drawcustom/icon_test.py | 2 +-
tests/drawcustom/line_test.py | 12 ++++----
tests/drawcustom/polygon_test.py | 4 +--
tests/drawcustom/progress_bar_test.py | 12 ++++----
tests/drawcustom/qr_code_test.py | 6 ++--
tests/drawcustom/rectangle_pattern_test.py | 6 ++--
tests/drawcustom/rectangle_test.py | 6 ++--
.../arc/{arc_basic.png => arc_basic.jpg} | Bin
...ie_slice_basic.png => pie_slice_basic.jpg} | Bin
.../test_images/{blank.png => blank.jpg} | Bin
.../{circle_filled.png => circle_filled.jpg} | Bin
...{circle_outline.png => circle_outline.jpg} | Bin
...e_percentage.png => circle_percentage.jpg} | Bin
...ple_elements.png => multiple_elements.jpg} | Bin
...ordinates.png => negative_coordinates.jpg} | Bin
..._elements.png => overlapping_elements.jpg} | Bin
...ize_elements.png => oversize_elements.jpg} | Bin
.../common/{rotated.png => rotated.jpg} | Bin
...ug_grid_basic.png => debug_grid_basic.jpg} | Bin
...cing.png => debug_grid_custom_spacing.jpg} | Bin
...ug_grid_solid.png => debug_grid_solid.jpg} | Bin
...bels.png => debug_grid_without_labels.jpg} | Bin
...llipse_drawing.png => ellipse_drawing.jpg} | Bin
...age.png => ellipse_drawing_percentage.jpg} | Bin
...d_line_basic.png => dashed_line_basic.jpg} | Bin
...ths.png => dashed_line_custom_lengths.jpg} | Bin
..._diagonal.png => dashed_line_diagonal.jpg} | Bin
..._vertical.png => dashed_line_vertical.jpg} | Bin
.../line/{line_basic.png => line_basic.jpg} | Bin
.../line/{line_custom.png => line_custom.jpg} | Bin
.../{polygon_basic.png => polygon_basic.jpg} | Bin
...{polygon_filled.png => polygon_filled.jpg} | Bin
.../{progress_bar.png => progress_bar.jpg} | Bin
...ess_bar_full.png => progress_bar_full.jpg} | Bin
...entage.png => progress_bar_percentage.jpg} | Bin
...ess_bar_zero.png => progress_bar_zero.jpg} | Bin
.../qr_code/{qr_code.png => qr_code.jpg} | Bin
.../{qr_code_long.png => qr_code_long.jpg} | Bin
..._percentage.png => qr_code_percentage.jpg} | Bin
...tangle_filled.png => rectangle_filled.jpg} | Bin
...ngle_outline.png => rectangle_outline.jpg} | Bin
...ners.png => rectangle_rounded_corners.jpg} | Bin
...ngle_pattern.png => rectangle_pattern.jpg} | Bin
... => rectangle_pattern_rounded_corners.jpg} | Bin
.../text/{large_font.png => large_font.jpg} | Bin
.../text/{small_font.png => small_font.jpg} | Bin
.../{text_anchors.png => text_anchors.jpg} | Bin
.../text/{text_basic.png => text_basic.jpg} | Bin
...color_markup.png => text_color_markup.jpg} | Bin
...t_mixed_fonts.png => text_mixed_fonts.jpg} | Bin
...ext_percentage.png => text_percentage.jpg} | Bin
...ecial_chars.png => text_special_chars.jpg} | Bin
.../{text_truncate.png => text_truncate.jpg} | Bin
.../{text_wrapping.png => text_wrapping.jpg} | Bin
...ng_anchor.png => text_wrapping_anchor.jpg} | Bin
...mpty_line.png => multiline_empty_line.jpg} | Bin
...{text_multiline.png => text_multiline.jpg} | Bin
...miter.png => text_multiline_delimiter.jpg} | Bin
... text_multiline_delimiter_and_newline.jpg} | Bin
tests/drawcustom/text_multiline_test.py | 14 ++++-----
tests/drawcustom/text_test.py | 28 +++++++++---------
67 files changed, 62 insertions(+), 62 deletions(-)
rename tests/drawcustom/test_images/arc/{arc_basic.png => arc_basic.jpg} (100%)
rename tests/drawcustom/test_images/arc/{pie_slice_basic.png => pie_slice_basic.jpg} (100%)
rename tests/drawcustom/test_images/{blank.png => blank.jpg} (100%)
rename tests/drawcustom/test_images/circle/{circle_filled.png => circle_filled.jpg} (100%)
rename tests/drawcustom/test_images/circle/{circle_outline.png => circle_outline.jpg} (100%)
rename tests/drawcustom/test_images/circle/{circle_percentage.png => circle_percentage.jpg} (100%)
rename tests/drawcustom/test_images/common/{multiple_elements.png => multiple_elements.jpg} (100%)
rename tests/drawcustom/test_images/common/{negative_coordinates.png => negative_coordinates.jpg} (100%)
rename tests/drawcustom/test_images/common/{overlapping_elements.png => overlapping_elements.jpg} (100%)
rename tests/drawcustom/test_images/common/{oversize_elements.png => oversize_elements.jpg} (100%)
rename tests/drawcustom/test_images/common/{rotated.png => rotated.jpg} (100%)
rename tests/drawcustom/test_images/debug_grid/{debug_grid_basic.png => debug_grid_basic.jpg} (100%)
rename tests/drawcustom/test_images/debug_grid/{debug_grid_custom_spacing.png => debug_grid_custom_spacing.jpg} (100%)
rename tests/drawcustom/test_images/debug_grid/{debug_grid_solid.png => debug_grid_solid.jpg} (100%)
rename tests/drawcustom/test_images/debug_grid/{debug_grid_without_labels.png => debug_grid_without_labels.jpg} (100%)
rename tests/drawcustom/test_images/ellipse/{ellipse_drawing.png => ellipse_drawing.jpg} (100%)
rename tests/drawcustom/test_images/ellipse/{ellipse_drawing_percentage.png => ellipse_drawing_percentage.jpg} (100%)
rename tests/drawcustom/test_images/line/{dashed_line_basic.png => dashed_line_basic.jpg} (100%)
rename tests/drawcustom/test_images/line/{dashed_line_custom_lengths.png => dashed_line_custom_lengths.jpg} (100%)
rename tests/drawcustom/test_images/line/{dashed_line_diagonal.png => dashed_line_diagonal.jpg} (100%)
rename tests/drawcustom/test_images/line/{dashed_line_vertical.png => dashed_line_vertical.jpg} (100%)
rename tests/drawcustom/test_images/line/{line_basic.png => line_basic.jpg} (100%)
rename tests/drawcustom/test_images/line/{line_custom.png => line_custom.jpg} (100%)
rename tests/drawcustom/test_images/polygon/{polygon_basic.png => polygon_basic.jpg} (100%)
rename tests/drawcustom/test_images/polygon/{polygon_filled.png => polygon_filled.jpg} (100%)
rename tests/drawcustom/test_images/progress_bar/{progress_bar.png => progress_bar.jpg} (100%)
rename tests/drawcustom/test_images/progress_bar/{progress_bar_full.png => progress_bar_full.jpg} (100%)
rename tests/drawcustom/test_images/progress_bar/{progress_bar_percentage.png => progress_bar_percentage.jpg} (100%)
rename tests/drawcustom/test_images/progress_bar/{progress_bar_zero.png => progress_bar_zero.jpg} (100%)
rename tests/drawcustom/test_images/qr_code/{qr_code.png => qr_code.jpg} (100%)
rename tests/drawcustom/test_images/qr_code/{qr_code_long.png => qr_code_long.jpg} (100%)
rename tests/drawcustom/test_images/qr_code/{qr_code_percentage.png => qr_code_percentage.jpg} (100%)
rename tests/drawcustom/test_images/rectangle/{rectangle_filled.png => rectangle_filled.jpg} (100%)
rename tests/drawcustom/test_images/rectangle/{rectangle_outline.png => rectangle_outline.jpg} (100%)
rename tests/drawcustom/test_images/rectangle/{rectangle_rounded_corners.png => rectangle_rounded_corners.jpg} (100%)
rename tests/drawcustom/test_images/rectangle_pattern/{rectangle_pattern.png => rectangle_pattern.jpg} (100%)
rename tests/drawcustom/test_images/rectangle_pattern/{rectangle_pattern_rounded_corners.png => rectangle_pattern_rounded_corners.jpg} (100%)
rename tests/drawcustom/test_images/text/{large_font.png => large_font.jpg} (100%)
rename tests/drawcustom/test_images/text/{small_font.png => small_font.jpg} (100%)
rename tests/drawcustom/test_images/text/{text_anchors.png => text_anchors.jpg} (100%)
rename tests/drawcustom/test_images/text/{text_basic.png => text_basic.jpg} (100%)
rename tests/drawcustom/test_images/text/{text_color_markup.png => text_color_markup.jpg} (100%)
rename tests/drawcustom/test_images/text/{text_mixed_fonts.png => text_mixed_fonts.jpg} (100%)
rename tests/drawcustom/test_images/text/{text_percentage.png => text_percentage.jpg} (100%)
rename tests/drawcustom/test_images/text/{text_special_chars.png => text_special_chars.jpg} (100%)
rename tests/drawcustom/test_images/text/{text_truncate.png => text_truncate.jpg} (100%)
rename tests/drawcustom/test_images/text/{text_wrapping.png => text_wrapping.jpg} (100%)
rename tests/drawcustom/test_images/text/{text_wrapping_anchor.png => text_wrapping_anchor.jpg} (100%)
rename tests/drawcustom/test_images/text_multiline/{multiline_empty_line.png => multiline_empty_line.jpg} (100%)
rename tests/drawcustom/test_images/text_multiline/{text_multiline.png => text_multiline.jpg} (100%)
rename tests/drawcustom/test_images/text_multiline/{text_multiline_delimiter.png => text_multiline_delimiter.jpg} (100%)
rename tests/drawcustom/test_images/text_multiline/{text_multiline_delimiter_and_newline.png => text_multiline_delimiter_and_newline.jpg} (100%)
diff --git a/tests/drawcustom/arc_test.py b/tests/drawcustom/arc_test.py
index 21c23c2..beb052f 100644
--- a/tests/drawcustom/arc_test.py
+++ b/tests/drawcustom/arc_test.py
@@ -31,7 +31,7 @@ async def test_arc_basic(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(ARC_IMG_PATH, 'arc_basic.png'))
+ example_img = Image.open(os.path.join(ARC_IMG_PATH, 'arc_basic.jpg'))
assert images_equal(generated_img, example_img), "Basic arc rendering failed"
@pytest.mark.asyncio
@@ -56,5 +56,5 @@ async def test_pie_slice_basic(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(ARC_IMG_PATH, 'pie_slice_basic.png'))
+ example_img = Image.open(os.path.join(ARC_IMG_PATH, 'pie_slice_basic.jpg'))
assert images_equal(generated_img, example_img), "Basic pie slice rendering failed"
\ No newline at end of file
diff --git a/tests/drawcustom/circle_test.py b/tests/drawcustom/circle_test.py
index ffe8154..0a13080 100644
--- a/tests/drawcustom/circle_test.py
+++ b/tests/drawcustom/circle_test.py
@@ -31,7 +31,7 @@ async def test_circle_filled(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(CIRCLE_IMG_PATH, 'circle_filled.png'))
+ example_img = Image.open(os.path.join(CIRCLE_IMG_PATH, 'circle_filled.jpg'))
assert images_equal(generated_img, example_img), "Basic filled circle rendering failed"
@pytest.mark.asyncio
@@ -55,7 +55,7 @@ async def test_circle_outline(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(CIRCLE_IMG_PATH, 'circle_outline.png'))
+ example_img = Image.open(os.path.join(CIRCLE_IMG_PATH, 'circle_outline.jpg'))
assert images_equal(generated_img, example_img), "Basic outline circle rendering failed"
@pytest.mark.asyncio
@@ -80,5 +80,5 @@ async def test_circle_percentage(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(CIRCLE_IMG_PATH, 'circle_percentage.png'))
+ example_img = Image.open(os.path.join(CIRCLE_IMG_PATH, 'circle_percentage.jpg'))
assert images_equal(generated_img, example_img), "Basic filled circle rendering failed"
diff --git a/tests/drawcustom/common_test.py b/tests/drawcustom/common_test.py
index a991340..ec55a69 100644
--- a/tests/drawcustom/common_test.py
+++ b/tests/drawcustom/common_test.py
@@ -30,7 +30,7 @@ async def test_multiple_elements(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(COMMON_IMG_PATH, 'multiple_elements.png'))
+ example_img = Image.open(os.path.join(COMMON_IMG_PATH, 'multiple_elements.jpg'))
assert images_equal(generated_img, example_img), "Multiple elements drawing failed"
@pytest.mark.asyncio
@@ -56,7 +56,7 @@ async def test_rotation(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(COMMON_IMG_PATH, 'rotated.png'))
+ example_img = Image.open(os.path.join(COMMON_IMG_PATH, 'rotated.jpg'))
assert images_equal(generated_img, example_img), "rotated elements drawing failed"
@pytest.mark.asyncio
@@ -76,7 +76,7 @@ async def test_oversize_elements(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(COMMON_IMG_PATH, 'oversize_elements.png'))
+ example_img = Image.open(os.path.join(COMMON_IMG_PATH, 'oversize_elements.jpg'))
assert images_equal(generated_img, example_img), "Oversize elements drawing failed"
@pytest.mark.asyncio
@@ -97,7 +97,7 @@ async def test_overlapping_elements(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(COMMON_IMG_PATH, 'overlapping_elements.png'))
+ example_img = Image.open(os.path.join(COMMON_IMG_PATH, 'overlapping_elements.jpg'))
assert images_equal(generated_img, example_img), "Overlapping elements drawing failed"
@pytest.mark.asyncio
@@ -117,5 +117,5 @@ async def test_negative_coordinates(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(COMMON_IMG_PATH, 'negative_coordinates.png'))
+ example_img = Image.open(os.path.join(COMMON_IMG_PATH, 'negative_coordinates.jpg'))
assert images_equal(generated_img, example_img), "Negative coordinate elements drawing failed"
diff --git a/tests/drawcustom/conftest.py b/tests/drawcustom/conftest.py
index f53cb65..cdeacc7 100644
--- a/tests/drawcustom/conftest.py
+++ b/tests/drawcustom/conftest.py
@@ -167,7 +167,7 @@ def images_equal(img1, img2):
def save_image(image_bytes):
"""Save image for debugging."""
- img_path = os.path.join(BASE_IMG_PATH, 'rename_me.png')
+ img_path = os.path.join(BASE_IMG_PATH, 'rename_me.jpg')
with open(img_path, 'wb') as f:
f.write(image_bytes)
diff --git a/tests/drawcustom/debug_grid_test.py b/tests/drawcustom/debug_grid_test.py
index 89d2075..dcbf9bf 100644
--- a/tests/drawcustom/debug_grid_test.py
+++ b/tests/drawcustom/debug_grid_test.py
@@ -26,7 +26,7 @@ async def test_debug_grid_basic(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(DEBUG_GRID_IMG_PATH, 'debug_grid_basic.png'))
+ example_img = Image.open(os.path.join(DEBUG_GRID_IMG_PATH, 'debug_grid_basic.jpg'))
assert images_equal(generated_img, example_img), "Basic debug grid rendering failed"
@pytest.mark.asyncio
@@ -47,7 +47,7 @@ async def test_debug_grid_custom_spacing(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(DEBUG_GRID_IMG_PATH, 'debug_grid_custom_spacing.png'))
+ example_img = Image.open(os.path.join(DEBUG_GRID_IMG_PATH, 'debug_grid_custom_spacing.jpg'))
assert images_equal(generated_img, example_img), "Custom spacing debug grid rendering failed"
@pytest.mark.asyncio
@@ -71,7 +71,7 @@ async def test_debug_grid_solid(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(DEBUG_GRID_IMG_PATH, 'debug_grid_solid.png'))
+ example_img = Image.open(os.path.join(DEBUG_GRID_IMG_PATH, 'debug_grid_solid.jpg'))
assert images_equal(generated_img, example_img), "Solid debug grid rendering failed"
@pytest.mark.asyncio
@@ -91,5 +91,5 @@ async def test_debug_grid_without_labels(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(DEBUG_GRID_IMG_PATH, 'debug_grid_without_labels.png'))
+ example_img = Image.open(os.path.join(DEBUG_GRID_IMG_PATH, 'debug_grid_without_labels.jpg'))
assert images_equal(generated_img, example_img), "Debug grid without labels rendering failed"
\ No newline at end of file
diff --git a/tests/drawcustom/ellipse_test.py b/tests/drawcustom/ellipse_test.py
index 44d1e5d..beb2955 100644
--- a/tests/drawcustom/ellipse_test.py
+++ b/tests/drawcustom/ellipse_test.py
@@ -32,7 +32,7 @@ async def test_circle_ellipse(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(ELLIPSE_IMG_PATH, 'ellipse_drawing.png'))
+ example_img = Image.open(os.path.join(ELLIPSE_IMG_PATH, 'ellipse_drawing.jpg'))
assert images_equal(generated_img, example_img), "Basic ellipse drawing failed"
@pytest.mark.asyncio
@@ -58,5 +58,5 @@ async def test_circle_ellipse_percentage(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(ELLIPSE_IMG_PATH, 'ellipse_drawing_percentage.png'))
+ example_img = Image.open(os.path.join(ELLIPSE_IMG_PATH, 'ellipse_drawing_percentage.jpg'))
assert images_equal(generated_img, example_img), "Basic ellipse drawing failed"
\ No newline at end of file
diff --git a/tests/drawcustom/icon_test.py b/tests/drawcustom/icon_test.py
index 69264b1..ee1edec 100644
--- a/tests/drawcustom/icon_test.py
+++ b/tests/drawcustom/icon_test.py
@@ -30,5 +30,5 @@
#
# generated_img = Image.open(BytesIO(image_data))
# save_image(image_data)
-# example_img = Image.open(os.path.join(ICON_IMG_PATH, 'icon_basic.png'))
+# example_img = Image.open(os.path.join(ICON_IMG_PATH, 'icon_basic.jpg'))
# assert images_equal(generated_img, example_img), "Basic icon rendering failed"
\ No newline at end of file
diff --git a/tests/drawcustom/line_test.py b/tests/drawcustom/line_test.py
index 12943d8..02a5a82 100644
--- a/tests/drawcustom/line_test.py
+++ b/tests/drawcustom/line_test.py
@@ -30,7 +30,7 @@ async def test_line_basic(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(LINE_IMG_PATH, 'line_basic.png'))
+ example_img = Image.open(os.path.join(LINE_IMG_PATH, 'line_basic.jpg'))
assert images_equal(generated_img, example_img), "Basic line rendering failed"
@pytest.mark.asyncio
@@ -55,7 +55,7 @@ async def test_line_custom(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(LINE_IMG_PATH, 'line_custom.png'))
+ example_img = Image.open(os.path.join(LINE_IMG_PATH, 'line_custom.jpg'))
assert images_equal(generated_img, example_img), "Custom line rendering failed"
@pytest.mark.asyncio
@@ -80,7 +80,7 @@ async def test_dashed_line_basic(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(LINE_IMG_PATH, 'dashed_line_basic.png'))
+ example_img = Image.open(os.path.join(LINE_IMG_PATH, 'dashed_line_basic.jpg'))
assert images_equal(generated_img, example_img), "Basic dashed line rendering failed"
@pytest.mark.asyncio
@@ -107,7 +107,7 @@ async def test_dashed_line_custom_lengths(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(LINE_IMG_PATH, 'dashed_line_custom_lengths.png'))
+ example_img = Image.open(os.path.join(LINE_IMG_PATH, 'dashed_line_custom_lengths.jpg'))
assert images_equal(generated_img, example_img), "Custom dashed line rendering failed"
@pytest.mark.asyncio
@@ -131,7 +131,7 @@ async def test_dashed_line_basic_vertical(image_gen, mock_tag_info):
return_value=mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(LINE_IMG_PATH, 'dashed_line_vertical.png'))
+ example_img = Image.open(os.path.join(LINE_IMG_PATH, 'dashed_line_vertical.jpg'))
assert images_equal(generated_img, example_img), "Vertical dashed line rendering failed"
@pytest.mark.asyncio
@@ -158,5 +158,5 @@ async def test_dashed_line_diagonal(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(LINE_IMG_PATH, 'dashed_line_diagonal.png'))
+ example_img = Image.open(os.path.join(LINE_IMG_PATH, 'dashed_line_diagonal.jpg'))
assert images_equal(generated_img, example_img), "Dashed line diagonal rendering failed"
\ No newline at end of file
diff --git a/tests/drawcustom/polygon_test.py b/tests/drawcustom/polygon_test.py
index af2eec1..2d7e7f0 100644
--- a/tests/drawcustom/polygon_test.py
+++ b/tests/drawcustom/polygon_test.py
@@ -26,7 +26,7 @@ async def test_polygon_basic(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(POLYGON_IMG_PATH, 'polygon_basic.png'))
+ example_img = Image.open(os.path.join(POLYGON_IMG_PATH, 'polygon_basic.jpg'))
assert images_equal(generated_img, example_img), "Basic polygon rendering failed"
@pytest.mark.asyncio
@@ -46,5 +46,5 @@ async def test_polygon_filled(image_gen, mock_tag_info):
return_value=mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(POLYGON_IMG_PATH, 'polygon_filled.png'))
+ example_img = Image.open(os.path.join(POLYGON_IMG_PATH, 'polygon_filled.jpg'))
assert images_equal(generated_img, example_img), "Filled polygon rendering failed"
\ No newline at end of file
diff --git a/tests/drawcustom/progress_bar_test.py b/tests/drawcustom/progress_bar_test.py
index 5c52abf..7443875 100644
--- a/tests/drawcustom/progress_bar_test.py
+++ b/tests/drawcustom/progress_bar_test.py
@@ -34,7 +34,7 @@ async def test_basic_progress_bar(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'progress_bar.png'))
+ example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'progress_bar.jpg'))
assert images_equal(generated_img, example_img), "Basic progress bar drawing failed"
@pytest.mark.asyncio
@@ -62,7 +62,7 @@ async def test_progress_bar_zero_progress(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'progress_bar_zero.png'))
+ example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'progress_bar_zero.jpg'))
assert images_equal(generated_img, example_img), "Basic progress bar drawing failed"
@pytest.mark.asyncio
@@ -91,7 +91,7 @@ async def test_progress_bar_full(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'progress_bar_full.png'))
+ example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'progress_bar_full.jpg'))
assert images_equal(generated_img, example_img), "Full progress bar drawing failed"
@pytest.mark.asyncio
@@ -119,7 +119,7 @@ async def test_progress_bar_negative_progress(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'progress_bar_zero.png'))
+ example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'progress_bar_zero.jpg'))
assert images_equal(generated_img, example_img), "Progress bar with negative percentage drawing failed"
@pytest.mark.asyncio
@@ -148,7 +148,7 @@ async def test_progress_bar_over_full(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'progress_bar_full.png'))
+ example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'progress_bar_full.jpg'))
assert images_equal(generated_img, example_img), "Over full progress bar drawing failed"
@pytest.mark.asyncio
@@ -175,5 +175,5 @@ async def test_basic_progress_bar_percentage(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'progress_bar_percentage.png'))
+ example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'progress_bar_percentage.jpg'))
assert images_equal(generated_img, example_img), "Basic progress bar with percentage drawing failed"
\ No newline at end of file
diff --git a/tests/drawcustom/qr_code_test.py b/tests/drawcustom/qr_code_test.py
index b317d89..8262b33 100644
--- a/tests/drawcustom/qr_code_test.py
+++ b/tests/drawcustom/qr_code_test.py
@@ -32,7 +32,7 @@ async def test_basic_qr_code(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'qr_code.png'))
+ example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'qr_code.jpg'))
assert images_equal(generated_img, example_img), "Basic qr code drawing failed"
@pytest.mark.asyncio
@@ -59,7 +59,7 @@ async def test_long_qr_code(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'qr_code_long.png'))
+ example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'qr_code_long.jpg'))
assert images_equal(generated_img, example_img), "Long qr code drawing failed"
@pytest.mark.asyncio
@@ -85,5 +85,5 @@ async def test_basic_qr_code_percentage(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'qr_code_percentage.png'))
+ example_img = Image.open(os.path.join(QR_CODE_IMG_PATH, 'qr_code_percentage.jpg'))
assert images_equal(generated_img, example_img), "Basic qr code drawing with percentage failed"
\ No newline at end of file
diff --git a/tests/drawcustom/rectangle_pattern_test.py b/tests/drawcustom/rectangle_pattern_test.py
index e066e89..b775823 100644
--- a/tests/drawcustom/rectangle_pattern_test.py
+++ b/tests/drawcustom/rectangle_pattern_test.py
@@ -36,7 +36,7 @@ async def test_rectangle_pattern(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(RECTANGLE_IMG_PATH, 'rectangle_pattern.png'))
+ example_img = Image.open(os.path.join(RECTANGLE_IMG_PATH, 'rectangle_pattern.jpg'))
assert images_equal(generated_img, example_img), "Rectangle pattern rendering failed"
@pytest.mark.asyncio
@@ -68,7 +68,7 @@ async def test_rectangle_pattern_rounded_corners(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(RECTANGLE_IMG_PATH, 'rectangle_pattern_rounded_corners.png'))
+ example_img = Image.open(os.path.join(RECTANGLE_IMG_PATH, 'rectangle_pattern_rounded_corners.jpg'))
assert images_equal(generated_img, example_img), "Rounded corner rectangle pattern rendering failed"
@pytest.mark.asyncio
@@ -98,5 +98,5 @@ async def test_rectangle_pattern(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(BASE_IMG_PATH, 'blank.png'))
+ example_img = Image.open(os.path.join(BASE_IMG_PATH, 'blank.jpg'))
assert images_equal(generated_img, example_img), "Rounded corner rectangle pattern rendering failed"
\ No newline at end of file
diff --git a/tests/drawcustom/rectangle_test.py b/tests/drawcustom/rectangle_test.py
index 7491f4b..00a35e3 100644
--- a/tests/drawcustom/rectangle_test.py
+++ b/tests/drawcustom/rectangle_test.py
@@ -32,7 +32,7 @@ async def test_rectangle_filled(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(RECTANGLE_IMG_PATH, 'rectangle_filled.png'))
+ example_img = Image.open(os.path.join(RECTANGLE_IMG_PATH, 'rectangle_filled.jpg'))
assert images_equal(generated_img, example_img), "Filled rectangle rendering failed"
@pytest.mark.asyncio
@@ -57,7 +57,7 @@ async def test_rectangle_outline(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(RECTANGLE_IMG_PATH, 'rectangle_outline.png'))
+ example_img = Image.open(os.path.join(RECTANGLE_IMG_PATH, 'rectangle_outline.jpg'))
assert images_equal(generated_img, example_img), "Outlined rectangle rendering failed"
@pytest.mark.asyncio
@@ -85,5 +85,5 @@ async def test_rectangle_rounded_corners(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(RECTANGLE_IMG_PATH, 'rectangle_rounded_corners.png'))
+ example_img = Image.open(os.path.join(RECTANGLE_IMG_PATH, 'rectangle_rounded_corners.jpg'))
assert images_equal(generated_img, example_img), "Rounded corner rectangle rendering failed"
\ No newline at end of file
diff --git a/tests/drawcustom/test_images/arc/arc_basic.png b/tests/drawcustom/test_images/arc/arc_basic.jpg
similarity index 100%
rename from tests/drawcustom/test_images/arc/arc_basic.png
rename to tests/drawcustom/test_images/arc/arc_basic.jpg
diff --git a/tests/drawcustom/test_images/arc/pie_slice_basic.png b/tests/drawcustom/test_images/arc/pie_slice_basic.jpg
similarity index 100%
rename from tests/drawcustom/test_images/arc/pie_slice_basic.png
rename to tests/drawcustom/test_images/arc/pie_slice_basic.jpg
diff --git a/tests/drawcustom/test_images/blank.png b/tests/drawcustom/test_images/blank.jpg
similarity index 100%
rename from tests/drawcustom/test_images/blank.png
rename to tests/drawcustom/test_images/blank.jpg
diff --git a/tests/drawcustom/test_images/circle/circle_filled.png b/tests/drawcustom/test_images/circle/circle_filled.jpg
similarity index 100%
rename from tests/drawcustom/test_images/circle/circle_filled.png
rename to tests/drawcustom/test_images/circle/circle_filled.jpg
diff --git a/tests/drawcustom/test_images/circle/circle_outline.png b/tests/drawcustom/test_images/circle/circle_outline.jpg
similarity index 100%
rename from tests/drawcustom/test_images/circle/circle_outline.png
rename to tests/drawcustom/test_images/circle/circle_outline.jpg
diff --git a/tests/drawcustom/test_images/circle/circle_percentage.png b/tests/drawcustom/test_images/circle/circle_percentage.jpg
similarity index 100%
rename from tests/drawcustom/test_images/circle/circle_percentage.png
rename to tests/drawcustom/test_images/circle/circle_percentage.jpg
diff --git a/tests/drawcustom/test_images/common/multiple_elements.png b/tests/drawcustom/test_images/common/multiple_elements.jpg
similarity index 100%
rename from tests/drawcustom/test_images/common/multiple_elements.png
rename to tests/drawcustom/test_images/common/multiple_elements.jpg
diff --git a/tests/drawcustom/test_images/common/negative_coordinates.png b/tests/drawcustom/test_images/common/negative_coordinates.jpg
similarity index 100%
rename from tests/drawcustom/test_images/common/negative_coordinates.png
rename to tests/drawcustom/test_images/common/negative_coordinates.jpg
diff --git a/tests/drawcustom/test_images/common/overlapping_elements.png b/tests/drawcustom/test_images/common/overlapping_elements.jpg
similarity index 100%
rename from tests/drawcustom/test_images/common/overlapping_elements.png
rename to tests/drawcustom/test_images/common/overlapping_elements.jpg
diff --git a/tests/drawcustom/test_images/common/oversize_elements.png b/tests/drawcustom/test_images/common/oversize_elements.jpg
similarity index 100%
rename from tests/drawcustom/test_images/common/oversize_elements.png
rename to tests/drawcustom/test_images/common/oversize_elements.jpg
diff --git a/tests/drawcustom/test_images/common/rotated.png b/tests/drawcustom/test_images/common/rotated.jpg
similarity index 100%
rename from tests/drawcustom/test_images/common/rotated.png
rename to tests/drawcustom/test_images/common/rotated.jpg
diff --git a/tests/drawcustom/test_images/debug_grid/debug_grid_basic.png b/tests/drawcustom/test_images/debug_grid/debug_grid_basic.jpg
similarity index 100%
rename from tests/drawcustom/test_images/debug_grid/debug_grid_basic.png
rename to tests/drawcustom/test_images/debug_grid/debug_grid_basic.jpg
diff --git a/tests/drawcustom/test_images/debug_grid/debug_grid_custom_spacing.png b/tests/drawcustom/test_images/debug_grid/debug_grid_custom_spacing.jpg
similarity index 100%
rename from tests/drawcustom/test_images/debug_grid/debug_grid_custom_spacing.png
rename to tests/drawcustom/test_images/debug_grid/debug_grid_custom_spacing.jpg
diff --git a/tests/drawcustom/test_images/debug_grid/debug_grid_solid.png b/tests/drawcustom/test_images/debug_grid/debug_grid_solid.jpg
similarity index 100%
rename from tests/drawcustom/test_images/debug_grid/debug_grid_solid.png
rename to tests/drawcustom/test_images/debug_grid/debug_grid_solid.jpg
diff --git a/tests/drawcustom/test_images/debug_grid/debug_grid_without_labels.png b/tests/drawcustom/test_images/debug_grid/debug_grid_without_labels.jpg
similarity index 100%
rename from tests/drawcustom/test_images/debug_grid/debug_grid_without_labels.png
rename to tests/drawcustom/test_images/debug_grid/debug_grid_without_labels.jpg
diff --git a/tests/drawcustom/test_images/ellipse/ellipse_drawing.png b/tests/drawcustom/test_images/ellipse/ellipse_drawing.jpg
similarity index 100%
rename from tests/drawcustom/test_images/ellipse/ellipse_drawing.png
rename to tests/drawcustom/test_images/ellipse/ellipse_drawing.jpg
diff --git a/tests/drawcustom/test_images/ellipse/ellipse_drawing_percentage.png b/tests/drawcustom/test_images/ellipse/ellipse_drawing_percentage.jpg
similarity index 100%
rename from tests/drawcustom/test_images/ellipse/ellipse_drawing_percentage.png
rename to tests/drawcustom/test_images/ellipse/ellipse_drawing_percentage.jpg
diff --git a/tests/drawcustom/test_images/line/dashed_line_basic.png b/tests/drawcustom/test_images/line/dashed_line_basic.jpg
similarity index 100%
rename from tests/drawcustom/test_images/line/dashed_line_basic.png
rename to tests/drawcustom/test_images/line/dashed_line_basic.jpg
diff --git a/tests/drawcustom/test_images/line/dashed_line_custom_lengths.png b/tests/drawcustom/test_images/line/dashed_line_custom_lengths.jpg
similarity index 100%
rename from tests/drawcustom/test_images/line/dashed_line_custom_lengths.png
rename to tests/drawcustom/test_images/line/dashed_line_custom_lengths.jpg
diff --git a/tests/drawcustom/test_images/line/dashed_line_diagonal.png b/tests/drawcustom/test_images/line/dashed_line_diagonal.jpg
similarity index 100%
rename from tests/drawcustom/test_images/line/dashed_line_diagonal.png
rename to tests/drawcustom/test_images/line/dashed_line_diagonal.jpg
diff --git a/tests/drawcustom/test_images/line/dashed_line_vertical.png b/tests/drawcustom/test_images/line/dashed_line_vertical.jpg
similarity index 100%
rename from tests/drawcustom/test_images/line/dashed_line_vertical.png
rename to tests/drawcustom/test_images/line/dashed_line_vertical.jpg
diff --git a/tests/drawcustom/test_images/line/line_basic.png b/tests/drawcustom/test_images/line/line_basic.jpg
similarity index 100%
rename from tests/drawcustom/test_images/line/line_basic.png
rename to tests/drawcustom/test_images/line/line_basic.jpg
diff --git a/tests/drawcustom/test_images/line/line_custom.png b/tests/drawcustom/test_images/line/line_custom.jpg
similarity index 100%
rename from tests/drawcustom/test_images/line/line_custom.png
rename to tests/drawcustom/test_images/line/line_custom.jpg
diff --git a/tests/drawcustom/test_images/polygon/polygon_basic.png b/tests/drawcustom/test_images/polygon/polygon_basic.jpg
similarity index 100%
rename from tests/drawcustom/test_images/polygon/polygon_basic.png
rename to tests/drawcustom/test_images/polygon/polygon_basic.jpg
diff --git a/tests/drawcustom/test_images/polygon/polygon_filled.png b/tests/drawcustom/test_images/polygon/polygon_filled.jpg
similarity index 100%
rename from tests/drawcustom/test_images/polygon/polygon_filled.png
rename to tests/drawcustom/test_images/polygon/polygon_filled.jpg
diff --git a/tests/drawcustom/test_images/progress_bar/progress_bar.png b/tests/drawcustom/test_images/progress_bar/progress_bar.jpg
similarity index 100%
rename from tests/drawcustom/test_images/progress_bar/progress_bar.png
rename to tests/drawcustom/test_images/progress_bar/progress_bar.jpg
diff --git a/tests/drawcustom/test_images/progress_bar/progress_bar_full.png b/tests/drawcustom/test_images/progress_bar/progress_bar_full.jpg
similarity index 100%
rename from tests/drawcustom/test_images/progress_bar/progress_bar_full.png
rename to tests/drawcustom/test_images/progress_bar/progress_bar_full.jpg
diff --git a/tests/drawcustom/test_images/progress_bar/progress_bar_percentage.png b/tests/drawcustom/test_images/progress_bar/progress_bar_percentage.jpg
similarity index 100%
rename from tests/drawcustom/test_images/progress_bar/progress_bar_percentage.png
rename to tests/drawcustom/test_images/progress_bar/progress_bar_percentage.jpg
diff --git a/tests/drawcustom/test_images/progress_bar/progress_bar_zero.png b/tests/drawcustom/test_images/progress_bar/progress_bar_zero.jpg
similarity index 100%
rename from tests/drawcustom/test_images/progress_bar/progress_bar_zero.png
rename to tests/drawcustom/test_images/progress_bar/progress_bar_zero.jpg
diff --git a/tests/drawcustom/test_images/qr_code/qr_code.png b/tests/drawcustom/test_images/qr_code/qr_code.jpg
similarity index 100%
rename from tests/drawcustom/test_images/qr_code/qr_code.png
rename to tests/drawcustom/test_images/qr_code/qr_code.jpg
diff --git a/tests/drawcustom/test_images/qr_code/qr_code_long.png b/tests/drawcustom/test_images/qr_code/qr_code_long.jpg
similarity index 100%
rename from tests/drawcustom/test_images/qr_code/qr_code_long.png
rename to tests/drawcustom/test_images/qr_code/qr_code_long.jpg
diff --git a/tests/drawcustom/test_images/qr_code/qr_code_percentage.png b/tests/drawcustom/test_images/qr_code/qr_code_percentage.jpg
similarity index 100%
rename from tests/drawcustom/test_images/qr_code/qr_code_percentage.png
rename to tests/drawcustom/test_images/qr_code/qr_code_percentage.jpg
diff --git a/tests/drawcustom/test_images/rectangle/rectangle_filled.png b/tests/drawcustom/test_images/rectangle/rectangle_filled.jpg
similarity index 100%
rename from tests/drawcustom/test_images/rectangle/rectangle_filled.png
rename to tests/drawcustom/test_images/rectangle/rectangle_filled.jpg
diff --git a/tests/drawcustom/test_images/rectangle/rectangle_outline.png b/tests/drawcustom/test_images/rectangle/rectangle_outline.jpg
similarity index 100%
rename from tests/drawcustom/test_images/rectangle/rectangle_outline.png
rename to tests/drawcustom/test_images/rectangle/rectangle_outline.jpg
diff --git a/tests/drawcustom/test_images/rectangle/rectangle_rounded_corners.png b/tests/drawcustom/test_images/rectangle/rectangle_rounded_corners.jpg
similarity index 100%
rename from tests/drawcustom/test_images/rectangle/rectangle_rounded_corners.png
rename to tests/drawcustom/test_images/rectangle/rectangle_rounded_corners.jpg
diff --git a/tests/drawcustom/test_images/rectangle_pattern/rectangle_pattern.png b/tests/drawcustom/test_images/rectangle_pattern/rectangle_pattern.jpg
similarity index 100%
rename from tests/drawcustom/test_images/rectangle_pattern/rectangle_pattern.png
rename to tests/drawcustom/test_images/rectangle_pattern/rectangle_pattern.jpg
diff --git a/tests/drawcustom/test_images/rectangle_pattern/rectangle_pattern_rounded_corners.png b/tests/drawcustom/test_images/rectangle_pattern/rectangle_pattern_rounded_corners.jpg
similarity index 100%
rename from tests/drawcustom/test_images/rectangle_pattern/rectangle_pattern_rounded_corners.png
rename to tests/drawcustom/test_images/rectangle_pattern/rectangle_pattern_rounded_corners.jpg
diff --git a/tests/drawcustom/test_images/text/large_font.png b/tests/drawcustom/test_images/text/large_font.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text/large_font.png
rename to tests/drawcustom/test_images/text/large_font.jpg
diff --git a/tests/drawcustom/test_images/text/small_font.png b/tests/drawcustom/test_images/text/small_font.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text/small_font.png
rename to tests/drawcustom/test_images/text/small_font.jpg
diff --git a/tests/drawcustom/test_images/text/text_anchors.png b/tests/drawcustom/test_images/text/text_anchors.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text/text_anchors.png
rename to tests/drawcustom/test_images/text/text_anchors.jpg
diff --git a/tests/drawcustom/test_images/text/text_basic.png b/tests/drawcustom/test_images/text/text_basic.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text/text_basic.png
rename to tests/drawcustom/test_images/text/text_basic.jpg
diff --git a/tests/drawcustom/test_images/text/text_color_markup.png b/tests/drawcustom/test_images/text/text_color_markup.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text/text_color_markup.png
rename to tests/drawcustom/test_images/text/text_color_markup.jpg
diff --git a/tests/drawcustom/test_images/text/text_mixed_fonts.png b/tests/drawcustom/test_images/text/text_mixed_fonts.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text/text_mixed_fonts.png
rename to tests/drawcustom/test_images/text/text_mixed_fonts.jpg
diff --git a/tests/drawcustom/test_images/text/text_percentage.png b/tests/drawcustom/test_images/text/text_percentage.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text/text_percentage.png
rename to tests/drawcustom/test_images/text/text_percentage.jpg
diff --git a/tests/drawcustom/test_images/text/text_special_chars.png b/tests/drawcustom/test_images/text/text_special_chars.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text/text_special_chars.png
rename to tests/drawcustom/test_images/text/text_special_chars.jpg
diff --git a/tests/drawcustom/test_images/text/text_truncate.png b/tests/drawcustom/test_images/text/text_truncate.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text/text_truncate.png
rename to tests/drawcustom/test_images/text/text_truncate.jpg
diff --git a/tests/drawcustom/test_images/text/text_wrapping.png b/tests/drawcustom/test_images/text/text_wrapping.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text/text_wrapping.png
rename to tests/drawcustom/test_images/text/text_wrapping.jpg
diff --git a/tests/drawcustom/test_images/text/text_wrapping_anchor.png b/tests/drawcustom/test_images/text/text_wrapping_anchor.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text/text_wrapping_anchor.png
rename to tests/drawcustom/test_images/text/text_wrapping_anchor.jpg
diff --git a/tests/drawcustom/test_images/text_multiline/multiline_empty_line.png b/tests/drawcustom/test_images/text_multiline/multiline_empty_line.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text_multiline/multiline_empty_line.png
rename to tests/drawcustom/test_images/text_multiline/multiline_empty_line.jpg
diff --git a/tests/drawcustom/test_images/text_multiline/text_multiline.png b/tests/drawcustom/test_images/text_multiline/text_multiline.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text_multiline/text_multiline.png
rename to tests/drawcustom/test_images/text_multiline/text_multiline.jpg
diff --git a/tests/drawcustom/test_images/text_multiline/text_multiline_delimiter.png b/tests/drawcustom/test_images/text_multiline/text_multiline_delimiter.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text_multiline/text_multiline_delimiter.png
rename to tests/drawcustom/test_images/text_multiline/text_multiline_delimiter.jpg
diff --git a/tests/drawcustom/test_images/text_multiline/text_multiline_delimiter_and_newline.png b/tests/drawcustom/test_images/text_multiline/text_multiline_delimiter_and_newline.jpg
similarity index 100%
rename from tests/drawcustom/test_images/text_multiline/text_multiline_delimiter_and_newline.png
rename to tests/drawcustom/test_images/text_multiline/text_multiline_delimiter_and_newline.jpg
diff --git a/tests/drawcustom/text_multiline_test.py b/tests/drawcustom/text_multiline_test.py
index 6ebbf8e..3b13f6b 100644
--- a/tests/drawcustom/text_multiline_test.py
+++ b/tests/drawcustom/text_multiline_test.py
@@ -32,7 +32,7 @@ async def test_text_multiline_basic(image_gen, mock_tag_info):
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'text_multiline.png'))
+ example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'text_multiline.jpg'))
assert images_equal(generated_img, example_img), "Basic text rendering failed"
@pytest.mark.asyncio
@@ -59,7 +59,7 @@ async def test_text_multiline_delimiter(image_gen, mock_tag_info):
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'text_multiline_delimiter.png'))
+ example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'text_multiline_delimiter.jpg'))
assert images_equal(generated_img, example_img), "Multiline text with delimiter rendering failed"
@pytest.mark.asyncio
@@ -85,7 +85,7 @@ async def test_text_multiline_empty_line(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'multiline_empty_line.png'))
+ example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'multiline_empty_line.jpg'))
assert images_equal(generated_img, example_img), "Multiline text with empty line rendering failed"
@pytest.mark.asyncio
@@ -111,7 +111,7 @@ async def test_text_multiline_delimiter_and_newline(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'text_multiline_delimiter_and_newline.png'))
+ example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'text_multiline_delimiter_and_newline.jpg'))
assert images_equal(generated_img, example_img), "Multiline text with delimiter and newline rendering failed"
# @pytest.mark.asyncio
@@ -142,7 +142,7 @@ async def test_text_multiline_delimiter_and_newline(image_gen, mock_tag_info):
#
# generated_img = Image.open(BytesIO(image_data))
# save_image(image_data)
-# example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'calendar_format.png'))
+# example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'calendar_format.jpg'))
# assert images_equal(generated_img, example_img), "Calendar format multiline rendering failed"
#
# @pytest.mark.asyncio
@@ -172,7 +172,7 @@ async def test_text_multiline_delimiter_and_newline(image_gen, mock_tag_info):
# )
#
# generated_img = Image.open(BytesIO(image_data))
-# example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'multiline_blank_lines.png'))
+# example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'multiline_blank_lines.jpg'))
# assert images_equal(generated_img, example_img), "Multiline text with blank lines rendering failed"
#
# @pytest.mark.asyncio
@@ -202,5 +202,5 @@ async def test_text_multiline_delimiter_and_newline(image_gen, mock_tag_info):
# )
#
# generated_img = Image.open(BytesIO(image_data))
-# example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'multiline_whitespace.png'))
+# example_img = Image.open(os.path.join(TEXT_MULTILINE_IMG_PATH, 'multiline_whitespace.jpg'))
# assert images_equal(generated_img, example_img), "Multiline text whitespace handling failed"
\ No newline at end of file
diff --git a/tests/drawcustom/text_test.py b/tests/drawcustom/text_test.py
index b278445..d64e6d6 100644
--- a/tests/drawcustom/text_test.py
+++ b/tests/drawcustom/text_test.py
@@ -31,7 +31,7 @@ async def test_text_basic(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_basic.png'))
+ example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_basic.jpg'))
assert images_equal(generated_img, example_img), "Basic text rendering failed"
@@ -55,7 +55,7 @@ async def test_small_font_size(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'small_font.png'))
+ example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'small_font.jpg'))
assert images_equal(generated_img, example_img), "Small font size rendering failed"
@@ -79,7 +79,7 @@ async def test_large_font_size(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'large_font.png'))
+ example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'large_font.jpg'))
assert images_equal(generated_img, example_img), "Large font size rendering failed"
@@ -104,7 +104,7 @@ async def test_text_wrapping(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_wrapping.png'))
+ example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_wrapping.jpg'))
assert images_equal(generated_img, example_img), "Text wrapping failed"
async def test_text_wrapping_with_anchor(image_gen, mock_tag_info):
@@ -130,7 +130,7 @@ async def test_text_wrapping_with_anchor(image_gen, mock_tag_info):
generated_img = Image.open(BytesIO(image_data))
save_image(image_data)
- example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_wrapping_anchor.png'))
+ example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_wrapping_anchor.jpg'))
assert images_equal(generated_img, example_img), "Text wrapping failed"
@@ -161,7 +161,7 @@ async def test_text_with_special_characters(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_special_chars.png'))
+ example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_special_chars.jpg'))
assert images_equal(generated_img, example_img), "Special characters rendering failed"
@@ -195,7 +195,7 @@ async def test_text_color_markup(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_color_markup.png'))
+ example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_color_markup.jpg'))
assert images_equal(generated_img, example_img), "Color markup rendering failed"
@pytest.mark.asyncio
@@ -220,7 +220,7 @@ async def test_text_percentage(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_percentage.png'))
+ example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_percentage.jpg'))
assert images_equal(generated_img, example_img), "Text with percentage rendering failed"
# @pytest.mark.asyncio
@@ -266,7 +266,7 @@ async def test_text_percentage(image_gen, mock_tag_info):
#
# generated_img = Image.open(BytesIO(image_data))
# save_image(image_data)
-# example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_alignment.png'))
+# example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_alignment.jpg'))
# assert images_equal(generated_img, example_img), "Text alignment failed"
@pytest.mark.asyncio
@@ -311,7 +311,7 @@ async def test_text_anchors(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_anchors.png'))
+ example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_anchors.jpg'))
assert images_equal(generated_img, example_img), "Text anchor points failed"
@pytest.mark.asyncio
@@ -346,7 +346,7 @@ async def test_text_mixed_fonts(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_mixed_fonts.png'))
+ example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_mixed_fonts.jpg'))
assert images_equal(generated_img, example_img), "Mixed fonts rendering failed"
@pytest.mark.asyncio
@@ -370,7 +370,7 @@ async def test_text_empty_string(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(BASE_IMG_PATH, 'blank.png'))
+ example_img = Image.open(os.path.join(BASE_IMG_PATH, 'blank.jpg'))
assert images_equal(generated_img, example_img), "Empty text handling failed"
async def test_text_truncate(image_gen, mock_tag_info):
@@ -395,7 +395,7 @@ async def test_text_truncate(image_gen, mock_tag_info):
image_data = await generate_test_image(image_gen, service_data)
generated_img = Image.open(BytesIO(image_data))
- example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_truncate.png'))
+ example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_truncate.jpg'))
assert images_equal(generated_img, example_img), "Text truncation failed"
# @pytest.mark.asyncio
@@ -445,5 +445,5 @@ async def test_text_truncate(image_gen, mock_tag_info):
# )
#
# generated_img = Image.open(BytesIO(image_data))
-# example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_basic.png'))
+# example_img = Image.open(os.path.join(TEXT_IMG_PATH, 'text_basic.jpg'))
# assert images_equal(generated_img, example_img), "Basic text rendering failed"
\ No newline at end of file