Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
make deps-install
- name: Run tests
run: |
pip install coverage pytest pytest-cov
pip install coverage pytest pytest-mock pytest-cov
make test testdoc
- name: "Upload coverage to Codecov"
if: github.repository == 'thingsapi/things.py'
Expand Down
3 changes: 2 additions & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ verify_ssl = true
name = "pypi"

[packages]
pytest = "*"
pytest-mock = "*"

[dev-packages]

black = "*"
coverage = "*"
flake8 = "*"
Expand Down
94 changes: 77 additions & 17 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 55 additions & 1 deletion tests/test_things.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io
import os
import sqlite3
import datetime
import time
import tracemalloc
import unittest
Expand Down Expand Up @@ -39,7 +40,8 @@
+ TRASHED_PROJECT_TRASHED_TODOS
)
PROJECTS = 4
UPCOMING = 1
UPCOMING = 2
UPCOMING_2020_12_18 = UPCOMING + 1
DEADLINE_PAST = 3
DEADLINE_FUTURE = 1
DEADLINE = DEADLINE_PAST + DEADLINE_FUTURE
Expand Down Expand Up @@ -130,6 +132,56 @@ def test_trashed(self):
def test_upcoming(self):
tasks = things.upcoming()
self.assertEqual(UPCOMING, len(tasks))
titles = {t['title'] for t in tasks}
assert 'To-Do in Upcoming' in titles
assert 'Completed To-Do in Upcoming' not in titles
assert 'Cancelled To-Do in Upcoming' not in titles

def test_upcoming_includes_completed_and_canceled(self):
# they are shown in upcoming if they have a start_date > today.
# those two test cases have start=1 which never happens in the
# real db- upcoming tasks always have start=2=Someday.

completed_todo = things.tasks(uuid='LE2WEGxANmtHWD3c9g5iWA')
canceled_todo = things.tasks(uuid='ADLex1EmJzLpu2GHxFvLvc')
assert completed_todo['stop_date'] == '2021-03-28 14:14:21'
assert completed_todo['start'] == 'Someday'
assert canceled_todo['stop_date'] == '2021-03-28 14:14:24'
assert canceled_todo['start'] == 'Someday'
# as their stop dates are after the manualLogDate, they should be shown in upcoming().
manual_log_date = datetime.datetime.fromtimestamp(1616958822.8444772).isoformat()
assert manual_log_date == '2021-03-28T14:13:42.844477'

@unittest.mock.patch("things.database.date_today")
def test_upcoming_includes_repeating_instance(self, today_mock):
today_mock.return_value = '2020-12-18'
created_from_template_uuid = 'K9bx7h1xCJdevvyWardZDq'
created_instance = things.tasks(uuid=created_from_template_uuid)
assert created_instance['status'] == 'incomplete'
assert created_instance['start'] == 'Anytime' # never occurs in real data
# I was not able to re-create a task that has a startDate
# and start different from 2/Someday.
assert created_instance['start_date'] == '2020-12-19'
tasks = things.upcoming()
uuids = {t['uuid'] for t in tasks}
# was not found!
assert created_from_template_uuid not in uuids

@unittest.mock.patch("things.database.date_today")
def test_upcoming_includes_repeating_template(self, today_mock):
today_mock.return_value = '2020-12-18'
tasks = things.upcoming()
self.assertEqual(UPCOMING_2020_12_18, len(tasks))
template_uuid = 'N1PJHsbjct4mb1bhcs7aHa'
uuids = {t['uuid'] for t in tasks}
assert template_uuid in uuids

def test_repeating_template_fields_set(self):
tasks = things.tasks(is_repeating_task_template=True)
for task in tasks:
assert 'is_repeating_task_template' in list(task)
assert str(task['is_repeating_task_template']) == 'True'
assert task['start_date'] == '2025-03-28'

def test_deadlines(self):
tasks = things.tasks(deadline="past")
Expand Down Expand Up @@ -214,6 +266,8 @@ def test_todos(self):
self.assertEqual(19, len(tasks))
with self.assertRaises(ValueError):
things.todos(status="invalid_value")

def test_todos_length(self):
todo = things.todos("A2oPvtt4dXoypeoLc8uYzY")
self.assertEqual(16, len(todo.keys())) # type: ignore

Expand Down
2 changes: 2 additions & 0 deletions things/.pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[pytest]
mock_use_standalone_module = true
4 changes: 3 additions & 1 deletion things/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,9 @@ def upcoming(**kwargs):

For details on parameters, see `things.api.tasks`.
"""
return tasks(start_date="future", start="Someday", **kwargs)
scheduled_tasks = tasks(start_date="future", start="Someday", **kwargs)
repeating_task_templates = tasks(is_repeating_task_template=True, **kwargs)
return scheduled_tasks + repeating_task_templates


def anytime(**kwargs):
Expand Down
8 changes: 8 additions & 0 deletions things/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Helper module to test the Things API documentation."""

import pytest
from pytest_mock import MockerFixture

import things

Expand All @@ -9,3 +10,10 @@
def add_imports(doctest_namespace): # noqa
"""Import default modules."""
doctest_namespace["things"] = things


@pytest.fixture
def patch_today(mocker : MockerFixture) -> None:
"""Fixture to patch today's date."""
mock = mocker.patch("things.database.date_today")
mock.return_value = '2025-09-01'
Loading