MCP-AnkiConnect
by samefarrar
- tests
import pytest
from pytest_mock import MockerFixture
from typing import List, Dict, Any
from mcp_ankiconnect.server import (
get_cards_by_due_and_deck,
num_cards_due_today,
list_decks_and_notes,
get_examples,
fetch_due_cards_for_review,
submit_reviews
)
@pytest.fixture
def mock_anki(mocker: MockerFixture):
# Create a mock client
mock_client = mocker.AsyncMock()
# Setup default return values
mock_client.deck_names.return_value = ["Default", "Test Deck"]
mock_client.find_cards.return_value = [1, 2, 3]
mock_client.cards_info.return_value = [
{"cardId": 1, "deck": "Default"},
{"cardId": 2, "deck": "Default"},
{"cardId": 3, "deck": "Default"}
]
# Mock the context manager
mocker.patch('mcp_ankiconnect.server.AnkiConnectClient', return_value=mock_client)
mock_client.__aenter__ = mocker.AsyncMock(return_value=mock_client)
mock_client.__aexit__ = mocker.AsyncMock()
return mock_client
@pytest.mark.asyncio
async def test_get_cards_by_due_and_deck(mock_anki):
# Test with no parameters
cards = await get_cards_by_due_and_deck()
mock_anki.find_cards.assert_called_with(query="is:due prop:due<=0")
assert cards == [1, 2, 3]
# Test with deck filter
cards = await get_cards_by_due_and_deck(deck="Default")
mock_anki.find_cards.assert_called_with(query="is:due prop:due<=0 deck:Default")
# Test with day parameter
cards = await get_cards_by_due_and_deck(day=1)
mock_anki.find_cards.assert_called_with(query="is:due prop:due<2")
@pytest.mark.asyncio
async def test_num_cards_due_today(mock_anki):
result = await num_cards_due_today()
assert "There are 3 cards due across all decks" in result
result = await num_cards_due_today(deck="Default")
assert "There are 3 cards due in deck 'Default'" in result
@pytest.mark.asyncio
async def test_list_decks_and_notes(mock_anki, mocker: MockerFixture):
mock_anki.model_names = mocker.AsyncMock(return_value=["Basic", "Cloze"])
mock_anki.model_field_names = mocker.AsyncMock(return_value=["Front", "Back"])
result = await list_decks_and_notes()
assert "Default" in result
assert "Test Deck" in result
assert "Basic" in result
assert "Cloze" in result
@pytest.mark.asyncio
async def test_get_examples(mock_anki, mocker: MockerFixture):
mock_anki.find_notes = mocker.AsyncMock(return_value=[1, 2])
mock_anki.notes_info = mocker.AsyncMock(return_value=[
{
"noteId": 1,
"tags": ["test"],
"modelName": "Basic",
"fields": {
"Front": {"value": "Question 1", "order": 0},
"Back": {"value": "Answer 1", "order": 1}
}
}
])
result = await get_examples(limit=1)
assert "Question 1" in result
assert "Answer 1" in result
@pytest.mark.asyncio
async def test_fetch_due_cards_for_review(mock_anki):
mock_anki.cards_info.return_value = [
{
"cardId": 1,
"fields": {
"Front": {"value": "Question", "order": 0},
"Back": {"value": "Answer", "order": 1}
},
"fieldOrder": 0
}
]
result = await fetch_due_cards_for_review(limit=1)
assert "<card id=\"1\">" in result
assert "<question>" in result
assert "<answer>" in result
@pytest.mark.asyncio
async def test_submit_reviews(mock_anki, mocker: MockerFixture):
mock_anki.answer_cards = mocker.AsyncMock(return_value=[True])
reviews = [
{"card_id": 1, "rating": "wrong"},
{"card_id": 2, "rating": "hard"},
{"card_id": 3, "rating": "good"}
]
result = await submit_reviews(reviews)
assert "successfully" in result
assert "Card 1" in result