class TestLaLetterBuilderCreateLetter: QUERY = """ mutation LaLetterBuilderCreateLetterMutation($input: LaLetterBuilderCreateLetterInput!) { output: laLetterBuilderCreateLetter(input: $input) { errors { field, messages }, } } """ @pytest.fixture(autouse=True) def setup_fixture(self, graphql_client, db): self.user = UserFactory(email="*****@*****.**") graphql_client.request.user = self.user self.graphql_client = graphql_client def execute(self, input={}): res = self.graphql_client.execute( self.QUERY, variables={"input": input}, ) return res["data"]["output"] def test_it_requires_login(self): self.graphql_client.request.user = AnonymousUser() assert self.execute()["errors"] == one_field_err( "You do not have permission to use this form!") def test_it_raises_err_when_no_onboarding_info_exists(self): assert self.execute()["errors"] == one_field_err( "You haven't provided any account details yet!") def test_it_raises_err_when_used_on_wrong_site(self): OnboardingInfoFactory(user=self.user) assert self.execute()["errors"] == one_field_err( "This form can only be used from the LA Letter Builder site.") def test_it_creates_letter( self, settings, use_laletterbuilder_site, ): settings.IS_DEMO_DEPLOYMENT = False settings.LANGUAGES = project.locales.ALL.choices self.user.locale = "es" self.user.save() OnboardingInfoFactory(user=self.user) assert not HabitabilityLetter.objects.filter( user=self.graphql_client.request.user).exists() # Create the letter assert self.execute()["errors"] == [] # TODO: add tests for all the other kinds of letters too letter = HabitabilityLetter.objects.get( user=self.graphql_client.request.user) assert letter.locale == "es" assert letter.html_content == "<>"
class AuthenticatedAPITestCase(APITestCase): def setUp(self): self.user = UserFactory() self.user_pass = factory.Faker("password") self.user.set_password(self.user_pass) self.user.save() self.token = Token.objects.create(user=self.user) self.client = APIClient() self.client.credentials(HTTP_AUTHORIZATION=f"Token {self.token.key}")
def create_user(*, email, password, first_name='', last_name='', is_active=True): user = UserFactory(email=email, first_name=first_name, last_name=last_name, is_active=is_active) user.set_password(password) user.save() return user
class TestCommentsViewSet(APITestCase): """Tests all CommentsViewSet functionality""" def setUp(self) -> None: self.user = UserFactory() token = Token.objects.get(user=self.user) self.client.credentials(HTTP_AUTHORIZATION=f'Token {token.key}') self.topic = TopicFactory(author=self.user) self.post = PostFactory(author=self.user, topic=self.topic) self.comment1 = CommentFactory(author=self.user, post=self.post) def test_get_comments_by_post(self): """Get all comments of particular post""" CommentFactory(author=self.user, body='Test comment 2', post=self.post) data = { 'post': self.post.id, } response = self.client.get(reverse('api:comments-list'), data) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data.get('results')), 2) def test_delete_comment(self): """Test user try to delete comment""" response = self.client.delete( reverse('api:comments-detail', kwargs={'pk': self.comment1.id})) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertTrue(Comment.objects.all().exists()) def test_successful_comment_deletion(self): """Tests that moderators and superusers can delete comments""" self.user.is_moderator = True self.user.save() response = self.client.delete( reverse('api:comments-detail', kwargs={'pk': self.comment1.id})) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.assertFalse(Comment.objects.all().exists()) self.comment1 = CommentFactory(author=self.user, post=self.post) self.user.is_moderator = False self.user.is_superuser = True self.user.save() response = self.client.delete( reverse('api:comments-detail', kwargs={'pk': self.comment1.id})) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.assertFalse(Comment.objects.all().exists())
def test_vendor_number_list_view(self): for i in range(3): user = UserFactory(is_staff=True) user.first_name = 'Test' user.save() profile = user.profile profile.vendor_number = FuzzyText().fuzz() profile.save() for i in range(3): TravelAgentFactory() with self.assertNumQueries(2): response = self.forced_auth_req('get', reverse('t2f:vendor_numbers'), user=self.unicef_staff) response_json = json.loads(response.rendered_content) self.assertEqual(len(response_json), 6)
class TestPostsViewSet(APITestCase): """Tests all PostsViewSet functionality""" def setUp(self) -> None: self.user = UserFactory() token = Token.objects.get(user=self.user) self.client.credentials(HTTP_AUTHORIZATION=f'Token {token.key}') self.topic = TopicFactory(author=self.user) self.post1 = PostFactory(author=self.user, topic=self.topic) self.post2 = PostFactory(author=self.user, topic=self.topic, body='Test post 2') def test_get_posts_by_topic(self): """Get all posts of particular topic""" data = {'topic': self.topic.id} response = self.client.get(reverse('api:posts-list'), data) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data.get('results')), 2) def test_patch_post_by_user(self): """Tests that user can edit post""" data = {'body': 'Edited post body'} response = self.client.patch( reverse('api:posts-detail', kwargs={'pk': self.post1.id}), data) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(data['body'], response.data.get('body')) def test_delete_post_by_user(self): """Users cannot delete their """ response = self.client.delete( reverse('api:posts-detail', kwargs={'pk': self.post1.id})) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_successfult_post_deletion(self): """Tests that moderators and admins are able to delete posts""" self.user.is_moderator = True self.user.save() response = self.client.delete( reverse('api:posts-detail', kwargs={'pk': self.post1.id})) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.assertEqual(Post.objects.count(), 1)
class TestAlreadyConfirmedAccount: """ Test AlreadyConfirmedAccount Function. """ def setup(self): """ Sets up test fixtures using Factory Boy instances. See factories.py module for more information. """ self.user = UserFactory() self.data = { 'first_name': self.user.first_name, 'last_name': self.user.last_name, 'email': self.user.email, 'password': self.user.password, 'confirm_password': self.user.password, 'acct_type': 'IND', 'toc': True, } def test_already_confirmed_account_email_response(self, client): """ Test already_confirmed_account email is sent on already verified account. """ self.user.is_active = True self.user.save() response = client.post('/accounts/reset/', {'email': self.user.email}, follow=True) assert len(mail.outbox) == 1, 'Returns 1 if email has been sent.' assert mail.outbox[ 0].subject == 'Your accounts is already confirmed.', 'Should return email subject line of sent email.' assert mail.outbox[0].to == [ '*****@*****.**' ], 'Should return user email used to register.' assert 'You have received this email because there was an attempt to reset the activation link for your account.' in str( mail.outbox[0].body ), 'Returns template text found in the body of sent email.'
class TestBeginDocusign: GRAPHQL = """ mutation { beginDocusign(input: {nextUrl: "/blop"}) { errors { field, messages } redirectUrl } } """ @pytest.fixture(autouse=True) def setup_fixture(self, db, graphql_client, monkeypatch): self.user = UserFactory(email="*****@*****.**", is_email_verified=True) graphql_client.request.user = self.user self.graphql_client = graphql_client self.fake_create_envelope_called = False self.fake_create_recipient_view_called = False monkeypatch.setattr(hpaction.docusign, "create_envelope_for_hpa", self._fake_create_envelope) monkeypatch.setattr(hpaction.docusign, "create_recipient_view_for_hpa", self._fake_create_recipient_view) def execute(self): return self.graphql_client.execute( self.GRAPHQL)["data"]["beginDocusign"] def _fake_create_envelope(self, envelope_definition, api_client): self.fake_create_envelope_called = True return "fake_envelope_id" def _fake_create_recipient_view(self, user, envelope_id, api_client, return_url): self.fake_create_recipient_view_called = True assert return_url.startswith("https://example.com/docusign/callback?") assert user.pk == self.user.pk return "https://fake-docusign" def ensure_error(self, message): assert self.execute()["errors"] == one_field_err(message) def test_it_raises_error_on_no_email(self): self.user.email = "" self.user.save() self.ensure_error("You have no email address!") def test_it_raises_error_on_unverified_email(self): self.user.is_email_verified = False self.user.save() self.ensure_error("Your email address is not verified!") def test_it_raises_error_on_no_docs(self): self.ensure_error("You have no HP Action documents to sign!") def test_it_works(self, mockdocusign, django_file_storage): HPActionDocumentsFactory(user=self.user, kind="EMERGENCY") result = self.execute() assert result == {"errors": [], "redirectUrl": "https://fake-docusign"} assert self.fake_create_envelope_called is True assert self.fake_create_recipient_view_called is True DocusignEnvelope.objects.get(id="fake_envelope_id") def test_it_reuses_existing_envelope(self, mockdocusign, django_file_storage): docs = HPActionDocumentsFactory(user=self.user, kind="EMERGENCY") DocusignEnvelopeFactory(docs=docs, id="boop") result = self.execute() assert result == {"errors": [], "redirectUrl": "https://fake-docusign"} assert self.fake_create_envelope_called is False assert self.fake_create_recipient_view_called is True DocusignEnvelope.objects.get(id="boop")
class TestUserTeamRequestViewSet(APITestCase): def setUp(self) -> None: self.user = UserFactory() self.user.email_confirmed = True self.user.save() token = Token.objects.get(user=self.user) self.client.credentials(HTTP_AUTHORIZATION=f'Token {token.key}') self.team = TeamFactory(owner=self.user) self.another_user1 = AnotherUserFactory() self.another_user2 = AnotherUserFactory(username='******', email='*****@*****.**') self.user_team_request = UserTeamRequestFactory( user=self.another_user1, team=self.team, ) self.user_team_request = UserTeamRequestFactory( user=self.another_user2, team=self.team, ) def test_get_requests_for_team_by_owner(self): """Checks getting all requests for particular team by team owner""" params = {'teamID': self.team.id} response = self.client.get( reverse('api:user-team-requests-get-requests-for-team'), params) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data.get('results')), 2) def test_get_request_only_from_one_team(self): """Checks that team owner will get only requests from his team""" another_user3 = AnotherUserFactory(username='******', email='*****@*****.**') another_user4 = AnotherUserFactory(username='******', email='*****@*****.**') another_user5 = AnotherUserFactory(username='******', email='*****@*****.**') another_user6 = AnotherUserFactory(username='******', email='*****@*****.**') another_team = TeamFactory( owner=another_user3, name='Soul Eaters', description= 'We`ll destroy all the souls. And the age of darkness will come') UserTeamRequestFactory( user=another_user4, team=another_team, ) UserTeamRequestFactory( user=another_user5, team=another_team, ) UserTeamRequestFactory( user=another_user6, team=another_team, ) params = {'teamID': self.team.id} response = self.client.get( reverse('api:user-team-requests-get-requests-for-team'), params) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data.get('results')), 2) def test_get_requests_for_team_by_user(self): """Checks that usual user can't fetch requests data""" token = Token.objects.get(user=self.another_user1) self.client.credentials(HTTP_AUTHORIZATION=f'Token {token.key}') params = {'teamID': self.team.id} response = self.client.get( reverse('api:user-team-requests-get-requests-for-team'), params) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_post_request_for_team(self): """Tests that user can create requests""" usual_user = UserFactory( username='******', email='*****@*****.**', ) token = Token.objects.get(user=usual_user) self.client.credentials(HTTP_AUTHORIZATION=f'Token {token.key}') data = {'team': self.team.id} response = self.client.post(reverse('api:user-team-requests-list'), data=data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) notification = UserNotification.objects.last() notification_message = UserNotification.get_notification_text( UserNotification.TEAM_REQUEST_WAS_SENT_WITH_DEACTIVATED_EMAIL, username=usual_user.username) self.assertEqual(notification.message, notification_message) def test_request_created_once(self): """Tests that request for user created only once""" usual_user = UserFactory( username='******', email='*****@*****.**', ) token = Token.objects.get(user=usual_user) self.client.credentials(HTTP_AUTHORIZATION=f'Token {token.key}') data = {'team': self.team.id} self.client.post(reverse('api:user-team-requests-list'), data=data) # first request response = self.client.post(reverse('api:user-team-requests-list'), data=data) # second request self.assertEqual(response.status_code, forum_status.STATUS_222_USER_ALREADY_REQUESTED) def test_team_owner_approved_request(self): """Tests owner approve user team request flow""" data = { 'approved': True, } response = self.client.patch(reverse( 'api:user-team-requests-detail', kwargs={'pk': self.user_team_request.id}), data=data) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(mail.outbox), 1) team_request = UserTeamRequest.objects.get( id=self.user_team_request.id) self.assertTrue(team_request.approved) self.assertTrue(team_request.email_was_send) def test_team_owner_rejected_request(self): """Tests owner reject user team request flow""" data = { 'approved': False, } response = self.client.patch(reverse( 'api:user-team-requests-detail', kwargs={'pk': self.user_team_request.id}), data=data) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(mail.outbox), 1) team_request = UserTeamRequest.objects.get( id=self.user_team_request.id) self.assertFalse(team_request.approved) self.assertTrue(team_request.email_was_send)
class TestResendActivationLinkView: """ Test of resend_activation_link view. """ def setup(self): """ Sets up test fixtures using Factory Boy instances. See factories.py module for more information. """ self.user = UserFactory() def test_resend_activation_link_view(self, client): """ Test the resend_activation_link view. """ response = client.get('/accounts/reset/') assert response.status_code == 200 assert response.resolver_match.url_name == 'activation-reset' assert response.resolver_match.func.__name__ == 'resend_activation_link' def test_resend_activation_view_template_context_html_rendering(self, client): """ Test context and html of resend_activation_link view and template. """ response = client.get('/accounts/reset/') assert response.templates[ 0].name == 'users/resend_activation_link.html', 'Should return correct path of view template.' assert 'form' in response.context, 'Should return "form" context from view.' assert 'Ibhuku | Resend Link' in response.content.decode( 'utf8'), 'Returns correct page <title> found on page.' def test_resend_activation_link_new_email(self, client): """ Test new activation link resent to user. """ response = client.post( '/accounts/reset/', {'email': self.user.email}, follow=True) assert response.status_code == 200, 'Returns 200 if page redirection is True.' assert 'Ibhuku | Activation Link Emailed' in response.content.decode( 'utf8'), 'Returns correct page <title> found on page.' assert response.templates[ 0].name == 'users/account_activation_sent.html', 'Should return rendered template path.' assert len( mail.outbox) == 1, 'Returns 1 mailbox entry if confirm account email sent.' assert mail.outbox[ 0].subject == 'Welcome to Ibhuku.com. Confirm your email.', 'Returns email subject.' assert mail.outbox[0].to == ['*****@*****.**'] assert 'By clicking on the following button/link, you are confirming your email address' in str(mail.outbox[ 0].body), 'Should return email body text.' def test_resend_activation_link_new_email_account_confirmed(self, client): """ Test resend activation link response if verified account/email is being used. """ self.user.is_active = True self.user.save() response = client.post( '/accounts/reset/', {'email': self.user.email}, follow=True) assert response.resolver_match.url_name == 'activation-exists', 'Returns view url' assert 'Ibhuku | Account Exists' in response.content.decode( 'utf8'), 'Returns correct page <title> found on page.' assert response.status_code == 200, 'Returns 200 if successful redirect' assert len( mail.outbox) == 1, 'Returns 1 mailbox entry if already confirmed email sent.' assert mail.outbox[ 0].subject == 'Your accounts is already confirmed.', 'Should return subject of email sent to user.' assert mail.outbox[0].to == [ '*****@*****.**'], 'Should return email message was sent to.' assert '*****@*****.**' in str(mail.outbox[ 0].body), 'Should return the user email address used to confirm the account in email text body.'
class TestUserModel: """ Test for the Users Model. """ def setup(self): """ Sets up test fixtures using Factory Boy instances. See factories.py module for more information. """ self.user1 = UserFactory() self.user2 = UserFactory( first_name='John', last_name='Doe', email='*****@*****.**') self.users = User.objects.all() # Test of User Model created instances def test_user1_instance_created(self): """ Test for creation of a user instance in the database. """ assert self.user1.first_name == 'Testy0', 'Should return user first name.' assert self.user1.email == '*****@*****.**', 'Should return user email.' assert self.user1.password == 'testpassword0000', 'Should return user password.' def test_multiple_users_saved_in_database(self): """ Test for number of user instances created in database. """ assert len( self.users) == 2, 'Should return number of instances created in database' def test_user_instance_get_full_name_method(self): """ Test the user model's get_full_name() method. """ assert self.user1.get_full_name( ) == 'Testy4McTesty4', 'Should return full_name method value.' assert self.user2.get_full_name( ) == 'JohnDoe', 'Should return full_name method value.' def test_user_get_short_name_method(self): """ Test the user model's get_short_name() method. """ assert self.user1.get_short_name( ) == 'TMcTesty6', 'Should return short_name method value.' assert self.user2.get_short_name( ) == 'JDoe', 'Should return short_name method value.' def test_user_model_saves(self): """ Test user model saves/updates user changed/new data. """ self.user1.password = '******' self.user1.is_active = True self.user1.acct_type = 'EDU' self.user1.save() assert self.user1.password == 'testpassword12345' assert self.user1.is_active == True assert self.user1.acct_type == 'EDU' # Test of User Model methods def test_user_model_unicode_method(self): """ Test the user model's __unicode__() method. """ assert self.user1.__unicode__( ) == 'Testy10McTesty10', 'Should return unicode method value.' assert self.user2.__unicode__( ) == 'JohnDoe', 'Should return unicode method value.' def test_user_model_str_method(self): """ Test the user model's __str__() method. """ assert self.user1.__str__( ) == 'Testy12McTesty12', 'Should return str method value.' assert self.user2.__str__( ) == 'JohnDoe', 'Should return str method value.'
class TestCoreLogic(APITestCase): def setUp(self) -> None: self.user = UserFactory() def test_coins_purchase_functionality(self): """Checks that coins calculates properly""" calculate_coins_for_user(user=self.user, amount=constants.CENTS_FOR_500_COINS) self.assertEqual(self.user.coins, constants.COINS_500) self.user.coins = 0 self.user.save() notification_message = UserNotification.get_notification_text( UserNotification.SUCCESSFUL_COINS_PURCHASE, username=self.user.username, amount=constants.COINS_500) notification = UserNotification.objects.last() self.assertEqual(notification.message, notification_message) calculate_coins_for_user(user=self.user, amount=constants.CENTS_FOR_750_COINS) self.assertEqual(self.user.coins, constants.COINS_750) self.user.coins = 0 self.user.save() calculate_coins_for_user(user=self.user, amount=constants.CENTS_FOR_1000_COINS) self.assertEqual(self.user.coins, constants.COINS_1000) self.user.coins = 0 self.user.save() calculate_coins_for_user(user=self.user, amount=constants.CENTS_FOR_2000_COINS) self.assertEqual(self.user.coins, constants.COINS_2000) self.user.coins = 0 self.user.save() calculate_coins_for_user(user=self.user, amount=constants.CENTS_FOR_5000_COINS) self.assertEqual(self.user.coins, constants.COINS_5000) self.user.coins = 0 self.user.save() calculate_coins_for_user(user=self.user, amount=constants.CENTS_FOR_10000_COINS) self.assertEqual(self.user.coins, constants.COINS_10000) self.user.coins = 0 self.user.save() def test_delete_moderators_removed_topics(self): two_weeks_ago = datetime.now() - timedelta(days=14) for index in range(5): TopicFactory(removed_by_moderator=True, removed_at=two_weeks_ago) delete_moderators_removed_topics() existing_topics = Topic.objects.all() self.assertFalse(bool(existing_topics))
class TestLaLetterBuilderSendLetter: SEND_QUERY = """ mutation laLetterBuilderSendLetter($input: LaLetterBuilderSendLetterInput!) { output: laLetterBuilderSendLetter(input: $input) { errors { field, messages }, } } """ @pytest.fixture(autouse=True) def setup_fixture(self, graphql_client, db): self.user = UserFactory(email="*****@*****.**") graphql_client.request.user = self.user self.graphql_client = graphql_client def create_landlord_details(self): LandlordDetailsFactory(user=self.user, email="*****@*****.**") def execute(self, input={}): res = self.graphql_client.execute( self.SEND_QUERY, variables={"input": input}, ) return res["data"]["output"] def test_it_requires_login(self): self.graphql_client.request.user = AnonymousUser() assert self.execute()["errors"] == one_field_err( "You do not have permission to use this form!") def test_it_raises_err_when_no_onboarding_info_exists(self): assert self.execute()["errors"] == one_field_err( "You haven't provided any account details yet!") def test_it_raises_err_when_no_landlord_details_exist(self): OnboardingInfoFactory(user=self.user) assert self.execute()["errors"] == one_field_err( "You haven't provided any landlord details yet!") def test_it_raises_err_when_used_on_wrong_site(self): self.create_landlord_details() OnboardingInfoFactory(user=self.user) assert self.execute()["errors"] == one_field_err( "This form can only be used from the LA Letter Builder site.") def test_it_sends_letter( self, settings, allow_lambda_http, use_laletterbuilder_site, requests_mock, mailoutbox, smsoutbox, mocklob, ): user = self.graphql_client.request.user settings.IS_DEMO_DEPLOYMENT = False settings.LANGUAGES = project.locales.ALL.choices self.user.locale = "es" self.user.save() self.create_landlord_details() OnboardingInfoFactory(user=self.user) letter_obj = HabitabilityLetter(user=user, locale="es", html_content="<test/>") letter_obj.save() blank_letter = HabitabilityLetter.objects.get(user=user, letter_sent_at=None, letter_emailed_at=None) assert blank_letter.html_content == "<test/>" # Send the letter assert self.execute()["errors"] == [] sent_letter = HabitabilityLetter.objects.get( user=self.graphql_client.request.user) assert ("LETTER TEXT" in sent_letter.html_content ) # TODO: change this when we get real text in there assert "Boop Jones" in sent_letter.html_content assert 'lang="en"' in sent_letter.html_content assert 'lang="es"' in sent_letter.localized_html_content
class TestNorentSendLetterV2: QUERY = """ mutation { norentSendLetterV2(input: {}) { errors { field, messages } } } """ @pytest.fixture(autouse=True) def setup_fixture(self, graphql_client, db): self.user = UserFactory(email="*****@*****.**") graphql_client.request.user = self.user self.graphql_client = graphql_client def create_landlord_details(self): LandlordDetailsFactory(user=self.user, email="*****@*****.**") def execute(self): res = self.graphql_client.execute(self.QUERY) return res["data"]["norentSendLetterV2"] def test_it_requires_login(self): self.graphql_client.request.user = AnonymousUser() assert self.execute()["errors"] == one_field_err( "You do not have permission to use this form!") def test_it_raises_err_when_no_rent_periods_are_chosen(self): OnboardingInfoFactory(user=self.user) assert self.execute()["errors"] == one_field_err( "You have not chosen any rent periods!") def test_it_raises_err_when_letter_already_sent(self): letter = LetterFactory(user=self.user) UpcomingLetterRentPeriodFactory( user=self.user, rent_period=letter.rent_periods.all()[0]) OnboardingInfoFactory(user=self.user) assert self.execute()["errors"] == one_field_err( "You have already sent a letter for one of the rent periods!") def test_it_raises_err_when_no_onboarding_info_exists(self): UpcomingLetterRentPeriodFactory(user=self.user) assert self.execute()["errors"] == one_field_err( "You haven't provided any account details yet!") def test_it_raises_err_when_no_landlord_details_exist(self): UpcomingLetterRentPeriodFactory(user=self.user) OnboardingInfoFactory(user=self.user) assert self.execute()["errors"] == one_field_err( "You haven't provided any landlord details yet!") def test_it_raises_err_when_used_on_wrong_site(self): UpcomingLetterRentPeriodFactory(user=self.user) self.create_landlord_details() OnboardingInfoFactory(user=self.user) assert self.execute()["errors"] == one_field_err( "This form can only be used from the NoRent site.") def test_it_works( self, allow_lambda_http, use_norent_site, requests_mock, mailoutbox, smsoutbox, settings, mocklob, ): settings.IS_DEMO_DEPLOYMENT = False settings.LANGUAGES = project.locales.ALL.choices UpcomingLetterRentPeriodFactory(user=self.user) self.user.locale = "es" self.user.save() self.create_landlord_details() OnboardingInfoFactory(user=self.user) assert self.execute()["errors"] == [] assert UpcomingLetterRentPeriod.objects.get_for_user(self.user) == [] letter = Letter.objects.get(user=self.graphql_client.request.user) assert len(letter.rent_periods.all()) == 1 assert str(letter.latest_rent_period.payment_date) == "2020-05-01" assert letter.locale == "es" assert "unable to pay rent" in letter.html_content assert "Boop Jones" in letter.html_content assert 'lang="en"' in letter.html_content assert 'lang="es"' in letter.localized_html_content assert letter.letter_sent_at is not None assert letter.tracking_number == mocklob.sample_letter[ "tracking_number"] assert letter.fully_processed_at is not None assert len(mailoutbox) == 2 ll_mail = mailoutbox[0] assert ll_mail.to == ["*****@*****.**"] assert "letter attached" in ll_mail.body assert "Boop Jones" in ll_mail.body assert "sent on behalf" in ll_mail.subject assert len(ll_mail.attachments) == 1 assert letter.letter_emailed_at is not None user_mail = mailoutbox[1] assert user_mail.to == ["*****@*****.**"] assert "https://example.com/es/faqs" in user_mail.body assert "Hola Boop" in user_mail.body assert "Tu carta de NoRent y pasos siguientes importantes" in user_mail.subject assert len(smsoutbox) == 1 assert "Boop Jones" in smsoutbox[0].body assert "USPS" in smsoutbox[0].body assert len(user_mail.attachments) == 1