Skip to content

save_exchange_record should be Optional #3728

save_exchange_record should be Optional

save_exchange_record should be Optional #3728

GitHub Actions / JUnit Test Report failed Nov 22, 2024 in 0s

865 tests run, 842 passed, 6 skipped, 17 failed.

Annotations

Check failure on line 529 in app/tests/e2e/verifier/test_verifier.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_verifier.test_accept_proof_request_verifier_has_issuer_role[clean-clean-clean-clean-clean-trust_registry]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f72041f4200>
method = 'post', url = '/v1/verifier/accept-request'
kwargs = {'json': {'dif_presentation_spec': None, 'indy_presentation_spec': {'requested_attributes': {'0_speed_uuid': {'cred_id...ibutes': {}, 'trace': None}, 'proof_id': 'v2-1a9ded88-7396-4f53-a0ad-6f331143c3ef', 'save_exchange_record': None, ...}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

meld_co_issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': 'fb87b3ab-e3f6-461f-a959-6921e817aa9a', 'created_at': '2024-11-22T17:40:39.958981Z', 'credential_definition_id': 'Vb8URxnLAs2WinBmxywSBW:3:CL:216:tag', ...}
meld_co_credential_definition_id = 'Vb8URxnLAs2WinBmxywSBW:3:CL:216:tag'
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f72041f4200>
meld_co_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f72041afb30>
meld_co_and_alice_connection = MeldCoAliceConnect(alice_connection_id='fb87b3ab-e3f6-461f-a959-6921e817aa9a', meld_co_connection_id='e67aef05-802b-48b5-ad9e-12c47f7b618f')

    @pytest.mark.anyio
    @pytest.mark.parametrize(
        "meld_co_and_alice_connection", ["trust_registry", "default"], indirect=True
    )
    async def test_accept_proof_request_verifier_has_issuer_role(
        meld_co_issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        meld_co_credential_definition_id: str,
        alice_member_client: RichAsyncClient,
        meld_co_client: RichAsyncClient,
        meld_co_and_alice_connection: MeldCoAliceConnect,
    ):
        request_body = {
            "connection_id": meld_co_and_alice_connection.meld_co_connection_id,
            "indy_proof_request": sample_indy_proof_request(
                restrictions=[{"cred_def_id": meld_co_credential_definition_id}]
            ).to_dict(),
        }
        send_proof_response = await send_proof_request(meld_co_client, request_body)
    
        meld_co_proof_id = send_proof_response["proof_id"]
        thread_id = send_proof_response["thread_id"]
    
        alice_payload = await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            state="request-received",
            filter_map={"thread_id": thread_id},
        )
        alice_proof_id = alice_payload["proof_id"]
    
        requested_credentials = await alice_member_client.get(
            f"{VERIFIER_BASE_PATH}/proofs/{alice_proof_id}/credentials"
        )
    
        assert await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            state="request-received",
            filter_map={
                "proof_id": alice_proof_id,
            },
        )
    
        referent = requested_credentials.json()[0]["cred_info"]["referent"]
        indy_request_attrs = IndyRequestedCredsRequestedAttr(
            cred_id=referent, revealed=True
        )
    
        proof_accept = AcceptProofRequest(
            proof_id=alice_proof_id,
            indy_presentation_spec=IndyPresSpec(
                requested_attributes={"0_speed_uuid": indy_request_attrs},
                requested_predicates={},
                self_attested_attributes={},
            ),
        )
    
>       response = await alice_member_client.post(
            VERIFIER_BASE_PATH + "/accept-request",
            json=proof_accept.model_dump(),
        )

app/tests/e2e/verifier/test_verifier.py:529: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f72041f4200>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/accept-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 38 in app/tests/e2e/issuer/test_save_exchange_record.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_save_exchange_record.test_issue_credential_with_save_exchange_record[clean-clean-clean-clean-clean-None]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7fb386b27c50>
method = 'post', url = '/v1/issuer/credentials'
kwargs = {'json': {'connection_id': '2a2eb3bb-1d25-4ea1-aad0-b5b04b40e84f', 'indy_credential_detail': {'attributes': {'age': '4...ce', 'speed': '10'}, 'credential_definition_id': '2AszGVdGiN6A2sa6AQPGD5:3:CL:245:tag'}, 'save_exchange_record': None}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/issuer/credentials'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

faber_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7fb386b27c50>
credential_definition_id = '2AszGVdGiN6A2sa6AQPGD5:3:CL:245:tag'
faber_and_alice_connection = FaberAliceConnect(alice_connection_id='058f4a74-e533-4aca-916d-5bbe40dbca25', faber_connection_id='2a2eb3bb-1d25-4ea1-aad0-b5b04b40e84f')
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7fb385f7d370>
save_exchange_record = None

    @pytest.mark.anyio
    @pytest.mark.parametrize("save_exchange_record", [None, False, True])
    async def test_issue_credential_with_save_exchange_record(
        faber_client: RichAsyncClient,
        credential_definition_id: str,
        faber_and_alice_connection: FaberAliceConnect,
        alice_member_client: RichAsyncClient,
        save_exchange_record: Optional[bool],
    ) -> CredentialExchange:
        credential = {
            "connection_id": faber_and_alice_connection.faber_connection_id,
            "indy_credential_detail": {
                "credential_definition_id": credential_definition_id,
                "attributes": sample_credential_attributes,
            },
            "save_exchange_record": save_exchange_record,
        }
    
        # create and send credential offer- issuer
        faber_send_response = (
>           await faber_client.post(
                CREDENTIALS_BASE_PATH,
                json=credential,
            )
        ).json()

app/tests/e2e/issuer/test_save_exchange_record.py:38: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7fb386b27c50>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/issuer/credentials'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/issuer/credentials', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 529 in app/tests/e2e/verifier/test_verifier.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_verifier.test_accept_proof_request_verifier_has_issuer_role[clean-clean-clean-clean-clean-default]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d94d10>
method = 'post', url = '/v1/verifier/accept-request'
kwargs = {'json': {'dif_presentation_spec': None, 'indy_presentation_spec': {'requested_attributes': {'0_speed_uuid': {'cred_id...ibutes': {}, 'trace': None}, 'proof_id': 'v2-17cf68cd-5ee7-4a7d-bc71-b4471cdd56ab', 'save_exchange_record': None, ...}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

meld_co_issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': 'd0611fc9-98b0-47c9-9762-a33a89902888', 'created_at': '2024-11-22T17:40:46.384371Z', 'credential_definition_id': 'Vb8URxnLAs2WinBmxywSBW:3:CL:216:tag', ...}
meld_co_credential_definition_id = 'Vb8URxnLAs2WinBmxywSBW:3:CL:216:tag'
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d94d10>
meld_co_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f72041afb30>
meld_co_and_alice_connection = MeldCoAliceConnect(alice_connection_id='d0611fc9-98b0-47c9-9762-a33a89902888', meld_co_connection_id='222ed84a-14f3-4c7d-8d98-4d70455382a9')

    @pytest.mark.anyio
    @pytest.mark.parametrize(
        "meld_co_and_alice_connection", ["trust_registry", "default"], indirect=True
    )
    async def test_accept_proof_request_verifier_has_issuer_role(
        meld_co_issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        meld_co_credential_definition_id: str,
        alice_member_client: RichAsyncClient,
        meld_co_client: RichAsyncClient,
        meld_co_and_alice_connection: MeldCoAliceConnect,
    ):
        request_body = {
            "connection_id": meld_co_and_alice_connection.meld_co_connection_id,
            "indy_proof_request": sample_indy_proof_request(
                restrictions=[{"cred_def_id": meld_co_credential_definition_id}]
            ).to_dict(),
        }
        send_proof_response = await send_proof_request(meld_co_client, request_body)
    
        meld_co_proof_id = send_proof_response["proof_id"]
        thread_id = send_proof_response["thread_id"]
    
        alice_payload = await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            state="request-received",
            filter_map={"thread_id": thread_id},
        )
        alice_proof_id = alice_payload["proof_id"]
    
        requested_credentials = await alice_member_client.get(
            f"{VERIFIER_BASE_PATH}/proofs/{alice_proof_id}/credentials"
        )
    
        assert await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            state="request-received",
            filter_map={
                "proof_id": alice_proof_id,
            },
        )
    
        referent = requested_credentials.json()[0]["cred_info"]["referent"]
        indy_request_attrs = IndyRequestedCredsRequestedAttr(
            cred_id=referent, revealed=True
        )
    
        proof_accept = AcceptProofRequest(
            proof_id=alice_proof_id,
            indy_presentation_spec=IndyPresSpec(
                requested_attributes={"0_speed_uuid": indy_request_attrs},
                requested_predicates={},
                self_attested_attributes={},
            ),
        )
    
>       response = await alice_member_client.post(
            VERIFIER_BASE_PATH + "/accept-request",
            json=proof_accept.model_dump(),
        )

app/tests/e2e/verifier/test_verifier.py:529: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d94d10>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/accept-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 98 in app/tests/e2e/verifier/test_predicate_proofs.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_predicate_proofs.test_predicate_proofs[clean-clean-clean-clean-clean-clean-<]

assert 422 == 400
 +  where 422 = HTTPException(status_code=422, detail='{"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}').status_code
 +    where HTTPException(status_code=422, detail='{"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}') = <ExceptionInfo HTTPException(status_code=422, detail='{"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}') tblen=4>.value
Raw output
acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7ff2df7d6840>
acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='d991b06a-f84f-4832-a9c2-f60ccf752968', acme_connection_id='3ca4d914-67a6-4e4e-b93d-d0f76d3790f8')
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7ff2df7a1e50>
issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': '5d3faf77-11e7-4661-a4f6-84507f1f486f', 'created_at': '2024-11-22T17:41:09.563954Z', 'credential_definition_id': '5kZ7Um6dCo4rNzdX8eijAf:3:CL:255:tag', ...}
predicate = '<'

    @pytest.mark.anyio
    @pytest.mark.parametrize("predicate", ["<", ">", "<=", ">="])
    async def test_predicate_proofs(
        acme_client: RichAsyncClient,
        acme_and_alice_connection: AcmeAliceConnect,
        alice_member_client: RichAsyncClient,
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        predicate: str,
    ):
        request_body = {
            "type": "indy",
            "indy_proof_request": {
                "requested_attributes": {},
                "requested_predicates": {
                    "over_18": {
                        "name": "age",
                        "p_type": predicate,
                        "p_value": 18,
                    }
                },
            },
            "connection_id": acme_and_alice_connection.acme_connection_id,
            "save_exchange_record": True,
        }
    
        send_proof_response = await send_proof_request(acme_client, request_body)
    
        thread_id = send_proof_response["thread_id"]
    
        alice_event = await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            filter_map={"thread_id": thread_id},
            state="request-received",
        )
    
        alice_proof_id = alice_event["proof_id"]
    
        requested_credentials = await alice_member_client.get(
            f"{VERIFIER_BASE_PATH}/proofs/{alice_proof_id}/credentials"
        )
    
        referent = requested_credentials.json()[0]["cred_info"]["referent"]
    
        proof_accept = AcceptProofRequest(
            proof_id=alice_proof_id,
            indy_presentation_spec=IndyPresSpec(
                requested_attributes={},
                requested_predicates={
                    "over_18": {
                        "cred_id": referent,
                    }
                },
                self_attested_attributes={},
            ),
        )
    
        if predicate in [">", ">="]:
            response = await alice_member_client.post(
                f"{VERIFIER_BASE_PATH}/accept-request",
                json=proof_accept.model_dump(),
            )
    
            result = response.json()
    
            pres_exchange_result = PresentationExchange(**result)
            assert isinstance(pres_exchange_result, PresentationExchange)
    
            acme_proof_event = await check_webhook_state(
                client=acme_client,
                topic="proofs",
                state="done",
                filter_map={"thread_id": thread_id},
            )
            assert acme_proof_event["verified"] is True
    
        else:
            with pytest.raises(HTTPException) as exc:
                await alice_member_client.post(
                    f"{VERIFIER_BASE_PATH}/accept-request", json=proof_accept.model_dump()
                )
    
>           assert exc.value.status_code == 400
E           assert 422 == 400
E            +  where 422 = HTTPException(status_code=422, detail='{"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}').status_code
E            +    where HTTPException(status_code=422, detail='{"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}') = <ExceptionInfo HTTPException(status_code=422, detail='{"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}') tblen=4>.value

app/tests/e2e/verifier/test_predicate_proofs.py:98: AssertionError

Check failure on line 133 in app/tests/e2e/verifier/test_verifier.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_verifier.test_accept_proof_request[clean-clean-clean-clean-clean-clean-trust_registry]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203938a40>
method = 'post', url = '/v1/verifier/accept-request'
kwargs = {'json': {'dif_presentation_spec': None, 'indy_presentation_spec': {'requested_attributes': {'0_speed_uuid': {'cred_id...ibutes': {}, 'trace': None}, 'proof_id': 'v2-206e7e91-aded-4089-a6fc-843a9dc77e0e', 'save_exchange_record': None, ...}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': 'd29f3784-1177-425c-b27d-974931bd5cbf', 'created_at': '2024-11-22T17:41:12.836406Z', 'credential_definition_id': '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag', ...}
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203938a40>
acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
credential_definition_id = '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag'
acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='19651091-891f-4949-878d-8dd921ea3c75', acme_connection_id='4f1d7509-a5e8-4500-99f7-57aef256ac60')

    @pytest.mark.anyio
    @pytest.mark.parametrize(
        "acme_and_alice_connection", ["trust_registry", "default"], indirect=True
    )
    async def test_accept_proof_request(
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        alice_member_client: RichAsyncClient,
        acme_client: RichAsyncClient,
        credential_definition_id: str,
        acme_and_alice_connection: AcmeAliceConnect,
    ):
        request_body = {
            "connection_id": acme_and_alice_connection.acme_connection_id,
            "indy_proof_request": {
                "name": "Proof Request",
                "version": "1.0.0",
                "requested_attributes": {
                    "0_speed_uuid": {
                        "name": "speed",
                        "restrictions": [{"cred_def_id": credential_definition_id}],
                    }
                },
                "requested_predicates": {},
            },
        }
        send_proof_response = await send_proof_request(acme_client, request_body)
    
        acme_proof_id = send_proof_response["proof_id"]
        thread_id = send_proof_response["thread_id"]
    
        alice_payload = await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            state="request-received",
            filter_map={
                "thread_id": thread_id,
            },
        )
    
        alice_proof_id = alice_payload["proof_id"]
    
        requested_credentials = await alice_member_client.get(
            f"{VERIFIER_BASE_PATH}/proofs/{alice_proof_id}/credentials"
        )
    
        referent = requested_credentials.json()[0]["cred_info"]["referent"]
        indy_request_attrs = IndyRequestedCredsRequestedAttr(
            cred_id=referent, revealed=True
        )
        proof_accept = AcceptProofRequest(
            proof_id=alice_proof_id,
            indy_presentation_spec=IndyPresSpec(
                requested_attributes={"0_speed_uuid": indy_request_attrs},
                requested_predicates={},
                self_attested_attributes={},
            ),
        )
    
>       response = await alice_member_client.post(
            VERIFIER_BASE_PATH + "/accept-request",
            json=proof_accept.model_dump(),
        )

app/tests/e2e/verifier/test_verifier.py:133: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203938a40>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/accept-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 74 in app/tests/e2e/verifier/test_predicate_proofs.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_predicate_proofs.test_predicate_proofs[clean-clean-clean-clean-clean-clean->]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7ff2df7b5340>
method = 'post', url = '/v1/verifier/accept-request'
kwargs = {'json': {'dif_presentation_spec': None, 'indy_presentation_spec': {'requested_attributes': {}, 'requested_predicates'...ibutes': {}, 'trace': None}, 'proof_id': 'v2-d111bb31-eb39-4378-b9b1-e30439d5ab61', 'save_exchange_record': None, ...}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7ff2df7d6840>
acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='92a50c89-1dc7-40c4-8974-6eea1b0f37b3', acme_connection_id='1a184139-4df9-435a-a289-8833635c0c32')
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7ff2df7b5340>
issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': 'fcc87fc0-32bc-48bf-b2ba-cbedc97905dc', 'created_at': '2024-11-22T17:41:16.206261Z', 'credential_definition_id': '5kZ7Um6dCo4rNzdX8eijAf:3:CL:255:tag', ...}
predicate = '>'

    @pytest.mark.anyio
    @pytest.mark.parametrize("predicate", ["<", ">", "<=", ">="])
    async def test_predicate_proofs(
        acme_client: RichAsyncClient,
        acme_and_alice_connection: AcmeAliceConnect,
        alice_member_client: RichAsyncClient,
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        predicate: str,
    ):
        request_body = {
            "type": "indy",
            "indy_proof_request": {
                "requested_attributes": {},
                "requested_predicates": {
                    "over_18": {
                        "name": "age",
                        "p_type": predicate,
                        "p_value": 18,
                    }
                },
            },
            "connection_id": acme_and_alice_connection.acme_connection_id,
            "save_exchange_record": True,
        }
    
        send_proof_response = await send_proof_request(acme_client, request_body)
    
        thread_id = send_proof_response["thread_id"]
    
        alice_event = await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            filter_map={"thread_id": thread_id},
            state="request-received",
        )
    
        alice_proof_id = alice_event["proof_id"]
    
        requested_credentials = await alice_member_client.get(
            f"{VERIFIER_BASE_PATH}/proofs/{alice_proof_id}/credentials"
        )
    
        referent = requested_credentials.json()[0]["cred_info"]["referent"]
    
        proof_accept = AcceptProofRequest(
            proof_id=alice_proof_id,
            indy_presentation_spec=IndyPresSpec(
                requested_attributes={},
                requested_predicates={
                    "over_18": {
                        "cred_id": referent,
                    }
                },
                self_attested_attributes={},
            ),
        )
    
        if predicate in [">", ">="]:
>           response = await alice_member_client.post(
                f"{VERIFIER_BASE_PATH}/accept-request",
                json=proof_accept.model_dump(),
            )

app/tests/e2e/verifier/test_predicate_proofs.py:74: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7ff2df7b5340>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/accept-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 133 in app/tests/e2e/verifier/test_verifier.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_verifier.test_accept_proof_request[clean-clean-clean-clean-clean-clean-default]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f72039387a0>
method = 'post', url = '/v1/verifier/accept-request'
kwargs = {'json': {'dif_presentation_spec': None, 'indy_presentation_spec': {'requested_attributes': {'0_speed_uuid': {'cred_id...ibutes': {}, 'trace': None}, 'proof_id': 'v2-f4edd59c-a1b4-4151-b13c-0a5bfd9123fc', 'save_exchange_record': None, ...}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': '65e0d1fa-b1a0-4bcb-8605-d5106a92b76b', 'created_at': '2024-11-22T17:41:20.248173Z', 'credential_definition_id': '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag', ...}
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f72039387a0>
acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
credential_definition_id = '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag'
acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='cee08c62-d6f3-4bf4-82db-aee261e0156c', acme_connection_id='818c5eea-5563-44d7-bbaf-737c63a34805')

    @pytest.mark.anyio
    @pytest.mark.parametrize(
        "acme_and_alice_connection", ["trust_registry", "default"], indirect=True
    )
    async def test_accept_proof_request(
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        alice_member_client: RichAsyncClient,
        acme_client: RichAsyncClient,
        credential_definition_id: str,
        acme_and_alice_connection: AcmeAliceConnect,
    ):
        request_body = {
            "connection_id": acme_and_alice_connection.acme_connection_id,
            "indy_proof_request": {
                "name": "Proof Request",
                "version": "1.0.0",
                "requested_attributes": {
                    "0_speed_uuid": {
                        "name": "speed",
                        "restrictions": [{"cred_def_id": credential_definition_id}],
                    }
                },
                "requested_predicates": {},
            },
        }
        send_proof_response = await send_proof_request(acme_client, request_body)
    
        acme_proof_id = send_proof_response["proof_id"]
        thread_id = send_proof_response["thread_id"]
    
        alice_payload = await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            state="request-received",
            filter_map={
                "thread_id": thread_id,
            },
        )
    
        alice_proof_id = alice_payload["proof_id"]
    
        requested_credentials = await alice_member_client.get(
            f"{VERIFIER_BASE_PATH}/proofs/{alice_proof_id}/credentials"
        )
    
        referent = requested_credentials.json()[0]["cred_info"]["referent"]
        indy_request_attrs = IndyRequestedCredsRequestedAttr(
            cred_id=referent, revealed=True
        )
        proof_accept = AcceptProofRequest(
            proof_id=alice_proof_id,
            indy_presentation_spec=IndyPresSpec(
                requested_attributes={"0_speed_uuid": indy_request_attrs},
                requested_predicates={},
                self_attested_attributes={},
            ),
        )
    
>       response = await alice_member_client.post(
            VERIFIER_BASE_PATH + "/accept-request",
            json=proof_accept.model_dump(),
        )

app/tests/e2e/verifier/test_verifier.py:133: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f72039387a0>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/accept-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 98 in app/tests/e2e/verifier/test_predicate_proofs.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_predicate_proofs.test_predicate_proofs[clean-clean-clean-clean-clean-clean-<=]

assert 422 == 400
 +  where 422 = HTTPException(status_code=422, detail='{"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}').status_code
 +    where HTTPException(status_code=422, detail='{"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}') = <ExceptionInfo HTTPException(status_code=422, detail='{"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}') tblen=4>.value
Raw output
acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7ff2df7d6840>
acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='3013f310-49f7-4169-a9b3-2b75f229181b', acme_connection_id='f493fbd5-817a-43e9-85e2-edf869ed8e9f')
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7ff2df7962d0>
issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': '6b3caf8c-fb83-4935-9541-ba7362108c63', 'created_at': '2024-11-22T17:41:24.278155Z', 'credential_definition_id': '5kZ7Um6dCo4rNzdX8eijAf:3:CL:255:tag', ...}
predicate = '<='

    @pytest.mark.anyio
    @pytest.mark.parametrize("predicate", ["<", ">", "<=", ">="])
    async def test_predicate_proofs(
        acme_client: RichAsyncClient,
        acme_and_alice_connection: AcmeAliceConnect,
        alice_member_client: RichAsyncClient,
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        predicate: str,
    ):
        request_body = {
            "type": "indy",
            "indy_proof_request": {
                "requested_attributes": {},
                "requested_predicates": {
                    "over_18": {
                        "name": "age",
                        "p_type": predicate,
                        "p_value": 18,
                    }
                },
            },
            "connection_id": acme_and_alice_connection.acme_connection_id,
            "save_exchange_record": True,
        }
    
        send_proof_response = await send_proof_request(acme_client, request_body)
    
        thread_id = send_proof_response["thread_id"]
    
        alice_event = await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            filter_map={"thread_id": thread_id},
            state="request-received",
        )
    
        alice_proof_id = alice_event["proof_id"]
    
        requested_credentials = await alice_member_client.get(
            f"{VERIFIER_BASE_PATH}/proofs/{alice_proof_id}/credentials"
        )
    
        referent = requested_credentials.json()[0]["cred_info"]["referent"]
    
        proof_accept = AcceptProofRequest(
            proof_id=alice_proof_id,
            indy_presentation_spec=IndyPresSpec(
                requested_attributes={},
                requested_predicates={
                    "over_18": {
                        "cred_id": referent,
                    }
                },
                self_attested_attributes={},
            ),
        )
    
        if predicate in [">", ">="]:
            response = await alice_member_client.post(
                f"{VERIFIER_BASE_PATH}/accept-request",
                json=proof_accept.model_dump(),
            )
    
            result = response.json()
    
            pres_exchange_result = PresentationExchange(**result)
            assert isinstance(pres_exchange_result, PresentationExchange)
    
            acme_proof_event = await check_webhook_state(
                client=acme_client,
                topic="proofs",
                state="done",
                filter_map={"thread_id": thread_id},
            )
            assert acme_proof_event["verified"] is True
    
        else:
            with pytest.raises(HTTPException) as exc:
                await alice_member_client.post(
                    f"{VERIFIER_BASE_PATH}/accept-request", json=proof_accept.model_dump()
                )
    
>           assert exc.value.status_code == 400
E           assert 422 == 400
E            +  where 422 = HTTPException(status_code=422, detail='{"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}').status_code
E            +    where HTTPException(status_code=422, detail='{"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}') = <ExceptionInfo HTTPException(status_code=422, detail='{"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}') tblen=4>.value

app/tests/e2e/verifier/test_predicate_proofs.py:98: AssertionError

Check failure on line 302 in app/tests/e2e/verifier/test_verifier.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_verifier.test_get_proof_and_get_proofs[clean-clean-clean-clean-clean-clean]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203938cb0>
method = 'post', url = '/v1/verifier/accept-request'
kwargs = {'json': {'dif_presentation_spec': None, 'indy_presentation_spec': {'requested_attributes': {'0_speed_uuid': {'cred_id...ibutes': {}, 'trace': None}, 'proof_id': 'v2-744259b2-facb-47ad-af36-89dde35fea17', 'save_exchange_record': None, ...}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='e9ac6a68-7d7e-4965-8a07-21e8bc41721f', acme_connection_id='d5b67050-51b2-4014-afac-90bcb8bfe065')
issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': '62193549-69db-4f72-b652-39cf15905cd9', 'created_at': '2024-11-22T17:41:28.549191Z', 'credential_definition_id': '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag', ...}
credential_definition_id = '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag'
acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203938cb0>

    @pytest.mark.anyio
    async def test_get_proof_and_get_proofs(
        acme_and_alice_connection: AcmeAliceConnect,
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        credential_definition_id: str,
        acme_client: RichAsyncClient,
        alice_member_client: RichAsyncClient,
    ):
        acme_connection_id = acme_and_alice_connection.acme_connection_id
    
        request_body = {
            "save_exchange_record": True,
            "connection_id": acme_connection_id,
            "indy_proof_request": sample_indy_proof_request(
                restrictions=[{"cred_def_id": credential_definition_id}]
            ).to_dict(),
        }
        send_proof_response = await send_proof_request(acme_client, request_body)
    
        # Assert that getting single proof record works
        acme_proof_id = send_proof_response["proof_id"]
        thread_id = send_proof_response["thread_id"]
    
        response = await acme_client.get(
            f"{VERIFIER_BASE_PATH}/proofs/{acme_proof_id}",
        )
        result = response.json()
        assert "connection_id" in result
        assert "created_at" in result
        assert "updated_at" in result
        assert "presentation" in result
        assert "presentation_request" in result
    
        await asyncio.sleep(0.3)  # allow moment for alice records to update
    
        # Fetch proofs for alice
        alice_payload = await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            state="request-received",
            filter_map={
                "thread_id": thread_id,
            },
        )
        alice_proof_id = alice_payload["proof_id"]
    
        # Get credential referent for alice to accept request
        referent = (
            await alice_member_client.get(
                f"{VERIFIER_BASE_PATH}/proofs/{alice_proof_id}/credentials"
            )
        ).json()[0]["cred_info"]["referent"]
    
        indy_request_attrs = IndyRequestedCredsRequestedAttr(
            cred_id=referent, revealed=True
        )
    
        proof_accept = AcceptProofRequest(
            proof_id=alice_proof_id,
            indy_presentation_spec=IndyPresSpec(
                requested_attributes={"0_speed_uuid": indy_request_attrs},
                requested_predicates={},
                self_attested_attributes={},
            ),
        )
    
        # Alice accepts
>       await alice_member_client.post(
            VERIFIER_BASE_PATH + "/accept-request",
            json=proof_accept.model_dump(),
        )

app/tests/e2e/verifier/test_verifier.py:302: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203938cb0>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/accept-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 76 in app/tests/e2e/verifier/test_self_attested.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_self_attested.test_self_attested_attributes[clean-clean-clean-clean-clean-clean]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f6c5a0bb320>
method = 'post', url = '/v1/verifier/accept-request'
kwargs = {'json': {'dif_presentation_spec': None, 'indy_presentation_spec': {'requested_attributes': {'name_attribute': {'cred_...234567890'}, 'trace': None}, 'proof_id': 'v2-a2539618-c772-4bca-8dc9-28bf771923ef', 'save_exchange_record': None, ...}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f6c5b59f680>
acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='cb6eb9cb-6be0-4b9e-a066-8478e018a122', acme_connection_id='21aa9761-fc4a-444b-8cdc-bafc3649020a')
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f6c5a0bb320>
issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': '3509d5d8-eb98-401c-ab43-cdcbe4d55d4d', 'created_at': '2024-11-22T17:41:29.281518Z', 'credential_definition_id': '38rLP4b9vGx9P2mNbR4cCX:3:CL:268:tag', ...}

    @pytest.mark.anyio
    async def test_self_attested_attributes(
        acme_client: RichAsyncClient,
        acme_and_alice_connection: AcmeAliceConnect,
        alice_member_client: RichAsyncClient,
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
    ):
    
        request_body = {
            "type": "indy",
            "indy_proof_request": {
                "requested_attributes": {
                    "name_attribute": {
                        "name": "name",
                    },
                    "self_attested_cell_nr": {
                        "name": "my_cell_nr",
                    },
                },
                "requested_predicates": {},
            },
            "connection_id": acme_and_alice_connection.acme_connection_id,
            "save_exchange_record": True,
        }
    
        send_proof_response = await send_proof_request(acme_client, request_body)
    
        thread_id = send_proof_response["thread_id"]
        acme_proof_id = send_proof_response["proof_id"]
    
        alice_event = await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            filter_map={"thread_id": thread_id},
            state="request-received",
        )
    
        alice_proof_id = alice_event["proof_id"]
    
        requested_credentials = await alice_member_client.get(
            f"{VERIFIER_BASE_PATH}/proofs/{alice_proof_id}/credentials"
        )
    
        referent = requested_credentials.json()[0]["cred_info"]["referent"]
    
        proof_accept = AcceptProofRequest(
            proof_id=alice_proof_id,
            indy_presentation_spec=IndyPresSpec(
                requested_attributes={
                    "name_attribute": {
                        "cred_id": referent,
                        "revealed": True,
                    }
                },
                requested_predicates={},
                self_attested_attributes={
                    "self_attested_cell_nr": "1234567890",
                },
            ),
        )
    
>       response = await alice_member_client.post(
            f"{VERIFIER_BASE_PATH}/accept-request",
            json=proof_accept.model_dump(),
        )

app/tests/e2e/verifier/test_self_attested.py:76: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f6c5a0bb320>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/accept-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 74 in app/tests/e2e/verifier/test_predicate_proofs.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_predicate_proofs.test_predicate_proofs[clean-clean-clean-clean-clean-clean->=]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7ff2df7d42f0>
method = 'post', url = '/v1/verifier/accept-request'
kwargs = {'json': {'dif_presentation_spec': None, 'indy_presentation_spec': {'requested_attributes': {}, 'requested_predicates'...ibutes': {}, 'trace': None}, 'proof_id': 'v2-84cf64a3-a589-4c76-b7ec-3bec3e11bb00', 'save_exchange_record': None, ...}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7ff2df7d6840>
acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='96113c70-cb1e-47e2-a766-cd62b5d2b3e2', acme_connection_id='eaaae3ea-3c9a-43e7-86b9-1e6684da8bdf')
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7ff2df7d42f0>
issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': '8aedb974-50c4-4e2d-800c-1d1c7379917b', 'created_at': '2024-11-22T17:41:29.927497Z', 'credential_definition_id': '5kZ7Um6dCo4rNzdX8eijAf:3:CL:255:tag', ...}
predicate = '>='

    @pytest.mark.anyio
    @pytest.mark.parametrize("predicate", ["<", ">", "<=", ">="])
    async def test_predicate_proofs(
        acme_client: RichAsyncClient,
        acme_and_alice_connection: AcmeAliceConnect,
        alice_member_client: RichAsyncClient,
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        predicate: str,
    ):
        request_body = {
            "type": "indy",
            "indy_proof_request": {
                "requested_attributes": {},
                "requested_predicates": {
                    "over_18": {
                        "name": "age",
                        "p_type": predicate,
                        "p_value": 18,
                    }
                },
            },
            "connection_id": acme_and_alice_connection.acme_connection_id,
            "save_exchange_record": True,
        }
    
        send_proof_response = await send_proof_request(acme_client, request_body)
    
        thread_id = send_proof_response["thread_id"]
    
        alice_event = await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            filter_map={"thread_id": thread_id},
            state="request-received",
        )
    
        alice_proof_id = alice_event["proof_id"]
    
        requested_credentials = await alice_member_client.get(
            f"{VERIFIER_BASE_PATH}/proofs/{alice_proof_id}/credentials"
        )
    
        referent = requested_credentials.json()[0]["cred_info"]["referent"]
    
        proof_accept = AcceptProofRequest(
            proof_id=alice_proof_id,
            indy_presentation_spec=IndyPresSpec(
                requested_attributes={},
                requested_predicates={
                    "over_18": {
                        "cred_id": referent,
                    }
                },
                self_attested_attributes={},
            ),
        )
    
        if predicate in [">", ">="]:
>           response = await alice_member_client.post(
                f"{VERIFIER_BASE_PATH}/accept-request",
                json=proof_accept.model_dump(),
            )

app/tests/e2e/verifier/test_predicate_proofs.py:74: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7ff2df7d42f0>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/accept-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 566 in app/tests/e2e/verifier/test_verifier.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_verifier.test_saving_of_presentation_exchange_records[clean-clean-clean-clean-clean-clean-None-None]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
method = 'post', url = '/v1/verifier/send-request'
kwargs = {'json': {'connection_id': 'bfc3a0ef-7059-4652-a273-a3ea62c42619', 'indy_proof_request': {'name': 'string', 'non_revok...quested_attributes': {'0_speed_uuid': {'name': 'speed', 'restrictions': [{...}]}}, ...}, 'save_exchange_record': None}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/send-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': 'dbb334c2-632b-44ac-8d26-5b91dd3c2575', 'created_at': '2024-11-22T17:41:39.292442Z', 'credential_definition_id': '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag', ...}
credential_definition_id = '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag'
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f72041f7d10>
acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='200ca3b1-cbd1-48c4-b364-8caa3d9ac91e', acme_connection_id='bfc3a0ef-7059-4652-a273-a3ea62c42619')
acme_save_exchange_record = None, alice_save_exchange_record = None

    @pytest.mark.anyio
    @pytest.mark.parametrize("acme_save_exchange_record", [None, False, True])
    @pytest.mark.parametrize("alice_save_exchange_record", [None, False, True])
    async def test_saving_of_presentation_exchange_records(
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        credential_definition_id: str,
        alice_member_client: RichAsyncClient,
        acme_client: RichAsyncClient,
        acme_and_alice_connection: AcmeAliceConnect,
        acme_save_exchange_record: Optional[bool],
        alice_save_exchange_record: Optional[bool],
    ):
        request_body = {
            "connection_id": acme_and_alice_connection.acme_connection_id,
            "indy_proof_request": sample_indy_proof_request(
                restrictions=[{"cred_def_id": credential_definition_id}]
            ).to_dict(),
            "save_exchange_record": acme_save_exchange_record,
        }
>       send_proof_response = await send_proof_request(acme_client, request_body)

app/tests/e2e/verifier/test_verifier.py:566: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
app/tests/util/verifier.py:10: in send_proof_request
    response = await client.post(
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/send-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/send-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 600 in app/tests/e2e/verifier/test_verifier.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_verifier.test_saving_of_presentation_exchange_records[clean-clean-clean-clean-clean-clean-None-False]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203da3c20>
method = 'post', url = '/v1/verifier/accept-request'
kwargs = {'json': {'dif_presentation_spec': None, 'indy_presentation_spec': {'requested_attributes': {'0_speed_uuid': {'cred_id...ibutes': {}, 'trace': None}, 'proof_id': 'v2-16d5bd13-d156-4711-8307-b23effa28fb1', 'save_exchange_record': None, ...}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': 'e768b912-999e-4f69-b5f4-0d83867a4172', 'created_at': '2024-11-22T17:41:44.426432Z', 'credential_definition_id': '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag', ...}
credential_definition_id = '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag'
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203da3c20>
acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='2b324149-767b-46ac-9f29-556ae0875d3d', acme_connection_id='79060d3e-423b-43d9-8791-6e928a4de16c')
acme_save_exchange_record = False, alice_save_exchange_record = None

    @pytest.mark.anyio
    @pytest.mark.parametrize("acme_save_exchange_record", [None, False, True])
    @pytest.mark.parametrize("alice_save_exchange_record", [None, False, True])
    async def test_saving_of_presentation_exchange_records(
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        credential_definition_id: str,
        alice_member_client: RichAsyncClient,
        acme_client: RichAsyncClient,
        acme_and_alice_connection: AcmeAliceConnect,
        acme_save_exchange_record: Optional[bool],
        alice_save_exchange_record: Optional[bool],
    ):
        request_body = {
            "connection_id": acme_and_alice_connection.acme_connection_id,
            "indy_proof_request": sample_indy_proof_request(
                restrictions=[{"cred_def_id": credential_definition_id}]
            ).to_dict(),
            "save_exchange_record": acme_save_exchange_record,
        }
        send_proof_response = await send_proof_request(acme_client, request_body)
    
        acme_proof_id = send_proof_response["proof_id"]
        thread_id = send_proof_response["thread_id"]
    
        alice_payload = await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            state="request-received",
            filter_map={
                "thread_id": thread_id,
            },
        )
        alice_proof_id = alice_payload["proof_id"]
    
        requested_credentials = await alice_member_client.get(
            f"{VERIFIER_BASE_PATH}/proofs/{alice_proof_id}/credentials"
        )
    
        referent = requested_credentials.json()[0]["cred_info"]["referent"]
        indy_request_attrs = IndyRequestedCredsRequestedAttr(
            cred_id=referent, revealed=True
        )
    
        proof_accept = AcceptProofRequest(
            proof_id=alice_proof_id,
            indy_presentation_spec=IndyPresSpec(
                requested_attributes={"0_speed_uuid": indy_request_attrs},
                requested_predicates={},
                self_attested_attributes={},
            ),
            save_exchange_record=alice_save_exchange_record,
        )
    
>       response = await alice_member_client.post(
            VERIFIER_BASE_PATH + "/accept-request",
            json=proof_accept.model_dump(),
        )

app/tests/e2e/verifier/test_verifier.py:600: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203da3c20>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/accept-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 600 in app/tests/e2e/verifier/test_verifier.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_verifier.test_saving_of_presentation_exchange_records[clean-clean-clean-clean-clean-clean-None-True]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7202dece60>
method = 'post', url = '/v1/verifier/accept-request'
kwargs = {'json': {'dif_presentation_spec': None, 'indy_presentation_spec': {'requested_attributes': {'0_speed_uuid': {'cred_id...ibutes': {}, 'trace': None}, 'proof_id': 'v2-b192346a-2fd5-473a-afdd-27ec5952b8c6', 'save_exchange_record': None, ...}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': '950e904d-58ef-4bcd-b77f-f8f4a6f9a3ad', 'created_at': '2024-11-22T17:41:50.047851Z', 'credential_definition_id': '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag', ...}
credential_definition_id = '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag'
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7202dece60>
acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='8322789e-aa68-4876-8e43-2d41aa40bafe', acme_connection_id='99f28de0-5e45-4592-8791-f3351928b731')
acme_save_exchange_record = True, alice_save_exchange_record = None

    @pytest.mark.anyio
    @pytest.mark.parametrize("acme_save_exchange_record", [None, False, True])
    @pytest.mark.parametrize("alice_save_exchange_record", [None, False, True])
    async def test_saving_of_presentation_exchange_records(
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        credential_definition_id: str,
        alice_member_client: RichAsyncClient,
        acme_client: RichAsyncClient,
        acme_and_alice_connection: AcmeAliceConnect,
        acme_save_exchange_record: Optional[bool],
        alice_save_exchange_record: Optional[bool],
    ):
        request_body = {
            "connection_id": acme_and_alice_connection.acme_connection_id,
            "indy_proof_request": sample_indy_proof_request(
                restrictions=[{"cred_def_id": credential_definition_id}]
            ).to_dict(),
            "save_exchange_record": acme_save_exchange_record,
        }
        send_proof_response = await send_proof_request(acme_client, request_body)
    
        acme_proof_id = send_proof_response["proof_id"]
        thread_id = send_proof_response["thread_id"]
    
        alice_payload = await check_webhook_state(
            client=alice_member_client,
            topic="proofs",
            state="request-received",
            filter_map={
                "thread_id": thread_id,
            },
        )
        alice_proof_id = alice_payload["proof_id"]
    
        requested_credentials = await alice_member_client.get(
            f"{VERIFIER_BASE_PATH}/proofs/{alice_proof_id}/credentials"
        )
    
        referent = requested_credentials.json()[0]["cred_info"]["referent"]
        indy_request_attrs = IndyRequestedCredsRequestedAttr(
            cred_id=referent, revealed=True
        )
    
        proof_accept = AcceptProofRequest(
            proof_id=alice_proof_id,
            indy_presentation_spec=IndyPresSpec(
                requested_attributes={"0_speed_uuid": indy_request_attrs},
                requested_predicates={},
                self_attested_attributes={},
            ),
            save_exchange_record=alice_save_exchange_record,
        )
    
>       response = await alice_member_client.post(
            VERIFIER_BASE_PATH + "/accept-request",
            json=proof_accept.model_dump(),
        )

app/tests/e2e/verifier/test_verifier.py:600: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7202dece60>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/accept-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/accept-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 566 in app/tests/e2e/verifier/test_verifier.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_verifier.test_saving_of_presentation_exchange_records[clean-clean-clean-clean-clean-clean-False-None]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
method = 'post', url = '/v1/verifier/send-request'
kwargs = {'json': {'connection_id': '654cb07d-16c6-4e0f-8523-2db20de78d93', 'indy_proof_request': {'name': 'string', 'non_revok...quested_attributes': {'0_speed_uuid': {'name': 'speed', 'restrictions': [{...}]}}, ...}, 'save_exchange_record': None}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/send-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': 'b74488f2-c91b-4029-9cde-d5cc6c1fe63f', 'created_at': '2024-11-22T17:41:55.727618Z', 'credential_definition_id': '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag', ...}
credential_definition_id = '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag'
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7202dd0770>
acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='3e42c4af-bb95-4e05-942f-d7aadd97a9a4', acme_connection_id='654cb07d-16c6-4e0f-8523-2db20de78d93')
acme_save_exchange_record = None, alice_save_exchange_record = False

    @pytest.mark.anyio
    @pytest.mark.parametrize("acme_save_exchange_record", [None, False, True])
    @pytest.mark.parametrize("alice_save_exchange_record", [None, False, True])
    async def test_saving_of_presentation_exchange_records(
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        credential_definition_id: str,
        alice_member_client: RichAsyncClient,
        acme_client: RichAsyncClient,
        acme_and_alice_connection: AcmeAliceConnect,
        acme_save_exchange_record: Optional[bool],
        alice_save_exchange_record: Optional[bool],
    ):
        request_body = {
            "connection_id": acme_and_alice_connection.acme_connection_id,
            "indy_proof_request": sample_indy_proof_request(
                restrictions=[{"cred_def_id": credential_definition_id}]
            ).to_dict(),
            "save_exchange_record": acme_save_exchange_record,
        }
>       send_proof_response = await send_proof_request(acme_client, request_body)

app/tests/e2e/verifier/test_verifier.py:566: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
app/tests/util/verifier.py:10: in send_proof_request
    response = await client.post(
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/send-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/send-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 566 in app/tests/e2e/verifier/test_verifier.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_verifier.test_saving_of_presentation_exchange_records[clean-clean-clean-clean-clean-clean-True-None]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
method = 'post', url = '/v1/verifier/send-request'
kwargs = {'json': {'connection_id': '1ddcdee2-514a-4f65-a565-1839cf8e3954', 'indy_proof_request': {'name': 'string', 'non_revok...quested_attributes': {'0_speed_uuid': {'name': 'speed', 'restrictions': [{...}]}}, ...}, 'save_exchange_record': None}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/send-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': '7687bec7-ccf9-4d90-ab13-b4ccddf9d632', 'created_at': '2024-11-22T17:42:15.479790Z', 'credential_definition_id': '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag', ...}
credential_definition_id = '5pAv9UW8haJsdJaDTfuCTN:3:CL:216:tag'
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203916870>
acme_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
acme_and_alice_connection = AcmeAliceConnect(alice_connection_id='87b68e73-28b3-4330-8dec-d3f5d1d44789', acme_connection_id='1ddcdee2-514a-4f65-a565-1839cf8e3954')
acme_save_exchange_record = None, alice_save_exchange_record = True

    @pytest.mark.anyio
    @pytest.mark.parametrize("acme_save_exchange_record", [None, False, True])
    @pytest.mark.parametrize("alice_save_exchange_record", [None, False, True])
    async def test_saving_of_presentation_exchange_records(
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        credential_definition_id: str,
        alice_member_client: RichAsyncClient,
        acme_client: RichAsyncClient,
        acme_and_alice_connection: AcmeAliceConnect,
        acme_save_exchange_record: Optional[bool],
        alice_save_exchange_record: Optional[bool],
    ):
        request_body = {
            "connection_id": acme_and_alice_connection.acme_connection_id,
            "indy_proof_request": sample_indy_proof_request(
                restrictions=[{"cred_def_id": credential_definition_id}]
            ).to_dict(),
            "save_exchange_record": acme_save_exchange_record,
        }
>       send_proof_response = await send_proof_request(acme_client, request_body)

app/tests/e2e/verifier/test_verifier.py:566: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
app/tests/util/verifier.py:10: in send_proof_request
    response = await client.post(
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7f7203d5eff0>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/send-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/send-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException

Check failure on line 38 in app/tests/e2e/verifier/test_verifier_oob.py

See this annotation in the file changed.

@github-actions github-actions / JUnit Test Report

test_verifier_oob.test_accept_proof_request_oob[clean-clean-clean-clean-clean-clean]

fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}
Raw output
self = <shared.util.rich_async_client.RichAsyncClient object at 0x7feeaa71f320>
method = 'post', url = '/v1/verifier/create-request'
kwargs = {'json': {'comment': 'some comment', 'dif_proof_request': None, 'indy_proof_request': {'name': 'string', 'non_revoked'...{'name': 'speed', 'names': None, 'non_revoked': None, 'restrictions': None}}, ...}, 'save_exchange_record': None, ...}}
attempt = 0, response = <Response [422 Unprocessable Entity]>, code = 422

    async def _request_with_retries(self, method: str, url: str, **kwargs) -> Response:
        for attempt in range(self.retries):
            try:
                response = await getattr(super(), method)(url, **kwargs)
>               return await self._handle_response(response)

shared/util/rich_async_client.py:67: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:50: in _handle_response
    response.raise_for_status()  # Raise exception for 4xx and 5xx status codes
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Response [422 Unprocessable Entity]>

    def raise_for_status(self) -> Response:
        """
        Raise the `HTTPStatusError` if one occurred.
        """
        request = self._request
        if request is None:
            raise RuntimeError(
                "Cannot call `raise_for_status` as the request "
                "instance has not been set on this response."
            )
    
        if self.is_success:
            return self
    
        if self.has_redirect_location:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "Redirect location: '{0.headers[location]}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
        else:
            message = (
                "{error_type} '{0.status_code} {0.reason_phrase}' for url '{0.url}'\n"
                "For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/{0.status_code}"
            )
    
        status_class = self.status_code // 100
        error_types = {
            1: "Informational response",
            3: "Redirect response",
            4: "Client error",
            5: "Server error",
        }
        error_type = error_types.get(status_class, "Invalid status code")
        message = message.format(self, error_type=error_type)
>       raise HTTPStatusError(message, request=request, response=self)
E       httpx.HTTPStatusError: Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/create-request'
E       For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422

/usr/local/lib/python3.12/site-packages/httpx/_models.py:763: HTTPStatusError

The above exception was the direct cause of the following exception:

issue_credential_to_alice = {'attributes': {'age': '44', 'name': 'Alice', 'speed': '10'}, 'connection_id': '1a0f8ec7-f83f-4902-ba45-cae9f720d265', 'created_at': '2024-11-22T17:42:21.076898Z', 'credential_definition_id': 'FaCpQiPvw8aEQ3FkGvG3D5:3:CL:243:tag', ...}
alice_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7feeaa71d460>
bob_member_client = <shared.util.rich_async_client.RichAsyncClient object at 0x7feeaa71f320>

    @pytest.mark.anyio
    async def test_accept_proof_request_oob(
        issue_credential_to_alice: CredentialExchange,  # pylint: disable=unused-argument
        alice_member_client: RichAsyncClient,
        bob_member_client: RichAsyncClient,
    ):
        # Create the proof request against aca-py
        create_proof_request = CreateProofRequest(
            indy_proof_request=sample_indy_proof_request(),
            comment="some comment",
        )
>       create_proof_response = await bob_member_client.post(
            VERIFIER_BASE_PATH + "/create-request",
            json=create_proof_request.model_dump(by_alias=True),
        )

app/tests/e2e/verifier/test_verifier_oob.py:38: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
shared/util/rich_async_client.py:81: in post
    return await self._request_with_retries("post", url, **kwargs)
shared/util/rich_async_client.py:78: in _request_with_retries
    await self._handle_error(e, url, method)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.util.rich_async_client.RichAsyncClient object at 0x7feeaa71f320>
e = HTTPStatusError("Client error '422 Unprocessable Entity' for url 'https://tenant-web.cloudapi.dev.didxtech.com/tenant/v1/verifier/create-request'\nFor more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422")
url = '/v1/verifier/create-request', method = 'post'

    async def _handle_error(self, e: HTTPStatusError, url: str, method: str) -> None:
        code = e.response.status_code
        message = e.response.text
        log_message = (
            f"{self.name} {method} `{url}` failed. "
            f"Status code: {code}. Response: `{message}`."
        )
        logger.error(log_message)
>       raise HTTPException(status_code=code, detail=message) from e
E       fastapi.exceptions.HTTPException: 422: {"detail":[{"type":"bool_type","loc":["body","save_exchange_record"],"msg":"Input should be a valid boolean","input":null}]}

shared/util/rich_async_client.py:61: HTTPException