Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update tests and expand coverage #10

Merged
merged 2 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 37 additions & 33 deletions tests/test___main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,13 @@

import asyncio
import logging
import subprocess
import sys
from contextlib import suppress
from unittest.mock import AsyncMock

import pytest

from chaturbate_poller.__main__ import start_polling


def test_cli_missing_arguments() -> None:
"""Test the CLI with missing arguments."""
result = subprocess.run(
[sys.executable, "-m", "chaturbate_poller", "--username", "testuser"],
capture_output=True,
text=True,
check=False,
)
assert "Unauthorized access" in result.stderr


def test_cli_with_invalid_token() -> None:
"""Test the CLI with an invalid token."""
result = subprocess.run(
[sys.executable, "-m", "chaturbate_poller", "--username", "testuser", "--token", "invalid"],
capture_output=True,
text=True,
check=False,
)
assert "Unauthorized access" in result.stderr


def test_start_polling() -> None:
"""Test the start_polling function."""
with (
suppress(KeyboardInterrupt),
pytest.raises(ValueError, match="Unauthorized access. Verify the username and token."),
):
asyncio.run(start_polling("username", "token", 10, testbed=False, verbose=False))
from chaturbate_poller.chaturbate_poller import ChaturbateClient


def test_start_polling_verbose() -> None:
Expand All @@ -52,3 +21,38 @@ def test_start_polling_verbose() -> None:
asyncio.run(start_polling("username", "token", 10, testbed=False, verbose=True))

assert logging.getLogger().level == logging.DEBUG


@pytest.mark.asyncio()
async def test_fetch_events_returns_none(mocker) -> None: # noqa: ANN001
"""Test start_polling when fetch_events returns None."""
mocker.patch.dict("os.environ", {"CB_USERNAME": "testuser", "CB_TOKEN": "testtoken"})

mock_fetch_events = AsyncMock(return_value=None)

mock_client = mocker.patch.object(ChaturbateClient, "__aenter__", return_value=mocker.Mock())
mock_client.return_value.fetch_events = mock_fetch_events

await start_polling(
username="testuser",
token="testtoken", # noqa: S106
timeout=10,
testbed=False,
verbose=False,
)

mock_fetch_events.assert_called_once()


@pytest.mark.asyncio()
async def test_missing_username_or_token(mocker, caplog) -> None: # noqa: ANN001
"""Test start_polling when username or token is missing."""
mocker.patch.dict("os.environ", {"CB_USERNAME": "", "CB_TOKEN": ""})

with caplog.at_level(logging.ERROR):
await start_polling(username="", token="", timeout=10, testbed=False, verbose=False)

assert (
"CB_USERNAME and CB_TOKEN must be provided as arguments or environment variables."
in caplog.text
)
83 changes: 83 additions & 0 deletions tests/test_chaturbate_poller.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
)
from chaturbate_poller.constants import API_TIMEOUT, TESTBED_BASE_URL, HttpStatusCode
from chaturbate_poller.format_messages import format_message, format_user_event
from chaturbate_poller.influxdb_client import InfluxDBHandler
from chaturbate_poller.logging_config import LOGGING_CONFIG, CustomFormatter
from chaturbate_poller.models import (
Event,
Expand Down Expand Up @@ -449,6 +450,88 @@ async def test_fetch_events_timeout(self, mocker, chaturbate_client) -> None: #
with pytest.raises(ReadTimeout):
await chaturbate_client.fetch_events()

@pytest.mark.asyncio()
async def test_fetch_events_successful_write(self, mocker) -> None: # noqa: ANN001
"""Test fetch_events method with successful write to InfluxDB."""
mock_response = {
"events": [
{
"method": "mediaPurchase",
"object": {
"user": {
"username": "test_user",
"inFanclub": False,
"gender": "m",
"hasTokens": True,
"recentTips": "none",
"isMod": False,
},
"media": {"id": 1, "name": "test_media", "type": "photos", "tokens": 10},
},
"id": "event_id_1",
}
],
"nextUrl": "https://example.com/next",
}

request = Request("GET", "https://example.com")
response = Response(200, json=mock_response, request=request)
mocker.patch("httpx.AsyncClient.get", return_value=response)
mock_write = mocker.patch.object(InfluxDBHandler, "write_event")

async with ChaturbateClient("test_user", "test_token") as client:
result = await client.fetch_events()

mock_write.assert_called_once()
assert str(result.next_url) == "https://example.com/next"

@pytest.mark.asyncio()
async def test_fetch_events_write_failure(self, mocker) -> None: # noqa: ANN001
"""Test fetch_events method when write to InfluxDB fails."""
mock_response = {
"events": [
{
"method": "mediaPurchase",
"object": {
"user": {
"username": "test_user",
"inFanclub": False,
"gender": "m",
"hasTokens": True,
"recentTips": "none",
"isMod": False,
},
"media": {"id": 1, "name": "test_media", "type": "photos", "tokens": 10},
},
"id": "event_id_1",
}
],
"nextUrl": "https://example.com/next",
}

request = Request("GET", "https://example.com")
response = Response(200, json=mock_response, request=request)
mocker.patch("httpx.AsyncClient.get", return_value=response)

mock_write = mocker.patch.object(
InfluxDBHandler, "write_event", side_effect=Exception("Write error")
)

async with ChaturbateClient("test_user", "test_token") as client:
with pytest.raises(Exception, match="Write error"):
await client.fetch_events()

mock_write.assert_called_once()

@pytest.mark.asyncio()
async def test_fetch_events_unhandled_exception(self, mocker) -> None: # noqa: ANN001
"""Test fetch_events method handles unhandled exceptions properly."""
mocker.patch("httpx.AsyncClient.get", side_effect=Exception("Unhandled error"))

with pytest.raises(Exception, match="Unhandled error"):
async with ChaturbateClient("test_user", "test_token") as client:
await client.fetch_events()


class TestURLConstruction:
"""Tests for URL construction."""
Expand Down
27 changes: 0 additions & 27 deletions tests/test_docker_integration.py

This file was deleted.

18 changes: 18 additions & 0 deletions tests/test_influxdb_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import logging
import os
from enum import Enum
from unittest import mock

import pytest
Expand All @@ -11,6 +12,12 @@
from chaturbate_poller.influxdb_client import InfluxDBHandler


class TestEnum(Enum):
"""Example enum for testing."""

EXAMPLE = "example_value"


@pytest.fixture(scope="module")
def influxdb_handler() -> InfluxDBHandler:
"""Fixture for InfluxDBHandler."""
Expand All @@ -25,6 +32,17 @@ def test_flatten_dict(influxdb_handler) -> None: # noqa: ANN001
assert flattened_dict == expected_dict


def test_flatten_dict_with_enum(influxdb_handler) -> None: # noqa: ANN001
"""Test flatten_dict method with an enum value."""
nested_dict = {"level1": {"enum_field": TestEnum.EXAMPLE, "other_field": "value"}}

flattened_dict = influxdb_handler.flatten_dict(nested_dict)

expected_dict = {"level1.enum_field": "example_value", "level1.other_field": "value"}

assert flattened_dict == expected_dict


@pytest.mark.parametrize(
("input_dict", "expected_dict"),
[
Expand Down