Ejemplo n.º 1
0
    def test_management_command_sets_needs_review_flag(self, fake_get):
        fake_get.return_value.status_code = 200
        fake_get.return_value.json.return_value = {
            "memberships": [{
                "id": "uk.parliament.data/Member/374/GovernmentPost/56",
                "source": "datadotparl/governmentpost",
                "role": "Deputy Prime Minister and First Secretary of State",
                "person_id": "uk.org.publicwhip/person/10488",
                "organization_id": "house-of-commons",
                "start_date": "2001-06-08",
                "end_date": "9999-12-30",
            }]
        }
        person = PersonFactory(id=999)

        person.tmp_person_identifiers.create(
            internal_identifier="uk.org.publicwhip/person/10488",
            value_type="theyworkforyou",
        )
        person.save()

        cmd = call_command(
            "moderation_queue_set_ministers_liable_to_vandalism")
        person.refresh_from_db()
        self.assertEqual(person.edit_limitations,
                         EditLimitationStatuses.NEEDS_REVIEW.name)
Ejemplo n.º 2
0
    def test_duplicate_latest_versions_regression(self):
        """
        If there are identical latest versions from the old and new person
        then a "duplicate" version is created, with a "after merging" commit
        message.

        Normally this would get de-duplicated to save filling up the versions
        data, but in the case of a merge we *always* want to keep the merge
        commit, so we can show a proper log message.

        This is a regression test to catch that case.

        https://github.com/DemocracyClub/yournextrepresentative/issues/860

        """

        person_1 = PersonFactory(
            pk=50536,
            versions=json.dumps(
                [
                    {
                        "data": {
                            "birth_date": "",
                            "extra_fields": {"favourite_biscuits": ""},
                            "other_names": [],
                            "facebook_page_url": "",
                            "email": "",
                            "linkedin_url": "",
                            "party_ppc_page_url": "https://www.wirralconservatives.com/helencameron",
                            "death_date": "",
                            "honorific_suffix": "",
                            "honorific_prefix": "",
                            "name": "Helen Cameron",
                            "twitter_username": "",
                            "id": "50537",
                            "biography": "",
                            "wikipedia_url": "",
                            "standing_in": {
                                "local.wirral.2019-05-02": {
                                    "name": "Clatterbridge",
                                    "post_id": "MTW:E05000958",
                                }
                            },
                            "homepage_url": "",
                            "party_memberships": {
                                "local.wirral.2019-05-02": {
                                    "name": "Conservative and Unionist Party",
                                    "id": "party:52",
                                }
                            },
                            "facebook_personal_url": "",
                            "gender": "female",
                        },
                        "information_source": "https://www.wirralconservatives.com/helencameron",
                        "timestamp": "2019-03-28T14:37:30.958127",
                        "version_id": "0036d8081d566648",
                        "username": "******",
                    }
                ]
            ),
        )
        person_2 = PersonFactory(
            pk=50537,
            versions=json.dumps(
                [
                    {
                        "data": {
                            "birth_date": "",
                            "extra_fields": {"favourite_biscuits": ""},
                            "other_names": [],
                            "facebook_page_url": "",
                            "email": "",
                            "linkedin_url": "",
                            "party_ppc_page_url": "https://www.wirralconservatives.com/helencameron",
                            "death_date": "",
                            "honorific_suffix": "",
                            "honorific_prefix": "",
                            "name": "Helen Cameron",
                            "twitter_username": "",
                            "id": "50536",
                            "biography": "",
                            "wikipedia_url": "",
                            "standing_in": {
                                "local.wirral.2019-05-02": {
                                    "name": "Clatterbridge",
                                    "post_id": "MTW:E05000958",
                                }
                            },
                            "homepage_url": "",
                            "party_memberships": {
                                "local.wirral.2019-05-02": {
                                    "name": "Conservative and Unionist Party",
                                    "id": "party:52",
                                }
                            },
                            "facebook_personal_url": "",
                            "gender": "female",
                        },
                        "information_source": "https://www.wirralconservatives.com/helencameron",
                        "timestamp": "2019-03-28T14:37:30.958127",
                        "version_id": "0036d8081d566648",
                        "username": "******",
                    }
                ]
            ),
        )

        merger = PersonMerger(person_1, person_2)
        merger.merge()
        person_1.refresh_from_db()
        # This would raise if the bug existed
        self.assertIsNotNone(person_1.version_diffs)
Ejemplo n.º 3
0
class PersonFormsIdentifierCRUDTestCase(TestUserMixin, WebTest):
    def setUp(self):
        # super().setUp()
        self.person = PersonFactory(name=faker_factory.name())
        self.pi = PersonIdentifier.objects.create(
            person=self.person,
            value="democlub",
            value_type="twitter_username",
            internal_identifier="123456",
        )

    def test_person_identifier_on_form(self):
        """
        Test that the PersonIdentifier is listed on the Person form.
        """
        resp = self.app.get(
            reverse("person-update", kwargs={"person_id": self.person.pk}),
            user=self.user,
        )

        pi_form = resp.context["identifiers_formset"].initial_forms[0]

        self.assertEqual(pi_form["value"].value(), "democlub")
        self.assertEqual(pi_form["value_type"].value(), "twitter_username")

    def test_form_can_add_new_pi(self):
        resp = self.app.get(
            reverse("person-update", kwargs={"person_id": self.person.pk}),
            user=self.user,
        )

        form = resp.forms[1]
        form["source"] = "Adding a home page"
        form["tmp_person_identifiers-1-value"] = "https://democracyclub.org.uk"
        form["tmp_person_identifiers-1-value_type"] = "homepage_url"
        form.submit()

        self.assertEqual(PersonIdentifier.objects.all().count(), 2)
        self.assertEqual(
            list(PersonIdentifier.objects.values_list("value", flat=True)),
            ["https://democracyclub.org.uk", "democlub"],
        )
        # Check that internal IDs still exist for unchanged values
        self.assertEqual(
            PersonIdentifier.objects.get(
                value_type="twitter_username").internal_identifier,
            "123456",
        )

    def test_form_can_update_pi(self):
        """
        Test that the PersonIdentifier can be updated
        """
        resp = self.app.get(
            reverse("person-update", kwargs={"person_id": self.person.pk}),
            user=self.user,
        )

        form = resp.forms[1]
        form["source"] = "They changed their username"
        form["tmp_person_identifiers-0-value"] = "@democracyclub"
        form.submit()

        pi = PersonIdentifier.objects.get()
        self.assertEqual(pi.value, "democracyclub")
        self.assertEqual(pi.value_type, "twitter_username")

    def test_form_can_delete_pi(self):
        """
        Test that the PersonIdentifier can be deleted by removing the value
        """
        resp = self.app.get(
            reverse("person-update", kwargs={"person_id": self.person.pk}),
            user=self.user,
        )

        form = resp.forms[1]
        form["source"] = "They deleted their account"
        form["tmp_person_identifiers-0-value"] = ""
        form.submit()

        self.assertFalse(PersonIdentifier.objects.exists())

    def test_form_valid_when_extra_value_type_selected(self):
        """
        If someone selects a value type but doesn't enter a value, it's still valid
        """
        resp = self.app.get(
            reverse("person-update", kwargs={"person_id": self.person.pk}),
            user=self.user,
        )

        form = resp.forms[1]
        form["source"] = "Just picking something from the dropdown"
        form["tmp_person_identifiers-1-value_type"] = "twitter_username"
        resp = form.submit()
        self.assertEqual(resp.status_code, 302)
        self.assertEqual(
            resp.location,
            reverse("person-view", kwargs={"person_id": self.person.pk}),
        )

        self.assertEqual(PersonIdentifier.objects.get().value, "democlub")

    def test_change_value_type(self):
        """
        The value stays the same, but the type changes
        """
        self.assertEqual(PersonIdentifier.objects.get().value_type,
                         "twitter_username")
        resp = self.app.get(
            reverse("person-update", kwargs={"person_id": self.person.pk}),
            user=self.user,
        )

        form = resp.forms[1]
        form["source"] = "Just picking something from the dropdown"
        form["tmp_person_identifiers-0-value_type"] = "homepage_url"
        resp = form.submit()
        self.assertEqual(resp.status_code, 302)
        self.assertEqual(
            resp.location,
            reverse("person-view", kwargs={"person_id": self.person.pk}),
        )

        self.assertEqual(PersonIdentifier.objects.get().value_type,
                         "homepage_url")

    def _submit_values(self, value, value_type="twitter_username"):
        resp = self.app.get(
            reverse("person-update", kwargs={"person_id": self.person.pk}),
            user=self.user,
        )

        form = resp.forms[1]
        form["source"] = "They changed their username"
        form["tmp_person_identifiers-0-value_type"] = value_type
        form["tmp_person_identifiers-0-value"] = value
        form.submit()
        return form.submit()

    def test_twitter_bad_url(self):
        resp = self._submit_values("http://example.com/blah")
        form = resp.context["identifiers_formset"]
        self.assertFalse(form.is_valid())
        self.assertEqual(
            form[0].non_field_errors(),
            [
                "The Twitter username must only consist of alphanumeric characters or underscore"
            ],
        )

    def test_twitter_full_url(self):
        resp = self._submit_values("https://twitter.com/madeuptwitteraccount")
        self.assertEqual(resp.status_code, 302)

        self.assertEqual(PersonIdentifier.objects.get().value,
                         "madeuptwitteraccount")

    def test_bad_email_address(self):
        resp = self._submit_values("whoops", "email")
        form = resp.context["identifiers_formset"]
        self.assertFalse(form.is_valid())
        self.assertEqual(form[0].non_field_errors(),
                         ["Enter a valid email address."])

    def test_clean_wikidata_ids(self):
        resp = self._submit_values("Whoops", "wikidata_id")
        form = resp.context["identifiers_formset"]
        self.assertFalse(form.is_valid())
        self.assertEqual(
            form[0].non_field_errors(),
            ["Wikidata ID be a 'Q12345' type identifier"],
        )

        self._submit_values("http://www.wikidata.org/entity/Q391562",
                            "wikidata_id")
        self.person.refresh_from_db()
        self.assertEqual(
            self.person.get_single_identifier_of_type("wikidata_id").value,
            "Q391562",
        )

    def test_remove_internal_id_on_user_save(self):
        """
        This tests for a specific condition:


        1. A Twitter user name is added, no internal ID is added
        2. Time passes, and the user changes their username
        3. Another person comes along and creates an account with the old
           username
        4. TwitterBot attaches the internal ID to the screen name, however this
           is now the wrong person's account
        5. A user to the site corrects the username
        6. TwitterBot comes along and "corrects" the username back to the screen
           name that maatches the internal ID (because it's designed to alter
           screen names)

        Basically the user can never stop TwitterBot from doing this,
        without removing the Twitter account and re-adding it in two saves.

        It's better to assume the screen name change is valid as per the user
        edit and remove the internal ID at time of edit, for TwitterBot to add
        later.
        """
        resp = self.app.get(
            reverse("person-update", kwargs={"person_id": self.person.pk}),
            user=self.user,
        )

        form = resp.forms[1]
        form["source"] = "They changed their username"
        form["tmp_person_identifiers-0-value"] = "democracyclub"
        form.submit()

        pi = PersonIdentifier.objects.get()
        self.assertEqual(pi.value, "democracyclub")
        self.assertEqual(pi.value_type, "twitter_username")
        self.assertEqual(pi.internal_identifier, None)

    def test_duplicate_values_raises_form_error(self):

        resp = self.app.get(
            reverse("person-update", kwargs={"person_id": self.person.pk}),
            user=self.user,
        )

        pi = PersonIdentifier.objects.create(
            person=self.person,
            value_type="facebook_personal_url",
            value="https://www.facebook.com/example",
        )

        form = resp.forms[1]
        form["source"] = "They changed their username"
        form["tmp_person_identifiers-0-value_type"] = "email"
        form["tmp_person_identifiers-0-value"] = "*****@*****.**"

        form[
            "tmp_person_identifiers-1-value"] = "https://www.facebook.com/example"
        form["tmp_person_identifiers-1-value_type"] = "facebook_page_url"

        form["tmp_person_identifiers-2-id"] = pi.pk
        form["tmp_person_identifiers-2-value"] = ""
        form["tmp_person_identifiers-2-value_type"] = "facebook_personal_url"

        resp = form.submit()

        self.assertEqual(resp.status_code, 302)
        resp = resp.follow()
        self.assertEqual(resp.context["person"].tmp_person_identifiers.count(),
                         2)