Skip to main content
Glama
hmumixaM

USCardForum MCP Server

by hmumixaM
test_topics.py10.5 kB
""" Integration tests for Topics API. Tests against the actual USCardForum API with comprehensive field assertions. """ import pytest from datetime import datetime from uscardforum.models.topics import TopicSummary, TopicInfo, Post class TestTopicSummaryModel: """Test TopicSummary model fields are populated correctly.""" def test_topic_summary_required_fields(self, client): """Test TopicSummary has all required fields populated.""" topics = client.get_hot_topics() assert len(topics) > 0, "Should have hot topics" topic = topics[0] assert isinstance(topic, TopicSummary) # Ensure serialized JSON fields match the TopicSummary domain model json_keys = set(topic.model_dump().keys()) model_keys = set(TopicSummary.model_fields.keys()) assert json_keys.issubset(model_keys) # Required fields must be present assert topic.id > 0, "id must be positive integer" assert topic.title, "title must not be empty" assert isinstance(topic.title, str), "title must be string" def test_topic_summary_count_fields(self, client): """Test TopicSummary count fields are non-negative integers.""" topics = client.get_hot_topics() topic = topics[0] # Count fields should be non-negative assert topic.posts_count >= 0, "posts_count must be non-negative" assert topic.views >= 0, "views must be non-negative" assert topic.like_count >= 0, "like_count must be non-negative" def test_topic_summary_optional_fields(self, client): """Test TopicSummary optional fields when present.""" topics = client.get_hot_topics() topic = topics[0] # Category ID should be present for most topics if topic.category_id is not None: assert topic.category_id > 0, "category_id must be positive" # Timestamps should be datetime when present if topic.created_at is not None: assert isinstance(topic.created_at, datetime), "created_at must be datetime" if topic.last_posted_at is not None: assert isinstance(topic.last_posted_at, datetime), "last_posted_at must be datetime" def test_topic_summary_from_new_topics(self, client): """Test TopicSummary parsing from new topics endpoint.""" topics = client.get_new_topics() assert len(topics) > 0 for topic in topics[:5]: # Check first 5 assert isinstance(topic, TopicSummary) assert topic.id > 0 assert topic.title def test_topic_summary_from_top_topics(self, client): """Test TopicSummary parsing from top topics endpoint.""" topics = client.get_top_topics() assert len(topics) > 0 for topic in topics[:5]: assert isinstance(topic, TopicSummary) assert topic.id > 0 assert topic.title class TestTopicInfoModel: """Test TopicInfo model fields are populated correctly.""" def test_topic_info_required_fields(self, client): """Test TopicInfo has all required fields.""" hot = client.get_hot_topics() topic_id = hot[0].id info = client.get_topic_info(topic_id) assert isinstance(info, TopicInfo) # The returned JSON should only contain fields defined on TopicInfo info_keys = set(info.model_dump().keys()) model_keys = set(TopicInfo.model_fields.keys()) assert info_keys.issubset(model_keys) # Required fields - note: model uses topic_id not id assert info.topic_id == topic_id, "topic_id must match request" assert info.post_count >= 1, "post_count must be at least 1" assert info.highest_post_number >= 1, "highest_post_number must be at least 1" def test_topic_info_field_types(self, client): """Test TopicInfo field types.""" hot = client.get_hot_topics() info = client.get_topic_info(hot[0].id) assert isinstance(info.topic_id, int) assert isinstance(info.post_count, int) assert isinstance(info.highest_post_number, int) def test_topic_info_optional_fields(self, client): """Test TopicInfo optional fields.""" hot = client.get_hot_topics() info = client.get_topic_info(hot[0].id) # Title may be present if info.title is not None: assert isinstance(info.title, str) assert len(info.title) > 0 # Timestamp if info.last_posted_at is not None: assert isinstance(info.last_posted_at, datetime) def test_topic_info_consistency(self, client): """Test TopicInfo values are internally consistent.""" hot = client.get_hot_topics() info = client.get_topic_info(hot[0].id) # highest_post_number should be >= 1 # Note: can be > post_count if posts were deleted assert info.highest_post_number >= 1 assert info.post_count >= 1 class TestPostModel: """Test Post model fields are populated correctly.""" def test_post_required_fields(self, client): """Test Post has all required fields.""" hot = client.get_hot_topics() posts = client.get_topic_posts(hot[0].id) assert len(posts) > 0, "Should have posts" post = posts[0] assert isinstance(post, Post) # The post JSON should not have fields outside the Post domain model post_keys = set(post.model_dump().keys()) model_keys = set(Post.model_fields.keys()) assert post_keys.issubset(model_keys) # Required fields assert post.id > 0, "id must be positive" assert post.post_number >= 1, "post_number must be at least 1" assert post.username, "username must not be empty" assert isinstance(post.username, str), "username must be string" def test_post_content_fields(self, client): """Test Post content fields.""" hot = client.get_hot_topics() posts = client.get_topic_posts(hot[0].id) post = posts[0] # cooked (HTML content) should be present assert post.cooked is not None, "cooked content must be present" assert isinstance(post.cooked, str), "cooked must be string" assert len(post.cooked) > 0, "cooked should not be empty" def test_post_count_fields(self, client): """Test Post count fields are non-negative.""" hot = client.get_hot_topics() posts = client.get_topic_posts(hot[0].id) post = posts[0] assert post.like_count >= 0, "like_count must be non-negative" assert post.reply_count >= 0, "reply_count must be non-negative" def test_post_timestamp_fields(self, client): """Test Post timestamp fields.""" hot = client.get_hot_topics() posts = client.get_topic_posts(hot[0].id) post = posts[0] if post.created_at is not None: assert isinstance(post.created_at, datetime), "created_at must be datetime" if post.updated_at is not None: assert isinstance(post.updated_at, datetime), "updated_at must be datetime" def test_post_reply_reference(self, client): """Test Post reply_to_post_number is valid when present.""" hot = client.get_hot_topics() posts = client.get_topic_posts(hot[0].id) # Find a reply post for post in posts: if post.reply_to_post_number is not None: assert post.reply_to_post_number >= 1, "reply_to must reference valid post" assert post.reply_to_post_number < post.post_number, "can only reply to earlier posts" break def test_first_post_is_number_one(self, client): """Test first post has post_number 1.""" hot = client.get_hot_topics() posts = client.get_topic_posts(hot[0].id) first_post = posts[0] assert first_post.post_number == 1, "First post should be number 1" class TestPostListFromTopic: """Test posts returned from topic endpoint.""" def test_posts_list_not_empty(self, client): """Test get_topic_posts returns non-empty list.""" hot = client.get_hot_topics() posts = client.get_topic_posts(hot[0].id) assert isinstance(posts, list), "Should return list" assert len(posts) > 0, "Should have posts" def test_all_posts_are_post_objects(self, client): """Test all items in posts list are Post objects.""" hot = client.get_hot_topics() posts = client.get_topic_posts(hot[0].id) for post in posts: assert isinstance(post, Post), "Each item must be Post object" assert post.id > 0, "Post id must be positive" assert post.post_number >= 1, "post_number must be at least 1" assert post.username, "username must not be empty" def test_posts_have_content(self, client): """Test posts have content fields.""" hot = client.get_hot_topics() posts = client.get_topic_posts(hot[0].id) for post in posts: assert post.cooked is not None, "cooked must be present" assert isinstance(post.cooked, str), "cooked must be string" def test_posts_sorted_by_number(self, client): """Test posts are sorted by post_number.""" hot = client.get_hot_topics() posts = client.get_topic_posts(hot[0].id) if len(posts) > 1: for i in range(len(posts) - 1): assert posts[i].post_number <= posts[i + 1].post_number, \ "Posts should be sorted by post_number" class TestTopicPagination: """Test topic pagination functionality.""" def test_get_topic_posts_with_post_number(self, client): """Test fetching posts starting at specific number.""" hot = client.get_hot_topics() posts = client.get_topic_posts(hot[0].id, post_number=1) assert isinstance(posts, list) assert len(posts) > 0 def test_get_all_topic_posts_with_limit(self, client): """Test get_all_topic_posts respects max_posts limit.""" hot = client.get_hot_topics() posts = client.get_all_topic_posts(hot[0].id, max_posts=5) assert isinstance(posts, list) assert len(posts) <= 5 for post in posts: assert isinstance(post, Post) assert post.id > 0 assert post.post_number >= 1 assert post.username assert post.cooked is not None

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hmumixaM/uscardforum-mcp4'

If you have feedback or need assistance with the MCP directory API, please join our Discord server