Esempio n. 1
0
 def setUp(self):
     self.locale = LocaleFactory.create(cldr_plurals="0,1")
     self.project = ProjectFactory.create(locales=[self.locale])
     self.main_resource = ResourceFactory.create(project=self.project, path="main.lang")
     self.other_resource = ResourceFactory.create(project=self.project, path="other.lang")
     self.main_entity = EntityFactory.create(
         resource=self.main_resource,
         string="Source String",
         string_plural="Plural Source String",
         key="Source String",
     )
     self.other_entity = EntityFactory.create(
         resource=self.other_resource,
         string="Other Source String",
         key="Key" + KEY_SEPARATOR + "Other Source String",
     )
     self.main_translation = TranslationFactory.create(
         entity=self.main_entity, locale=self.locale, plural_form=0, string="Translated String"
     )
     self.main_translation_plural = TranslationFactory.create(
         entity=self.main_entity, locale=self.locale, plural_form=1, string="Translated Plural String"
     )
     self.other_translation = TranslationFactory.create(
         entity=self.other_entity, locale=self.locale, string="Other Translated String"
     )
     self.subpage = SubpageFactory.create(project=self.project, name="Subpage", resources=[self.main_resource])
Esempio n. 2
0
    def test_multiple_translations(self):
        """
        If there are multiple translations to the same locale, only authors of
        the final approved version should be returned.
        """
        first_author, second_author = UserFactory.create_batch(2)

        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            user=first_author,
            approved=True
        )
        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            user=second_author,
            approved=False
        )

        self.changeset.update_vcs_entity(self.translated_locale, self.main_db_entity, MagicMock())

        self.changeset.execute_update_vcs()

        assert_equal(
            self.changeset.commit_authors_per_locale[self.translated_locale.code],
            [first_author]
        )
Esempio n. 3
0
    def test_unchanged_resources_sync(self):
        """
        Synchronization shouldn't modify resources if their
        entities weren't changed.
        """
        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            approved=True,
            date=aware_datetime(2015, 1, 1)
        )

        resource_file = MagicMock()
        self.changeset.vcs_project.resources = {
            self.main_db_entity.resource.path: resource_file
        }

        with patch.object(
            self.main_db_entity, 'has_changed', return_value=False
        ) as mock_has_changed:
            self.changeset.update_vcs_entity(
                self.translated_locale, self.main_db_entity, MagicMock()
            )

            self.changeset.execute_update_vcs()
            assert mock_has_changed.called
            assert len(resource_file.save.mock_calls) == 0
Esempio n. 4
0
    def test_no_new_translations(self):
        """
        Don't change any resource if there aren't any new translations.
        """
        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            approved=True,
            date=aware_datetime(2015, 1, 1)
        )

        with patch.object(
            self.main_db_entity, 'has_changed', return_value=False
        ) as mock_has_changed:
            resource_file = MagicMock()
            self.changeset.update_vcs_entity(
                self.translated_locale, self.main_db_entity, MagicMock()
            )
            self.changeset.vcs_project.resources = {
                self.main_db_entity.resource.path: resource_file
            }

            self.changeset.execute_update_vcs()

            assert mock_has_changed.called
            assert not resource_file.save.called
Esempio n. 5
0
    def test_obsolete_entities_asymmetric_resources_sync(self):
        """
        Synchronization should modify asymmetric resources files
        if their entities were made obsolete, even if their
        entities weren't changed.
        """
        TranslationFactory.create(locale=self.translated_locale, entity=self.main_db_entity,
            approved=True, date=aware_datetime(2015, 1, 1))

        resource_file = MagicMock()
        self.changeset.vcs_project.resources = {
            self.main_db_entity.resource.path: resource_file
        }

        # Entity must be made obsolete
        self.changeset.changes['obsolete_vcs'] = [self.main_db_entity.pk]

        # Resource file format must be asymmetric
        self.main_db_entity.resource.format = 'dtd'
        self.main_db_entity.resource.save()

        with patch.object(self.main_db_entity, 'has_changed', return_value=False) as mock_has_changed:
            self.changeset.update_vcs_entity(self.translated_locale, self.main_db_entity, MagicMock())

            self.changeset.execute_update_vcs()
            assert mock_has_changed.called
            assert resource_file.save.called
Esempio n. 6
0
    def test_save_latest_translation_update(self):
        """
        When a translation is saved, update the latest_translation
        attribute on the related project, locale, stats, and
        project_locale objects.
        """
        locale = LocaleFactory.create(latest_translation=None)
        project = ProjectFactory.create(locales=[locale], latest_translation=None)
        resource = ResourceFactory.create(project=project)
        stats = StatsFactory.create(locale=locale, resource=resource, latest_translation=None)
        project_locale = ProjectLocale.objects.get(locale=locale, project=project)

        assert_is_none(locale.latest_translation)
        assert_is_none(project.latest_translation)
        assert_is_none(stats.latest_translation)
        assert_is_none(project_locale.latest_translation)

        translation = TranslationFactory.create(
            locale=locale,
            entity__resource=resource,
            date=aware_datetime(1970, 1, 1)
        )
        self.assert_latest_translation(locale, translation)
        self.assert_latest_translation(project, translation)
        self.assert_latest_translation(stats, translation)
        self.assert_latest_translation(project_locale, translation)

        # Ensure translation is replaced for newer translations
        newer_translation = TranslationFactory.create(
            locale=locale,
            entity__resource=resource,
            date=aware_datetime(1970, 2, 1)
        )
        self.assert_latest_translation(locale, newer_translation)
        self.assert_latest_translation(project, newer_translation)
        self.assert_latest_translation(stats, newer_translation)
        self.assert_latest_translation(project_locale, newer_translation)

        # Ensure translation isn't replaced for older translations.
        TranslationFactory.create(
            locale=locale,
            entity__resource=resource,
            date=aware_datetime(1970, 1, 5)
        )
        self.assert_latest_translation(locale, newer_translation)
        self.assert_latest_translation(project, newer_translation)
        self.assert_latest_translation(stats, newer_translation)
        self.assert_latest_translation(project_locale, newer_translation)

        # Ensure approved_date is taken into consideration as well.
        newer_approved_translation = TranslationFactory.create(
            locale=locale,
            entity__resource=resource,
            approved_date=aware_datetime(1970, 3, 1)
        )
        self.assert_latest_translation(locale, newer_approved_translation)
        self.assert_latest_translation(project, newer_approved_translation)
        self.assert_latest_translation(stats, newer_approved_translation)
        self.assert_latest_translation(project_locale, newer_approved_translation)
Esempio n. 7
0
    def test_contributors_limit(self):
        """
        Checks if proper count of user is returned.
        """
        TranslationFactory.create_batch(110)

        top_contributors = User.translators.with_translation_counts()

        assert_equal(top_contributors.count(), 100)
Esempio n. 8
0
    def test_no_translations(self):
        """
        We don't attribute anyone if there aren't any new translations.
        """
        TranslationFactory.create(locale=self.translated_locale, entity=self.main_db_entity,
            approved=True, date=aware_datetime(2015, 1, 1))

        with patch.object(self.main_db_entity, 'has_changed', return_value=False):
            self.changeset.update_vcs_entity(self.translated_locale, self.main_db_entity, MagicMock())
            self.changeset.execute_update_vcs()
            assert_equal(self.changeset.commit_authors_per_locale[self.translated_locale.code], [])
Esempio n. 9
0
    def test_excluded_contributors(self):
        """
        Checks if contributors with mails in settings.EXCLUDE are excluded
        from top contributors list.
        """
        included_contributor = TranslationFactory.create(user__email="*****@*****.**").user
        excluded_contributor = TranslationFactory.create(user__email="*****@*****.**").user

        top_contributors = User.translators.with_translation_counts()
        assert_true(included_contributor in top_contributors)
        assert_true(excluded_contributor not in top_contributors)
Esempio n. 10
0
 def setUp(self):
     self.locale = LocaleFactory.create(
         cldr_plurals="0,1"
     )
     self.project = ProjectFactory.create(
         locales=[self.locale]
     )
     self.main_resource = ResourceFactory.create(
         project=self.project,
         path='main.lang'
     )
     self.other_resource = ResourceFactory.create(
         project=self.project,
         path='other.lang'
     )
     self.main_entity = EntityFactory.create(
         resource=self.main_resource,
         string='Source String',
         string_plural='Plural Source String',
         key='Source String'
     )
     self.other_entity = EntityFactory.create(
         resource=self.other_resource,
         string='Other Source String',
         key='Key' + KEY_SEPARATOR + 'Other Source String'
     )
     self.main_translation = TranslationFactory.create(
         entity=self.main_entity,
         locale=self.locale,
         plural_form=0,
         string='Translated String'
     )
     self.main_translation_plural = TranslationFactory.create(
         entity=self.main_entity,
         locale=self.locale,
         plural_form=1,
         string='Translated Plural String'
     )
     self.other_translation = TranslationFactory.create(
         entity=self.other_entity,
         locale=self.locale,
         string='Other Translated String'
     )
     self.subpage = SubpageFactory.create(
         project=self.project,
         name='Subpage',
         resources=[self.main_resource]
     )
Esempio n. 11
0
 def create_db_entities_translations(self):
     """
     Create entities and translations in the database for strings
     from the fake checkout.
     """
     self.main_db_entity = EntityFactory.create(
         resource=self.main_db_resource,
         string='Source String',
         key='Source String',
         obsolete=False
     )
     self.other_db_entity = EntityFactory.create(
         resource=self.other_db_resource,
         string='Other Source String',
         key='Other Source String',
         obsolete=False
     )
     self.main_db_translation = TranslationFactory.create(
         entity=self.main_db_entity,
         plural_form=None,
         locale=self.translated_locale,
         string='Translated String',
         date=aware_datetime(1970, 1, 1),
         approved=True,
         extra={'tags': []}
     )
Esempio n. 12
0
    def test_remove_duplicate_approvals(self):
        """
        Ensure that duplicate approvals are removed.
        """
        # Trigger creation of new approved translation.
        self.main_vcs_translation.strings[None] = 'New Translated String'
        self.main_vcs_translation.fuzzy = False

        # Translation approved after the sync started simulates the race
        # where duplicate translations occur.
        duplicate_translation = TranslationFactory.create(
            entity=self.main_db_entity,
            locale=self.translated_locale,
            string='Other New Translated String',
            approved=True,
            approved_date=aware_datetime(1970, 1, 3)
        )
        ChangedEntityLocale.objects.filter(entity=self.main_db_entity).delete()

        with patch('pontoon.sync.tasks.VCSProject', return_value=self.vcs_project):
            sync_project_repo(self.db_project.pk, self.repository.pk,
                              self.project_sync_log.pk, self.now)

        # Only one translation should be approved: the duplicate_translation.
        assert_equal(self.main_db_entity.translation_set.filter(approved=True).count(), 1)
        new_translation = self.main_db_entity.translation_set.get(
            string='New Translated String'
        )
        assert_false(new_translation.approved)
        assert_true(new_translation.approved_date is None)

        duplicate_translation.refresh_from_db()
        assert_true(duplicate_translation.approved)
        assert_equal(duplicate_translation.approved_date, aware_datetime(1970, 1, 3))
Esempio n. 13
0
    def setUp(self):
        """
        We setup a sample contributor with random set of translations.
        """
        super(ContributorTimelineViewTests, self).setUp()
        self.project = ProjectFactory.create()
        self.translations = OrderedDict()

        for i in range(26):
            date = make_aware(datetime(2016, 12, 1) - timedelta(days=i))
            translations_count = randint(1, 3)
            self.translations.setdefault((date, translations_count), []).append(
                sorted(
                    TranslationFactory.create_batch(
                        translations_count,
                        date=date,
                        user=self.user,
                        entity__resource__project=self.project,
                    ),
                    key=lambda t: t.pk,
                    reverse=True,
                )
            )

        mock_render = patch('pontoon.contributors.views.render', return_value=HttpResponse(''))
        self.mock_render = mock_render.start()
        self.addCleanup(mock_render.stop)
Esempio n. 14
0
    def test_removed_translation(self):
        """
        Suggestions should be available even after an Entity or
        Translation has been removed.
        """
        translation = TranslationFactory.create(approved=True)
        assert TranslationMemoryEntry.objects.get(
            source=translation.entity.string,
            target=translation.string,
            locale=translation.locale
        )

        entity = translation.entity
        translation.delete()
        assert TranslationMemoryEntry.objects.get(
            source=translation.entity.string,
            target=translation.string,
            locale=translation.locale
        )

        entity.delete()
        assert TranslationMemoryEntry.objects.get(
            source=translation.entity.string,
            target=translation.string,
            locale=translation.locale
        )
Esempio n. 15
0
    def test_update_db_unapprove_existing(self):
        """
        Any existing translations that don't match anything in VCS get
        unapproved, unless they were created after self.now.
        """
        self.main_db_translation.approved = True
        self.main_db_translation.approved_date = aware_datetime(1970, 1, 1)
        self.main_db_translation.approved_user = UserFactory.create()
        self.main_db_translation.save()
        self.main_vcs_translation.strings[None] = 'New Translated String'

        created_after_translation = TranslationFactory.create(
            entity=self.main_db_entity,
            approved=True,
            approved_date=aware_datetime(1970, 1, 3)
        )

        self.update_main_db_entity()
        self.main_db_translation.refresh_from_db()
        assert_attributes_equal(
            self.main_db_translation,
            approved=False,
            approved_user=None,
            approved_date=None
        )

        created_after_translation.refresh_from_db()
        assert_attributes_equal(
            created_after_translation,
            approved=True,
            approved_date=aware_datetime(1970, 1, 3)
        )
Esempio n. 16
0
 def _translation(self, user, submitted, approved):
     return TranslationFactory.create(
         date=aware_datetime(*submitted),
         user=user,
         approved_date=aware_datetime(*approved) if approved else None,
         approved_user=user
     )
Esempio n. 17
0
    def test_get_latest_activity_with_latest(self):
        """
        If the locale has a latest_translation and no project is given,
        return it.
        """
        translation = TranslationFactory.create()
        locale = LocaleFactory.create(latest_translation=translation)

        assert_equal(locale.get_latest_activity(), translation.latest_activity)
Esempio n. 18
0
    def test_get_latest_activity_success(self):
        """
        If the matching ProjectLocale has a latest_translation, return
        it's latest_activity.
        """
        translation = TranslationFactory.create(locale=self.locale, entity__resource__project=self.project)
        ProjectLocaleFactory.create(project=self.project, locale=self.locale, latest_translation=translation)

        assert_equal(ProjectLocale.get_latest_activity(self.project, self.locale), translation.latest_activity)
Esempio n. 19
0
 def test_approved_translation_in_memory(self):
     """
     Every save of approved translation should generate a new
     entry in the translation memory.
     """
     translation = TranslationFactory.create(approved=True)
     assert TranslationMemoryEntry.objects.get(
         source=translation.entity.string, target=translation.string, locale=translation.locale
     )
Esempio n. 20
0
 def test_unapproved_translation_in_memory(self):
     """
     Unapproved translation shouldn't be in the translation memory.
     """
     translation = TranslationFactory.create(approved=False)
     with assert_raises(TranslationMemoryEntry.DoesNotExist):
         TranslationMemoryEntry.objects.get(
             source=translation.entity.string, target=translation.string, locale=translation.locale
         )
Esempio n. 21
0
    def test_users_without_translations(self):
        """
        Checks if user contributors without translations aren't returned.
        """
        active_contributor = TranslationFactory.create(user__email="*****@*****.**").user
        inactive_contributor = UserFactory.create(email="*****@*****.**")

        top_contributors = User.translators.with_translation_counts()
        assert_true(active_contributor in top_contributors)
        assert_true(inactive_contributor not in top_contributors)
Esempio n. 22
0
    def test_no_translations(self):
        """
        We don't attribute anyone if there aren't any new translations.
        """
        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            approved=True,
            date=aware_datetime(2015, 1, 1),
        )

        with patch.object(self.main_db_entity, "has_changed", return_value=False):
            self.changeset.update_vcs_entity(
                self.translated_locale, self.main_db_entity, MagicMock()
            )
            self.changeset.execute_update_vcs()
            assert (
                self.changeset.commit_authors_per_locale[self.translated_locale.code]
                == []
            )
Esempio n. 23
0
    def test_unique_translations(self):
        """
        Checks if contributors with identical translations are returned.
        """

        unique_translator = TranslationFactory.create().user
        identical_translator = IdenticalTranslationFactory.create().user
        top_contributors = User.translators.with_translation_counts()

        assert_true(unique_translator in top_contributors)
        assert_true(identical_translator not in top_contributors)
Esempio n. 24
0
    def test_locale_top_contributors(self):
        """
        Tests if view returns top contributors specific for given locale.
        """
        first_locale = LocaleFactory.create()
        first_locale_contributor = TranslationFactory.create(locale=first_locale,
            entity__resource__project__locales=[first_locale]).user

        second_locale = LocaleFactory.create()
        second_locale_contributor = TranslationFactory.create(locale=second_locale,
            entity__resource__project__locales=[second_locale]).user

        with patch.object(views.LocaleContributorsView, 'render_to_response', return_value=HttpResponse('')) as mock_render:
            self.client.get('/{}/contributors/'.format(first_locale.code))
            assert_equal(mock_render.call_args[0][0]['locale'], first_locale)
            assert_equal(list(mock_render.call_args[0][0]['contributors']), [first_locale_contributor])

            self.client.get('/{}/contributors/'.format(second_locale.code))
            assert_equal(mock_render.call_args[0][0]['locale'], second_locale)
            assert_equal(list(mock_render.call_args[0][0]['contributors']), [second_locale_contributor])
Esempio n. 25
0
    def test_locale_top_contributors(self):
        """
        Tests if view returns top contributors specific for given locale.
        """
        first_locale = LocaleFactory.create()
        first_locale_contributor = TranslationFactory.create(locale=first_locale,
            entity__resource__project__locales=[first_locale]).user

        second_locale = LocaleFactory.create()
        second_locale_contributor = TranslationFactory.create(locale=second_locale,
            entity__resource__project__locales=[second_locale]).user

        with patch.object(views.LocaleContributorsView, 'render_to_response', return_value=HttpResponse('')) as mock_render:
            self.client.get('/{}/contributors/'.format(first_locale.code))
            assert_equal(mock_render.call_args[0][0]['locale'], first_locale)
            assert_equal(list(mock_render.call_args[0][0]['contributors']), [first_locale_contributor])

            self.client.get('/{}/contributors/'.format(second_locale.code))
            assert_equal(mock_render.call_args[0][0]['locale'], second_locale)
            assert_equal(list(mock_render.call_args[0][0]['contributors']), [second_locale_contributor])
Esempio n. 26
0
    def test_get_latest_activity_with_latest(self):
        """
        If the project has a latest_translation and no locale is given,
        return it.
        """
        project = ProjectFactory.create()
        translation = TranslationFactory.create(entity__resource__project=project)
        project.latest_translation = translation
        project.save()

        assert_equal(project.get_latest_activity(), translation.latest_activity)
Esempio n. 27
0
    def test_unique_translations(self):
        """
        Checks if contributors with identical translations are returned.
        """

        unique_translator = TranslationFactory.create().user
        identical_translator = IdenticalTranslationFactory.create().user
        top_contributors = User.translators.with_translation_counts()

        assert_true(unique_translator in top_contributors)
        assert_true(identical_translator not in top_contributors)
Esempio n. 28
0
    def test_users_without_translations(self):
        """
        Checks if user contributors without translations aren't returned.
        """
        active_contributor = TranslationFactory.create(
            user__email='*****@*****.**').user
        inactive_contributor = UserFactory.create(email='*****@*****.**')

        top_contributors = User.translators.with_translation_counts()
        assert_true(active_contributor in top_contributors)
        assert_true(inactive_contributor not in top_contributors)
Esempio n. 29
0
    def test_period_filters(self):
        """
        Total counts should be filtered by given date.
        Test creates 2 contributors with different activity periods and checks if they are filtered properly.
        """

        first_contributor = self.create_contributor_with_translation_counts(approved=12, unapproved=1, needs_work=2,
            date=aware_datetime(2015, 3, 2))

        # Second contributor
        self.create_contributor_with_translation_counts(approved=2, unapproved=11, needs_work=2,
            date=aware_datetime(2015, 6, 1))

        TranslationFactory.create_batch(5, approved=True, user=first_contributor, date=aware_datetime(2015, 7, 2))

        top_contributors = User.translators.with_translation_counts(aware_datetime(2015, 6, 10))

        assert_equal(top_contributors.count(), 1)
        assert_attributes_equal(top_contributors[0], translations_count=5,
            translations_approved_count=5, translations_unapproved_count=0,
            translations_needs_work_count=0)

        top_contributors = User.translators.with_translation_counts(aware_datetime(2015, 5, 10))

        assert_equal(top_contributors.count(), 2)
        assert_attributes_equal(top_contributors[0], translations_count=15,
            translations_approved_count=2, translations_unapproved_count=11,
            translations_needs_work_count=2)
        assert_attributes_equal(top_contributors[1], translations_count=5,
            translations_approved_count=5, translations_unapproved_count=0,
            translations_needs_work_count=0)

        top_contributors = User.translators.with_translation_counts(aware_datetime(2015, 1, 10))

        assert_equal(top_contributors.count(), 2)
        assert_attributes_equal(top_contributors[0], translations_count=20,
            translations_approved_count=17, translations_unapproved_count=1,
            translations_needs_work_count=2)
        assert_attributes_equal(top_contributors[1], translations_count=15,
            translations_approved_count=2, translations_unapproved_count=11,
            translations_needs_work_count=2)
Esempio n. 30
0
    def setUp(self):
        super(TranslationActionsTests, self).setUp()
        project = ProjectFactory.create()
        locale = LocaleFactory.create()

        ProjectLocale.objects.create(project=project, locale=locale)

        translation = TranslationFactory.create(locale=locale, entity__resource__project=project)
        translation.approved = True
        translation.save()

        self.translation = translation
Esempio n. 31
0
    def test_project_top_contributors(self):
        """
        Tests if view returns top contributors specific for given project.
        """
        first_project = ProjectFactory.create()
        ResourceFactory.create(project=first_project)
        first_project_contributor = TranslationFactory.create(entity__resource__project=first_project).user

        second_project = ProjectFactory.create()
        ResourceFactory.create(project=second_project)
        second_project_contributor = TranslationFactory.create(entity__resource__project=second_project).user

        with patch.object(views.ProjectContributorsView, 'render_to_response', return_value=HttpResponse('')) as mock_render:

            self.client.get('/projects/{}/contributors/'.format(first_project.slug))
            assert_equal(mock_render.call_args[0][0]['project'], first_project)
            assert_equal(list(mock_render.call_args[0][0]['contributors']), [first_project_contributor])

            self.client.get('/projects/{}/contributors/'.format(second_project.slug))
            assert_equal(mock_render.call_args[0][0]['project'], second_project)
            assert_equal(list(mock_render.call_args[0][0]['contributors']), [second_project_contributor])
Esempio n. 32
0
    def test_project_top_contributors(self):
        """
        Tests if view returns top contributors specific for given project.
        """
        first_project = ProjectFactory.create()
        ResourceFactory.create(project=first_project)
        first_project_contributor = TranslationFactory.create(entity__resource__project=first_project).user

        second_project = ProjectFactory.create()
        ResourceFactory.create(project=second_project)
        second_project_contributor = TranslationFactory.create(entity__resource__project=second_project).user

        with patch.object(views.ProjectContributorsView, 'render_to_response', return_value=HttpResponse('')) as mock_render:

            self.client.get('/projects/{}/contributors/'.format(first_project.slug))
            assert_equal(mock_render.call_args[0][0]['project'], first_project)
            assert_equal(list(mock_render.call_args[0][0]['contributors']), [first_project_contributor])

            self.client.get('/projects/{}/contributors/'.format(second_project.slug))
            assert_equal(mock_render.call_args[0][0]['project'], second_project)
            assert_equal(list(mock_render.call_args[0][0]['contributors']), [second_project_contributor])
Esempio n. 33
0
    def test_plural_translations(self):
        """
        If entity has some plural translations and approved translations their authors
        should be included in commit message.
        """
        first_author, second_author, third_author = UserFactory.create_batch(3)

        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            user=first_author,
            approved=True
        )
        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            user=third_author,
            approved=True,
            plural_form=1
        )
        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            user=second_author,
            approved=False
        )

        self.changeset.update_vcs_entity(self.translated_locale, self.main_db_entity, MagicMock())

        self.changeset.execute_update_vcs()

        assert_equal(
            set(self.changeset.commit_authors_per_locale[self.translated_locale.code]),
            {first_author, third_author}
        )
Esempio n. 34
0
    def test_plural_translations(self):
        """
        If entity has some plural translations and approved translations their authors
        should be included in commit message.
        """
        first_author, second_author, third_author = UserFactory.create_batch(3)

        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            user=first_author,
            approved=True
        )
        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            user=third_author,
            approved=True,
            plural_form=1
        )
        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            user=second_author,
            approved=False
        )

        self.changeset.update_vcs_entity(self.translated_locale, self.main_db_entity, MagicMock())

        self.changeset.execute_update_vcs()

        assert_equal(
            set(self.changeset.commit_authors_per_locale[self.translated_locale.code]),
            {first_author, third_author}
        )
Esempio n. 35
0
    def test_project_top_contributors(self):
        """
        Tests if view returns top contributors specific for given project.
        """
        first_project = ProjectFactory.create()
        ResourceFactory.create(project=first_project)
        first_project_contributor = TranslationFactory.create(
            entity__resource__project=first_project).user

        second_project = ProjectFactory.create()
        ResourceFactory.create(project=second_project)
        second_project_contributor = TranslationFactory.create(
            entity__resource__project=second_project).user

        with patch.object(
                views.ProjectContributorsView,
                "render_to_response",
                return_value=HttpResponse(""),
        ) as mock_render:
            self.client.get(
                "/projects/{}/ajax/contributors/".format(first_project.slug),
                HTTP_X_REQUESTED_WITH="XMLHttpRequest",
            )
            assert_equal(mock_render.call_args[0][0]["project"], first_project)
            assert_equal(
                list(mock_render.call_args[0][0]["contributors"]),
                [first_project_contributor],
            )

            self.client.get(
                "/projects/{}/ajax/contributors/".format(second_project.slug),
                HTTP_X_REQUESTED_WITH="XMLHttpRequest",
            )
            assert_equal(mock_render.call_args[0][0]["project"],
                         second_project)
            assert_equal(
                list(mock_render.call_args[0][0]["contributors"]),
                [second_project_contributor],
            )
Esempio n. 36
0
    def test_get_latest_activity_with_latest(self):
        """
        If the project has a latest_translation and no locale is given,
        return it.
        """
        project = ProjectFactory.create()
        translation = TranslationFactory.create(
            entity__resource__project=project)
        project.latest_translation = translation
        project.save()

        assert_equal(project.get_latest_activity(),
                     translation.latest_activity)
Esempio n. 37
0
    def setUp(self):
        super(TranslationUpdateTestCase, self).setUp()

        locale = LocaleFactory.create()
        project = ProjectFactory.create()
        ProjectLocale.objects.create(
            project=project,
            locale=locale,
        )
        resource = ResourceFactory.create(project=project)
        entity = EntityFactory.create(resource=resource)

        self.translation = TranslationFactory.create(entity=entity, locale=locale)
        self.translation.locale.translators_group.user_set.add(self.user)
Esempio n. 38
0
    def test_get_latest_activity_success(self):
        """
        If the matching ProjectLocale has a latest_translation, return
        it's latest_activity.
        """
        translation = TranslationFactory.create(
            locale=self.locale, entity__resource__project=self.project)
        ProjectLocaleFactory.create(project=self.project,
                                    locale=self.locale,
                                    latest_translation=translation)

        assert_equal(
            ProjectLocale.get_latest_activity(self.project, self.locale),
            translation.latest_activity)
Esempio n. 39
0
    def test_no_new_translations(self):
        """
        Don't change any resource if there aren't any new translations.
        """
        TranslationFactory.create(locale=self.translated_locale,
                                  entity=self.main_db_entity,
                                  approved=True,
                                  date=aware_datetime(2015, 1, 1))

        with patch.object(self.main_db_entity,
                          'has_changed',
                          return_value=False) as mock_has_changed:
            resource_file = MagicMock()
            self.changeset.update_vcs_entity(self.translated_locale,
                                             self.main_db_entity, MagicMock())
            self.changeset.vcs_project.resources = {
                self.main_db_entity.resource.path: resource_file
            }

            self.changeset.execute_update_vcs()

            assert mock_has_changed.called
            assert not resource_file.save.called
Esempio n. 40
0
    def test_unchanged_resources_sync(self):
        """
        Synchronization shouldn't modify resources if their entities weren't changed.
        """
        TranslationFactory.create(locale=self.translated_locale,
                                  entity=self.main_db_entity,
                                  approved=True,
                                  date=aware_datetime(2015, 1, 1))
        resource_file = MagicMock()

        self.changeset.vcs_project.resources = {
            self.main_db_entity.resource.path: resource_file
        }

        with patch.object(self.main_db_entity,
                          'has_changed',
                          return_value=False) as mock_has_changed:
            self.changeset.update_vcs_entity(self.translated_locale,
                                             self.main_db_entity, MagicMock())

            self.changeset.execute_update_vcs()
            assert mock_has_changed.called
            assert len(resource_file.save.mock_calls) == 0
Esempio n. 41
0
def test_project_top_contributors(client):
    """
    Tests if view returns top contributors specific for given project.
    """
    first_project = ProjectFactory.create(visibility=Project.Visibility.PUBLIC)
    ResourceFactory.create(project=first_project)
    first_project_contributor = TranslationFactory.create(
        entity__resource__project=first_project
    ).user

    second_project = ProjectFactory.create(visibility=Project.Visibility.PUBLIC)
    ResourceFactory.create(project=second_project)
    second_project_contributor = TranslationFactory.create(
        entity__resource__project=second_project
    ).user

    with patch(
        "pontoon.projects.views.ProjectContributorsView.render_to_response",
        return_value=HttpResponse(""),
    ) as mock_render:
        client.get(
            "/projects/{}/ajax/contributors/".format(first_project.slug),
            HTTP_X_REQUESTED_WITH="XMLHttpRequest",
        )
        assert mock_render.call_args[0][0]["project"] == first_project
        assert list(mock_render.call_args[0][0]["contributors"]) == [
            first_project_contributor
        ]

        client.get(
            "/projects/{}/ajax/contributors/".format(second_project.slug),
            HTTP_X_REQUESTED_WITH="XMLHttpRequest",
        )
        assert mock_render.call_args[0][0]["project"] == second_project
        assert list(mock_render.call_args[0][0]["contributors"]) == [
            second_project_contributor
        ]
Esempio n. 42
0
 def create_contributor_with_translation_counts(self, approved=0, unapproved=0, needs_work=0, **kwargs):
     """
     Helper method, creates contributor with given translations counts.
     """
     contributor = UserFactory.create()
     TranslationFactory.create_batch(approved, user=contributor, approved=True, **kwargs)
     TranslationFactory.create_batch(unapproved, user=contributor, approved=False, fuzzy=False, **kwargs)
     TranslationFactory.create_batch(needs_work, user=contributor, fuzzy=True, **kwargs)
     return contributor
Esempio n. 43
0
    def test_unapprove_translation(self):
        """Check if unapprove view works properly."""
        translation = TranslationFactory.create()
        translation.approved = True
        translation.save()

        response = self.client.ajax_post('/unapprove-translation/', {
            'translation': translation.pk,
            'paths': [],
        })
        assert_code(response, 200)

        translation.refresh_from_db()
        assert_equal(translation.approved, False)
        assert_equal(translation.unapproved_user, self.user)
Esempio n. 44
0
    def test_multiple_translations(self):
        """
        If there are multiple translations to the same locale, only authors of
        the final approved version should be returned.
        """
        first_author, second_author = UserFactory.create_batch(2)

        TranslationFactory.create(locale=self.translated_locale,
                                  entity=self.main_db_entity,
                                  user=first_author,
                                  approved=True)
        TranslationFactory.create(locale=self.translated_locale,
                                  entity=self.main_db_entity,
                                  user=second_author,
                                  approved=False)

        self.changeset.update_vcs_entity(self.translated_locale,
                                         self.main_db_entity, MagicMock())

        self.changeset.execute_update_vcs()

        assert_equal(
            self.changeset.commit_authors_per_locale[
                self.translated_locale.code], [first_author])
Esempio n. 45
0
    def test_bulk_check_valid_translations(self):
        translation1, translation2 = TranslationFactory.create_batch(
            2,
            locale=self.translated_locale,
            entity=self.main_db_entity,
            approved=True,
            date=aware_datetime(2015, 1, 1))

        self.mock_changed_translations.return_value = [
            translation1,
            translation2,
        ]
        assert_equal(self.changeset.bulk_check_translations(), {
            translation1.pk,
            translation2.pk,
        })
        assert_equal(Error.objects.count(), 0)
        assert_equal(Warning.objects.count(), 0)
Esempio n. 46
0
    def test_remove_duplicate_approvals(self):
        """
        Ensure that duplicate approvals are removed.
        """
        # Trigger creation of new approved translation.
        self.main_vcs_translation.strings[None] = "New Translated String"
        self.main_vcs_translation.fuzzy = False
        self.mock_pull_changes.return_value = [
            True,
            {
                self.repository.pk:
                Locale.objects.filter(pk=self.translated_locale.pk)
            },
        ]

        # Translation approved after the sync started simulates the race
        # where duplicate translations occur.
        duplicate_translation = TranslationFactory.create(
            entity=self.main_db_entity,
            locale=self.translated_locale,
            string="Other New Translated String",
            approved=True,
            approved_date=aware_datetime(1970, 1, 3),
        )
        ChangedEntityLocale.objects.filter(entity=self.main_db_entity).delete()

        with patch("pontoon.sync.tasks.VCSProject",
                   return_value=self.vcs_project):
            sync_translations(self.db_project.pk, self.project_sync_log.pk,
                              self.now)

        # Only one translation should be approved: the duplicate_translation.
        assert_equal(
            self.main_db_entity.translation_set.filter(approved=True).count(),
            1)
        new_translation = self.main_db_entity.translation_set.get(
            string="New Translated String")
        assert_false(new_translation.approved)
        assert_true(new_translation.approved_date is None)

        duplicate_translation.refresh_from_db()
        assert_true(duplicate_translation.approved)
        assert_equal(duplicate_translation.approved_date,
                     aware_datetime(1970, 1, 3))
Esempio n. 47
0
    def test_bulk_check_invalid_translations(self):
        """
        Test scenario:
        * check if errors are detected
        * check if only valid translation will land in the Translate Memory
        """
        invalid_translation, valid_translation = TranslationFactory.create_batch(
            2,
            locale=self.translated_locale,
            entity=self.main_db_entity,
            approved=True,
            date=aware_datetime(2015, 1, 1),
        )
        invalid_translation.string = "a\nb"
        invalid_translation.save()

        # Clear TM entries for those translations
        invalid_translation.memory_entries.all().delete()
        valid_translation.memory_entries.all().delete()

        self.mock_changed_translations.return_value = [
            invalid_translation,
            valid_translation,
        ]

        valid_translations = self.changeset.bulk_check_translations()

        assert valid_translations == {valid_translation.pk}

        (error, ) = Error.objects.all()

        assert error.library == FailedCheck.Library.PONTOON
        assert error.message == "Newline characters are not allowed"
        assert error.translation == invalid_translation

        self.changeset.translations_to_update = {
            valid_translation.pk: valid_translation
        }

        self.changeset.bulk_create_translation_memory_entries(
            valid_translations)

        assert not invalid_translation.memory_entries.exists()
        assert valid_translation.memory_entries.count() == 1
Esempio n. 48
0
    def test_bulk_check_invalid_translations(self):
        """
        Test scenario:
        * check if errors are detected
        * check if only valid translation will land in the Translate Memory
        """
        invalid_translation, valid_translation = TranslationFactory.create_batch(
            2,
            locale=self.translated_locale,
            entity=self.main_db_entity,
            approved=True,
            date=aware_datetime(2015, 1, 1)
        )
        invalid_translation.string = 'a\nb'
        invalid_translation.save()

        # Clear TM entries for those translations
        invalid_translation.memory_entries.all().delete()
        valid_translation.memory_entries.all().delete()

        self.mock_changed_translations.return_value = [
            invalid_translation,
            valid_translation,
        ]

        valid_translations = self.changeset.bulk_check_translations()

        assert_equal(valid_translations, {valid_translation.pk})

        error, = Error.objects.all()

        assert_equal(error.library, 'p')
        assert_equal(error.message, 'Newline characters are not allowed')
        assert_equal(error.translation, invalid_translation)

        self.changeset.translations_to_update = {
            valid_translation.pk: valid_translation
        }

        self.changeset.bulk_create_translation_memory_entries(valid_translations)

        assert_equal(invalid_translation.memory_entries.count(), 0)
        assert_equal(valid_translation.memory_entries.count(), 1)
Esempio n. 49
0
    def test_project_locale_modified(self):
        """
        If ProjectLocale is modified (like setting the
        latest_translation), has_changed should not be modified.
        """
        locale = LocaleFactory.create()
        project = ProjectFactory.create(locales=[locale])
        project.has_changed = False
        project.save()

        project.refresh_from_db()
        assert_false(project.has_changed)

        project_locale = ProjectLocale.objects.get(project=project, locale=locale)
        project_locale.latest_translation = TranslationFactory.create(
            entity__resource__project=project, locale=locale)
        project_locale.save()

        project.refresh_from_db()
        assert_false(project.has_changed)
Esempio n. 50
0
    def test_multiple_authors(self):
        """
        Commit message should include authors from translations of separate
        entities.
        """
        first_author, second_author = UserFactory.create_batch(2)
        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            user=first_author,
            approved=True
        )
        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.main_db_entity,
            approved=False
        )
        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.other_db_entity,
            user=second_author,
            approved=True
        )
        TranslationFactory.create(
            locale=self.translated_locale,
            entity=self.other_db_entity,
            approved=False
        )

        self.changeset.update_vcs_entity(self.translated_locale, self.main_db_entity, MagicMock())
        self.changeset.update_vcs_entity(self.translated_locale, self.other_db_entity, MagicMock())

        self.changeset.execute_update_vcs()

        assert_equal(
            self.changeset.commit_authors_per_locale[self.translated_locale.code],
            [first_author, second_author]
        )
Esempio n. 51
0
    def test_save_latest_translation_missing_project_locale(self):
        """
        If a translation is saved for a locale that isn't active on the
        project, do not fail due to a missing ProjectLocale.
        """
        locale = LocaleFactory.create(latest_translation=None)
        project = ProjectFactory.create(latest_translation=None)
        resource = ResourceFactory.create(project=project)
        translatedresource = TranslatedResourceFactory.create(
            locale=locale, resource=resource, latest_translation=None)

        # This calls .save, this should fail if we're not properly
        # handling the missing ProjectLocale.
        translation = TranslationFactory.create(locale=locale,
                                                entity__resource=resource,
                                                date=aware_datetime(
                                                    1970, 1, 1))

        self.assert_latest_translation(locale, translation)
        self.assert_latest_translation(project, translation)
        self.assert_latest_translation(translatedresource, translation)
Esempio n. 52
0
def contributor_translations(settings, user_a, project_a):
    """
    Setup a sample contributor with random set of translations.
    """
    translations = OrderedDict()
    for i in range(6):
        date = make_aware(datetime(2016, 12, 1) - timedelta(days=i))
        translations_count = 2
        translations.setdefault((date, translations_count), []).append(
            sorted(
                TranslationFactory.create_batch(
                    translations_count,
                    date=date,
                    user=user_a,
                    entity__resource__project=project_a,
                ),
                key=lambda t: t.pk,
                reverse=True,
            ))
    settings.CONTRIBUTORS_TIMELINE_EVENTS_PER_PAGE = 2
    yield translations
Esempio n. 53
0
    def test_removed_translation(self):
        """
        Suggestions should be available even after an Entity or
        Translation has been removed.
        """
        translation = TranslationFactory.create(approved=True)
        assert TranslationMemoryEntry.objects.get(
            source=translation.entity.string,
            target=translation.string,
            locale=translation.locale)

        entity = translation.entity
        translation.delete()
        assert TranslationMemoryEntry.objects.get(
            source=translation.entity.string,
            target=translation.string,
            locale=translation.locale)

        entity.delete()
        assert TranslationMemoryEntry.objects.get(
            source=translation.entity.string,
            target=translation.string,
            locale=translation.locale)
Esempio n. 54
0
    def test_update_db_unapprove_existing(self):
        """
        Any existing translations that don't match anything in VCS get
        unapproved, unless they were created after self.now.
        """
        self.main_db_translation.approved = True
        self.main_db_translation.approved_date = aware_datetime(1970, 1, 1)
        self.main_db_translation.approved_user = UserFactory.create()
        self.main_db_translation.save()
        self.main_vcs_translation.strings[None] = "New Translated String"

        created_after_translation = TranslationFactory.create(
            entity=self.main_db_entity,
            approved=True,
            approved_date=aware_datetime(1970, 1, 3),
        )

        self.update_main_db_entity()
        self.main_db_translation.refresh_from_db()
        assert_attributes_equal(
            self.main_db_translation,
            approved=False,
            approved_user=None,
            approved_date=None,
        )

        assert ActionLog.objects.filter(
            action_type="translation:rejected",
            translation=self.main_db_translation.pk,
        ).exists()

        created_after_translation.refresh_from_db()
        assert_attributes_equal(
            created_after_translation,
            approved=True,
            approved_date=aware_datetime(1970, 1, 3),
        )
Esempio n. 55
0
    def setUp(self):
        """
        We setup a sample contributor with random set of translations.
        """
        super(ContributorTimelineViewTests, self).setUp()
        self.project = ProjectFactory.create()
        self.translations = OrderedDict()

        for i in xrange(26):
            date = make_aware(datetime(2016, 12, 1) - timedelta(days=i))
            translations_count = randint(1, 3)
            self.translations.setdefault(
                (date, translations_count), []).append(
                    TranslationFactory.create_batch(
                        translations_count,
                        date=date,
                        user=self.user,
                        entity__resource__project=self.project,
                    ))

        mock_render = patch('pontoon.base.views.render',
                            return_value=HttpResponse(''))
        self.mock_render = mock_render.start()
        self.addCleanup(mock_render.stop)
Esempio n. 56
0
 def create_contributor_with_translation_counts(self,
                                                approved=0,
                                                unapproved=0,
                                                needs_work=0,
                                                **kwargs):
     """
     Helper method, creates contributor with given translations counts.
     """
     contributor = UserFactory.create()
     TranslationFactory.create_batch(approved,
                                     user=contributor,
                                     approved=True,
                                     **kwargs)
     TranslationFactory.create_batch(unapproved,
                                     user=contributor,
                                     approved=False,
                                     fuzzy=False,
                                     **kwargs)
     TranslationFactory.create_batch(needs_work,
                                     user=contributor,
                                     fuzzy=True,
                                     **kwargs)
     return contributor
Esempio n. 57
0
    def setUp(self):
        self.now = aware_datetime(1970, 1, 1)

        timezone_patch = patch("pontoon.sync.tasks.timezone")
        self.mock_timezone = timezone_patch.start()
        self.addCleanup(timezone_patch.stop)
        self.mock_timezone.now.return_value = self.now

        self.translated_locale = LocaleFactory.create(code="translated-locale")
        self.inactive_locale = LocaleFactory.create(code="inactive-locale")
        self.repository = RepositoryFactory()

        self.db_project = ProjectFactory.create(
            name="db-project",
            locales=[self.translated_locale],
            repositories=[self.repository],
        )
        self.main_db_resource = ResourceFactory.create(project=self.db_project,
                                                       path="main.lang",
                                                       format="lang")
        self.other_db_resource = ResourceFactory.create(
            project=self.db_project, path="other.lang", format="lang")
        self.missing_db_resource = ResourceFactory.create(
            project=self.db_project, path="missing.lang", format="lang")
        self.main_db_entity = EntityFactory.create(
            resource=self.main_db_resource,
            string="Source String",
            key="Source String",
            obsolete=False,
        )
        self.other_db_entity = EntityFactory.create(
            resource=self.other_db_resource,
            string="Other Source String",
            key="Other Source String",
            obsolete=False,
        )
        self.main_db_translation = TranslationFactory.create(
            entity=self.main_db_entity,
            plural_form=None,
            locale=self.translated_locale,
            string="Translated String",
            date=aware_datetime(1970, 1, 1),
            approved=True,
            extra={"tags": []},
        )

        # Load paths from the fake locale directory.
        checkout_path_patch = patch.object(
            Project,
            "checkout_path",
            new_callable=PropertyMock,
            return_value=FAKE_CHECKOUT_PATH,
        )
        checkout_path_patch.start()

        self.addCleanup(checkout_path_patch.stop)

        vcs_changed_files = {
            self.main_db_resource.path: [self.translated_locale],
            self.other_db_resource.path: [self.translated_locale],
            self.missing_db_resource.path: [self.translated_locale],
        }

        changed_files_patch = patch.object(
            VCSProject,
            "changed_files",
            new_callable=PropertyMock,
            return_value=vcs_changed_files,
        )
        changed_files_patch.start()
        self.addCleanup(changed_files_patch.stop)

        source_repository = patch.object(
            Project,
            "source_repository",
            new_callable=PropertyMock,
            return_value=self.db_project.repositories.all()[0],
        )
        source_repository.start()
        self.addCleanup(source_repository.stop)

        self.vcs_project = VCSProject(self.db_project)
        self.main_vcs_resource = self.vcs_project.resources[
            self.main_db_resource.path]
        self.other_vcs_resource = self.vcs_project.resources[
            self.other_db_resource.path]
        self.missing_vcs_resource = self.vcs_project.resources[
            self.missing_db_resource.path]
        self.main_vcs_entity = self.main_vcs_resource.entities["Source String"]
        self.main_vcs_translation = self.main_vcs_entity.translations[
            "translated-locale"]

        # Mock VCSResource.save() for each resource to avoid altering
        # the filesystem.
        resource_save_patch = patch.object(VCSResource, "save")
        resource_save_patch.start()
        self.addCleanup(resource_save_patch.stop)

        self.changeset = ChangeSet(
            self.db_project,
            self.vcs_project,
            aware_datetime(1970, 1, 1),
            self.translated_locale,
        )
Esempio n. 58
0
    def test_period_filters(self):
        """
        Total counts should be filtered by given date.
        Test creates 2 contributors with different activity periods and checks if they are filtered properly.
        """

        first_contributor = self.create_contributor_with_translation_counts(
            approved=12,
            unapproved=1,
            needs_work=2,
            date=aware_datetime(2015, 3, 2))

        # Second contributor
        self.create_contributor_with_translation_counts(approved=2,
                                                        unapproved=11,
                                                        needs_work=2,
                                                        date=aware_datetime(
                                                            2015, 6, 1))

        TranslationFactory.create_batch(5,
                                        approved=True,
                                        user=first_contributor,
                                        date=aware_datetime(2015, 7, 2))

        top_contributors = User.translators.with_translation_counts(
            aware_datetime(2015, 6, 10))

        assert_equal(top_contributors.count(), 1)
        assert_attributes_equal(top_contributors[0],
                                translations_count=5,
                                translations_approved_count=5,
                                translations_unapproved_count=0,
                                translations_needs_work_count=0)

        top_contributors = User.translators.with_translation_counts(
            aware_datetime(2015, 5, 10))

        assert_equal(top_contributors.count(), 2)
        assert_attributes_equal(top_contributors[0],
                                translations_count=15,
                                translations_approved_count=2,
                                translations_unapproved_count=11,
                                translations_needs_work_count=2)
        assert_attributes_equal(top_contributors[1],
                                translations_count=5,
                                translations_approved_count=5,
                                translations_unapproved_count=0,
                                translations_needs_work_count=0)

        top_contributors = User.translators.with_translation_counts(
            aware_datetime(2015, 1, 10))

        assert_equal(top_contributors.count(), 2)
        assert_attributes_equal(top_contributors[0],
                                translations_count=20,
                                translations_approved_count=17,
                                translations_unapproved_count=1,
                                translations_needs_work_count=2)
        assert_attributes_equal(top_contributors[1],
                                translations_count=15,
                                translations_approved_count=2,
                                translations_unapproved_count=11,
                                translations_needs_work_count=2)