Files
wordloop/backend/tests/test_wiki_service.py
john 05e173b293 Ship native iOS app, Wiki/TTS backend, and skeleton loading UX.
Replace the WebView shell with SwiftUI screens, add account-scoped Wiki and TTS APIs with adaptive review and photo scan support, and keep web/iOS pages usable while data loads asynchronously.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-08 15:13:59 +08:00

139 lines
4.4 KiB
Python

import unittest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from database import Base
from models import QuizRecord, User, UserSettings, WikiPage, WikiSource, Word
from services.wiki_service import wiki_service
class WikiServiceTest(unittest.TestCase):
def setUp(self):
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
self.db = sessionmaker(bind=engine)()
def tearDown(self):
self.db.close()
def create_user(self, username: str) -> User:
user = User(
username=username,
password_hash="test",
created_at="2026-06-06T00:00:00Z",
)
self.db.add(user)
self.db.flush()
self.db.add(
UserSettings(
user_id=user.id,
ai_wiki_enabled=1,
ai_wiki_auto_organize=1,
)
)
self.db.commit()
return user
def create_word(self, user: User, text: str) -> Word:
word = Word(
user_id=user.id,
book_id=0,
source_text=text,
target_text="测试",
source_lang="en",
target_lang="zh",
status="learning",
correct_count=1,
wrong_count=0,
consecutive_correct_count=1,
mastery_score=100,
train_count=1,
total_train_seconds=3,
difficulty=5.0,
stability_hours=24.0,
created_at="2026-06-06T00:00:00Z",
)
self.db.add(word)
self.db.commit()
return word
def test_ingest_builds_private_markdown_page(self):
user = self.create_user("alice")
word = self.create_word(user, "resilient")
wiki_service.ingest_word(self.db, user, word)
page = (
self.db.query(WikiPage)
.filter(WikiPage.user_id == user.id, WikiPage.category == "word")
.one()
)
self.assertIn("# resilient", page.content)
self.assertIn("WordLoop 原始学习事件 1 条", page.content)
self.assertEqual(
self.db.query(WikiSource).filter(WikiSource.user_id == user.id).count(),
1,
)
def test_quiz_ingest_updates_only_own_wiki(self):
alice = self.create_user("alice")
bob = self.create_user("bob")
word = self.create_word(alice, "resilient")
wiki_service.ingest_word(self.db, alice, word)
record = QuizRecord(
user_id=alice.id,
word_id=word.id,
question_type="spell",
user_answer="resilient",
correct_answer="resilient",
is_correct=1,
duration_seconds=2,
created_at="2026-06-06T00:01:00Z",
)
self.db.add(record)
self.db.commit()
wiki_service.ingest_quiz(self.db, alice, word, record)
alice_status = wiki_service.status(self.db, alice)
bob_status = wiki_service.status(self.db, bob)
self.assertGreater(alice_status["page_count"], 0)
self.assertEqual(alice_status["latest_page"]["source_count"], 2)
self.assertEqual(bob_status["page_count"], 0)
self.assertIsNone(bob_status["latest_page"])
def test_recompile_prunes_orphan_status_collection(self):
user = self.create_user("alice")
word = self.create_word(user, "resilient")
word.status = "new"
self.db.commit()
wiki_service.ingest_word(self.db, user, word)
word.status = "learning"
self.db.commit()
wiki_service.rebuild(self.db, user)
slugs = {
page.slug
for page in self.db.query(WikiPage).filter(WikiPage.user_id == user.id).all()
}
self.assertNotIn("learning/new", slugs)
self.assertIn("learning/learning", slugs)
def test_graph_returns_wiki_pages_and_links(self):
user = self.create_user("alice")
word = self.create_word(user, "resilient")
wiki_service.ingest_word(self.db, user, word)
graph = wiki_service.graph(self.db, user)
node_slugs = {node["slug"] for node in graph["nodes"]}
relations = {link["relation"] for link in graph["links"]}
self.assertIn("index", node_slugs)
self.assertIn(f"vocabulary/{word.id}-resilient", node_slugs)
self.assertIn("learning_status", relations)
self.assertIn("collection", relations)
if __name__ == "__main__":
unittest.main()