예제 #1
0
    def test_freeze_parent_task_sets_state(
        self,
        repo: FakeRepository,
        parent_and_child_tasks: Tuple[RecurrentTask, Task],
        caplog: LogCaptureFixture,
    ) -> None:
        """
        Given: A recurrent parent and child tasks.
        When: using the freeze_tasks on the child task
        Then: The parent's state becomes frozen, and the last child is deleted from
            the repository.
        """
        parent_task, child_task = parent_and_child_tasks
        selector = TaskSelector(task_ids=[parent_task.id_],
                                model=RecurrentTask)

        services.freeze_tasks(repo, selector)  # act

        with pytest.raises(EntityNotFoundError):
            repo.get(child_task.id_, [Task])
        parent_task = repo.get(parent_task.id_, [RecurrentTask])
        assert parent_task.active is False
        assert parent_task.state == TaskState.FROZEN
        assert (
            "pydo.services",
            logging.INFO,
            f"Frozen recurrent task {parent_task.id_}: {parent_task.description} and "
            f"deleted it's last child {child_task.id_}",
        ) in caplog.record_tuples
예제 #2
0
    def test_thawing_a_parent_with_completed_children_works(
            self, repo: FakeRepository,
            insert_parent_task: Tuple[RecurrentTask, Task]) -> None:
        """
        Given: A parent with completed children
        When: Thawing the parent
        Then: The parent is thawed and the next children is breeded
        """
        parent_task, child_task = insert_parent_task
        services._close_task(repo, child_task, TaskState.DONE)
        repo.commit()
        selector = TaskSelector(task_ids=[parent_task.id_],
                                model=RecurrentTask)
        services.freeze_tasks(repo, selector)

        services.thaw_tasks(repo, selector)  # act

        parent_task = repo.get(parent_task.id_, [RecurrentTask])
        assert parent_task.state == TaskState.BACKLOG
        children_tasks = repo.search(
            {
                "parent_id": parent_task.id_,
                "active": True
            }, [Task])
        assert len(children_tasks) == 1
예제 #3
0
def repo_fake() -> Generator[FakeRepository, None, None]:
    """Return an instance of the FakeRepository."""
    fake_repo = FakeRepository()

    yield fake_repo

    fake_repo.close()
예제 #4
0
def test_greetings(repo: FakeRepository) -> None:
    author = Author(id_=20, first_name="Brandon")
    repo.add(author)
    repo.commit()

    result = create_greeting(repo, 20)

    assert result == "Hi Brandon!"
예제 #5
0
    def test_add_can_create_simple_task(
        self,
        repo: FakeRepository,
        faker: Faker,
        caplog: LogCaptureFixture,
    ) -> None:
        """
        Given: Some desired task attributes for a simple task.
        When: using the add_task service.
        Then: The task is added to the repository.
        """
        now = datetime.now()
        description = faker.sentence()
        change = TaskChanges(task_attributes={"description": description})

        result = services.add_task(repo, change)

        # Ensure that the object is in the repository
        task = repo.get(result.id_, [Task])
        assert task.description == description
        assert task.state == "backlog"
        assert (task.created - now).total_seconds() < 2
        assert (task.modified - now).total_seconds() < 2
        assert task.closed is None
        assert task.area is None
        assert (
            "pydo.services",
            logging.INFO,
            f"Added task {task.id_}: {task.description}",
        ) in caplog.record_tuples
예제 #6
0
    def test_close_child_task_with_delete_parent_true_also_do_parent(
            self,
            action: Callable[..., None],
            state: str,
            repo: FakeRepository,
            parent_and_child_tasks: Tuple[RecurrentTask, Task],
            freezer: FrozenDateTimeFactory,  # noqa: W0613
    ) -> None:
        """
        Given: A repository with a parent and a child task.
        When: Using the do_tasks or rm_tasks on the child_id
            with the delete_parent flag.
        Then: The child and parent are closed.
        """
        now = datetime.now()
        parent_task, child_task = parent_and_child_tasks
        selector = TaskSelector(task_ids=[child_task.id_])

        action(repo, selector, delete_parent=True)  # act

        parent_task = repo.get(parent_task.id_, [RecurrentTask])
        assert parent_task.state == state
        assert parent_task.closed == now
        assert child_task.state == state
        assert child_task.closed == now
예제 #7
0
    def test_close_task_sets_state_and_close_date(
        self,
        action: Callable[[FakeRepository, TaskSelector], None],
        state: str,
        repo: FakeRepository,
        task: Task,
        freezer: FrozenDateTimeFactory,  # noqa: W0613
        caplog: LogCaptureFixture,
    ) -> None:
        """
        Given: An existent task.
        When: using the do_tasks or rm_tasks.
        Then: The task is closed with the respective state and the closed date is set.
        """
        selector = TaskSelector(task_ids=[task.id_])
        now = datetime.now()

        action(repo, selector)  # act

        task = repo.get(task.id_, [Task])
        assert task.closed == now
        assert task.modified == now
        assert task.state == state
        assert (
            "pydo.services",
            logging.INFO,
            f"Closing task {task.id_}: {task.description} with state {state}",
        ) in caplog.record_tuples
예제 #8
0
    def test_close_task_doesnt_close_already_closed_tasks(
        self,
        action: Callable[[FakeRepository, TaskSelector], None],
        state: str,
        repo: FakeRepository,
        tasks: List[Task],
        freezer: FrozenDateTimeFactory,  # noqa: W0613
        caplog: LogCaptureFixture,
    ) -> None:
        """
        Given: An existent closed task.
        When: using the do_tasks or rm_tasks.
        Then: Only the open task is closed.
        """
        closed_task = tasks[0]
        services._close_task(repo, closed_task, TaskState.DONE)
        caplog.clear()
        selector = TaskSelector(task_ids=[closed_task.id_, tasks[1].id_])

        action(repo, selector)  # act

        task = repo.get(tasks[1].id_, [Task])
        assert task.state == state
        assert (
            "pydo.services",
            logging.INFO,
            f"Closing task {closed_task.id_}: {closed_task.description} "
            f"with state {state}",
        ) not in caplog.record_tuples
예제 #9
0
    def test_modify_task_modifies_task_attributes(
        self,
        repo: FakeRepository,
        faker: Faker,
        task: Task,
        caplog: LogCaptureFixture,
    ) -> None:
        """
        Given: An existent task.
        When: Using modify_task to modify the description.
        Then: The description is modified.
        """
        now = datetime.now()
        description = faker.sentence()
        selector = TaskSelector(task_ids=[task.id_])
        change = TaskChanges(task_attributes={"description": description}, )

        services.modify_tasks(repo, selector, change)  # act

        modified_task = repo.get(task.id_, [Task])
        assert modified_task.description == description
        assert (modified_task.modified - now).total_seconds() < 2
        assert (
            "pydo.services",
            logging.INFO,
            f"Modified task {task.id_}.",
        ) in caplog.record_tuples
예제 #10
0
    def test_modify_child_task_parent_notifies_orphan_if_no_parent(
        self,
        repo: FakeRepository,
        task: Task,
        caplog: LogCaptureFixture,
        faker: Faker,
    ) -> None:
        """
        Given: A task without parent
        When: modifying the task with modify_parent = True
        Then: A warning is shown that the task has no parent.
        """
        selector = TaskSelector(task_ids=[task.id_])
        description = faker.sentence()
        change = TaskChanges(task_attributes={"description": description})

        services.modify_tasks(repo, selector, change,
                              modify_parent=True)  # act

        modified_task = repo.get(task.id_, [Task])
        assert modified_task.description == description
        assert (
            "pydo.services",
            logging.WARNING,
            f"Task {task.id_} doesn't have a parent task.",
        ) in caplog.record_tuples
예제 #11
0
    def test_close_child_task_generates_next_children(
        self,
        action: Callable[[FakeRepository, TaskSelector], None],
        state: str,
        repo: FakeRepository,
        parent_and_child_tasks: Tuple[RecurrentTask, Task],
        caplog: LogCaptureFixture,
    ) -> None:
        """
        Given: A repository with a parent and a child task.
        When: Using the do_tasks or rm_tasks on the child_id.
        Then: The child is closed, the new child is created, and the parent
            is left open.
        """
        now = datetime.now()
        parent_task, child_task = parent_and_child_tasks
        selector = TaskSelector(task_ids=[child_task.id_])

        action(repo, selector)  # act

        parent_task = repo.get(parent_task.id_, [RecurrentTask])
        new_child = repo.search({
            "parent_id": parent_task.id_,
            "active": True
        }, [Task])[-1]
        assert new_child is not None
        assert new_child > child_task
        assert parent_task.state == "backlog"
        assert child_task.state == state
        assert child_task.closed is not None
        assert (child_task.closed - now).total_seconds() < 2
        assert new_child.state == "backlog"
        assert (new_child.created - now).total_seconds() < 2
        assert new_child.due is not None
        assert new_child.due >= parent_task.due
        assert (
            "pydo.services",
            logging.INFO,
            f"Closing child task {child_task.id_}: {child_task.description} with state"
            f" {state}",
        ) in caplog.record_tuples
        assert (
            "pydo.services",
            logging.INFO,
            f"Added child task {new_child.id_}: {new_child.description}",
        ) in caplog.record_tuples
예제 #12
0
    def test_add_generates_recurrent_tasks(
        self,
        repo: FakeRepository,
        faker: Faker,
        caplog: LogCaptureFixture,
        recurrence_type: str,
    ) -> None:
        """
        Given: Some desired task attributes for a recurrent or repeating task.
        When: using the add_task service.
        Then: Both parent and child tasks are added to the repository.
        """
        task_attributes = {
            "description": faker.sentence(),
            "due": faker.date_time(),
            "recurrence": "1d",
            "recurrence_type": recurrence_type,
            "state": "todo",
        }

        result = services.add_task(
            repo, TaskChanges(task_attributes=task_attributes))

        assert isinstance(result, RecurrentTask)
        parent_task = repo.get(result.id_, [RecurrentTask])
        child_task = repo.search({"parent_id": parent_task.id_}, [Task])[0]
        # Assert the id of the child is sequential with the parent's
        assert child_task.parent_id == parent_task.id_
        assert child_task.state == "todo"
        assert child_task.due >= task_attributes["due"]
        assert parent_task.recurrence == task_attributes["recurrence"]
        assert parent_task.recurrence_type == task_attributes[
            "recurrence_type"]
        assert parent_task.due == task_attributes["due"]
        assert (
            "pydo.services",
            logging.INFO,
            f"Added {parent_task.recurrence_type} task {parent_task.id_}:"
            f" {parent_task.description}",
        ) in caplog.record_tuples
        assert (
            "pydo.services",
            logging.INFO,
            f"Added first child task with id {child_task.id_}",
        ) in caplog.record_tuples
예제 #13
0
def test_add_works_with_return_value_of_function(
        repo_fake: FakeRepository) -> None:
    """
    Given: A Fake repository and a function that returns a list of entities
    When: Using repo.add on the result of the function
    Then: no mypy error is returned
    """
    books = get_books()

    result = repo_fake.add(books)

    assert len(result) == 5
예제 #14
0
    def test_modify_task_modifies_parent_attributes(
        self,
        repo: FakeRepository,
        caplog: LogCaptureFixture,
        faker: Faker,
        insert_parent_task: Tuple[RecurrentTask, Task],
    ) -> None:
        """
        Given: A recurrent task and it's child
        When: modifying the child with modify_parent = True
        Then: Both parent and child attributes are changed.
        """
        parent_task, child_task = insert_parent_task
        selector = TaskSelector(task_ids=[child_task.id_])
        description = faker.sentence()
        change = TaskChanges(task_attributes={"description": description})

        services.modify_tasks(repo, selector, change,
                              modify_parent=True)  # act

        modified_child_task = repo.get(child_task.id_, [Task])
        modified_parent_task = repo.get(parent_task.id_, [RecurrentTask])
        assert modified_child_task.description == description
        assert modified_parent_task.description == description
예제 #15
0
    def test_modify_task_adds_tags(self, repo: FakeRepository, task: Task,
                                   faker: Faker) -> None:
        """
        Given: A task without tags
        When: modifying it to add a tag
        Then: the tags are added
        """
        selector = TaskSelector(task_ids=[task.id_])
        tag = faker.word()
        change = TaskChanges(tags_to_add=[tag])

        services.modify_tasks(repo, selector, change)  # act

        modified_task = repo.get(task.id_, [Task])
        assert modified_task.tags == [tag]
예제 #16
0
    def test_modify_task_removes_tags(self, repo: FakeRepository, task: Task,
                                      faker: Faker) -> None:
        """
        Given: A task with a tag
        When: modifying it to remove the tag
        Then: the tags are removed, but the rest of the properties are kept.
        """
        tag = faker.word()
        selector = TaskSelector(task_ids=[task.id_])
        change = TaskChanges(tags_to_add=[tag])
        services.modify_tasks(repo, selector, change)
        change = TaskChanges(tags_to_remove=[tag])

        services.modify_tasks(repo, selector, change)  # act

        modified_task = repo.get(task.id_, [Task])
        assert modified_task.tags == []
        assert modified_task.description == task.description
예제 #17
0
    def test_thawing_a_parent_without_children_works(
            self, repo: FakeRepository) -> None:
        """
        Given: A parent without children
        When: Thawing the parent
        Then: The parent is thawed and the first children is breeded
        """
        now = datetime.now()
        task = RecurrentTaskFactory(state="frozen")
        repo.add(task)
        repo.commit()
        selector = TaskSelector(task_ids=[task.id_])

        services.thaw_tasks(repo, selector)  # act

        parent_task = repo.get(task.id_, [RecurrentTask])
        assert parent_task.state == TaskState.BACKLOG
        assert (parent_task.modified - now).total_seconds() < 2
        children_tasks = repo.search({"parent_id": parent_task.id_}, [Task])
        assert len(children_tasks) == 1
예제 #18
0
def repo() -> FakeRepository:
    return FakeRepository()
예제 #19
0
파일: conftest.py 프로젝트: lyz-code/pydo
def repo_() -> FakeRepository:
    """Configure a FakeRepository instance."""
    return FakeRepository([Task, RecurrentTask])