from tests.utils import (TestCaseSansDB, TestCaseWithDB, TestCaseWithServer,
Expected)
from plomtask.processes import Process, ProcessStep
-from plomtask.conditions import Condition
from plomtask.exceptions import NotFoundException
"""Module tests requiring DB setup."""
checked_class = Process
- def test_from_table_row(self) -> None:
- """Test .from_table_row() properly reads in class from DB."""
- super().test_from_table_row()
- p, set1, set2, set3 = self.p_of_conditions()
- p.save(self.db_conn)
- assert isinstance(p.id_, int)
- for row in self.db_conn.row_where(self.checked_class.table_name,
- 'id', p.id_):
- r = Process.from_table_row(self.db_conn, row)
- self.assertEqual(sorted(r.conditions), sorted(set1))
- self.assertEqual(sorted(r.enables), sorted(set2))
- self.assertEqual(sorted(r.disables), sorted(set3))
-
- def test_Process_steps(self) -> None:
- """Test addition, nesting, and non-recursion of ProcessSteps"""
- # pylint: disable=too-many-locals
- # pylint: disable=too-many-statements
- p1, p2, p3 = self.three_processes()
- assert isinstance(p1.id_, int)
- assert isinstance(p2.id_, int)
- assert isinstance(p3.id_, int)
- steps_p1: list[ProcessStep] = []
- # # add step of process p2 as first (top-level) step to p1
- # s_p2_to_p1 = ProcessStep(None, p1.id_, p2.id_, None)
- # steps_p1 += [s_p2_to_p1]
- # p1.set_steps(self.db_conn, steps_p1)
- # p1_dict: dict[int, ProcessStepsNode] = {}
- # p1_dict[1] = ProcessStepsNode(p2, None, True, {})
- # self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict)
- # # add step of process p3 as second (top-level) step to p1
- # s_p3_to_p1 = ProcessStep(None, p1.id_, p3.id_, None)
- # steps_p1 += [s_p3_to_p1]
- # p1.set_steps(self.db_conn, steps_p1)
- # p1_dict[2] = ProcessStepsNode(p3, None, True, {})
- # self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict)
- # # add step of process p3 as first (top-level) step to p2,
- # steps_p2: list[ProcessStep] = []
- # s_p3_to_p2 = ProcessStep(None, p2.id_, p3.id_, None)
- # steps_p2 += [s_p3_to_p2]
- # p2.set_steps(self.db_conn, steps_p2)
- # # expect it as implicit sub-step of p1's second (p3) step
- # p2_dict = {3: ProcessStepsNode(p3, None, False, {})}
- # p1_dict[1].steps[3] = p2_dict[3]
- # self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict)
- # # add step of process p2 as explicit sub-step to p1's second sub-step
- # s_p2_to_p1_first = ProcessStep(None, p1.id_, p2.id_, s_p3_to_p1.id_)
- # steps_p1 += [s_p2_to_p1_first]
- # p1.set_steps(self.db_conn, steps_p1)
- # seen_3 = ProcessStepsNode(p3, None, False, {}, False)
- # p1_dict[1].steps[3].seen = True
- # p1_dict[2].steps[4] = ProcessStepsNode(p2, s_p3_to_p1.id_, True,
- # {3: seen_3})
- # self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict)
-
- # add step of process p3 as explicit sub-step to non-existing p1
- # sub-step (of id=999), expect it to become another p1 top-level step
- s_p3_to_p1_999 = ProcessStep(None, p1.id_, p3.id_, 999)
- steps_p1 += [s_p3_to_p1_999]
- p1.set_steps(self.db_conn, steps_p1)
- p1_dict[5] = ProcessStepsNode(p3, None, True, {})
- self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict)
- # add step of process p3 as explicit sub-step to p1's implicit p3
- # sub-step, expect it to become another p1 top-level step
- s_p3_to_p1_impl_p3 = ProcessStep(None, p1.id_, p3.id_,
- s_p3_to_p2.id_)
- steps_p1 += [s_p3_to_p1_impl_p3]
- p1.set_steps(self.db_conn, steps_p1)
- p1_dict[6] = ProcessStepsNode(p3, None, True, {})
- self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict)
- self.assertEqual(p1.used_as_step_by(self.db_conn), [])
- self.assertEqual(p2.used_as_step_by(self.db_conn), [p1])
- self.assertEqual(p3.used_as_step_by(self.db_conn), [p1, p2])
- # add step of process p3 as explicit sub-step to p1's first
- # sub-step, expect it to eliminate implicit p3 sub-step
- s_p3_to_p1_first_explicit = ProcessStep(None, p1.id_, p3.id_,
- s_p2_to_p1.id_)
- p1_dict[1].steps = {7: ProcessStepsNode(p3, 1, True, {})}
- p1_dict[2].steps[4].steps[3].seen = False
- steps_p1 += [s_p3_to_p1_first_explicit]
- p1.set_steps(self.db_conn, steps_p1)
- self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict)
- # ensure implicit steps non-top explicit steps are shown
- s_p3_to_p2_first = ProcessStep(None, p2.id_, p3.id_, s_p3_to_p2.id_)
- steps_p2 += [s_p3_to_p2_first]
- p2.set_steps(self.db_conn, steps_p2)
- p1_dict[1].steps[3].steps[7] = ProcessStepsNode(p3, 3, False, {},
- True)
- p1_dict[2].steps[4].steps[3].steps[7] = ProcessStepsNode(
- p3, 3, False, {}, False)
- self.assertEqual(p1.get_steps(self.db_conn, None), p1_dict)
- # ensure suppressed step nodes are hidden
- assert isinstance(s_p3_to_p2.id_, int)
- p1.set_step_suppressions(self.db_conn, [s_p3_to_p2.id_])
- p1_dict[1].steps[3].steps = {}
- p1_dict[1].steps[3].is_suppressed = True
- p1_dict[2].steps[4].steps[3].steps = {}
- p1_dict[2].steps[4].steps[3].is_suppressed = True
- self.assertEqual(p1.get_steps(self.db_conn), p1_dict)
-
def test_remove(self) -> None:
"""Test removal of Processes and ProcessSteps."""
super().test_remove()
self.post_exp_process([exp], {}, 1)
# post first (top-level) step of proc2 to proc1 by 'step_of' in 2
self.post_exp_process([exp], {'step_of': 1}, 2)
- exp.lib_set('ProcessStep', [exp.procstep_as_dict(1, owner_id=1, step_process_id=2)])
+ exp.lib_set('ProcessStep',
+ [exp.procstep_as_dict(1, owner_id=1, step_process_id=2)])
exp.set('steps', [
exp.stepnode_as_dict(
step_id=1,
step_nodes = [exp.stepnode_as_dict(step_id=1, proc_id=2)]
exp.set('steps', step_nodes)
self.check_json_get(url, exp)
- # fail on single--step recursion
+ # fail on zero-step recursion
p_min = {'title': '', 'description': '', 'effort': 0}
self.check_post(p_min | {'new_top_step': 1}, url, 400)
self.check_post(p_min | {'step_of': 1}, url, 400)
step_nodes[1]['steps'] = [
exp.stepnode_as_dict(step_id=4, proc_id=4)]
self.check_json_get(url, exp)
- # fail on multi-step recursion via new step(s)
- self.post_exp_process([exp], {}, 5)
- self.post_exp_process([exp], {'new_top_step': 1}, 5)
- exp.lib_set('ProcessStep', [exp.procstep_as_dict(
- 5, owner_id=5, step_process_id=1)])
- self.check_post(p_min | {'step_of': 5, 'new_top_step': 5}, url, 400)
+ # to ensure suppressed step nodes are hidden, add new step to proc4,
+ # implicitly adding it as sub-step to the proc4 steps in proc1, but
+ # suppress one of the proc4 occurences there, marking its
+ # .is_suppressed *and* hiding the new step below it
+ p = {'kept_steps': [1, 2, 4], 'suppressed_steps': [3]}
+ self.post_exp_process([exp], {'step_of': [4]}, 5)
+ self.post_exp_process([exp], p, 1)
+ exp.lib_set('ProcessStep',
+ [exp.procstep_as_dict(5, owner_id=4, step_process_id=5)])
+ assert isinstance(step_nodes[0]['steps'], list)
+ assert isinstance(step_nodes[1]['steps'], list)
+ step_nodes[0]['steps'][0]['is_suppressed'] = True
+ step_nodes[1]['steps'][0]['steps'] = [
+ exp.stepnode_as_dict(step_id=5, proc_id=5, is_explicit=False)]
+ self.check_json_get(url, exp)
+ # ensure implicit steps' non-top explicit sub-steps are shown
self.post_exp_process([exp], {}, 6)
- self.post_exp_process([exp], {'new_top_step': 5}, 6)
+ self.post_exp_process([exp], {'kept_steps': [5], 'step_of': [1, 2],
+ 'new_step_to_5': 6}, 4)
exp.lib_set('ProcessStep', [exp.procstep_as_dict(
- 6, owner_id=6, step_process_id=5)])
- self.check_post(p_min | {'step_of': 5, 'new_top_step': 6}, url, 400)
- # fail on multi-step recursion via explicit sub-step
+ 6, owner_id=4, parent_step_id=5, step_process_id=6)])
+ step_nodes[1]['steps'][0]['steps'][0]['steps'] = [
+ exp.stepnode_as_dict(step_id=6, proc_id=6, is_explicit=False)]
+ self.check_json_get(url, exp)
+ # try to post sub-step to non-existing sub-step, expect it to become
+ # top-level step instead
+ p['new_step_to_9'] = 5
+ self.post_exp_process([exp], p, 1)
+ exp.lib_set('ProcessStep',
+ [exp.procstep_as_dict(7, owner_id=1, step_process_id=5)])
+ step_nodes += [
+ exp.stepnode_as_dict(step_id=7, proc_id=5)]
+ self.check_json_get(url, exp)
+ del p['new_step_to_9']
+ assert isinstance(p['kept_steps'], list)
+ p['kept_steps'] += [7]
+ # try to post sub-step to implicit sub-step, expect same result
+ p['new_step_to_5'] = 5
+ self.post_exp_process([exp], p, 1)
+ exp.lib_set('ProcessStep',
+ [exp.procstep_as_dict(8, owner_id=1, step_process_id=5)])
+ step_nodes += [
+ exp.stepnode_as_dict(step_id=8, proc_id=5)]
+ self.check_json_get(url, exp)
+ del p['new_step_to_5']
+ p['kept_steps'] += [8]
+ # post sub-step to explicit sub-step with implicit sub-step of same
+ # step process ID, expect it to eliminate/replace implicit sub-step
+ p['new_step_to_4'] = 5
+ self.post_exp_process([exp], p, 1)
+ step_nodes[1]['steps'][0]['steps'][0] = exp.stepnode_as_dict(
+ step_id=9, proc_id=5)
+ exp.lib_set('ProcessStep', [exp.procstep_as_dict(
+ 9, owner_id=1, parent_step_id=4, step_process_id=5)])
+ self.check_json_get(url, exp)
+ del p['new_step_to_4']
+ p['kept_steps'] += [9]
+ # fail on single-step recursion via top step
+ self.post_exp_process([exp], {}, 7)
+ self.post_exp_process([exp], {'new_top_step': 1}, 7)
+ exp.lib_set('ProcessStep', [exp.procstep_as_dict(
+ 10, owner_id=7, step_process_id=1)])
+ p['step_of'] = [7]
+ self.check_post(p_min | p | {'new_top_step': 7}, url, 400)
+ # fail on double-step recursion via top step
+ self.post_exp_process([exp], {}, 8)
+ self.post_exp_process([exp], {'new_top_step': 7}, 8)
+ exp.lib_set('ProcessStep', [exp.procstep_as_dict(
+ 11, owner_id=8, step_process_id=7)])
+ self.check_post(p_min | p | {'new_top_step': 8}, url, 400)
+ # fail on single-step recursion via explicit sub-step
+ self.check_json_get(url, exp)
+ self.check_post(p_min | p | {'new_step_to_8': 7}, url, 400)
+ # fail on double-step recursion via explicit sub-step
self.check_json_get(url, exp)
- p = {'step_of': 5, 'kept_steps': [1, 2, 4], 'new_step_to_2': 6}
- self.check_post(p_min | p, url, 400)
+ self.check_post(p_min | p | {'new_step_to_8': 8}, url, 400)
def test_fail_GET_process(self) -> None:
"""Test invalid GET /process params."""