mirror of
https://github.com/Hopiu/bowser.git
synced 2026-03-16 19:10:24 +00:00
Refactor test files to remove unnecessary imports and improve readability
- Removed unused imports from various test files to streamline code. - Cleaned up whitespace in test cases for better consistency. - Updated dependency management in `uv.lock` to reflect changes in optional dependencies. - Ensured all tests maintain functionality while enhancing clarity and organization.
This commit is contained in:
parent
4b3ba9144d
commit
c9ef5e5c44
29 changed files with 989 additions and 625 deletions
345
.github/skills/skills.md
vendored
Normal file
345
.github/skills/skills.md
vendored
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
# Skills Index
|
||||
|
||||
This file defines **canonical project skills** the LLM must follow. Each skill specifies the *one correct command* for a common project action.
|
||||
|
||||
1. **Run the Project** → `uv run bowser`
|
||||
2. **Test the Project** → `uv run pytest`
|
||||
3. **Lint the Project** → `uv run ruff`
|
||||
|
||||
Deviating from these commands is considered incorrect behavior unless explicitly instructed.
|
||||
|
||||
---
|
||||
|
||||
# Skill: Run the Project with `uv run bowser`
|
||||
|
||||
## Purpose
|
||||
Teach the LLM **how and when to run this project** using the canonical command:
|
||||
|
||||
```bash
|
||||
uv run bowser
|
||||
```
|
||||
|
||||
This skill ensures the LLM consistently uses the correct entry point, avoids ad‑hoc commands, and follows project conventions.
|
||||
|
||||
---
|
||||
|
||||
## Canonical Command
|
||||
|
||||
**Always run the project using:**
|
||||
|
||||
```bash
|
||||
uv run bowser
|
||||
```
|
||||
|
||||
Do **not**:
|
||||
- Call `python` directly
|
||||
- Run scripts via file paths
|
||||
- Use alternative task runners (e.g. `make`, `poetry run`, `pipenv run`)
|
||||
|
||||
`uv` is the authoritative environment and dependency manager for this project, and `bowser` is the defined runtime entry point.
|
||||
|
||||
---
|
||||
|
||||
## What `uv run bowser` Means
|
||||
|
||||
- `uv run`:
|
||||
- Ensures dependencies are resolved and installed according to the project configuration
|
||||
- Executes commands inside the correct, isolated environment
|
||||
|
||||
- `bowser`:
|
||||
- The project’s primary executable / CLI
|
||||
- Encapsulates startup logic, configuration loading, and runtime behavior
|
||||
|
||||
Together, they guarantee a reproducible and correct execution environment.
|
||||
|
||||
---
|
||||
|
||||
## When to Use This Command
|
||||
|
||||
Use `uv run bowser` whenever you need to:
|
||||
|
||||
- Start the application
|
||||
- Run the main service or agent
|
||||
- Execute project logic end‑to‑end
|
||||
- Validate runtime behavior
|
||||
- Demonstrate how the project is launched
|
||||
|
||||
If the task says **“run the project”**, **“start the app”**, or **“execute Bowser”**, this is the command.
|
||||
|
||||
---
|
||||
|
||||
## When *Not* to Use This Command
|
||||
|
||||
Do **not** use `uv run bowser` when:
|
||||
|
||||
- Running tests (use the project’s test command instead)
|
||||
- Running one‑off scripts unless explicitly routed through `bowser`
|
||||
- Installing dependencies
|
||||
- Linting or formatting code
|
||||
|
||||
If unsure, default to **not running anything** and explain what would be executed.
|
||||
|
||||
---
|
||||
|
||||
## How to Explain This to Humans
|
||||
|
||||
When documenting or instructing users, say:
|
||||
|
||||
> “Run the project with `uv run bowser`.”
|
||||
|
||||
Optionally add:
|
||||
|
||||
> “This ensures the correct environment and entry point are used.”
|
||||
|
||||
Do **not** over‑explain unless the user asks.
|
||||
|
||||
---
|
||||
|
||||
## Error Handling Guidance
|
||||
|
||||
If `uv run bowser` fails:
|
||||
|
||||
1. Assume a dependency or configuration issue
|
||||
2. Report the error output verbatim
|
||||
3. Do **not** substitute another execution method
|
||||
4. Suggest fixing the root cause, not changing the command
|
||||
|
||||
---
|
||||
|
||||
## Mental Model for the LLM
|
||||
|
||||
- There is **one** correct way to run the project
|
||||
- That way is **stable and intentional**
|
||||
- Deviating from it is a bug
|
||||
|
||||
Think of `uv run bowser` as:
|
||||
|
||||
> “The project’s on‑switch.”
|
||||
|
||||
---
|
||||
|
||||
## Summary (Checklist)
|
||||
|
||||
Before suggesting how to run the project, verify:
|
||||
|
||||
- [ ] You are using `uv run`
|
||||
- [ ] You are invoking `bowser`
|
||||
- [ ] You are not calling Python directly
|
||||
- [ ] You are not inventing alternate commands
|
||||
|
||||
If all are true, you are doing it right.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# Skill: Test the Project with `uv run pytest`
|
||||
|
||||
## Purpose
|
||||
Teach the LLM **how and when to run tests** for this project using the canonical command:
|
||||
|
||||
```bash
|
||||
uv run pytest
|
||||
```
|
||||
|
||||
This skill ensures tests are executed in the correct environment, using the project’s standard tooling, without inventing alternate commands.
|
||||
|
||||
---
|
||||
|
||||
## Canonical Command
|
||||
|
||||
**Always run tests using:**
|
||||
|
||||
```bash
|
||||
uv run pytest
|
||||
```
|
||||
|
||||
Do **not**:
|
||||
- Call `pytest` directly
|
||||
- Use `python -m pytest`
|
||||
- Run tests via ad-hoc scripts or task runners
|
||||
|
||||
`uv` is the authoritative environment manager, and `pytest` is the test runner for this project.
|
||||
|
||||
---
|
||||
|
||||
## What `uv run pytest` Means
|
||||
|
||||
- `uv run`:
|
||||
- Ensures dependencies (including test dependencies) are resolved correctly
|
||||
- Runs inside the same environment model as the application
|
||||
|
||||
- `pytest`:
|
||||
- Discovers and runs the project’s test suite
|
||||
- Applies project-level configuration (e.g. `pytest.ini`, `pyproject.toml`)
|
||||
|
||||
Together, they guarantee consistent and reproducible test execution.
|
||||
|
||||
---
|
||||
|
||||
## When to Use This Command
|
||||
|
||||
Use `uv run pytest` whenever you need to:
|
||||
|
||||
- Run the full test suite
|
||||
- Verify a change before or after modifying code
|
||||
- Reproduce a failing test
|
||||
- Validate behavior without starting the application
|
||||
|
||||
If the task says **“run tests”**, **“test the project”**, or **“verify with pytest”**, this is the command.
|
||||
|
||||
---
|
||||
|
||||
## When *Not* to Use This Command
|
||||
|
||||
Do **not** use `uv run pytest` when:
|
||||
|
||||
- Running the application (use `uv run bowser`)
|
||||
- Installing dependencies
|
||||
- Linting or formatting code
|
||||
- Executing non-test scripts
|
||||
|
||||
If unsure, default to explaining what tests would be run rather than executing them.
|
||||
|
||||
---
|
||||
|
||||
## Error Handling Guidance
|
||||
|
||||
If `uv run pytest` fails:
|
||||
|
||||
1. Capture and report the full pytest output
|
||||
2. Identify whether the failure is:
|
||||
- A test assertion failure
|
||||
- A missing dependency or import error
|
||||
- A configuration issue
|
||||
3. Do **not** change the command to work around the failure
|
||||
4. Fix the underlying cause, then re-run the same command
|
||||
|
||||
---
|
||||
|
||||
## Mental Model for the LLM
|
||||
|
||||
- There is **one** correct way to run tests
|
||||
- Test execution should mirror the real runtime environment
|
||||
- Consistency matters more than convenience
|
||||
|
||||
Think of `uv run pytest` as:
|
||||
|
||||
> “The project’s truth-check.”
|
||||
|
||||
---
|
||||
|
||||
## Summary (Checklist)
|
||||
|
||||
Before suggesting how to test the project, verify:
|
||||
|
||||
- [ ] You are using `uv run`
|
||||
- [ ] You are invoking `pytest`
|
||||
- [ ] You are not calling Python directly
|
||||
- [ ] You are not inventing alternate test commands
|
||||
|
||||
If all are true, you are doing it right.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# Skill: Lint the Project with `uv run ruff`
|
||||
|
||||
## Purpose
|
||||
Teach the LLM **how and when to lint the project** using the canonical command:
|
||||
|
||||
```bash
|
||||
uv run ruff
|
||||
```
|
||||
|
||||
This skill ensures linting is performed consistently, using the project’s configured rules and environment.
|
||||
|
||||
---
|
||||
|
||||
## Canonical Command
|
||||
|
||||
**Always lint the project using:**
|
||||
|
||||
```bash
|
||||
uv run ruff
|
||||
```
|
||||
|
||||
Do **not**:
|
||||
- Call `ruff` directly
|
||||
- Use alternative linters unless explicitly instructed
|
||||
- Invoke formatting or linting via ad-hoc scripts
|
||||
|
||||
`uv` guarantees the correct environment, and `ruff` enforces the project’s linting standards.
|
||||
|
||||
---
|
||||
|
||||
## What `uv run ruff` Means
|
||||
|
||||
- `uv run`:
|
||||
- Executes linting inside the managed project environment
|
||||
- Ensures the correct version of `ruff` and dependencies are used
|
||||
|
||||
- `ruff`:
|
||||
- Performs fast, opinionated linting
|
||||
- Applies rules configured in project files (e.g. `pyproject.toml`)
|
||||
|
||||
Together, they provide deterministic and repeatable lint results.
|
||||
|
||||
---
|
||||
|
||||
## When to Use This Command
|
||||
|
||||
Use `uv run ruff` whenever you need to:
|
||||
|
||||
- Check code quality
|
||||
- Identify linting or style issues
|
||||
- Validate changes before committing
|
||||
- Respond to a request to “lint the project” or “run ruff”
|
||||
|
||||
---
|
||||
|
||||
## When *Not* to Use This Command
|
||||
|
||||
Do **not** use `uv run ruff` when:
|
||||
|
||||
- Running the application (`uv run bowser`)
|
||||
- Running tests (`uv run pytest`)
|
||||
- Formatting code unless `ruff` is explicitly configured to do so
|
||||
- Installing dependencies
|
||||
|
||||
If unsure, explain what linting would check instead of executing it.
|
||||
|
||||
---
|
||||
|
||||
## Error Handling Guidance
|
||||
|
||||
If `uv run ruff` reports issues:
|
||||
|
||||
1. Treat findings as authoritative
|
||||
2. Report errors or warnings clearly
|
||||
3. Do **not** suppress or bypass lint rules
|
||||
4. Fix the code, then re-run the same command
|
||||
|
||||
---
|
||||
|
||||
## Mental Model for the LLM
|
||||
|
||||
- Linting enforces shared standards
|
||||
- Speed and consistency matter more than flexibility
|
||||
- There is **one** correct linting command
|
||||
|
||||
Think of `uv run ruff` as:
|
||||
|
||||
> “The project’s code-quality gate.”
|
||||
|
||||
---
|
||||
|
||||
## Summary (Checklist)
|
||||
|
||||
Before suggesting how to lint the project, verify:
|
||||
|
||||
- [ ] You are using `uv run`
|
||||
- [ ] You are invoking `ruff`
|
||||
- [ ] You are not inventing alternate linting tools
|
||||
|
||||
If all are true, you are doing it right.
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ dependencies = [
|
|||
"Jinja2>=3.0", # Template engine for pages
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=9.0.0",
|
||||
"pytest-cov>=7.0.0",
|
||||
|
|
@ -35,12 +35,14 @@ managed = true
|
|||
packages = ["src"]
|
||||
|
||||
[tool.black]
|
||||
line-length = 100
|
||||
line-length = 120
|
||||
target-version = ["py311"]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 100
|
||||
line-length = 120
|
||||
target-version = "py311"
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E", "F", "W"]
|
||||
|
||||
[tool.mypy]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# ruff: noqa: E402
|
||||
"""Browser entry and orchestration."""
|
||||
|
||||
import gi
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# ruff: noqa: E402
|
||||
"""Browser chrome (Adwaita UI)."""
|
||||
|
||||
import gi
|
||||
|
|
@ -433,8 +434,10 @@ class Chrome:
|
|||
# Store sub-timings for display
|
||||
if self.debug_mode:
|
||||
self._render_sub_timings = sub_timings
|
||||
self._visible_line_count = len([l for l in self.text_layout
|
||||
if self.scroll_y - 50 <= l["y"] + l["font_size"] <= self.scroll_y + height + 50])
|
||||
self._visible_line_count = len([
|
||||
line for line in self.text_layout
|
||||
if self.scroll_y - 50 <= line["y"] + line["font_size"] <= self.scroll_y + height + 50
|
||||
])
|
||||
|
||||
def _draw_selection_highlight(self, canvas, width: int):
|
||||
"""Draw selection highlight rectangle."""
|
||||
|
|
@ -531,7 +534,13 @@ class Chrome:
|
|||
if self._render_sub_timings:
|
||||
y += 16
|
||||
text_paint.setColor(skia.Color(150, 200, 255, 255))
|
||||
canvas.drawString(f"render_dom breakdown ({self._visible_line_count} lines):", panel_x + 5, y, small_font, text_paint)
|
||||
canvas.drawString(
|
||||
f"render_dom breakdown ({self._visible_line_count} lines):",
|
||||
panel_x + 5,
|
||||
y,
|
||||
small_font,
|
||||
text_paint,
|
||||
)
|
||||
|
||||
sub_sorted = sorted(self._render_sub_timings.items(), key=lambda x: x[1], reverse=True)
|
||||
for name, duration in sub_sorted:
|
||||
|
|
@ -750,7 +759,7 @@ class Chrome:
|
|||
line_bottom = line_info["y"] + line_info["height"]
|
||||
line_left = line_info["x"]
|
||||
char_positions = line_info.get("char_positions", [])
|
||||
text = line_info["text"]
|
||||
# text not needed for highlight geometry
|
||||
|
||||
# Skip lines completely outside selection
|
||||
if line_bottom < sel_start[1] or line_top > sel_end[1]:
|
||||
|
|
@ -764,13 +773,21 @@ class Chrome:
|
|||
if line_top <= sel_start[1] < line_bottom:
|
||||
# Find character index at sel_start x
|
||||
start_char_idx = self._x_to_char_index(sel_start[0], line_left, char_positions)
|
||||
hl_left = line_left + char_positions[start_char_idx] if start_char_idx < len(char_positions) else line_left
|
||||
hl_left = (
|
||||
line_left + char_positions[start_char_idx]
|
||||
if start_char_idx < len(char_positions)
|
||||
else line_left
|
||||
)
|
||||
|
||||
# If this line contains the end of selection
|
||||
if line_top <= sel_end[1] < line_bottom:
|
||||
# Find character index at sel_end x
|
||||
end_char_idx = self._x_to_char_index(sel_end[0], line_left, char_positions)
|
||||
hl_right = line_left + char_positions[end_char_idx] if end_char_idx < len(char_positions) else hl_right
|
||||
hl_right = (
|
||||
line_left + char_positions[end_char_idx]
|
||||
if end_char_idx < len(char_positions)
|
||||
else hl_right
|
||||
)
|
||||
|
||||
# Draw highlight
|
||||
if hl_right > hl_left:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"""Tab and frame orchestration stubs."""
|
||||
|
||||
from typing import Optional
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
import logging
|
||||
|
||||
from ..network.url import URL
|
||||
|
|
@ -8,6 +8,9 @@ from ..network import http
|
|||
from ..parser.html import parse_html, Element
|
||||
from ..templates import render_startpage, render_error_page
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .browser import Browser
|
||||
|
||||
|
||||
class Frame:
|
||||
def __init__(self, tab: "Tab", parent_frame=None, frame_element=None):
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
from ..parser.html import Element, Text
|
||||
from ..render.fonts import get_font, linespace
|
||||
from .block import BlockLayout, LineLayout
|
||||
|
||||
|
||||
class LayoutLine:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"""Inline and text layout."""
|
||||
|
||||
from ..render.fonts import get_font, measure_text, linespace
|
||||
from ..render.fonts import get_font, linespace
|
||||
|
||||
|
||||
class TextLayout:
|
||||
|
|
|
|||
|
|
@ -7,7 +7,12 @@ import logging
|
|||
from .url import URL
|
||||
|
||||
|
||||
def request(url: URL, payload: Optional[bytes] = None, method: str = "GET", max_redirects: int = 10) -> Tuple[int, str, bytes]:
|
||||
def request(
|
||||
url: URL,
|
||||
payload: Optional[bytes] = None,
|
||||
method: str = "GET",
|
||||
max_redirects: int = 10,
|
||||
) -> Tuple[int, str, bytes]:
|
||||
"""
|
||||
Fetch a URL and follow redirects, returning (status_code, content_type, body).
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from typing import Optional
|
|||
from ..parser.html import Element
|
||||
from ..layout.document import DocumentLayout
|
||||
from .fonts import get_font
|
||||
from .paint import DisplayList, DrawText, DrawRect
|
||||
from .paint import DisplayList
|
||||
|
||||
|
||||
class RenderPipeline:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Template rendering utilities."""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||
import logging
|
||||
|
|
@ -66,13 +65,7 @@ def render_error_page(status_code: int, url: str = "", error_message: str = "")
|
|||
"""
|
||||
logger = logging.getLogger("bowser.templates")
|
||||
|
||||
# Map common status codes to templates
|
||||
template_map = {
|
||||
404: "error_404.html",
|
||||
500: "error_500.html",
|
||||
# Network errors
|
||||
"network": "error_network.html",
|
||||
}
|
||||
# Determine template per status
|
||||
|
||||
if status_code == 404:
|
||||
template = "error_404.html"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for browser tab management."""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import Mock, patch
|
||||
from src.browser.browser import Browser
|
||||
from src.browser.tab import Tab
|
||||
|
|
@ -140,7 +139,7 @@ class TestBrowser:
|
|||
browser.chrome.tabs_box = Mock()
|
||||
|
||||
tab1 = browser.new_tab("https://example.com")
|
||||
tab2 = browser.new_tab("https://other.com")
|
||||
_ = browser.new_tab("https://other.com")
|
||||
|
||||
browser.set_active_tab(tab1)
|
||||
assert browser.active_tab is tab1
|
||||
|
|
@ -168,7 +167,7 @@ class TestBrowser:
|
|||
browser.chrome.paint = Mock()
|
||||
browser.chrome.tabs_box = Mock()
|
||||
|
||||
tab1 = browser.new_tab("https://example.com")
|
||||
_ = browser.new_tab("https://example.com")
|
||||
tab2 = browser.new_tab("https://other.com")
|
||||
tab3 = browser.new_tab("https://third.com")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for cookie management."""
|
||||
|
||||
import pytest
|
||||
from src.network.cookies import CookieJar
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
"""Tests for DOM graph visualization."""
|
||||
|
||||
import pytest
|
||||
from src.parser.html import parse_html, Element, Text
|
||||
from src.parser.html import parse_html
|
||||
from src.debug.dom_graph import generate_dot_graph, print_dom_tree
|
||||
|
||||
|
||||
|
|
@ -93,8 +92,8 @@ class TestDOMGraph:
|
|||
# Should have increasing indentation
|
||||
lines = tree.split('\n')
|
||||
# Find the nested <p> line - should be more indented than <div>
|
||||
p_line = [l for l in lines if '<p>' in l][0]
|
||||
div_line = [l for l in lines if '<div>' in l][0]
|
||||
p_line = [line for line in lines if '<p>' in line][0]
|
||||
div_line = [line for line in lines if '<div>' in line][0]
|
||||
|
||||
# Count leading spaces
|
||||
p_indent = len(p_line) - len(p_line.lstrip())
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
"""Tests for DOM graph page rendering."""
|
||||
|
||||
import pytest
|
||||
from src.templates import render_dom_graph_page
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
"""Tests for Frame and content loading."""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import Mock, patch
|
||||
from src.browser.tab import Frame, Tab
|
||||
from src.browser.tab import Tab
|
||||
from src.network.url import URL
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for HTML parsing functionality."""
|
||||
|
||||
import pytest
|
||||
from src.parser.html import parse_html, Text, Element
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"""Tests for HTTP functionality."""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import Mock, patch, MagicMock
|
||||
from unittest.mock import Mock, patch
|
||||
from src.network.url import URL
|
||||
from src.network import http
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
# ruff: noqa: E402
|
||||
"""Tests for layout components."""
|
||||
|
||||
import pytest
|
||||
import sys
|
||||
from unittest.mock import Mock, patch, MagicMock
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
# Mock skia before importing layout modules
|
||||
mock_skia = MagicMock()
|
||||
|
|
@ -131,7 +132,12 @@ class TestDocumentLayout:
|
|||
body = Element("body")
|
||||
p = Element("p")
|
||||
# Long text that should wrap
|
||||
p.children = [Text("This is a very long paragraph that should wrap to multiple lines when the width is narrow enough")]
|
||||
p.children = [
|
||||
Text(
|
||||
"This is a very long paragraph that should wrap to multiple lines "
|
||||
"when the width is narrow enough"
|
||||
)
|
||||
]
|
||||
body.children = [p]
|
||||
|
||||
layout = DocumentLayout(body)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for HTML parsing."""
|
||||
|
||||
import pytest
|
||||
from src.parser.html import Text, Element, print_tree
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
# ruff: noqa: E402
|
||||
"""Tests for rendering primitives."""
|
||||
|
||||
import pytest
|
||||
import sys
|
||||
from unittest.mock import Mock, patch, MagicMock
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
# Mock skia before importing render modules
|
||||
mock_skia = MagicMock()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for template rendering."""
|
||||
|
||||
import pytest
|
||||
from src.templates import render_template, render_error_page, render_startpage
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for URL parsing and resolution."""
|
||||
|
||||
import pytest
|
||||
from src.network.url import URL
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for URL normalization."""
|
||||
|
||||
import pytest
|
||||
from src.browser.browser import Browser
|
||||
|
||||
|
||||
|
|
|
|||
17
uv.lock
17
uv.lock
|
|
@ -49,7 +49,7 @@ dependencies = [
|
|||
{ name = "skia-python" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "black" },
|
||||
{ name = "mypy" },
|
||||
|
|
@ -60,16 +60,19 @@ dev = [
|
|||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "black", marker = "extra == 'dev'", specifier = ">=25.0" },
|
||||
{ name = "jinja2", specifier = ">=3.0" },
|
||||
{ name = "mypy", marker = "extra == 'dev'", specifier = ">=1.9.0" },
|
||||
{ name = "pygobject", specifier = ">=3.54.0" },
|
||||
{ name = "pytest", marker = "extra == 'dev'", specifier = ">=9.0.0" },
|
||||
{ name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=7.0.0" },
|
||||
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.9.0" },
|
||||
{ name = "skia-python", specifier = ">=87.9" },
|
||||
]
|
||||
provides-extras = ["dev"]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "black", specifier = ">=25.0" },
|
||||
{ name = "mypy", specifier = ">=1.9.0" },
|
||||
{ name = "pytest", specifier = ">=9.0.0" },
|
||||
{ name = "pytest-cov", specifier = ">=7.0.0" },
|
||||
{ name = "ruff", specifier = ">=0.9.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
|
|
|
|||
Loading…
Reference in a new issue