def test_invalid_record(
            self, mock_logging: mock.MagicMock,
            mock_requests: 'requests_mock._RequestObjectProxy') -> None:
        """Test collecting strings with a record not passing checks."""

        mock_requests.post('https://slack.example.com/webhook')
        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create(
            'contact_lead', {
                'card_content': ' Translation needed ',
                'email_template':
                "This is a templated email that doesn't need translation",
                'name': 'I need to be translated',
            })
        collect_strings.main(['apiKey', '--collection', 'contact_lead'])
        self._assert_all_translations([])
        self.assertTrue(mock_logging.call_count,
                        msg=mock_logging.call_args_list)
        self.assertEqual(1, mock_requests.call_count)
        self.assertEqual(
            {
                'attachments': [{
                    'mrkdwn_in': ['text'],
                    'title':
                    'Automatic String Collect',
                    'text':
                    'Here is the report:\nAll the collections have been collected.'
                    + '\nErrors in collection:\ncontact_lead: 1\n'
                }],
            },
            mock_requests.request_history[0].json(),
        )
    def test_main(self):
        """Test collection of strings in various tables and fields."""

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'first-advice',
                'explanations (for client)': 'my explanation',
                'title': 'First Advice',
            })
        bob_advice_base.create('advice_modules', {
            'advice_id': 'second-advice',
            'title': 'Second Advice',
        })
        bob_advice_base.create('diagnostic_sentences', {
            'sentence_template': 'A sentence template',
        })
        collect_strings.main('apikey')

        translations = \
            list(airtable.Airtable('appkEc8N0Bw4Uok43', '').iterate('translations'))
        self.assertEqual([
            'A sentence template', 'First Advice', 'Second Advice',
            'my explanation'
        ], sorted(t.get('fields', {}).get('string') for t in translations))
    def test_duplicates(self) -> None:
        """Avoid creating duplicate rows for the same translation."""

        airtable.Airtable('appkEc8N0Bw4Uok43',
                          '').create('translations', {
                              'string': 'Already translated',
                          })
        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'first-advice',
                'title': 'Already translated',
                'explanations': 'New translation',
                'trigger_scoring_model': 'constant(2)',
            })
        bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'second-advice',
                'title': 'New translation',
                'trigger_scoring_model': 'constant(2)',
            })
        collect_strings.main(['apikey'])

        self._assert_all_translations([
            'Already translated',
            'New translation',
            'adviceModules:first-advice:title',
            'adviceModules:second-advice:title',
        ])
    def test_client_collection(self) -> None:
        """Test collecting strings for client-side translation from a specific table."""

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create(
            'contact_lead', {
                'card_content': 'Translation needed',
                'email_template':
                "This is a templated email that doesn't need translation",
                'name': 'I need to be translated',
            })
        bob_advice_base.create('email_templates', {
            'reason': "That's why",
            'title': 'Please, translate me',
        })
        bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'first-advice',
                'title': 'Title to translate',
                'static_explanations': 'New translation',
                'explanations': 'No translation needed',
            })
        collect_strings.main(
            ['apiKey', '--collection', 'client-advice_modules'])
        self._assert_all_translations([
            'adviceModules:first-advice:static_explanations',
            'adviceModules:first-advice:title'
        ])
    def test_generator(self) -> None:
        """Generate several strings to translate from a single Airtable field."""

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create(
            'specific_to_job_advice', {
                'expanded_card_items':
                'Nous avons réuni quelques idées pour vous aider à réussir '
                'votre approche\u00a0:\n* Se présenter aux boulangers entre 4h et 7h du matin.\n* '
                'Demander au vendeur / à la vendeuse à quelle heure arrive le chef le matin.',
                'short_title':
                'Un court titre à traduire',
                'for-job-group':
                'NOT_INTERESTING',
                'card_text':
                'Un texte de carte à traduire',
                'title':
                'Un titre à traduire',
                'diagnostic_topics': ['PROFILE_DIAGNOSTIC'],
            })

        collect_strings.main(['apikey'])

        self._assert_all_translations([
            'Demander au vendeur / à la vendeuse à quelle heure arrive le chef le matin.',
            'Nous avons réuni quelques idées pour vous aider à réussir votre approche\u00a0:',
            'Se présenter aux boulangers entre 4h et 7h du matin.',
            'Un court titre à traduire',
            'Un texte de carte à traduire',
            'Un titre à traduire',
        ])
    def test_collect_all(self, mock_post: mock.MagicMock) -> None:
        """Test collection of strings in various tables and fields."""

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'first-advice',
                'explanations (for client)': 'my explanation',
                'title': 'First Advice',
            })
        bob_advice_base.create('advice_modules', {
            'advice_id': 'second-advice',
            'title': 'Second Advice',
        })
        bob_advice_base.create('diagnostic_sentences', {
            'sentence_template': 'A sentence template',
            'order': 1,
        })
        collect_strings.main(['apikey'])

        self._assert_all_translations([
            'A sentence template', 'First Advice', 'Second Advice',
            'my explanation'
        ])
        mock_post.assert_not_called()
    def test_delete_unused(self) -> None:
        """Delete unused translations."""

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create('advice_modules', {
            'title': 'Other module',
            'advice_id': 'other'
        })
        module = bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'first-advice',
                'static_explanations': 'Original text',
                'title': 'Title to translate',
            })
        collect_strings.main(['apiKey', '--collection', 'client'])

        bob_advice_base.delete('advice_modules', module['id'])
        bob_advice_base.create('advice_modules', {
            'advice_id': 'second-advice',
            'static_explanations': 'New text',
        })
        collect_strings.main(
            ['apiKey', '--collection', 'client', '--unused', 'delete'])

        self._assert_all_translations([
            'adviceModules:other:title',
            'adviceModules:second-advice:static_explanations',
        ])
    def test_invalid_converter(
            self, mock_logging: mock.MagicMock,
            mock_requests: 'requests_mock._RequestObjectProxy') -> None:
        """Test collecting strings with a broken converter."""

        mock_requests.post('https://slack.example.com/webhook')
        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create('contact_lead', {
            'title': 'Title to translate',
        })
        collect_strings.main(['apiKey', '--collection', 'contact_lead'])
        self._assert_all_translations([])
        mock_logging.assert_called_once()
        self.assertEqual(1, mock_requests.call_count)
        self.assertEqual(
            {
                'attachments': [{
                    'mrkdwn_in': ['text'],
                    'title':
                    'Automatic String Collect',
                    'text':
                    'Here is the report:\nAll the collections have been collected.'
                    + '\nErrors in collection:\ncontact_lead: 1\n'
                }],
            },
            mock_requests.request_history[0].json(),
        )
    def test_delete_unused_with_generator(self) -> None:
        """Delete unused translations including ones dropped from generators."""

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        piece_of_advice = bob_advice_base.create(
            'specific_to_job_advice', {
                'id':
                'baker',
                'expanded_card_items':
                'A list of items to translate in multiple piece:\n'
                '* first item (will be removed)\n'
                '* second item (is kept)',
                'short_title':
                'Un court titre à traduire',
                'fr:for-job-group':
                'NOT_INTERESTING',
                'card_text':
                'Un texte de carte à traduire',
                'title':
                'Un titre à traduire',
                'diagnostic_topics': ['PROFILE_DIAGNOSTIC'],
            })

        collect_strings.main(['apikey'])

        bob_advice_base.delete('specific_to_job_advice', piece_of_advice['id'])
        bob_advice_base.create(
            'specific_to_job_advice', {
                'id':
                'baker',
                'expanded_card_items':
                'A list of items to translate in multiple pieces:\n'
                '* second item (is kept)',
                'short_title':
                'Un court titre à traduire',
                'fr:for-job-group':
                'NOT_INTERESTING',
                'card_text':
                'Un texte de carte à traduire',
                'title':
                'Un titre à traduire',
                'diagnostic_topics': ['PROFILE_DIAGNOSTIC'],
            })

        collect_strings.main(['apiKey', '--unused', 'delete'])

        self._assert_all_translations([
            'A list of items to translate in multiple pieces:',
            'second item (is kept)',
            'Un court titre à traduire',
            'Un texte de carte à traduire',
            'Un titre à traduire',
            'specificToJobAdvice:baker:title',
            'specificToJobAdvice:baker:card_text',
            'specificToJobAdvice:baker:expanded_card_header',
            'specificToJobAdvice:baker:short_title',
        ])
    def test_job_group_info(self) -> None:
        """Test collecting strings for the job_group_info collection from importer."""

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create(
            'skills_for_future', {
                'description': 'Translation needed',
                'name': 'I need to be translated',
                'assets': [1],
            })
        collect_strings.main(['apiKey', '--collection', 'job_group_info'])
        self._assert_all_translations(
            ['I need to be translated', 'Translation needed'])
    def test_last_used(self) -> None:
        """Check the behavior of last_used."""

        airtable.Airtable('appkEc8N0Bw4Uok43',
                          '').create('translations', {
                              'string': 'Very old translation',
                          })
        airtable.Airtable('appkEc8N0Bw4Uok43',
                          '').create('translations', {
                              'string': 'Old translation',
                              'last_used': '2018-09-12T14:35:43.000Z',
                          })
        airtable.Airtable('appkEc8N0Bw4Uok43', '').create(
            'translations', {
                'string': 'Already translated',
                'last_used': '2018-09-12T14:35:43.000Z',
            })
        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create('advice_modules', {
            'advice_id': 'first-advice',
            'title': 'Already translated',
        })
        bob_advice_base.create('advice_modules', {
            'advice_id': 'second-advice',
            'title': 'New translation',
        })
        date_before = datetime.datetime.utcnow() - datetime.timedelta(
            seconds=1)
        collect_strings.main(['apikey'])

        translations = \
            list(airtable.Airtable('appkEc8N0Bw4Uok43', '').iterate('translations'))
        actual = {
            t.get('fields', {}).get('string'): t.get('fields',
                                                     {}).get('last_used')
            for t in translations
        }
        self.assertEqual(None, actual['Very old translation'])
        self.assertEqual('2018-09-12T14:35:43.000Z', actual['Old translation'])
        last_used = actual['New translation']
        self.assertTrue(last_used)
        self.assertEqual(last_used, actual['Already translated'])
        self.assertRegex(last_used,
                         r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d*)?Z$')
        last_used_date = datetime.datetime.strptime(
            re.sub(r'\.\d*Z$', '', last_used), '%Y-%m-%dT%H:%M:%S')
        self.assertLess(date_before, last_used_date)
    def test_list_unused_replaced(self, mock_warning: mock.MagicMock) -> None:
        """List unused translations including replaced translations."""

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create(
            'advice_modules', {
                'title': 'Other module',
                'advice_id': 'other',
                'trigger_scoring_model': 'constant(2)',
            })
        module = bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'first-advice',
                'trigger_scoring_model': 'constant(1)',
                'title': 'Title to translate',
            })
        collect_strings.main(
            ['apiKey', '--collection', 'advice_modules', '--unused', 'list'])
        self.assertFalse(mock_warning.called)

        bob_advice_base.update('advice_modules', module['id'],
                               {'title': 'Updated title to translate'})
        collect_strings.main(
            ['apiKey', '--collection', 'advice_modules', '--unused', 'list'])
        self.assertEqual(1,
                         mock_warning.call_count,
                         msg=mock_warning.call_args_list)
        warning_text = mock_warning.call_args[0][0] % mock_warning.call_args[
            0][1]
        self.assertIn('advice_modules', warning_text)
        self.assertIn('title', warning_text)
        self.assertIn('first-advice', warning_text)
        self.assertIn('"Title to translate"', warning_text)
        self.assertIn('"Updated title to translate"', warning_text)
        self.assertNotIn('"Other module"', warning_text)

        self._assert_all_translations([
            'Other module',
            'Title to translate',
            'Updated title to translate',
            'adviceModules:first-advice:title',
            'adviceModules:other:title',
        ])
    def test_list_unused_replaced(self, mock_warning: mock.MagicMock) -> None:
        """List unused translations including replaced translations."""

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create('advice_modules', {
            'title': 'Other module',
            'advice_id': 'other'
        })
        module = bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'first-advice',
                'explanations (for client)': 'Original text',
                'title': 'Title to translate',
            })
        collect_strings.main(
            ['apiKey', '--collection', 'client', '--unused', 'list'])
        self.assertFalse(mock_warning.called)

        bob_advice_base.delete('advice_modules', module['id'])
        module = bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'first-advice',
                'explanations (for client)': 'New text',
                'title': 'Title to translate',
            })
        collect_strings.main(
            ['apiKey', '--collection', 'client', '--unused', 'list'])
        self.assertEqual(1,
                         mock_warning.call_count,
                         msg=mock_warning.call_args_list)
        warning_text = mock_warning.call_args[0][0] % mock_warning.call_args[
            0][1]
        self.assertIn('advice_modules', warning_text)
        self.assertIn('explanations (for client)', warning_text)
        self.assertIn('first-advice', warning_text)
        self.assertIn('"Original text"', warning_text)
        self.assertIn('"New text"', warning_text)
        self.assertNotIn('"Title to translate"', warning_text)

        self._assert_all_translations([
            'New text', 'Original text', 'Other module', 'Title to translate'
        ])
    def test_exsting_duplicates(
            self, mock_requests: 'requests_mock._RequestObjectProxy') -> None:
        """Detect existing duplicate rows for the same translation."""

        mock_requests.post('https://slack.example.com/webhook')

        record_1 = airtable.Airtable('appkEc8N0Bw4Uok43',
                                     '').create('translations', {
                                         'string': 'Already translated',
                                     })
        id_1 = record_1['id']
        record_2 = airtable.Airtable('appkEc8N0Bw4Uok43',
                                     '').create('translations', {
                                         'string': 'Already translated',
                                     })
        id_2 = record_2['id']
        collect_strings.main(['apikey'])

        self._assert_all_translations([
            'Already translated',
            'Already translated',
        ])

        self.assertEqual(1, mock_requests.call_count)
        self.assertEqual(
            {
                'attachments': [{
                    'mrkdwn_in': ['text'],
                    'title':
                    'Automatic String Collect',
                    'text':
                    'Here is the report:\nDuplicate records found for 1 string:\n'
                    +
                    f' * <https://airtable.com/tblQL7A5EgRJWhQFo/{id_1}|{id_1}>, '
                    f'<https://airtable.com/tblQL7A5EgRJWhQFo/{id_2}|{id_2}>\n'
                }],
            },
            mock_requests.request_history[0].json(),
        )
    def test_delete_replaced(self) -> None:
        """Delete replaced translations."""

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create(
            'advice_modules', {
                'title': 'Other module',
                'advice_id': 'other',
                'trigger_scoring_model': 'constant(1)',
            })
        module = bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'first-advice',
                'eshort_title': 'Original text',
                'title': 'Title to translate',
                'trigger_scoring_model': 'constant(1)',
            })
        collect_strings.main(['apiKey', '--collection', 'advice_modules'])

        module = bob_advice_base.update_all(
            'advice_modules', module['id'], {
                'advice_id': 'first-advice',
                'short_title': 'New text',
                'trigger_scoring_model': 'constant(1)',
            })
        collect_strings.main([
            'apiKey', '--collection', 'advice_modules', '--unused',
            'delete-replaced'
        ])

        self._assert_all_translations([
            'New text',
            'Other module',
            'Title to translate',
            'adviceModules:first-advice:short_title',
            'adviceModules:first-advice:title',
            'adviceModules:other:title',
        ])
    def test_collection(self) -> None:
        """Test collecting strings for a given collection from importer."""

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create(
            'contact_lead', {
                'card_content': 'Translation needed',
                'email_template': 'This is a templated email',
                'filters': ['constant(2)'],
                'name': 'I need to be translated',
            })
        bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'first-advice',
                'title': 'Title to translate',
                'static_explanations': 'New translation',
                'explanations': 'No translation needed',
            })
        collect_strings.main(['apiKey', '--collection', 'contact_lead'])
        self._assert_all_translations([
            'I need to be translated', 'This is a templated email',
            'Translation needed'
        ])
    def test_list_unused(self, mock_warning: mock.MagicMock) -> None:
        """List unused translations."""

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create('advice_modules', {
            'title': 'Other module',
            'advice_id': 'other'
        })
        module = bob_advice_base.create('advice_modules', {
            'advice_id': 'first-advice',
            'title': 'Title to translate',
        })
        collect_strings.main(
            ['apiKey', '--collection', 'client', '--unused', 'list'])
        self.assertFalse(mock_warning.called)

        bob_advice_base.delete('advice_modules', module['id'])
        module = bob_advice_base.create('advice_modules', {
            'advice_id': 'second-advice',
            'title': 'Title to translate',
        })
        collect_strings.main(
            ['apiKey', '--collection', 'client', '--unused', 'list'])
        self.assertEqual(1,
                         mock_warning.call_count,
                         msg=mock_warning.call_args_list)
        warning_text = mock_warning.call_args[0][0] % mock_warning.call_args[
            0][1]
        self.assertIn('adviceModules', warning_text)
        self.assertIn('title', warning_text)
        self.assertIn('"first-advice"', warning_text)

        self._assert_all_translations([
            'adviceModules:other:title',
            'adviceModules:first-advice:title',
            'adviceModules:second-advice:title',
        ])
    def test_collect_all(
            self, mock_requests: 'requests_mock._RequestObjectProxy') -> None:
        """Test collection of strings in various tables and fields."""

        mock_requests.post('https://slack.example.com/webhook')

        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'first-advice',
                'static_explanations': 'my explanation',
                'title': 'First Advice',
                'trigger_scoring_model': 'constant(0)',
            })
        bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'second-advice',
                'title': 'Second Advice',
                'trigger_scoring_model': 'constant(1)',
            })
        bob_advice_base.create(
            'diagnostic_main_challenges', {
                'category_id': 'my-category',
                'description': 'My category description',
                'metric_title': 'A category metric title',
                'order': 1,
            })
        diagnostic_overall_record = bob_advice_base.create(
            'diagnostic_overall', {
                'category_id': 'my-category',
                'sentence_template': 'An overall diagnostic sentence',
                'text_template': 'An overall diagnostic text',
                'score': 4,
                'order': 1,
            })
        diagnostic_overall_record_id = diagnostic_overall_record['id']
        collect_strings.main(['apikey'])

        self._assert_all_translations([
            'A category metric title',
            'An overall diagnostic sentence',
            'An overall diagnostic text',
            'First Advice',
            'My category description',
            'Second Advice',
            'adviceModules:first-advice:static_explanations',
            'adviceModules:first-advice:title',
            'adviceModules:second-advice:title',
            f'diagnosticOverall:{diagnostic_overall_record_id}:sentence_template',
            f'diagnosticOverall:{diagnostic_overall_record_id}:text_template',
            'diagnosticMainChallenges:my-category:description',
            'diagnosticMainChallenges:my-category:metric_title',
            'proto:AreaType:CITY',
            'proto:AreaType:COUNTRY',
            'proto:AreaType:DEPARTEMENT',
            'proto:AreaType:REGION',
            'proto:AreaType:UNKNOWN_AREA_TYPE',
            'proto:AreaType:WORLD',
            'proto:EmploymentType:ALTERNANCE',
            'proto:EmploymentType:ANY_CONTRACT_LESS_THAN_A_MONTH',
            'proto:EmploymentType:CDD',
            'proto:EmploymentType:CDD_LESS_EQUAL_3_MONTHS',
            'proto:EmploymentType:CDD_OVER_3_MONTHS',
            'proto:EmploymentType:CDI',
            'proto:EmploymentType:FULL_TIME_EMPLOYMENT',
            'proto:EmploymentType:INTERIM',
            'proto:EmploymentType:INTERNSHIP',
            'proto:EmploymentType:PART_TIME_EMPLOYMENT',
            'proto:EmploymentType:UNDEFINED_EMPLOYMENT_TYPE',
            'proto:DegreeLevel:BAC_BACPRO',
            'proto:DegreeLevel:BTS_DUT_DEUG',
            'proto:DegreeLevel:CAP_BEP',
            'proto:DegreeLevel:DEA_DESS_MASTER_PHD',
            'proto:DegreeLevel:LICENCE_MAITRISE',
            'proto:DegreeLevel:NO_DEGREE',
            'proto:DegreeLevel:UNKNOWN_DEGREE',
        ],
                                      are_proto_included=True)
        self.assertEqual(0, mock_requests.call_count)
    def test_last_used(self, mock_now: mock.MagicMock) -> None:
        """Check the behavior of last_used."""

        mock_now.return_value = datetime.datetime(2021, 2, 4, 21, 55)

        airtable.Airtable('appkEc8N0Bw4Uok43',
                          '').create('translations', {
                              'string': 'Very old translation',
                          })
        airtable.Airtable('appkEc8N0Bw4Uok43',
                          '').create('translations', {
                              'string': 'Old translation',
                              'last_used': '2018-09-12T14:35:43.000Z',
                          })
        airtable.Airtable('appkEc8N0Bw4Uok43', '').create(
            'translations', {
                'string': 'Already translated',
                'last_used': '2018-09-12T14:35:43.000Z',
            })
        bob_advice_base = airtable.Airtable('appXmyc7yYj0pOcae', '')
        bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'first-advice',
                'trigger_scoring_model': 'constant(0)',
                'title': 'Already translated',
            })
        bob_advice_base.create(
            'advice_modules', {
                'advice_id': 'second-advice',
                'trigger_scoring_model': 'constant(0)',
                'title': 'New translation',
            })

        collect_strings.main(['apikey'])

        translations = \
            list(airtable.Airtable('appkEc8N0Bw4Uok43', '').iterate('translations'))
        actual = {
            t.get('fields', {}).get('string'): t.get('fields',
                                                     {}).get('last_used')
            for t in translations
        }
        self.assertEqual(None, actual['Very old translation'])
        self.assertEqual('2018-09-12T14:35:43.000Z', actual['Old translation'])
        last_used = typing.cast(str, actual['New translation'])
        self.assertTrue(last_used)
        self.assertEqual(last_used, actual['Already translated'])
        self.assertRegex(last_used,
                         r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d*)?Z$')
        self.assertEqual('2021-02-04T21:55:00Z', last_used)

        # Wait two hours.
        mock_now.return_value = datetime.datetime(2021, 2, 4, 23, 55)

        collect_strings.main(['apikey'])

        actual = {
            t.get('fields', {}).get('string'): t.get('fields',
                                                     {}).get('last_used')
            for t in translations
        }
        self.assertEqual(
            last_used,
            actual['Already translated'],
            msg=
            "The last_used field should not be updated as it's on the same day"
        )

        # Wait for the next day.
        mock_now.return_value = datetime.datetime(2021, 2, 5, 6, 55)

        collect_strings.main(['apikey'])

        actual = {
            t.get('fields', {}).get('string'): t.get('fields',
                                                     {}).get('last_used')
            for t in translations
        }
        self.assertEqual(
            '2021-02-05T06:55:00Z',
            actual['Already translated'],
            msg="The last_used field should be updated as it's on a new day")