def test_undo_empty_planned(): """ Test undoing the addition of a task to an empty session. """ # Construct session. session = Session("test") # Insert task and undo insertion. session.insert_task( day=4, planned=True, name="test", priority=1.0, start_time=time(hour=12), hours=1.5, ) session.undo() # Test session values. assert session.history_pos == 0 assert len(session.edit_history) == 2 assert len(session.edit_history[0][0].tasks) == 0 assert len(session.edit_history[0][1].tasks) == 0 assert len(session.edit_history[1][0].tasks) == 1 assert len(session.edit_history[1][1].tasks) == 0 task = session.edit_history[1][0].tasks[0] assert task.name == "test" assert task.priority == 1.0 assert task.start_time.date() == session.base_date + timedelta(days=4) assert task.start_time.time() == time(hour=12) assert task.end_time.date() == session.base_date + timedelta(days=4) assert task.end_time.time() == time(hour=13, minute=30)
def test_edit_task_time_valid(): """ Edit the time of a single task in a valid way, i.e. it doesn't interfere with other tasks. """ # Set up case. Note that we have to manually set the base date of the session in # order to access the task, since it has a hard-coded date. session = Session("example", load=True) session.base_date = session.current_schedules()[0].tasks[0].start_time.date() session.base_date -= timedelta(days=session.base_date.weekday()) planned = True day = 4 task_index = 0 new_values = {"start_time": datetime(2020, 5, 1, hour=13)} # Store pre-insert session values. pre_history_pos = session.history_pos pre_edit_history = list(session.edit_history) original_task = session.get_task(planned=planned, day=day, task_index=task_index) new_task = deepcopy(original_task) new_task.start_time = new_values["start_time"] # Edit task. session.edit_task( planned=planned, day=day, task_index=task_index, new_values=new_values, ) # Test session values. assert session.history_pos == pre_history_pos + 1 assert len(session.edit_history) == len(pre_edit_history) + 1 assert session.edit_history[:-1] == pre_edit_history assert pre_edit_history[-1][0].tasks[0] == original_task assert session.edit_history[-1][0].tasks[0] == new_task assert session.edit_history[-1][1] == pre_edit_history[-1][1]
def test_insert_task_overlap(): """ Insert an invalid (overlapping) task into the planned schedule of a nonempty session, and check that an error gets raised. """ # Construct session. session = Session("example", load=True) # Store pre-insert session values. pre_history_pos = session.history_pos pre_edit_history = list(session.edit_history) # Insert task. error = False try: session.insert_task( day=5, planned=True, name="test", priority=1.0, start_time=time(hour=13), hours=1, ) except ValueError: error = True # Ensure error was thrown. assert error
def test_insert_task_empty_planned(): """ Insert a task into the planned schedule of an empty session. """ # Construct session. session = Session("test") # Insert task. session.insert_task( day=0, planned=True, name="test", priority=1.0, start_time=time(hour=12), hours=1.5, ) # Test session values. assert session.history_pos == 1 assert len(session.edit_history) == 2 assert len(session.edit_history[0][0].tasks) == 0 assert len(session.edit_history[0][1].tasks) == 0 assert len(session.edit_history[1][0].tasks) == 1 assert len(session.edit_history[1][1].tasks) == 0 task = session.edit_history[1][0].tasks[0] assert task.name == "test" assert task.priority == 1.0 assert task.start_time == datetime.combine(session.base_date, time(hour=12)) assert task.end_time == datetime.combine( session.base_date, time(hour=13, minute=30) )
def test_delete_task_single_actual(): """ Test deleting task from a schedule with only one task in actual. """ # Construct session. Note that we have to manually set the base date of the session # in order to access the task, since it has a hard-coded date. session = Session("test") session.insert_task( day=4, planned=False, name="test", priority=1.0, start_time=time(hour=12), hours=1.5, ) session.base_date = session.current_schedules( )[1].tasks[0].start_time.date() session.base_date -= timedelta(days=session.base_date.weekday()) # Delete the task. session.delete_task(planned=False, day=4, task_index=0) # Test session values. assert session.history_pos == 2 assert len(session.edit_history) == 3 assert len(session.edit_history[0][0].tasks) == 0 assert len(session.edit_history[0][1].tasks) == 0 assert len(session.edit_history[1][0].tasks) == 0 assert len(session.edit_history[1][1].tasks) == 1 assert len(session.edit_history[2][0].tasks) == 0 assert len(session.edit_history[2][1].tasks) == 0
def test_undo_filled_planned(): """ Test undoing an edit task action on a filled out planned schedule. """ # Set up case. Note that we have to manually set the base date of the session in # order to access the task, since it has a hard-coded date. session = Session("example", load=True) session.base_date = session.current_schedules( )[0].tasks[0].start_time.date() session.base_date -= timedelta(days=session.base_date.weekday()) planned = True day = 4 task_index = 0 new_values = {"name": "new_name"} # Store pre-edit values. old_history_pos = session.history_pos old_planned, old_actual = session.current_schedules() # Edit task, then undo. session.edit_task( planned=planned, day=day, task_index=task_index, new_values=new_values, ) session.undo() # Test session values. new_planned, new_actual = session.current_schedules() assert session.history_pos == old_history_pos assert old_planned == new_planned assert old_actual == new_actual
def test_move_tasks_invalid(): """ Test moving tasks in an invalid way. """ # Construct session. Note that we have to manually set the base date of the session in # order to access the task, since it has a hard-coded date. session = Session("example", load=True) session.base_date = session.current_schedules( )[0].tasks[0].start_time.date() session.base_date -= timedelta(days=session.base_date.weekday()) planned = True day = 4 start_task_index = 0 end_task_index = 1 # Move task into invalid time slot. error = False try: session.move_tasks( planned=planned, day=day, start_task_index=start_task_index, end_task_index=end_task_index, time_delta=timedelta(hours=2), ) except: error = True # Ensure that error was thrown. assert error
def test_delete_task_full(): """ Test deleting task from a full schedule. """ # Construct session. Note that we have to manually set the base date of the session in # order to access the task, since it has a hard-coded date. session = Session("example", load=True) session.base_date = session.current_schedules( )[0].tasks[0].start_time.date() session.base_date -= timedelta(days=session.base_date.weekday()) planned = True day = 5 task_index = 0 # Store pre-delete session values. pre_history_pos = session.history_pos pre_edit_history = list(session.edit_history) original_task = session.get_task(planned=planned, day=day, task_index=task_index) # Delete task. session.delete_task(planned=planned, day=day, task_index=task_index) # Test session values. assert session.history_pos == pre_history_pos + 1 assert len(session.edit_history) == len(pre_edit_history) + 1 assert session.edit_history[:-1] == pre_edit_history assert pre_edit_history[-1][0].tasks[2] == original_task assert session.edit_history[-1][0].tasks == list_exclude( pre_edit_history[-1][0].tasks, 2) assert session.edit_history[-1][1] == pre_edit_history[-1][1]
def test_redo_filled(): """ Test redoing an action on a filled out planned schedule. """ # Set up case. Note that we have to manually set the base date of the session in # order to access the task, since it has a hard-coded date. session = Session("example", load=True) session.base_date = session.current_schedules( )[0].tasks[0].start_time.date() session.base_date -= timedelta(days=session.base_date.weekday()) # Store pre-edit values. old_history_pos = session.history_pos old_history_len = len(session.edit_history) old_planned, old_actual = session.current_schedules() # Undo then redo last action. session.undo() session.redo() # Test session values. new_planned, new_actual = session.current_schedules() assert session.history_pos == old_history_pos assert old_planned == new_planned assert old_actual == new_actual assert len(session.edit_history) == old_history_len
def test_edit_task_time_invalid(): """ Edit the time of a single task in an invalid way, i.e. it interferes with other tasks. """ # Set up case. Note that we have to manually set the base date of the session in # order to access the task, since it has a hard-coded date. session = Session("example", load=True) session.base_date = session.current_schedules()[0].tasks[0].start_time.date() session.base_date -= timedelta(days=session.base_date.weekday()) planned = True day = 4 task_index = 0 new_values = { "start_time": datetime(2020, 5, 1, hour=13), "end_time": datetime(2020, 5, 1, hour=14), } # Edit task in a way that creates overlap, i.e. should throw an error. error = False try: session.edit_task( planned=planned, day=day, task_index=task_index, new_values=new_values, ) except: error = True # Ensure error was thrown. assert error
def test_daily_points_score_empty(): """ Daily points for an empty schedule. """ # Construct session. session = Session("test") # Construct expected point/score values. p_ind_pts = [0.0] * DAYS_IN_WEEK p_cum_pts = [0.0] * DAYS_IN_WEEK a_ind_pts = [0.0] * DAYS_IN_WEEK a_cum_pts = [0.0] * DAYS_IN_WEEK ind_score = [100.0] * DAYS_IN_WEEK cum_score = [100.0] * DAYS_IN_WEEK # Test point values. for day in range(DAYS_IN_WEEK): assert (session.daily_points(day, planned=False, cumulative=False) == p_ind_pts[day]) assert (session.daily_points(day, planned=False, cumulative=True) == p_cum_pts[day]) assert (session.daily_points(day, planned=True, cumulative=False) == a_ind_pts[day]) assert (session.daily_points(day, planned=True, cumulative=True) == a_cum_pts[day]) assert session.daily_score(day, cumulative=False) == ind_score[day] assert session.daily_score(day, cumulative=True) == cum_score[day]
def test_load_from_invalid(): """ Test loading in a saved session wehn given an invalid name to load. We just check that an error gets raised. """ # Try to load session. error = False try: session = Session("bad_example", load=True) except: error = True # Ensure an error was raised. assert error
def test_redo_edge(): """ Test redoing when there is nothing to redo. """ # Construct session. session = Session("test") # Undo. session.redo() # Test session values. assert session.history_pos == 0 assert len(session.edit_history) == 1 assert len(session.edit_history[0][0].tasks) == 0 assert len(session.edit_history[0][1].tasks) == 0
def test_move_week_backward(): """ Test moving the displayed week backward. """ # Construct session. Note that we have to manually set the base date of the session in # order to access the task, since it has a hard-coded date. session = Session("example", load=True) session.base_date = session.current_schedules()[0].tasks[0].start_time.date() session.base_date -= timedelta(days=session.base_date.weekday()) # Move the week forward. session.move_week(forward=False) # Test week value. assert session.base_date == date(2020, 4, 20)
def test_move_tasks_full(): """ Test moving multiple tasks in a full schedule. """ # Construct session. Note that we have to manually set the base date of the session in # order to access the task, since it has a hard-coded date. session = Session("example", load=True) session.base_date = session.current_schedules( )[0].tasks[0].start_time.date() session.base_date -= timedelta(days=session.base_date.weekday()) planned = True day = 4 start_task_index = 0 end_task_index = 2 # Store pre-move session values. pre_history_pos = session.history_pos pre_edit_history = list(session.edit_history) original_tasks = [ session.get_task(planned=planned, day=day, task_index=i) for i in range(start_task_index, end_task_index) ] # Move tasks. session.move_tasks( planned=planned, day=day, start_task_index=start_task_index, end_task_index=end_task_index, time_delta=timedelta(hours=2), ) # Test session values. edited_tasks = [deepcopy(task) for task in original_tasks] edited_tasks[0].start_time = datetime(2020, 5, 1, hour=14) edited_tasks[0].end_time = datetime(2020, 5, 1, hour=15, minute=30) edited_tasks[1].start_time = datetime(2020, 5, 1, hour=15, minute=30) edited_tasks[1].end_time = datetime(2020, 5, 1, hour=16, minute=30) assert session.history_pos == pre_history_pos + 1 assert len(session.edit_history) == len(pre_edit_history) + 1 assert session.edit_history[:-1] == pre_edit_history assert pre_edit_history[-1][0].tasks[0:2] == original_tasks assert session.edit_history[-1][0].tasks[0:2] == edited_tasks assert session.edit_history[-1][0].tasks[2:] == pre_edit_history[-1][ 0].tasks[2:] assert session.edit_history[-1][1] == pre_edit_history[-1][1]
def test_insert_task_nonempty_planned(): """ Insert a task into the planned schedule of a nonempty session. """ # Construct session. session = Session("example", load=True) # Store pre-insert session values. pre_history_pos = session.history_pos pre_edit_history = list(session.edit_history) # Insert task. task = Task( "test", priority=1.0, start_time=datetime(2020, 5, 1, hour=15), end_time=datetime(2020, 5, 1, hour=16), ) session.insert_task( day=4, planned=True, name="test", priority=1.0, start_time=time(hour=15), hours=1, ) # Test session values. assert session.history_pos == pre_history_pos + 1 assert len(session.edit_history) == len(pre_edit_history) + 1 assert session.edit_history[:-1] == pre_edit_history assert session.edit_history[-1][1] == pre_edit_history[-1][1] assert ( list_exclude(session.edit_history[-1][0].tasks, 2) == pre_edit_history[-1][0].tasks ) task = session.edit_history[-1][0].tasks[2] assert task.name == "test" assert task.priority == 1.0 assert task.start_time == datetime.combine( session.base_date, time(hour=15) ) + timedelta(days=4) assert task.end_time == datetime.combine( session.base_date, time(hour=16) ) + timedelta(days=4)
def test_move_tasks_single_planned(): """ Test moving a single task from a planned schedule with only a single task. """ # Construct session. Note that we have to manually set the base date of the session # in order to access the task, since it has a hard-coded date. session = Session("test") session.insert_task( day=4, planned=True, name="test", priority=1.0, start_time=time(hour=12), hours=1.5, ) session.base_date = session.current_schedules( )[0].tasks[0].start_time.date() session.base_date -= timedelta(days=session.base_date.weekday()) # Move the task. session.move_tasks( planned=True, day=4, start_task_index=0, end_task_index=1, time_delta=timedelta(hours=2), ) # Test session values. assert session.history_pos == 2 assert len(session.edit_history) == 3 assert len(session.edit_history[0][0].tasks) == 0 assert len(session.edit_history[0][1].tasks) == 0 assert len(session.edit_history[1][0].tasks) == 1 assert len(session.edit_history[1][1].tasks) == 0 assert len(session.edit_history[2][0].tasks) == 1 assert len(session.edit_history[2][1].tasks) == 0 task = session.edit_history[2][0].tasks[0] assert task.name == "test" assert task.priority == 1.0 assert task.start_time.date() == session.base_date + timedelta(days=4) assert task.start_time.time() == time(hour=14) assert task.end_time.date() == session.base_date + timedelta(days=4) assert task.end_time.time() == time(hour=15, minute=30)
def test_redo_empty_planned(): """ Test redoing the addition of a task to an empty session. """ # Construct session. session = Session("test") # Insert task. session.insert_task( day=4, planned=True, name="test", priority=1.0, start_time=time(hour=12), hours=1.5, ) # Store session values. old_planned, old_actual = session.current_schedules() # Undo, then redo insertion. session.undo() session.redo() # Test session values. new_planned, new_actual = session.current_schedules() assert session.history_pos == 1 assert len(session.edit_history) == 2 assert new_planned == old_planned assert new_actual == old_actual assert len(session.edit_history[0][0].tasks) == 0 assert len(session.edit_history[0][1].tasks) == 0 assert len(session.edit_history[1][0].tasks) == 1 assert len(session.edit_history[1][1].tasks) == 0 task = session.edit_history[1][0].tasks[0] assert task.name == "test" assert task.priority == 1.0 assert task.start_time.date() == session.base_date + timedelta(days=4) assert task.start_time.time() == time(hour=12) assert task.end_time.date() == session.base_date + timedelta(days=4) assert task.end_time.time() == time(hour=13, minute=30)
def test_insert_task_sorted(): """ Insert a task into the actual schedule of a nonempty session, and check that the new task gets sorted correctly. """ # Construct session. session = Session("example", load=True) # Store pre-insert session values. pre_history_pos = session.history_pos pre_edit_history = list(session.edit_history) # Insert task. session.insert_task( day=5, planned=False, name="test", priority=1.0, start_time=time(hour=12, minute=30), hours=0.5, ) # Test session values. assert session.history_pos == pre_history_pos + 1 assert len(session.edit_history) == len(pre_edit_history) + 1 assert session.edit_history[:-1] == pre_edit_history assert session.edit_history[-1][0] == pre_edit_history[-1][0] assert ( list_exclude(session.edit_history[-1][1].tasks, 3) == pre_edit_history[-1][1].tasks ) task = session.edit_history[-1][1].tasks[3] assert task.name == "test" assert task.priority == 1.0 assert task.start_time == datetime.combine( session.base_date, time(hour=12, minute=30) ) + timedelta(days=5) assert task.end_time == datetime.combine( session.base_date, time(hour=13) ) + timedelta(days=5)
def test_set_new_schedules_1(): """ Call `set_new_schedules()` in the first case of edit history (cases listed in docstring of `set_new_schedules()`). """ # Construct session. session = Session("test") # Construct planned and new schedules. planned_task = Task( "planned_task", priority=1.0, start_time=datetime(2020, 5, 1, hour=12), end_time=datetime(2020, 5, 1, hour=13, minute=30), ) actual_task = Task( "actual_task", priority=1.0, start_time=datetime(2020, 5, 1, hour=13), end_time=datetime(2020, 5, 1, hour=14, minute=30), ) planned = Schedule("planned", [planned_task]) actual = Schedule("actual", [actual_task]) # Set new schedules in session. session.set_new_schedules(planned, actual) # Test session values. assert session.history_pos == 1 assert len(session.edit_history) == 2 assert len(session.edit_history[0][0].tasks) == 0 assert len(session.edit_history[0][1].tasks) == 0 assert len(session.edit_history[1][0].tasks) == 1 assert len(session.edit_history[1][1].tasks) == 1 assert session.edit_history[1][0].tasks[0] == planned_task assert session.edit_history[1][1].tasks[0] == actual_task
def test_delete_task_invalid(): """ Test deleting a nonexistent task from a full schedule. """ # Construct session. Note that we have to manually set the base date of the session in # order to access the task, since it has a hard-coded date. session = Session("example", load=True) session.base_date = session.current_schedules( )[0].tasks[0].start_time.date() session.base_date -= timedelta(days=session.base_date.weekday()) planned = True day = 6 task_index = 1 # Delete nonexistent task. error = False try: session.delete_task(planned=planned, day=day, task_index=task_index) except: error = True # Ensure that error was thrown. assert error
def test_load_from_valid(): """ Test loading in a saved session when given a valid save name to load. Note that this will have to change in the case that scripts/save_example.py changes, as this essentially a hard-coded check for the result of the current implementation of that script. """ # Load session. session = Session("example", load=True) # Compare session values. planned_tasks, actual_tasks = EXAMPLE_TASKS assert session.history_pos == 12 assert len(session.edit_history) == 13 assert session.edit_history[0][0].tasks == [] assert session.edit_history[0][1].tasks == [] for i in range(len(planned_tasks)): assert session.edit_history[i + 1][0].tasks == planned_tasks[:i + 1] assert session.edit_history[i + 1][1].tasks == [] for i in range(len(actual_tasks)): n = len(planned_tasks) assert session.edit_history[n + i + 1][0].tasks == planned_tasks assert session.edit_history[n + i + 1][1].tasks == actual_tasks[:i + 1]
def test_set_new_schedules_2(): """ Call `set_new_schedules()` in the second case of edit history (cases listed in docstring of `set_new_schedules()`). """ # Construct session. session = Session("test") # Construct planned and new schedules. planned_tasks = [ Task( "planned_task_1", priority=1.0, start_time=datetime(2020, 5, 1, hour=12), end_time=datetime(2020, 5, 1, hour=13, minute=30), ), Task( "planned_task_2", priority=1.0, start_time=datetime(2020, 5, 1, hour=12, minute=30), end_time=datetime(2020, 5, 1, hour=14), ), ] actual_tasks = [ Task( "actual_task_1", priority=1.0, start_time=datetime(2020, 5, 1, hour=13), end_time=datetime(2020, 5, 1, hour=14, minute=30), ), Task( "actual_task_2", priority=1.0, start_time=datetime(2020, 5, 1, hour=13, minute=30), end_time=datetime(2020, 5, 1, hour=15), ), ] planned = [ Schedule("planned_1", [planned_tasks[0]]), Schedule("planned_2", [planned_tasks[1]]), ] actual = [ Schedule("actual_1", [actual_tasks[0]]), Schedule("actual_2", [actual_tasks[1]]), ] # Set new schedules in session, undo, then redo with new versions. session.set_new_schedules(planned[0], actual[0]) session.undo() session.set_new_schedules(planned[1], actual[1]) # Test session values. assert session.history_pos == 1 assert len(session.edit_history) == 2 assert len(session.edit_history[0][0].tasks) == 0 assert len(session.edit_history[0][1].tasks) == 0 assert len(session.edit_history[1][0].tasks) == 1 assert len(session.edit_history[1][1].tasks) == 1 assert session.edit_history[1][0].tasks[0] == planned_tasks[1] assert session.edit_history[1][1].tasks[0] == actual_tasks[1]
def test_daily_points_score_current_week(): """ Daily points for a schedule with tasks only in current week. """ # Construct session. session = Session("test") b = session.base_date planned_tasks = [ { "day": 1, "planned": True, "name": "pt1", "priority": 1.0, "start_time": time(hour=12), "hours": 1.5, }, { "day": 1, "planned": True, "name": "pt1", "priority": 2.0, "start_time": time(hour=13, minute=30), "hours": 2.0, }, { "day": 3, "planned": True, "name": "pt3", "priority": 1.0, "start_time": time(hour=13, minute=30), "hours": 2.0, }, ] actual_tasks = [ { "day": 1, "planned": False, "name": "at2", "priority": 2.0, "start_time": time(hour=14, minute=30), "hours": 1.0, }, { "day": 3, "planned": False, "name": "at3", "priority": 1.0, "start_time": time(hour=19, minute=30), "hours": 2.0, }, ] for task_kwargs in planned_tasks: session.insert_task(**task_kwargs) for task_kwargs in actual_tasks: session.insert_task(**task_kwargs) # Construct expected point/score values. p_ind_pts = [0.0, 5.5, 0.0, 2.0, 0.0, 0.0, 0.0] p_cum_pts = [0.0, 5.5, 5.5, 7.5, 7.5, 7.5, 7.5] a_ind_pts = [0.0, 2.0, 0.0, 2.0, 0.0, 0.0, 0.0] a_cum_pts = [0.0, 2.0, 2.0, 4.0, 4.0, 4.0, 4.0] ind_score = [100.0, 100.0 * 2.0 / 5.5] + [100.0] * 5 cum_score = [100.0] + [100.0 * 2.0 / 5.5] * 2 + [100.0 * 4.0 / 7.5] * 4 # Test point values. for day in range(DAYS_IN_WEEK): assert (session.daily_points(day, planned=True, cumulative=False) == p_ind_pts[day]) assert (session.daily_points(day, planned=True, cumulative=True) == p_cum_pts[day]) assert (session.daily_points(day, planned=False, cumulative=False) == a_ind_pts[day]) assert (session.daily_points(day, planned=False, cumulative=True) == a_cum_pts[day]) assert session.daily_score(day, cumulative=False) == ind_score[day] assert session.daily_score(day, cumulative=True) == cum_score[day]