Refactor create_pages.py and write tests

This commit is contained in:
2023-03-20 02:18:04 +01:00
parent 2df11adb16
commit 40569cb91c
3 changed files with 499 additions and 139 deletions

192
tests/test_create_pages.py Normal file
View File

@ -0,0 +1,192 @@
import re
from datetime import datetime
from typing import TYPE_CHECKING
import dateparser
import interactions
import pytz
from apscheduler.job import Job
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from interactions.ext.paginator import Page
from discord_reminder_bot.create_pages import (
_get_pages,
_get_pause_or_unpause_button,
_get_row_of_buttons,
_get_trigger_text,
_make_button,
_pause_job,
_unpause_job,
)
from discord_reminder_bot.main import send_to_discord
if TYPE_CHECKING:
from collections.abc import Generator
def _test_pause_unpause_button(job: Job, button_label: str) -> None:
button2: interactions.Button | None = _get_pause_or_unpause_button(job)
assert button2
assert button2.label == button_label
assert button2.style == interactions.ButtonStyle.PRIMARY
assert button2.type == interactions.ComponentType.BUTTON
assert button2.emoji is None
assert button2.custom_id == button_label.lower()
assert button2.url is None
assert button2.disabled is None
class TestCountdown:
jobstores: dict[str, SQLAlchemyJobStore] = {"default": SQLAlchemyJobStore(url="sqlite:///:memory")}
job_defaults: dict[str, bool] = {"coalesce": True}
scheduler = AsyncIOScheduler(
jobstores=jobstores,
timezone=pytz.timezone("Europe/Stockholm"),
job_defaults=job_defaults,
)
parsed_date: datetime | None = dateparser.parse(
"18 January 2040",
settings={
"PREFER_DATES_FROM": "future",
"TO_TIMEZONE": "Europe/Stockholm",
},
)
assert parsed_date
run_date: str = parsed_date.strftime("%Y-%m-%d %H:%M:%S")
normal_job: Job = scheduler.add_job(
send_to_discord,
run_date=run_date,
kwargs={
"channel_id": 865712621109772329,
"message": "Running PyTest",
"author_id": 126462229892694018,
},
)
cron_job: Job = scheduler.add_job(
send_to_discord,
"cron",
minute="0",
kwargs={
"channel_id": 865712621109772329,
"message": "Running PyTest",
"author_id": 126462229892694018,
},
)
interval_job: Job = scheduler.add_job(
send_to_discord,
"interval",
minutes=1,
kwargs={
"channel_id": 865712621109772329,
"message": "Running PyTest",
"author_id": 126462229892694018,
},
)
def test_get_trigger_text(self) -> None: # noqa: ANN101
# FIXME: This try except train should be replaced with a better solution lol
trigger_text: str = _get_trigger_text(self.normal_job)
try:
regex: str = r"2040-01-18 00:00 \(in \d+ days, \d+ hours, \d+ minutes\)"
assert re.match(regex, trigger_text)
except AssertionError:
try:
regex2: str = r"2040-01-18 00:00 \(in \d+ days, \d+ minutes\)"
assert re.match(regex2, trigger_text)
except AssertionError:
regex3: str = r"2040-01-18 00:00 \(in \d+ days\, \d+ minutes\)"
assert re.match(regex3, trigger_text)
def test_make_button(self) -> None: # noqa: ANN101
button_name: str = "Test"
button: interactions.Button = _make_button(label=button_name, style=interactions.ButtonStyle.PRIMARY)
assert button.label == button_name
assert button.style == interactions.ButtonStyle.PRIMARY
assert button.custom_id == button_name.lower()
assert button.disabled is None
assert button.emoji is None
def test_get_pause_or_unpause_button(self) -> None: # noqa: ANN101
button: interactions.Button | None = _get_pause_or_unpause_button(self.normal_job)
assert button is None
_test_pause_unpause_button(self.cron_job, "Pause")
self.cron_job.pause()
_test_pause_unpause_button(self.cron_job, "Unpause")
self.cron_job.resume()
_test_pause_unpause_button(self.interval_job, "Pause")
self.interval_job.pause()
_test_pause_unpause_button(self.interval_job, "Unpause")
self.interval_job.resume()
def test_get_row_of_buttons(self) -> None: # noqa: ANN101
row: interactions.ActionRow = _get_row_of_buttons(self.normal_job)
assert row
assert row.components
# A normal job should have 2 buttons, edit and delete
assert len(row.components) == 2 # noqa: PLR2004
row2: interactions.ActionRow = _get_row_of_buttons(self.cron_job)
assert row2
assert row2.components
# A cron job should have 3 buttons, edit, delete and pause/unpause
assert len(row2.components) == 3 # noqa: PLR2004
# A cron job should have 3 buttons, edit, delete and pause/unpause
assert len(row2.components) == 3 # noqa: PLR2004
def test_get_pages(self) -> None: # noqa: ANN101
ctx = None # TODO: We should check ctx as well and not only channel id
channel: interactions.Channel = interactions.Channel(id=interactions.Snowflake(865712621109772329))
pages: Generator[Page, None, None] = _get_pages(job=self.normal_job, channel=channel, ctx=ctx) # type: ignore # noqa: PGH003, E501
assert pages
for page in pages:
assert page
assert page.title == "Running PyTest"
assert page.components
assert page.embeds
assert page.embeds.fields is not None # type: ignore # noqa: PGH003
assert page.embeds.fields[0].name == "**Channel:**" # type: ignore # noqa: PGH003
assert page.embeds.fields[0].value == "#" # type: ignore # noqa: PGH003
assert page.embeds.fields[1].name == "**Message:**" # type: ignore # noqa: PGH003
assert page.embeds.fields[1].value == "Running PyTest" # type: ignore # noqa: PGH003
assert page.embeds.fields[2].name == "**Trigger:**" # type: ignore # noqa: PGH003
trigger_text: str = page.embeds.fields[2].value # type: ignore # noqa: PGH003
# FIXME: This try except train should be replaced with a better solution lol
try:
regex: str = r"2040-01-18 00:00 \(in \d+ days, \d+ hours, \d+ minutes\)"
assert re.match(regex, trigger_text)
except AssertionError:
try:
regex2: str = r"2040-01-18 00:00 \(in \d+ days, \d+ minutes\)"
assert re.match(regex2, trigger_text)
except AssertionError:
regex3: str = r"2040-01-18 00:00 \(in \d+ days\, \d+ minutes\)"
assert re.match(regex3, trigger_text)
# Check if type is Page
assert isinstance(page, Page)
def test_pause_job(self) -> None: # noqa: ANN101
assert _pause_job(self.interval_job, self.scheduler) == f"Job {self.interval_job.id} paused."
assert _pause_job(self.cron_job, self.scheduler) == f"Job {self.cron_job.id} paused."
assert _pause_job(self.normal_job, self.scheduler) == f"Job {self.normal_job.id} paused."
def test_unpause_job(self) -> None: # noqa: ANN101
assert _unpause_job(self.interval_job, self.scheduler) == f"Job {self.interval_job.id} unpaused."
assert _unpause_job(self.cron_job, self.scheduler) == f"Job {self.cron_job.id} unpaused."
assert _unpause_job(self.normal_job, self.scheduler) == f"Job {self.normal_job.id} unpaused."

68
tests/test_parse.py Normal file
View File

@ -0,0 +1,68 @@
from datetime import datetime
import tzlocal
from discord_reminder_bot.parse import ParsedTime, parse_time
def test_parse_time() -> None:
"""Test the parse_time function."""
parsed_time: ParsedTime = parse_time("18 January 2040")
assert parsed_time.err is False
assert not parsed_time.err_msg
assert parsed_time.date_to_parse == "18 January 2040"
assert parsed_time.parsed_time
assert parsed_time.parsed_time.strftime("%Y-%m-%d %H:%M:%S") == "2040-01-18 00:00:00"
parsed_time: ParsedTime = parse_time("18 January 2040 12:00")
assert parsed_time.err is False
assert not parsed_time.err_msg
assert parsed_time.date_to_parse == "18 January 2040 12:00"
assert parsed_time.parsed_time
assert parsed_time.parsed_time.strftime("%Y-%m-%d %H:%M:%S") == "2040-01-18 12:00:00"
parsed_time: ParsedTime = parse_time("18 January 2040 12:00:00")
assert parsed_time.err is False
assert not parsed_time.err_msg
assert parsed_time.date_to_parse == "18 January 2040 12:00:00"
assert parsed_time.parsed_time
assert parsed_time.parsed_time.strftime("%Y-%m-%d %H:%M:%S") == "2040-01-18 12:00:00"
parsed_time: ParsedTime = parse_time("18 January 2040 12:00:00 UTC")
assert parsed_time.err is False
assert not parsed_time.err_msg
assert parsed_time.date_to_parse == "18 January 2040 12:00:00 UTC"
assert parsed_time.parsed_time
assert parsed_time.parsed_time.strftime("%Y-%m-%d %H:%M:%S") == "2040-01-18 13:00:00"
parsed_time: ParsedTime = parse_time("18 January 2040 12:00:00 Europe/Stockholm")
assert parsed_time.err is True
assert parsed_time.err_msg == "Could not parse the date."
assert parsed_time.date_to_parse == "18 January 2040 12:00:00 Europe/Stockholm"
assert parsed_time.parsed_time is None
def test_ParsedTime() -> None: # noqa: N802
"""Test the ParsedTime class."""
parsed_time: ParsedTime = ParsedTime(
err=False,
err_msg="",
date_to_parse="18 January 2040",
parsed_time=datetime(2040, 1, 18, 0, 0, 0, tzinfo=tzlocal.get_localzone()),
)
assert parsed_time.err is False
assert not parsed_time.err_msg
assert parsed_time.date_to_parse == "18 January 2040"
assert parsed_time.parsed_time
assert parsed_time.parsed_time.strftime("%Y-%m-%d %H:%M:%S") == "2040-01-18 00:00:00"
parsed_time: ParsedTime = ParsedTime(
err=True,
err_msg="Could not parse the date.",
date_to_parse="18 January 2040 12:00:00 Europe/Stockholm",
parsed_time=None,
)
assert parsed_time.err is True
assert parsed_time.err_msg == "Could not parse the date."
assert parsed_time.date_to_parse == "18 January 2040 12:00:00 Europe/Stockholm"
assert parsed_time.parsed_time is None