from tests.utils import (TestCaseSansDB, TestCaseWithDB, TestCaseWithServer,
Expected)
from plomtask.conditions import Condition
-from plomtask.processes import Process
-from plomtask.todos import Todo
-from plomtask.exceptions import HandledException
class TestsSansDB(TestCaseSansDB):
checked_class = Condition
default_init_kwargs = {'is_active': 0}
- def test_remove(self) -> None:
- """Test .remove() effects on DB and cache."""
- super().test_remove()
- proc = Process(None)
- proc.save(self.db_conn)
- todo = Todo(None, proc, False, '2024-01-01')
- todo.save(self.db_conn)
- # check condition can only be deleted if not depended upon
- for depender in (proc, todo):
- c = Condition(None)
- c.save(self.db_conn)
- assert isinstance(c.id_, int)
- depender.set_condition_relations(self.db_conn, [c.id_], [], [], [])
- depender.save(self.db_conn)
- with self.assertRaises(HandledException):
- c.remove(self.db_conn)
- depender.set_condition_relations(self.db_conn, [], [], [], [])
- depender.save(self.db_conn)
- c.remove(self.db_conn)
-
class ExpectedGetConditions(Expected):
"""Builder of expectations for GET /conditions."""
self.check_minimal_inputs('/condition', valid_payload)
# check valid POST payload on bad paths
self.check_post(valid_payload, '/condition?id=foo', 400)
+ # check cannot delete depended-upon Condition
+ self.post_exp_cond([], {})
+ for key in ('conditions', 'blockers', 'enables', 'disables'):
+ self.post_exp_process([], {key: [1]}, 1)
+ self.check_post({'delete': ''}, '/condition?id=1', 500)
+ self.post_exp_process([], {}, 1)
+ self.post_exp_day([], {'new_todo': '1'})
+ for key in ('conditions', 'blockers', 'enables', 'disables'):
+ self.post_exp_todo([], {key: [1]}, 1)
+ self.check_post({'delete': ''}, '/condition?id=1', 500)
def test_POST_condition(self) -> None:
"""Test (valid) POST /condition and its effect on GET /condition[s]."""
exp_single, exp_all = ExpectedGetCondition(1), ExpectedGetConditions()
all_exps = [exp_single, exp_all]
# test valid POST's effect on single /condition and full /conditions
- self.post_exp_cond(all_exps, {'title': 'foo', 'description': 'oof'},
- post_to_id=False)
+ self.post_exp_cond(all_exps, {}, post_to_id=False)
self.check_json_get(url_single, exp_single)
self.check_json_get(url_all, exp_all)
# test (no) effect of invalid POST to existing Condition on /condition
self.check_post({}, url_single, 400)
self.check_json_get(url_single, exp_single)
- # test effect of POST changing title and activeness
+ # test effect of POST changing title, description, and activeness
self.post_exp_cond(all_exps, {'title': 'bar', 'description': 'oof',
'is_active': 1})
self.check_json_get(url_single, exp_single)
- self.check_json_get(url_all, exp_all)
# test POST sans 'is_active' setting it negative
- self.post_exp_cond(all_exps, {'title': 'bar', 'description': 'oof'})
+ self.post_exp_cond(all_exps, {})
self.check_json_get(url_single, exp_single)
- self.check_json_get(url_all, exp_all)
# test deletion POST's effect, both to return id=1 into empty single,
# full /conditions into empty list
+ self.check_json_get(url_single, exp_single)
self.post_exp_cond(all_exps, {'delete': ''}, redir_to_id=False)
exp_single.set('is_new', True)
self.check_json_get(url_single, exp_single)
# make Condition and two Processes that among them establish all
# possible ConditionsRelations to it, check /condition displays all
exp = ExpectedGetCondition(1)
- self.post_exp_cond([exp], {'title': 'foo', 'description': 'oof'},
- post_to_id=False)
+ self.post_exp_cond([exp], {}, post_to_id=False)
for i, p in enumerate([('conditions', 'disables'),
('enables', 'blockers')]):
self.post_exp_process([exp], {k: [1] for k in p}, i+1)
"""Tests against our HTTP server/handler (and database)."""
checked_class = Todo
- def _post_exp_todo(
- self, id_: int, payload: dict[str, Any], exp: Expected) -> None:
- self.check_post(payload, f'/todo?id={id_}')
- exp.set_todo_from_post(id_, payload)
-
def test_basic_fail_POST_todo(self) -> None:
"""Test basic malformed/illegal POST /todo requests."""
self.post_exp_process([], {}, 1)
# test posting doneness, comment, calendarization, effort
todo_post = {'is_done': 1, 'calendarize': 1,
'comment': 'foo', 'effort': 2.3}
- self._post_exp_todo(1, todo_post, exp)
+ self.post_exp_todo([exp], todo_post, 1)
self.check_json_get('/todo?id=1', exp)
# test implicitly un-setting comment/calendarize/is_done by empty post
- self._post_exp_todo(1, {}, exp)
+ self.post_exp_todo([exp], {}, 1)
self.check_json_get('/todo?id=1', exp)
# test effort post can be explicitly unset by "effort":"" post
self.check_post({'effort': ''}, '/todo?id=1')
self.check_json_get('/todo?id=1', exp)
todo_post = {'conditions': [1], 'disables': [1],
'blockers': [2], 'enables': [2]}
- self._post_exp_todo(1, todo_post, exp)
+ self.post_exp_todo([exp], todo_post, 1)
self.check_json_get('/todo?id=1', exp)
def test_POST_todo_deletion(self) -> None:
self.post_exp_process([exp], {}, 1)
self.post_exp_day([exp], {'new_todo': [1]})
self.post_exp_day([exp], {'new_todo': [1]})
- self._post_exp_todo(1, {'adopt': 2}, exp)
+ self.post_exp_todo([exp], {'adopt': 2}, 1)
exp.set('steps_todo_to_process', [
exp.step_as_dict(node_id=1, process=None, todo=2)])
self.check_json_get('/todo?id=1', exp)
# test Todo un-adopting by just not sending an adopt
- self._post_exp_todo(1, {}, exp)
+ self.post_exp_todo([exp], {}, 1)
exp.set('steps_todo_to_process', [])
self.check_json_get('/todo?id=1', exp)
# test fail on trying to adopt non-existing Todo
# test cannot self-adopt
self.check_post({'adopt': 1}, '/todo?id=1', 400)
# test cannot do 1-step circular adoption
- self._post_exp_todo(2, {'adopt': 1}, exp)
+ self.post_exp_todo([exp], {'adopt': 1}, 2)
self.check_post({'adopt': 2}, '/todo?id=1', 400)
# test cannot do 2-step circular adoption
self.post_exp_day([exp], {'new_todo': [1]})
- self._post_exp_todo(3, {'adopt': 2}, exp)
+ self.post_exp_todo([exp], {'adopt': 2}, 3)
self.check_post({'adopt': 3}, '/todo?id=1', 400)
# test can adopt Todo into ProcessStep chain via its Process (with key
# 'step_filler' equivalent to single-element 'adopt' if intable)
self.post_exp_day([exp], {'new_todo': [2]})
self.post_exp_day([exp], {'new_todo': [3]})
self.check_json_get('/todo?id=1', exp)
- self._post_exp_todo(1, {'step_filler_to_1': 5, 'adopt': [4]}, exp)
+ self.post_exp_todo([exp], {'step_filler_to_1': 5, 'adopt': [4]}, 1)
exp.lib_get('Todo', 1)['children'] += [5]
slots[0]['todo'] = 4
slots[1]['todo'] = 5
slots[1]['children'] = [exp.step_as_dict(
node_id=3, process=4, todo=None, fillable=True)]
self.post_exp_day([exp], {'new_todo': [4]})
- self._post_exp_todo(1, {'adopt': [4, 5, 6]}, exp)
+ self.post_exp_todo([exp], {'adopt': [4, 5, 6]}, 1)
slots += [exp.step_as_dict(
node_id=4, process=None, todo=6, fillable=False)]
self.check_json_get('/todo?id=1', exp)
def set_cond_from_post(self, id_: int, d: dict[str, Any]) -> None:
"""Set Condition of id_ in library based on POST dict d."""
- if d == {'delete': ''}:
+ if 'delete' in d:
self.lib_del('Condition', id_)
return
cond = self.lib_get('Condition', id_)
# pylint: disable=too-many-arguments
target = f'/condition?id={id_}' if post_to_id else '/condition'
redir = f'/condition?id={id_}' if redir_to_id else '/conditions'
+ if 'title' not in payload:
+ payload['title'] = 'foo'
+ if 'description' not in payload:
+ payload['description'] = 'foo'
self.check_post(payload, target, redir=redir)
for exp in exps:
exp.set_cond_from_post(id_, payload)
exp.set_proc_from_post(id_, payload)
return payload
+ def post_exp_todo(self,
+ exps: list[Expected],
+ payload: dict[str, Any],
+ id_: int,
+ ) -> None:
+ """POST /todo, appropriately updated Expecteds."""
+ self.check_post(payload, f'/todo?id={id_}')
+ for exp in exps:
+ exp.set_todo_from_post(id_, payload)
+
def check_filter(self, exp: Expected, category: str, key: str,
val: str, list_ids: list[int]) -> None:
"""Check GET /{category}?{key}={val} sorts to list_ids."""