def test_fallback_language( self, mock_requests: 'requests_mock._RequestObjectProxy') -> None: """Check that translations fallback to available language.""" mock_requests.post('https://api.mailjet.com/v3/REST/template', json={ 'Count': 1, 'Data': [{ 'ID': 5678 }], 'Total': 1 }) mock_requests.post( 'https://api.mailjet.com/v3/REST/template/5678/detailcontent') translate_mailjet.main(('--lang', 'en_UK', 'reset-password')) create_template_req = mock_requests.request_history[0].json() self.assertEqual('DO NOT EDIT reset-password (en_UK)', create_template_req['Name']) self.assertEqual('en_GB', create_template_req['Locale']) detail_content = mock_requests.request_history[1].json() self.assertEqual({'Headers', 'Text-part', 'Html-part', 'MJMLContent'}, detail_content.keys()) self.assertFalse(detail_content['Text-part']) self.assertEqual( { 'From': 'Bob Emploi <*****@*****.**>', 'Reply-To': '', 'Subject': 'Update your Bob password', }, detail_content['Headers'])
def test_not_translatable( self, unused_requests: 'requests_mock._RequestObjectProxy') -> None: """Error when trying to translate an untranslatable template.""" with self.assertRaises(ValueError): translate_mailjet.main(('--lang', 'en', 'not-translatable'))
def test_existing( self, mock_requests: 'requests_mock._RequestObjectProxy') -> None: """Translate all existing i18n templates in one call.""" expected_requests = [ mock_requests.get( 'https://api.mailjet.com/v3/REST/template/123456/detailcontent', json={ 'Count': 1, 'Data': [{}], 'Total': 1 }), mock_requests.get( 'https://api.mailjet.com/v3/REST/template/123/detailcontent', json={ 'Count': 1, 'Data': [{}], 'Total': 1 }), mock_requests.post( 'https://api.mailjet.com/v3/REST/template/123456/detailcontent' ), mock_requests.post( 'https://api.mailjet.com/v3/REST/template/123/detailcontent'), ] translate_mailjet.main(('existing', )) self.assertEqual([True] * 4, [r.called for r in expected_requests])
def test_space_checks( self, unused_mock_requests: 'requests_mock._RequestObjectProxy') -> None: """Check that translations are checked for whitespaces before being used.""" client = airtable.Airtable('appkEc8N0Bw4Uok43', '') record_id = next(record['id'] for record in client.iterate('tblQL7A5EgRJWhQFo') if record['fields']['string'].startswith( 'Ce message vous a été envoyé')) client.delete('tblQL7A5EgRJWhQFo', record_id) client.create( 'tblQL7A5EgRJWhQFo', { 'string': 'Ce message vous a été envoyé à la suite du recueil de vos données sur BOB ' 'EMPLOI. La fréquence des envois est limitée, mais peut être plus importante en ' 'fonction de l’action de l’association. Vous avez la possibilité d’exercer vos droits ' 'd’accès, de rectification et de suppression en écrivant à l’adresse suivante : ' '[email protected].', 'en': 'This message contains a space before an exclamation mark !', 'fr@tu': "Ce message t'a été envoyé", }) with self.assertRaises(ValueError) as error: translate_mailjet.main(('--lang', 'en', 'reset-password')) self.assertIn('a space before an exclamation mark** **!', str(error.exception) + str(error.exception.__cause__))
def test_multiple( self, mock_requests: 'requests_mock._RequestObjectProxy') -> None: """Translate several templates to several languages in one call.""" create_template_request = mock_requests.post( 'https://api.mailjet.com/v3/REST/template', json={ 'Count': 1, 'Data': [{ 'ID': 5678 }], 'Total': 1 }) update_template_request = mock_requests.post( 'https://api.mailjet.com/v3/REST/template/5678/detailcontent') translate_mailjet.main(('--lang', 'en', '--lang', 'fr@tu', 'reset-password', 'reset-password2')) self.assertEqual(4, create_template_request.call_count, [(r.url, r.body and r.body[:30]) for r in create_template_request.request_history]) self.assertEqual(4, update_template_request.call_count, [(r.url, r.body and r.body[:30]) for r in create_template_request.request_history])
def test_template_exists_map( self, mock_requests: 'requests_mock._RequestObjectProxy') -> None: """Trying the tool when the template already exists in the map and has changes.""" get_template_request = mock_requests.get( 'https://api.mailjet.com/v3/REST/template/123456/detailcontent', json={ 'Count': 1, 'Total': 1, 'Data': [{ 'Headers': {}, 'Text-part': '', 'Html-part': '<html/>', 'MJMLContent': {}, }] }) update_template_request = mock_requests.post( 'https://api.mailjet.com/v3/REST/template/123456/detailcontent') translate_mailjet.main(('--lang', 'es', 'reset-password')) self.assertTrue(get_template_request.called) self.assertTrue(update_template_request.called)
def test_too_many_requests( self, mock_requests: 'requests_mock._RequestObjectProxy') -> None: """Mailjet API rate is limiting our ability to get an existing template.""" get_template_request = mock_requests.get( 'https://api.mailjet.com/v3/REST/template/123456/detailcontent', status_code=429, text='Too Many Requests', ) with self.assertRaises(requests.exceptions.HTTPError): translate_mailjet.main(('--lang', 'es', 'reset-password')) self.assertTrue(get_template_request.called)
def test_mjml_as_xml(self, mock_requests: requests_mock.Mocker) -> None: """Test with a source file where the MJML is in XML format.""" client = airtable.Airtable('appkEc8N0Bw4Uok43', '') for string, en_string in self._english_translations.items(): client.create('tblQL7A5EgRJWhQFo', { 'string': string, 'en': en_string, }) mock_requests.post('https://api.mailjet.com/v3/REST/template', json={ 'Count': 1, 'Data': [{ 'ID': 5678 }], 'Total': 1 }) mock_requests.post( 'https://api.mailjet.com/v3/REST/template/5678/detailcontent') translate_mailjet.main(('--lang', 'en', 'mjml-as-xml')) create_template_req = mock_requests.request_history[0].json() self.assertEqual('DO NOT EDIT mjml-as-xml (en)', create_template_req['Name']) self.assertEqual('en_US', create_template_req['Locale']) detail_content = mock_requests.request_history[1].json() self.assertEqual({'Headers', 'Text-part', 'Html-part', 'MJMLContent'}, detail_content.keys()) self.assertFalse(detail_content['Text-part']) self.assertEqual( { 'From': 'Joanna <*****@*****.**>', 'Reply-To': '', 'ReplyEmail': '', 'SenderName': 'Joanna', 'SenderEmail': '*****@*****.**', 'Subject': 'A video that I wanted to show you', }, detail_content['Headers']) mjml_content = detail_content['MJMLContent'] self.assertIsInstance(mjml_content, str) self.assertRegex( mjml_content, '<mj-image [^>]* src="https://t.bob-emploi.fr/tplimg/6u2u/b/oirn/2ugx1-english.png"' ) self.assertNotIn("Joanna et l'équipe de Bob", mjml_content) self.assertIn('>Joanna and the Bob team<', mjml_content)
def test_template_exists( self, mock_requests: 'requests_mock._RequestObjectProxy') -> None: """Trying the tool when the template already exists but is not in the map.""" mock_requests.post( 'https://api.mailjet.com/v3/REST/template', status_code=400, json={ 'ErrorCode': 'ps-0015', 'StatusCode': 400, 'ErrorMessage': 'A template with "name": "reset-password (en)" already exists.', 'ErrorRelatedTo': ['template'], }) with self.assertRaises(requests.exceptions.HTTPError): translate_mailjet.main(('--lang', 'en', 'reset-password'))
def test_mustache_error_in_translation( self, unused_mock_requests: requests_mock.Mocker) -> None: """Check that the translation fails if a string translation breaks mustaches.""" client = airtable.Airtable('appkEc8N0Bw4Uok43', '') translations = self._english_translations | { # pylint: disable=line-too-long '<0>Vous recevez cet email car vous êtes inscrit{1}e{2}{3}{2}·e{4}{4} sur </0><5><6><7><8><7>Bob</7></8></7></6></5><0> et avez demandé des emails de coaching. </0><9><6><7><8><7>Cliquez ici</7></8></7></6></9><0> si vous ne souhaitez plus en recevoir ou moins souvent. Vous avez arrêté de chercher du travail et souhaitez mettre votre compte Bob en veille ? </0><10><6><7><8><7>cliquez ici</7></8></7></6></10><0>.</0>': '<0>Vous recevez cet email car vous êtes inscrit{1}e{2}{3}{2}·e{4}</0>', } for string, en_string in translations.items(): client.create('tblQL7A5EgRJWhQFo', { 'string': string, 'en': en_string, }) with self.assertRaises(ValueError) as error: translate_mailjet.main(('--lang', 'en', 'mjml-as-xml')) self.assertIn('Missing "endif"', str(error.exception))
def test_existing_dry_run( self, mock_requests: 'requests_mock._RequestObjectProxy', mock_logging: mock.MagicMock) -> None: """Dry run for translating existing i18n templates.""" expected_requests = [ mock_requests.get( 'https://api.mailjet.com/v3/REST/template/123456/detailcontent', json={ 'Count': 1, 'Data': [{}], 'Total': 1 }), mock_requests.get( 'https://api.mailjet.com/v3/REST/template/123/detailcontent', json={ 'Count': 1, 'Data': [{}], 'Total': 1 }), mock_requests.post( 'https://api.mailjet.com/v3/REST/template/123456/detailcontent' ), mock_requests.post( 'https://api.mailjet.com/v3/REST/template/123/detailcontent'), ] translate_mailjet.main(('existing', '--dry-run')) self.assertEqual([True] * 2 + [False] * 2, [r.called for r in expected_requests]) mock_logging.assert_any_call('Data would be updated for "%s" in "%s".', 'reset-password', 'es') mock_logging.assert_any_call('Data would be updated for "%s" in "%s".', 'reset-password', 'it')
def test_simple_usage( self, mock_requests: 'requests_mock._RequestObjectProxy') -> None: """Basic usage of the translate tool.""" mock_requests.post('https://api.mailjet.com/v3/REST/template', json={ 'Count': 1, 'Data': [{ 'ID': 5678 }], 'Total': 1 }) mock_requests.post( 'https://api.mailjet.com/v3/REST/template/5678/detailcontent') translate_mailjet.main(('--lang', 'en', 'reset-password')) create_template_req = mock_requests.request_history[0].json() self.assertEqual('DO NOT EDIT reset-password (en)', create_template_req['Name']) self.assertEqual('en_US', create_template_req['Locale']) detail_content = mock_requests.request_history[1].json() self.assertEqual({'Headers', 'Text-part', 'Html-part', 'MJMLContent'}, detail_content.keys()) self.assertFalse(detail_content['Text-part']) self.assertEqual( { 'From': 'Bob Emploi <*****@*****.**>', 'Reply-To': '', 'Subject': 'Update your Bob password', }, detail_content['Headers']) self.assertIn( '<p style="margin: 10px 0;color:#000000;font-family:Arial; font-size:14.6667px">' 'Hi\xa0{{var:firstname}},</p><p style="margin: 10px 0;color:#000000;font-family:Arial; ' 'font-size:14.6667px">You have requested a password change, you can now modify it by ' 'clicking on the button below.</p>', detail_content['Html-part'], ) self.assertIn( '<a href=\"{{var:resetLink}}\" style=\"background:#58BBFB;color:#ffffff;font-family:Ubu' 'ntu, Helvetica, Arial, sans-serif;font-size:13px;font-weight:normal;line-height:120%;' 'Margin:0;text-decoration:none;text-transform:none;\" target=\"_blank\">Update the ' 'password</a>', detail_content['Html-part'], ) self.assertIn('src="https://t.bob-emploi.fr/en-image.png"', detail_content['Html-part']) self.assertIn('a href="https://twitter.com/hellobob"', detail_content['Html-part']) self.assertIn( '>Update the password<', detail_content['MJMLContent'], ) self.assertIn( 'src="https://t.bob-emploi.fr/en-image.png"', detail_content['MJMLContent'], ) self.assertIn( 'href="https://twitter.com/hellobob"', detail_content['MJMLContent'], ) with open(self._mailjet_json_path, 'rt', encoding='utf-8') as map_file: map_content = map_file.read() self.assertEqual( textwrap.dedent('''\ [ { "i18n": { "en": 5678 }, "mailjetTemplate": 71254, "name": "reset-password" } ] '''), map_content)