def test_get_task_updated(self):
        # 当該タスクに対してより新しいTaskStatusが追加された場合に
        # get_taskで最新のTaskStatusが取得できることを確認します。

        manipulator = TaskManipulator()
        
        # 事前にタスクを作成
        TODO_TITLE = "test-task"
        TODO_USER = User.objects.get(pk=2) 
        TODO_DESCRIPTION = "test-description"
        TODO_STATUS = TaskStatus.objects.get(pk=1)

        manipulator = TaskManipulator()

        TODO_TASK = manipulator.create(
            title=TODO_TITLE,
            user=TODO_USER,
            description=TODO_DESCRIPTION
        )
        
        # TaskHistoryにRUNNNINGの状態のものを追加
        RUNNING_STATUS = TaskStatus.objects.get(pk=2)
        TaskHistory(
            status=RUNNING_STATUS,
            task=TODO_TASK
        ).save()

        task, status = manipulator.get_task(user=TODO_USER, task_id=TODO_TASK.id) 

        self.assertEqual(task, TODO_TASK)
        self.assertEqual(status, RUNNING_STATUS)
    def test_get_task(self):
        # 当該Userに紐づくTaskが1つある場合に
        # Task, TaskStatus(TODO状態)が
        # 返ってくることを確認します。

        manipulator = TaskManipulator()
        
        # 事前にタスクを作成
        TODO_TITLE = "test-task"
        TODO_USER = User.objects.get(pk=2) 
        TODO_DESCRIPTION = "test-description"
        TODO_STATUS = TaskStatus.objects.get(pk=1)

        manipulator = TaskManipulator()

        TODO_TASK = manipulator.create(
            title=TODO_TITLE,
            user=TODO_USER,
            description=TODO_DESCRIPTION
        )
        
        task, status = manipulator.get_task(user=TODO_USER, task_id=TODO_TASK.id)

        self.assertEqual(task.title, TODO_TITLE)
        self.assertEqual(task.user, TODO_USER)
        self.assertEqual(task.description, TODO_DESCRIPTION)
        self.assertEqual(status, TODO_STATUS) 
    def test_delete_task_with_other_users(self):
        """
        存在するが、他Userに紐付いているTaskを
        削除しようとしてNoneが返ってくることを期待する。
        """
        manipulator = TaskManipulator()
        TODO_USER = User.objects.get(pk=2)
        TODO_TITLE = "todo"
        TODO_DESCRIPTION = "todo-description"

        TODO_TASK = manipulator.create(
            user=TODO_USER,
            title=TODO_TITLE,
            description=TODO_DESCRIPTION
        )

        user = User.objects.get(pk=1)
        task_id = manipulator.delete_task(
            user=user,
            task_id=TODO_TASK.id
        )

        self.assertIsNone(task_id)

        # 当該タスクが削除されていないことを確認する。
        task, _ = manipulator.get_task(user=TODO_USER, task_id=TODO_TASK.id)

        self.assertEqual(task, TODO_TASK)
    def test_delete_task(self):
        """
        Taskが正常に削除され、かつ、
        削除されたTaskのIDが返ってくることを期待する。
        """
        
        manipulator = TaskManipulator()
        TODO_USER = User.objects.get(pk=2)
        TODO_TITLE = "todo"
        TODO_DESCRIPTION = "todo-description"

        TODO_TASK = manipulator.create(
            user=TODO_USER,
            title=TODO_TITLE,
            description=TODO_DESCRIPTION
        )

        task_id = manipulator.delete_task(
            user=TODO_USER,
            task_id=TODO_TASK.id
        )
        

        self.assertEqual(task_id, TODO_TASK.id)

        # 正常に削除できていることを確認する。
        task, task_status = manipulator.get_task(user=TODO_USER, task_id=task_id)

        self.assertIsNone(task)
        self.assertIsNone(task_status)
    def get(self, request, task_id=None):
        """
        1) task_idが指定されている場合
        ・対応するidを持つTaskがリクエストしたUserのものである場合は
          当該Task1つのみを当該Taskに含んだを返す。
        ・対応するTaskが存在しない場合は空配列と404 Not Foundを返す
        ・対応するTaskが存在してもリクエストしたUserのものではない場合も
        404 Not Foundとから配列を返す。
        2) task_idが指定されていない場合
        ・リクエストしたUserのTaskの配列を返す(200 OK)

        <返すレスポンスの形式>
        [
            {
                "id": Task.id,
                "title": Task.title,
                "description": Task.description,
                "status": Taskの最新TaskStatus.name
            },...
        ]
        """
        user = request.user
        manipulator = TaskManipulator()

        tasks = []
        if task_id is None:
            ts = manipulator.get_tasks(user=user)
        
            for task, task_status in ts:
                tasks.append({
                    "id": task.id,
                    "title": task.title,
                    "description": task.description,
                    "status": task_status.name,
                })
            

        else:
            task, task_status = manipulator.get_task(user=user, task_id=task_id)

            if task is None or task_status is None:
                # 一方のみがNone出ないことはアプリケーションの仕様上
                # ありえないが念の為
                serializer = TaskSerializer(tasks, many=True)
                return Response(data=serializer.data, status=status.HTTP_404_NOT_FOUND)

            tasks.append({
                "id": task.id,
                "title": task.title,
                "description": task.description,
                "status": task_status.name,
            })
        
        serializer = TaskSerializer(tasks, many=True)
        return Response(data=serializer.data, status=status.HTTP_200_OK)
    def test_get_task_not_exist(self):
        # 存在しないTaskのidを指定して
        # None, Noneが返ってくることを期待する。
        manipulator = TaskManipulator()

        TODO_USER = User.objects.get(pk=2) 

        # 明らかに存在しないTaskのidを指定する
        task, status = manipulator.get_task(user=TODO_USER, task_id=100)

        self.assertIsNone(task)
        self.assertIsNone(status)
    def delete(self, request, task_id):
        """
        削除対象としたいtask_id以外は、特に不要
        レスポンスメッセージとして以下を期待
        {
            "id": 削除したTaskのID,
            "title": 削除したTaskのtitle,
            "description": 削除したTaskのdescription
        }
        削除に成功した場合は200 OKを返す。
        削除対象のTaskが存在しない場合は404 Not Foundを返す。
        404 Not Foundを返す際は、レスポンスボディは空
        (本当にTaskが存在しない場合、
        Taskに紐づくUserがリクエストしたUserと異なる場合も同様)
        """

        manipulator = TaskManipulator()

        user = request.user

        task, _ = manipulator.get_task(user=user, task_id=task_id)

        if task is None:
            return Response(status=status.HTTP_404_NOT_FOUND)

        response_task = {
            "id": task.id,
            "title": task.title,
            "description": task.description
        }

        task_id = manipulator.delete_task(user=user, task_id=task.id)

        if task_id is None:
            # 基本的にはこれは到達不可能コード
            # (事前に削除対象のタスクが存在し、
            # リクエストしたユーザのものであることを確認済みであるため)
            return Response(status=status.HTTP_404_NOT_FOUND)

        serializer = TaskSerializer(response_task)

        return Response(data=serializer.data, status=status.HTTP_200_OK)
    def test_get_task_with_other_users(self):
        # 指定したidのTaskは存在するが、
        # 他UserのTaskである場合。
        manipulator = TaskManipulator()
        
        # 事前にタスクを作成
        TODO_TITLE = "test-task"
        TODO_USER = User.objects.get(pk=2)
        TODO_DESCRIPTION = "test-description"

        manipulator = TaskManipulator()

        TODO_TASK = manipulator.create(
            title=TODO_TITLE,
            user=TODO_USER,
            description=TODO_DESCRIPTION
        )

        USER = User.objects.get(pk=1) # Task作成時のUserとは別Userを指定
        task, status = manipulator.get_task(user=USER, task_id=TODO_TASK.id)
        
        self.assertIsNone(task)
        self.assertIsNone(status)