def test_raise_exception_when_password_is_invalid(self, stubed_requests_post):
        # Given
        application_id = "5"
        stubed_requests_post.return_value = MagicMock(status_code=400)

        # When
        with pytest.raises(ApiJouveException) as api_jouve_exception:
            get_application_content(application_id)

        # Then
        assert str(api_jouve_exception.value.message) == "Error getting API Jouve authentication token"
        assert api_jouve_exception.value.route == "/REST/server/authenticationtokens"
        assert api_jouve_exception.value.status_code == 400
    def test_calls_jouve_api_with_previously_fetched_token(self, mocked_requests_post):
        # Given
        token = "token-for-tests"
        application_id = 5

        get_token_response = MagicMock(status_code=200)
        get_token_response.json = MagicMock(return_value=get_token_detail_response(token))

        get_application_by_json = get_application_by_detail_response(
            application_id=application_id,
            birth_date="24/08/1995",
        )
        get_application_by_response = MagicMock(status_code=200)
        get_application_by_response.json = MagicMock(return_value=get_application_by_json)

        mocked_requests_post.side_effect = [get_token_response, get_application_by_response]

        # When
        jouve_content = get_application_content(application_id)
        beneficiary_pre_subscription = get_subscription_from_content(jouve_content)

        # Then
        assert mocked_requests_post.call_args_list[0] == call(
            "https://jouve.com/REST/server/authenticationtokens",
            headers={"Content-Type": "application/json"},
            json={
                "Username": "******",
                "Password": "******",
                "VaultGuid": "12",
                "Expiration": "2020-10-15T10:00:00",
            },
        )
        assert mocked_requests_post.call_args_list[1] == call(
            "https://jouve.com/REST/vault/extensionmethod/VEM_GetJeuneByID",
            data=str(application_id),
            headers={"X-Authentication": token},
        )
        assert isinstance(beneficiary_pre_subscription, BeneficiaryPreSubscription)
        assert beneficiary_pre_subscription.activity == "Apprenti"
        assert beneficiary_pre_subscription.address == "18 avenue des fleurs"
        assert beneficiary_pre_subscription.application_id == 5
        assert beneficiary_pre_subscription.city == "RENNES"
        assert beneficiary_pre_subscription.civility == "Mme"
        assert beneficiary_pre_subscription.date_of_birth.date() == datetime(1995, 8, 24).date()
        assert beneficiary_pre_subscription.department_code == "35"
        assert beneficiary_pre_subscription.email == "*****@*****.**"
        assert beneficiary_pre_subscription.first_name == "Céline"
        assert beneficiary_pre_subscription.last_name == "DURAND"
        assert beneficiary_pre_subscription.phone_number == "0123456789"
        assert beneficiary_pre_subscription.postal_code == "35123"
        assert beneficiary_pre_subscription.public_name == "Céline DURAND"
        assert beneficiary_pre_subscription.id_piece_number == "id-piece-number"
    def test_raise_exception_when_token_is_invalid(self, stubed_requests_post):
        # Given
        token = "token-for-tests"
        application_id = "5"

        get_token_response = MagicMock(status_code=200)
        get_token_response.json = MagicMock(return_value=get_token_detail_response(token))

        get_application_by_json = get_application_by_detail_response()
        get_application_by_response = MagicMock(status_code=500)
        get_application_by_response.json = MagicMock(return_value=get_application_by_json)

        stubed_requests_post.side_effect = [get_token_response, get_application_by_response]

        # When
        with pytest.raises(ApiJouveException) as api_jouve_exception:
            get_application_content(application_id)

        # Then
        assert str(api_jouve_exception.value.message) == "Error getting API jouve GetJeuneByID"
        assert api_jouve_exception.value.route == "/REST/vault/extensionmethod/VEM_GetJeuneByID"
        assert api_jouve_exception.value.status_code == 500
    def test_jouve_response_with_wrong_values_are_supiscious(self, _get_raw_content, jouve_field, wrong_possible_value):
        response_data = get_application_by_detail_response()
        response_data[jouve_field] = wrong_possible_value
        _get_raw_content.return_value = response_data

        jouve_content = get_application_content("fake-application-id")
        pre_subscription = get_subscription_from_content(jouve_content)
        item_found = False
        for item in pre_subscription.fraud_fields["non_blocking_controls"]:
            if item.key == jouve_field:
                assert item.valid == False
                item_found = True

        assert item_found
    def execute(
        self,
        application_id: int,
        run_fraud_detection: bool = True,
        ignore_id_piece_number_field: bool = False,
        fraud_detection_ko: bool = False,
    ) -> None:
        try:
            jouve_content = jouve_backend.get_application_content(
                application_id,
                ignore_id_piece_number_field=ignore_id_piece_number_field)
            beneficiary_pre_subscription = jouve_backend.get_subscription_from_content(
                jouve_content)
        except jouve_backend.ApiJouveException as api_jouve_exception:
            logger.error(
                api_jouve_exception.message,
                extra={
                    "route": api_jouve_exception.route,
                    "statusCode": api_jouve_exception.status_code,
                    "applicationId": application_id,
                },
            )
            return
        except jouve_backend.JouveContentValidationError as exc:
            logger.error(
                "Validation error when parsing Jouve content: %s",
                exc.message,
                extra={
                    "application_id": application_id,
                    "validation_errors": exc.errors
                },
            )
            return

        preexisting_account = find_user_by_email(
            beneficiary_pre_subscription.email)
        if not preexisting_account:
            save_beneficiary_import_with_status(
                ImportStatus.ERROR,
                application_id,
                source=BeneficiaryImportSources.demarches_simplifiees,
                source_id=jouve_backend.DEFAULT_JOUVE_SOURCE_ID,
                detail=
                f"Aucun utilisateur trouvé pour l'email {beneficiary_pre_subscription.email}",
            )
            return

        try:
            on_jouve_result(preexisting_account, jouve_content)
        except Exception as exc:  # pylint: disable=broad-except
            logger.exception("Error on jouve result: %s", exc)

        try:
            validate(
                beneficiary_pre_subscription,
                preexisting_account=preexisting_account,
                ignore_id_piece_number_field=ignore_id_piece_number_field,
            )
            if fraud_detection_ko:
                raise FraudDetected(
                    "Forced by 'fraud_detection_ko' script argument")
            if run_fraud_detection:
                validate_fraud(beneficiary_pre_subscription)

        except SuspiciousFraudDetected:
            send_fraud_suspicion_email(beneficiary_pre_subscription)
            subscription_messages.create_message_jouve_manual_review(
                preexisting_account, application_id=application_id)
        except FraudDetected as cant_register_beneficiary_exception:
            # detail column cannot contain more than 255 characters
            detail = f"Fraud controls triggered: {cant_register_beneficiary_exception}"[:
                                                                                        255]
            self.beneficiary_repository.reject(
                beneficiary_pre_subscription,
                detail=detail,
                user=preexisting_account,
            )
        except BeneficiaryIsADuplicate as exception:
            exception_reason = str(exception)

            logger.info(
                "User is a duplicate : cannot register user from application",
                extra={
                    "applicationId": application_id,
                    "reason": exception_reason,
                },
            )
            subscription_messages.on_duplicate_user(preexisting_account)
            self.beneficiary_repository.reject(beneficiary_pre_subscription,
                                               detail=exception_reason,
                                               user=preexisting_account)

            old_user_emails.send_rejection_email_to_beneficiary_pre_subscription(
                beneficiary_pre_subscription=beneficiary_pre_subscription,
                beneficiary_is_eligible=True)
        except SubscriptionJourneyOnHold as exc:
            logger.warning("User subscription is on hold",
                           extra={
                               "applicationId": application_id,
                               "reason": str(exc)
                           })
        except CantRegisterBeneficiary as cant_register_beneficiary_exception:
            exception_reason = str(cant_register_beneficiary_exception)
            logger.warning(
                "Couldn't register user from application",
                extra={
                    "applicationId": application_id,
                    "reason": exception_reason,
                },
            )
            self.beneficiary_repository.reject(beneficiary_pre_subscription,
                                               detail=exception_reason,
                                               user=preexisting_account)
            old_user_emails.send_rejection_email_to_beneficiary_pre_subscription(
                beneficiary_pre_subscription=beneficiary_pre_subscription,
                beneficiary_is_eligible=False)
        else:
            user = self.beneficiary_repository.save(
                beneficiary_pre_subscription, user=preexisting_account)
            logger.info("User registered from application",
                        extra={
                            "applicationId": application_id,
                            "userId": user.id
                        })