async def test_batch_status_as_post(self):
        """Verifies a POST to /batch_status works properly.

        It will receive a Protobuf response with:
            - batch statuses of:
                * 'committed': COMMITTED
                * 'pending': PENDING
                * 'bad': UNKNOWN

        It should send a Protobuf request with:
            - a batch_ids property of ['committed', 'pending', 'bad']

        It should send back a JSON response with:
            - a response status of 200
            - an empty link property
            - a data property matching the batch statuses received
        """
        statuses = [
            BatchStatus(batch_id='committed', status=BatchStatus.COMMITTED),
            BatchStatus(batch_id='pending', status=BatchStatus.PENDING),
            BatchStatus(batch_id='bad', status=BatchStatus.UNKNOWN)
        ]
        self.stream.preset_response(batch_statuses=statuses)

        request = await self.client.post(
            '/batch_status',
            data=json.dumps(['committed', 'pending', 'bad']).encode(),
            headers={'content-type': 'application/json'})
        self.stream.assert_valid_request_sent(
            batch_ids=['committed', 'pending', 'bad'])
        self.assertEqual(200, request.status)

        response = await request.json()
        self.assertNotIn('link', response)
        self.assert_statuses_match(statuses, response['data'])
    async def test_batch_status_with_many_ids(self):
        """Verifies a GET /batch_status with many ids works properly.

        It will receive a Protobuf response with:
            - batch statuses of:
                * 'committed': COMMITTED
                * 'unknown': UNKNOWN
                * 'bad': UNKNOWN

        It should send a Protobuf request with:
            - a batch_ids property of ['committed', 'unknown', 'bad']

        It should send back a JSON response with:
            - a response status of 200
            - link property ending in '/batch_status?id=committed,unknown,bad'
            - a data property matching the batch statuses received
        """
        statuses = [
            BatchStatus(batch_id='committed', status=BatchStatus.COMMITTED),
            BatchStatus(batch_id='unknown', status=BatchStatus.UNKNOWN),
            BatchStatus(batch_id='bad', status=BatchStatus.UNKNOWN)
        ]
        self.stream.preset_response(batch_statuses=statuses)

        response = await self.get_assert_200(
            '/batch_status?id=committed,unknown,bad')
        self.stream.assert_valid_request_sent(
            batch_ids=['committed', 'unknown', 'bad'])

        self.assert_has_valid_link(response,
                                   '/batch_status?id=committed,unknown,bad')
        self.assert_statuses_match(statuses, response['data'])
    async def test_batch_status_with_invalid_data(self):
        """Verifies a GET /batch_status with fetched invalid data works.

        It will receive a Protobuf response with:
            - batch_id: 'bad-batch'
            - status: INVALID
            - invalid_transaction: 'bad-transaction'
            - message: 'error message'
            - extended_data: b'error data'

        It should send a Protobuf request with:
            - a batch_ids property of ['bad']

        It should send back a JSON response with:
            - a response status of 200
            - a link property that ends in '/batch_status?id=bad'
            - a data property matching the batch statuses received
        """
        statuses = [
            BatchStatus(batch_id='bad-batch',
                        status=BatchStatus.INVALID,
                        invalid_transactions=[
                            BatchStatus.InvalidTransaction(
                                transaction_id='bad-transaction',
                                message='error message',
                                extended_data=b'error data')
                        ])
        ]
        self.stream.preset_response(batch_statuses=statuses)

        response = await self.get_assert_200('/batch_status?id=bad')
        self.stream.assert_valid_request_sent(batch_ids=['bad'])

        self.assert_has_valid_link(response, '/batch_status?id=bad')
        self.assert_statuses_match(statuses, response['data'])
    async def test_batch_status_with_wait(self):
        """Verifies a GET /batch_status with a wait set works properly.

        It will receive a Protobuf response with:
            - batch statuses of {batch_id: 'pending', status: COMMITTED}

        It should send a Protobuf request with:
            - a batch_ids property of ['pending']
            - a wait_for_commit property that is True
            - a timeout property of 4 (Rest Api default)

        It should send back a JSON response with:
            - a response status of 200
            - a link property that ends in '/batch_status?id=pending&wait'
            - a data property matching the batch statuses received
        """
        statuses = [
            BatchStatus(batch_id='pending', status=BatchStatus.COMMITTED)
        ]
        self.connection.preset_response(batch_statuses=statuses)

        response = await self.get_assert_200('/batch_status?id=pending&wait')
        self.connection.assert_valid_request_sent(batch_ids=['pending'],
                                                  wait_for_commit=True,
                                                  timeout=4)

        self.assert_has_valid_link(response, '/batch_status?id=pending&wait')
        self.assert_statuses_match(statuses, response['data'])
    async def test_post_batch_with_timeout(self):
        """Verifies a POST /batches works when timed out while waiting.

        It will receive a Protobuf response with:
            - batch statuses of {'pending': PENDING}

        It should send a Protobuf request with:
            - a batches property that matches the batches sent
            - a wait_for_commit property that is True
            - a timeout property of 4 (Rest Api default)

        It should send back a JSON response with:
            - a response status of 200
            - a link property that ends in '/batch_status?id=pending'
            - a data property matching the batch statuses received
        """
        batches = Mocks.make_batches('pending')
        statuses = [
            BatchStatus(batch_id='pending', status=BatchStatus.PENDING)
        ]
        self.connection.preset_response(batch_statuses=statuses)

        request = await self.post_batches(batches, wait=True)
        self.connection.assert_valid_request_sent(batches=batches,
                                                  wait_for_commit=True,
                                                  timeout=4)
        self.assertEqual(202, request.status)

        response = await request.json()
        self.assert_has_valid_link(response, '/batch_status?id=pending&wait')
        self.assert_statuses_match(statuses, response['data'])
    async def test_post_batch_with_wait(self):
        """Verifies a POST /batches can wait for commit properly.

        It will receive a Protobuf response with:
            - batch statuses of {'a': COMMITTED}

        It should send a Protobuf request with:
            - a batches property that matches the batches sent
            - a wait_for_commit property that is True
            - a timeout property of 4 (Rest Api default)

        It should send back a JSON response with:
            - a response status of 201
            - no data property
            - a link property that ends in '/batches?id=a'
        """
        batches = Mocks.make_batches('a')
        statuses = [BatchStatus(batch_id='a', status=BatchStatus.COMMITTED)]
        self.connection.preset_response(batch_statuses=statuses)

        request = await self.post_batches(batches, wait=True)
        self.connection.assert_valid_request_sent(batches=batches,
                                                  wait_for_commit=True,
                                                  timeout=4)
        self.assertEqual(201, request.status)

        response = await request.json()
        self.assert_has_valid_link(response, '/batches?id=a')
        self.assertNotIn('data', response)
    async def test_batch_status_with_one_id(self):
        """Verifies a GET /batch_status with one id works properly.

        It will receive a Protobuf response with:
            - batch statuses of {batch_id: 'pending',  status: PENDING}

        It should send a Protobuf request with:
            - a batch_ids property of ['pending']

        It should send back a JSON response with:
            - a response status of 200
            - a link property that ends in '/batch_status?id=pending'
            - a data property matching the batch statuses received
        """
        statuses = [
            BatchStatus(batch_id='pending', status=BatchStatus.PENDING)
        ]
        self.connection.preset_response(batch_statuses=statuses)

        response = await self.get_assert_200('/batch_status?id=pending')
        self.connection.assert_valid_request_sent(batch_ids=['pending'])

        self.assert_has_valid_link(response, '/batch_status?id=pending')
        self.assert_statuses_match(statuses, response['data'])