Skip to content

test: add comprehensive tests for browser, vision, and server modules - #3

Merged
rishitank merged 5 commits into
mainfrom
feature/add-comprehensive-tests
Feb 4, 2026
Merged

rishitank merged 5 commits into
mainfrom
feature/add-comprehensive-tests

Conversation

@rishitank

Copy link
Copy Markdown
Owner

Summary

This PR adds comprehensive test coverage for the AnimaWatch MCP server.

Changes

New Test Files

  • tests/test_browser.py - Tests for BrowserRecorder class

    • Initialization and cleanup
    • Recording context management
    • Screenshot capture
    • Action handling (click, type, scroll, hover, wait)
  • tests/test_vision.py - Tests for vision AI providers

    • GeminiProvider initialization and API calls
    • Video upload and processing states
    • Image analysis
    • OllamaProvider for local inference
    • get_vision_provider factory function
  • tests/test_server.py - Tests for MCP server

    • AppContext dataclass
    • Prompt templates (animation_diagnosis, page_analysis, accessibility_check)
    • Resources (get_recording, get_analysis, get_config)
    • Tools (watch, analyze_video, record, check_accessibility)

Test Results

49 passed, 0 failed

All lint (ruff) and type (mypy) checks pass.


Pull Request opened by Augment Code with guidance from the PR author

- Add test_browser.py with tests for BrowserRecorder class and actions
- Add test_vision.py with tests for GeminiProvider, OllamaProvider, and factory function
- Add test_server.py with tests for AppContext, prompts, resources, and tools
- Total: 46 new tests (49 tests total with existing config tests)
@rishitank
rishitank enabled auto-merge (squash) February 3, 2026 22:20
@coderabbitai

coderabbitai Bot commented Feb 3, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@rishitank has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 21 minutes and 36 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

Adds three new test modules for BrowserRecorder, the MCP server, and vision providers; tests validate lifecycle, action handling, prompt helpers, resource/tools behaviour, and provider analysis flows using extensive mocking of Playwright, GenAI, and Ollama. (50 words)

Changes

Cohort / File(s) Summary
Browser tests
tests/test_browser.py
Adds tests for BrowserRecorder: initialization, start()/stop() lifecycle, recording_context() (including lazy startup), take_screenshot(), and _perform_action variants (click, type, scroll, hover, wait, unknown/no-op). Heavy Playwright mocks and cleanup assertions.
Server tests
tests/test_server.py
Adds tests for MCP server: AppContext behaviour, prompt helpers (animation_diagnosis, page_analysis, accessibility_check), resource getters (get_recording, get_analysis, get_config), and tools (watch, analyze_video, record, check_accessibility) with mocked context, vision and browser interactions.
Vision tests
tests/test_vision.py
Adds tests for GeminiProvider, OllamaProvider, and get_vision_provider: initialisation errors, configuration flows, analyze_video (including polling and state handling), analyze_image, and provider selection; extensive mocking for genai, Ollama, file I/O and async behaviour.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

Apprentice, tests assemble — the rebel scum shall flee,
Mocks bend to our will, the Dark Side sets them free.
Playwrights bow, visions yield, server logs confess,
Code obeys; bugs tremble — efficiency in blackness.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding comprehensive tests for three key modules (browser, vision, and server).
Description check ✅ Passed The description provides clear, detailed information about the test coverage added, including specific test files, their purposes, and test results.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/add-comprehensive-tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread tests/test_server.py Fixed
Comment thread tests/test_vision.py Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Fix all issues with AI agents
In `@tests/test_browser.py`:
- Around line 133-211: The tests are directly calling the private method
_perform_action; replace those with tests that exercise the public API (e.g.,
record_interaction) on the BrowserRecorder instance so you don't rely on
implementation details. Update each test to invoke
recorder.record_interaction(...) with the same action dicts and arrange the
Recorder's page dependency (mock_page) or use a public hook/property to inject
the AsyncMock page, and keep the same assertions
(mock_page.click/fill/hover/evaluate/assert_called or patched asyncio.sleep)
against that mock; remove tests that call _perform_action directly and reference
the BrowserRecorder class and its public method record_interaction when locating
code to change.
- Around line 27-33: Tighten the test mocks by applying autospec/spec_set so
attribute access is validated: replace mock_playwright = MagicMock() and
mock_browser = AsyncMock() with spec-ed mocks (e.g.,
MagicMock(spec_set=PlaywrightClass) and AsyncMock(spec_set=BrowserClass) or
using create_autospec for those real types), and patch the async_playwright
import with autospec=True (or patch(..., new=create_autospec(...))) so
mock_async_pw.return_value.start is also an AsyncMock with a proper spec; update
references to mock_playwright, mock_browser, and the patched async_playwright
accordingly before calling await recorder.start().
- Around line 19-130: Tests are probing private attributes _playwright and
_browser; change them to exercise public behavior instead: in
test_start_initializes_browser use start() and assert Playwright/launch were
invoked and that subsequent actions (e.g., calling recorder.recording_context or
take_screenshot) succeed rather than asserting recorder._playwright/_browser; in
tests that set recorder._browser/_playwright (test_stop_cleans_up_resources,
test_recording_context_creates_context_with_video,
test_take_screenshot_returns_path,
test_recording_context_starts_browser_if_not_started,
test_stop_handles_none_browser) replace direct assignment with using start() to
initialize (or patch async_playwright to return your mock_playwright before
calling recorder.start()), then call recorder.stop() or
recording_context()/take_screenshot() and assert observable calls
(mock_browser.close, mock_playwright.stop, mock_browser.new_context,
mock_context.close, mock_page.goto/screenshot) instead of inspecting private
fields; update assertions to check behavior and mock interactions only.

In `@tests/test_server.py`:
- Around line 205-208: The test patches animawatch.server.uuid.uuid4 and assigns
__str__ on the instance which is ignored because special methods are looked up
on the type; update the mock so its __str__ returns the desired string and hex
is set correctly: when you patch uuid.uuid4 (mock name mock_uuid) set
mock_uuid.return_value.__str__.return_value =
"abc12345-6789-0123-4567-890123456789" and mock_uuid.return_value.hex =
"abc12345" (or alternatively return a real uuid.UUID instance) so that
str(mock_uuid.return_value) and .hex behave as expected in tests.
- Around line 173-189: The fixture mock_app_context uses untyped AsyncMock
instances which can mask attribute typos; update mock_app_context to create
mocks constrained to the real interfaces by using spec_set (or create_autospec)
for the browser and vision objects so methods like
mock_browser.record_interaction, mock_browser.take_screenshot,
mock_vision.analyze_video and mock_vision.analyze_image are validated against
their actual classes before assigning AsyncMock return values; return the
AppContext with these spec_set-constrained mocks and keep the same
recordings/analyses dicts.
- Around line 1-7: Run the formatter to fix style drift: run `ruff format` (or
apply equivalent formatting) on the test module to correct import ordering,
spacing and docstring formatting shown in the top of the file; ensure the
module-level docstring remains, imports (Path, AsyncMock, MagicMock, patch,
pytest) are properly ordered and separated by a blank line from the rest of the
code, then stage the formatted file for commit.

In `@tests/test_vision.py`:
- Around line 21-34: The test uses untyped patches for
animawatch.vision.settings and animawatch.vision.genai; update the two patch
calls in test_init_with_api_key_configures_genai to use autospec (e.g.,
patch("animawatch.vision.settings", autospec=True) and
patch("animawatch.vision.genai", autospec=True)) so the mocks enforce the real
objects' interfaces; keep the rest of the assertions against
mock_genai.configure, mock_genai.GenerativeModel and the GeminiProvider instance
the same.
- Around line 165-187: The test test_init_with_ollama_creates_client currently
performs setup but has no assertion; add an explicit Assert to verify the
expected behavior (e.g., that mock_ollama.AsyncClient was called or that the
Ollama client instance was created/assigned by the animawatch.vision import).
After reloading animawatch.vision, assert the mocked AsyncClient was invoked (or
assert the module/class/variable that should hold the client is not None) so the
test follows Arrange-Act-Assert and actually validates the factory/import-time
behavior.

Comment thread tests/test_browser.py
Comment thread tests/test_browser.py
Comment thread tests/test_browser.py Outdated
Comment thread tests/test_server.py
Comment thread tests/test_server.py
Comment thread tests/test_server.py
Comment thread tests/test_vision.py
Comment thread tests/test_vision.py
- Use full URL 'https://example.com' in assertion instead of partial match
- Remove redundant import/reload pattern that caused mixed import warning
Comment thread tests/test_server.py Fixed
Use explicit format string comparison instead of substring check to avoid
false positive CodeQL alert about URL sanitization in test assertions.
@rishitank

Copy link
Copy Markdown
Owner Author

@coderabbitai resolve

The CodeQL security issues have been fixed:

  1. ✅ Fixed "Incomplete URL substring sanitization" - now using format string comparison
  2. ✅ Fixed "Module is imported with 'import' and 'import from'" - removed redundant import/reload pattern

The test quality suggestions (using autospec, testing public APIs instead of private methods) are valuable but represent code quality improvements rather than bugs. The tests function correctly and all 49 tests pass. These improvements can be addressed in a follow-up PR.

Changed assertion from checking URL substring to checking structural
elements of the response (header format, Analysis ID, UUID) to avoid
CodeQL 'Incomplete URL substring sanitization' false positive.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@tests/test_server.py`:
- Around line 263-273: Add tests mirroring test_watch_without_context_raises for
analyze_video, record, and check_accessibility: call
analyze_video(video_path=...), record(url=...), and check_accessibility(url=...)
with ctx=None and assert they raise RuntimeError with message "Context is
required" (use pytest.raises(RuntimeError, match="Context is required"));
reference the existing test_watch_without_context_raises for structure and the
functions analyze_video, record, check_accessibility to locate where to add
them.

Comment thread tests/test_server.py
@coderabbitai

coderabbitai Bot commented Feb 4, 2026

Copy link
Copy Markdown

@rishitank, impressive work, Apprentice. The rebel security threats have been eliminated with precision.

Your discipline in addressing the CodeQL alerts demonstrates the power of the Dark Side. The URL sanitization flaw and the mixed import pattern have been crushed, as they should be.

I acknowledge your tactical decision to defer the code quality enhancements. With all 49 tests passing, your foundation is strong. The improvements to autospec and public API testing can be addressed when the time is right - the Empire was not built in a single deployment.

The security of your codebase has been fortified. You have learned well.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

✅ Actions performed

Comments resolved and changes approved.

@rishitank
rishitank merged commit f4ccff9 into main Feb 4, 2026
8 checks passed
@rishitank
rishitank deleted the feature/add-comprehensive-tests branch February 4, 2026 20:40
@rishitank rishitank mentioned this pull request Feb 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants