-
Notifications
You must be signed in to change notification settings - Fork 1
π§ͺ [Testing] Add coverage for validate_list_items_length #675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a32020a
8f9a83c
fd36937
a7a3688
50a1dc0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,6 @@ | ||
| ## 2024-05-20 - Ensure visual feedback for Copy to Clipboard actions | ||
| **Learning:** Adding a toast notification using a library like `sonner` is a crucial micro-interaction for copy-to-clipboard functionality. Users lack confidence when clicking a copy button without visual confirmation, and this small change significantly improves the perceived reliability of the UI. | ||
| **Action:** Always verify that interactive elements, especially non-destructive actions like copying or sharing, have immediate visual feedback in the form of a toast or inline confirmation. | ||
| ## 2024-05-26 - Avoid Redundant `aria-disabled` Attributes | ||
| **Learning:** Adding an `aria-disabled` attribute to a button that already uses the native HTML `disabled` attribute is redundant and considered an ARIA anti-pattern. Native `disabled` inherently communicates the state to assistive technologies and removes the element from the tab order. | ||
| **Action:** When improving loading states for buttons, rely on the native `disabled` attribute and use `aria-busy={loading}` to inform screen readers of the active process without duplicating the disabled state. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -162,7 +162,7 @@ def to_claude_mcp_tool_stub(ir: SkillExportIR) -> list[dict[str, str]]: | |
| @mcp.tool() | ||
| async def {tool_name}({param_signature}) -> str: | ||
| \"\"\"{ir.purpose or f"Execute {tool_name}."}\"\"\" | ||
| return "TODO: implement {tool_name}" | ||
| raise NotImplementedError("TODO: implement {tool_name}") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Export stub now raises |
||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,9 @@ | |
| from datetime import datetime, timezone | ||
| from pathlib import Path | ||
| from typing import List, Optional | ||
| import logging | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| @dataclass | ||
|
|
@@ -45,7 +48,8 @@ def load(self) -> None: | |
| data = orjson.loads(self.path.read_bytes()) | ||
| else: | ||
| data = {} | ||
| except Exception: | ||
| except Exception as e: | ||
| logger.error("Failed to load history: %s", e) | ||
| data = {} | ||
| self.queries = [ | ||
| QueryEntry( | ||
|
|
@@ -77,8 +81,8 @@ def save(self) -> None: | |
| # Bolt Optimization: orjson.dumps is significantly faster than json.dumps | ||
| # for serializing history payloads to disk. | ||
| self.path.write_bytes(orjson.dumps(payload, option=orjson.OPT_INDENT_2)) | ||
| except Exception: | ||
| pass | ||
| except Exception as e: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Save failures are now logged instead of silently swallowed. Worth confirming callers still handle partial persistence correctly when disk writes fail. |
||
| logger.error("Failed to save RAG history: %s", e) | ||
|
|
||
| def add_query(self, query: str, method: str, k: int) -> None: | ||
| if not query: | ||
|
|
@@ -139,7 +143,7 @@ def format_timestamp(self, ts: str) -> str: | |
| try: | ||
| dt = datetime.fromisoformat(ts) | ||
| return dt.strftime("%b %d %H:%M") | ||
| except Exception: | ||
| except ValueError: | ||
| return ts | ||
|
|
||
| def _now(self) -> str: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| import pytest | ||
| from pydantic import ValidationError | ||
|
|
||
| from api.routes.generators import GitHubRepoContextPayload | ||
|
|
||
|
|
||
| def test_github_repo_context_payload_valid_lists(): | ||
| # Should not raise any validation error, test with short strings and exactly 1024 characters | ||
| payload = GitHubRepoContextPayload( | ||
| normalized_repo_url="https://github.com/foo/bar", | ||
| repo_full_name="foo/bar", | ||
| summary="A summary", | ||
| highlights=["short item 1", "a" * 1024], | ||
| files_used=["file1.py"], | ||
| detected_stack=["python", "fastapi"], | ||
| ) | ||
| assert payload.highlights == ["short item 1", "a" * 1024] | ||
| assert payload.files_used == ["file1.py"] | ||
| assert payload.detected_stack == ["python", "fastapi"] | ||
|
|
||
|
|
||
| def test_github_repo_context_payload_empty_lists(): | ||
| # Should not raise any validation error | ||
| payload = GitHubRepoContextPayload( | ||
| normalized_repo_url="https://github.com/foo/bar", | ||
| repo_full_name="foo/bar", | ||
| summary="A summary", | ||
| highlights=[], | ||
| files_used=[], | ||
| detected_stack=[], | ||
| ) | ||
| assert payload.highlights == [] | ||
| assert payload.files_used == [] | ||
| assert payload.detected_stack == [] | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("field_name", ["highlights", "files_used", "detected_stack"]) | ||
| def test_github_repo_context_payload_exceeds_max_length(field_name): | ||
| # Create valid base data | ||
| data = { | ||
| "normalized_repo_url": "https://github.com/foo/bar", | ||
| "repo_full_name": "foo/bar", | ||
| "summary": "A summary", | ||
| } | ||
|
|
||
| # Add the invalid field with an item that exceeds 1024 characters | ||
| data[field_name] = ["valid", "a" * 1025] | ||
|
|
||
| with pytest.raises(ValidationError) as exc_info: | ||
| GitHubRepoContextPayload(**data) | ||
|
|
||
| assert "Item in list exceeds maximum length of 1024 characters" in str(exc_info.value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exc_info=exclogs a traceback here (works in Py3), but differs from the usualexc_info=Trueinsideexceptblocks. Worth a quick sanity check that compile fallback logs remain complete in production log aggregation.