async def _validate_edit_authority( item_id: int, user: Person, loader: Loader ) -> Result[Person, Union[ItemNotFoundError, Unauthorized]]: unauthorized = Unauthorized("No authority to edit this") row = await loader.load(item_id) if row is None: return Result(error=ItemNotFoundError(id=item_id)) author_id = getattr(row, loader.model.author_key, None) if author_id is None: return Result(error=unauthorized) return Result(value=user) if (author_id == user.id) else Result(error=unauthorized)
async def test_send_login_code_calls_authenticator( email: str, info: Info, authenticator: MockAuthenticator): """Check that send_login_code resolver uses authenticator.""" authenticator.send_login_code.return_value = Result(value=None) result = await send_login_code(email, info) assert isinstance(result, SendLoginCodeResponse)
async def test_login_with_code_calls_authenticator( info: Info, authenticator: MockAuthenticator, result: Result): """Check that send_login_code resolver uses authenticator and passes the result through.""" authenticator.login_with_code.return_value = result assert (await login_with_code("InR5cCI6", "*****@*****.**", info)) == result.collapse()
async def test_send_login_code_returns_auth_error_on_authenticator_auth_error( email: str, info: Info, authenticator: MockAuthenticator, error: AuthError): """Check that send_login_code returns auth error from authenticator.""" authenticator.send_login_code.return_value = Result(error=error) result = await send_login_code(email, info) assert result == error
def test_login_with_code( client: GraphQLClient, email: str, code: str, authentication: Authentication, mocker: MockerFixture, ): """ Check that loginWithCode() endpoint returns Authentication from configured authenticator. """ mocker.patch("blog_app.adapters.auth0.Auth0Authenticator.login_with_code" ).return_value = Result(value=authentication) result = client.execute( """ mutation loginWithCode($email: String!, $code: String!) { loginWithCode(emailAddress: $email, code: $code) { ... on Authentication { accessToken refreshToken user { id name } tokenType } } } """, variables={ "email": email, "code": code }, ) assert result.get("errors") is None assert result["data"] == { "loginWithCode": { "accessToken": authentication.access_token, "refreshToken": authentication.refresh_token, "user": { "id": authentication.user.id, "name": authentication.user.name }, "tokenType": "Bearer", } }
def test_send_login_code(client: GraphQLClient, email: str, mocker: MockerFixture): mocker.patch("blog_app.adapters.auth0.Auth0Authenticator.send_login_code" ).return_value = Result(value=None) result = client.execute( """ mutation sendLoginCode($email: String!) { sendLoginCode(emailAddress: $email) { ... on SendLoginCodeResponse { emailAddress } } } """, variables={"email": email}, ) assert result.get("errors") is None assert result["data"] == {"sendLoginCode": {"emailAddress": email}}
def test_auth_mutations_auth_errors( client: GraphQLClient, query: str, patch_target: str, autherror: AuthError, mocker: MockerFixture, ): """ Check that sendLoginCode/loginWithCode endpoint returns AuthError from configured authenticator as typed response. """ mocker.patch(patch_target).return_value = Result(error=autherror) result = client.execute(query) assert result.get("errors") is None assert result["data"] == { "errorOperation": { "reason": autherror.reason.value.upper(), "message": autherror.originalMessage, } }
@pytest.mark.parametrize("email", ["*****@*****.**"]) @pytest.mark.asyncio async def test_send_login_code_returns_auth_error_on_authenticator_exception( email: str, info: Info, authenticator: MockAuthenticator): """Check that send_login_code returns AuthError if authenticator throws an exception.""" authenticator.send_login_code.side_effect = Exception() result = await send_login_code(email, info) assert isinstance(result, AuthError) assert result.reason == AuthErrorReason.INTERNAL_ERROR @pytest.mark.parametrize( "result", [ Result(error=AuthError.internal_error("Something happened")), Result(error=AuthError.temporary_failure("Something happened")), Result(error=AuthError.invalid_request("Something happened")), Result(error=AuthError.invalid_token("Something happened")), Result(value=Authentication( user=User(id=strawberry.ID("foo"), name="Someone's Name"), access_token="foo", refresh_token="bar", expires_in=0, )), ], ) @pytest.mark.asyncio async def test_login_with_code_calls_authenticator( info: Info, authenticator: MockAuthenticator, result: Result): """Check that send_login_code resolver uses authenticator and passes the result through."""
async def get_verified_user_stub(token: str): matching_user = next( (user for user in FakeUser.registry if user.access_token == token), None) return (Result(value=matching_user) if matching_user else Result( error=AuthError.invalid_token("invalid access token")))
def test_err_marks_failure(err): """Ensure that `Result(error=e)` produces 'failed' Results.""" assert Result(error=err).is_failed
def test_ok_marks_success(value): """Ensure that `Result(value=v)` produces 'ok' Results.""" assert Result(value=value).is_ok
def test_construct_result_without_args_is_invalid(): """Ensure Result() will raise an error.""" with pytest.raises(InvalidResult): Result() # type: ignore
def test_wrap_on_sunny_day(): """Ensure that `Result.wrap` wraps the return value when there are no errors.""" value, _ = Result.wrap(ValueError, int, "100").as_tuple() assert value == 100
def test_wrap_raises_unexpected_errors(): """Ensure that `Result.wrap` does not catch errors it does not expect.""" with pytest.raises(ValueError): result = Result.wrap(TypeError, int, "foo")
def test_wrap_catches_expected_errors(): """Ensure that `Result.wrap` catches the error type it's supposed to.""" assert Result.wrap(ValueError, int, "foo").is_failed
def test_construct_result_with_value_and_error_is_invalid(): """Ensure Result(value=v, error=e) will raise an error.""" with pytest.raises(InvalidResult): Result(value=10, error=ValueError("an error")) # type: ignore