Beispiel #1
0
def test_creation_without_api_key(client: Client) -> None:
    """Test whether creation without sending the API key whilst logged in is forbidden."""
    client, headers, _ = setup_user_client(client,
                                           is_staff=False,
                                           is_grafeas_staff=False)
    result = client.get(reverse("volunteer-list"), USER_CREATION_DATA)
    assert result.status_code == status.HTTP_403_FORBIDDEN
    def test_create_no_coc(self, client: Client) -> None:
        """Test that no transcription can be created without accepting the CoC."""
        client, headers, user = setup_user_client(client)
        user.accepted_coc = False
        user.save()

        submission = create_submission()
        data = {
            "submission_id": submission.id,
            "username": user.username,
            "original_id": "ABC",
            "source": submission.source.name,
            "url": "https://example.com",
            "text": "test content",
        }

        result = client.post(
            reverse("transcription-list"),
            json.dumps(data),
            content_type="application/json",
            **headers,
        )

        assert result.status_code == status.HTTP_403_FORBIDDEN
        assert Transcription.objects.count() == 0
    def test_with_blacklisted_user(self, client: Client) -> None:
        """Test whether a creation with a blacklisted user is rejected."""
        client, headers, user = setup_user_client(client)
        user.blacklisted = True
        user.save()

        submission = create_submission()
        data = {
            "submission_id": submission.id,
            "username": user.username,
            "original_id": "ABC",
            "source": submission.source.name,
            "url": "https://example.com",
            "text": "test content",
        }

        result = client.post(
            reverse("transcription-list"),
            json.dumps(data),
            content_type="application/json",
            **headers,
        )

        assert result.status_code == status.HTTP_423_LOCKED
        assert Transcription.objects.count() == 0
    def test_time_frames(
        self,
        client: Client,
        time_frame: str,
        dates: List[datetime],
        results: List[Dict[str, Union[str, int]]],
    ) -> None:
        """Verify that the time_frame parameter properly changes the response."""
        client, headers, user = setup_user_client(client, id=123456)

        for date in dates:
            create_transcription(
                create_submission(completed_by=user, complete_time=date),
                user,
                create_time=make_aware(date),
            )

        result = client.get(
            reverse("submission-rate") +
            f"?time_frame={time_frame}&completed_by=123456",
            content_type="application/json",
            **headers,
        )
        assert result.status_code == status.HTTP_200_OK
        response = result.json()
        assert response["results"] == results
    def test_report_not_removed(self, client: Client) -> None:
        """Verify that reporting sends a message to Slack."""
        mock = MagicMock()
        slack_client.chat_postMessage = mock
        client, headers, user = setup_user_client(client)

        submission = create_submission(id=3)
        assert not submission.removed_from_queue
        assert not submission.report_reason
        assert not submission.report_slack_channel_id
        assert not submission.report_slack_message_ts

        data = {"reason": "Violation of ALL the rules"}

        result = client.patch(reverse("submission-report",
                                      args=[submission.id]),
                              json.dumps(data),
                              content_type="application/json",
                              **headers)

        submission.refresh_from_db()

        assert result.status_code == status.HTTP_201_CREATED
        assert not submission.removed_from_queue
        assert submission.report_reason == "Violation of ALL the rules"
    def test_ocr_on_create_with_cannot_ocr_flag(
            self, client: Client, settings: SettingsWrapper) -> None:
        """Verify the OCR process exits early if the cannot_ocr flag is already set."""
        settings.ENABLE_OCR = True
        settings.IMAGE_DOMAINS = ["example.com"]
        assert Transcription.objects.count() == 0

        client, headers, _ = setup_user_client(client)
        source = get_default_test_source()
        data = {
            "original_id": "spaaaaace",
            "source": source.pk,
            "content_url": "http://example.com/a.jpg",
            "cannot_ocr": "True",
        }

        with patch("api.models.process_image", return_value={"text":
                                                             "AAA"}) as mock:
            # mock it anyway just in case this fails -- we don't want to actually
            # call OCR
            result = client.post(
                reverse("submission-list"),
                data,
                content_type="application/json",
                **headers,
            )
            mock.assert_not_called()

        assert result.status_code == status.HTTP_201_CREATED
        assert Transcription.objects.count() == 0
 def test_submission_create_with_full_args(self, client: Client) -> None:
     """Test whether creation with all arguments is successful."""
     client, headers, _ = setup_user_client(client)
     source = get_default_test_source()
     data = {
         "original_id": "spaaaaace",
         "source": source.pk,
         "url": "http://example.com",
         "tor_url": "http://example.com/tor",
         "content_url": "http://a.com",
         "title": "This is a Submission",
         "nsfw": False,
     }
     result = client.post(
         reverse("submission-list"),
         data,
         content_type="application/json",
         **headers,
     )
     assert result.status_code == status.HTTP_201_CREATED
     submission = Submission.objects.get(id=result.json()["id"])
     assert submission.original_id == data["original_id"]
     assert submission.source == source
     assert submission.url == data["url"]
     assert submission.tor_url == data["tor_url"]
     assert submission.content_url == data["content_url"]
     assert submission.nsfw == data["nsfw"]
     assert submission.title == data["title"]
Beispiel #8
0
    def test_post_errors(self, client: Client, error: int,
                         expected_redirect: str) -> None:
        """Verify that errors from the API translate correctly to responses."""
        client, _, user = setup_user_client(client)
        add_social_auth_to_user(user)

        submission = create_submission(
            original_id=int(random.random() * 1000),
            content_url="http://imgur.com",
            title="a",
            claimed_by=user,
        )

        class Response:
            ...

        response = Response()
        response.status_code = error

        with patch("api.views.submission.SubmissionViewSet.done",
                   lambda a, b, c: response):
            response = client.post(
                reverse("transcribe_submission",
                        kwargs={"submission_id": submission.id}),
                data={"transcription": "AAA"},
            )
            assert reverse(expected_redirect) in response.url
Beispiel #9
0
    def test_claim_already_claimed_other_user(self, client: Client) -> None:
        """Test a claim on a Submission already claimed by another user.

        This should be prevented and return an error.
        """
        BlossomUser.objects.all().delete()
        client, headers, user = setup_user_client(client,
                                                  id=1,
                                                  username="******")
        other_user = create_user(id=2, username="******")
        submission = create_submission(claimed_by=other_user)
        data = {"username": user.username}

        result = client.patch(
            reverse("submission-claim", args=[submission.id]),
            json.dumps(data),
            content_type="application/json",
            **headers,
        )
        assert result.status_code == status.HTTP_409_CONFLICT
        claimed_by = result.json()
        assert claimed_by["id"] == 2
        assert claimed_by["username"] == "user_2"

        submission.refresh_from_db()
        assert submission.claimed_by == other_user
Beispiel #10
0
    def test_summary_blacklisted_user(self, client: Client) -> None:
        """Test that a blacklisted user is reported as having 0 gamma."""
        client, headers, user = setup_user_client(client)
        user.blacklisted = True
        user.save()

        for _ in range(3):
            create_submission(completed_by=user)

        assert Submission.objects.filter(completed_by=user).count() == 3

        result = client.get(
            reverse("volunteer-summary") + f"?username={user.username}",
            **headers)

        assert result.status_code == status.HTTP_200_OK
        assert result.json().get("username") == user.username
        assert result.json()["gamma"] == 0

        user.blacklisted = False
        user.save()

        result = client.get(
            reverse("volunteer-summary") + f"?username={user.username}",
            **headers)

        assert result.json()["gamma"] == 3
Beispiel #11
0
    def test_check_reddit_for_missing_information(
            self, client: Client, settings: SettingsWrapper) -> None:
        """Verify that if information is missing we will check Reddit for it."""
        client, _, user = setup_user_client(client)
        add_social_auth_to_user(user)
        settings.ENABLE_REDDIT = True

        class RedditSubmission:
            class Response:
                over_18 = True
                title = "AAA"

            def submission(self, **kwargs: Any) -> Response:
                """Return a mocked response from Reddit."""
                return self.Response()

        with patch("app.middleware.configure_reddit",
                   lambda a: RedditSubmission()):
            submission = create_submission(
                original_id=int(random.random() * 1000),
                content_url="http://imgur.com",
            )

            client.get(reverse("choose_transcription"))

            submission.refresh_from_db()
            assert submission.title == "AAA"
            assert submission.nsfw is True
Beispiel #12
0
    def test_is_returning_transcriber(
        self,
        client: Client,
        recent_gamma: int,
        total_gamma: int,
        expected: bool,
    ) -> None:
        """Test whether returning transcribers are determined correctly."""
        # Mock both the total gamma
        with patch(
                "authentication.models.BlossomUser.gamma",
                new_callable=PropertyMock,
                return_value=total_gamma,
        ):
            # Mock the Slack client to catch the sent messages by the function under test.
            client, headers, user = setup_user_client(client)
            now = datetime.datetime.now(tz=pytz.UTC)

            # Create the recent transcriptions
            for i in range(0, recent_gamma):
                submission = create_submission(
                    id=i + 100,
                    claimed_by=user,
                    completed_by=user,
                    complete_time=now,
                )
                create_transcription(submission,
                                     user,
                                     id=i + 100,
                                     create_time=now)

            assert _is_returning_transcriber(user) == expected
    def test_list_with_null_filters(
        self, client: Client, filter_str: str, result_count: int
    ) -> None:
        """Verify that attributes can be filtered by null."""
        client, headers, user = setup_user_client(client, id=123)
        today = timezone.now()

        create_submission(
            id=1,
            claimed_by=user,
            completed_by=user,
            claim_time=today,
            complete_time=today,
            title="Test Submission",
            url="https://example.org",
            tor_url="https://example.org",
            content_url="https://example.org",
            redis_id="abc",
        )
        create_submission(id=2)

        result = client.get(
            reverse("submission-list") + f"?{filter_str}",
            content_type="application/json",
            **headers,
        )
        assert result.status_code == status.HTTP_200_OK
        assert len(result.json()["results"]) == result_count
Beispiel #14
0
def test_creation_with_normal_user(client: Client) -> None:
    """Test whether creation is not allowed to a user which is not a staff member."""
    client, headers, _ = setup_user_client(client,
                                           is_grafeas_staff=False,
                                           is_staff=False)
    result = client.post(reverse("volunteer-list"), USER_CREATION_DATA)
    assert result.status_code == status.HTTP_403_FORBIDDEN
    def test_random_none_available(self, client: Client) -> None:
        """Test that no transcription is returned when there is none available."""
        client, headers, user = setup_user_client(client)
        result = client.get(reverse("transcription-review-random"), **headers)

        assert not result.content
        assert result.status_code == status.HTTP_200_OK
    def test_list_with_contains_filters(self, client: Client, filter_str: str,
                                        result_count: int) -> None:
        """Test whether the transcription text can be searched."""
        client, headers, user = setup_user_client(client, id=123)

        submission = create_submission(id=1)

        create_transcription(
            submission,
            user,
            id=2,
            text="This is a very interesting text and such.",
        )
        create_transcription(
            submission,
            user,
            id=3,
            text="A text is a form of literature.",
        )
        create_transcription(
            submission,
            user,
            id=4,
            text="Bla bla bla bla.",
        )

        result = client.get(
            reverse("transcription-list") + f"?{filter_str}",
            content_type="application/json",
            **headers,
        )
        assert result.status_code == status.HTTP_200_OK
        assert len(result.json()["results"]) == result_count
    def test_list_with_null_filters(self, client: Client, filter_str: str,
                                    result_count: int) -> None:
        """Verify that filtering for null works correctly."""
        client, headers, user = setup_user_client(client, id=123)

        submission = create_submission(id=1)

        create_transcription(
            submission,
            user,
            id=2,
            original_id="abc",
            url="https://example.org",
            text="Test Transcription",
        )
        create_transcription(submission,
                             user,
                             id=3,
                             original_id=None,
                             url=None,
                             text=None)

        result = client.get(
            reverse("transcription-list") + f"?{filter_str}",
            content_type="application/json",
            **headers,
        )
        assert result.status_code == status.HTTP_200_OK
        assert len(result.json()["results"]) == result_count
    def test_list_with_time_filters(self, client: Client) -> None:
        """Verify that the transcriptions can be filtered by time."""
        client, headers, user = setup_user_client(client)

        dates = [
            datetime(2021, 1, 1),
            datetime(2021, 2, 1),
            datetime(2021, 2, 3),
            datetime(2021, 5, 10),
        ]

        for date in dates:
            create_transcription(create_submission(),
                                 user,
                                 create_time=make_aware(date))

        result = client.get(
            reverse("transcription-list") +
            "?create_time__gte=2021-02-01T00:00:00Z" +
            "&create_time__lte=2021-04-01T00:00:00Z",
            content_type="application/json",
            **headers,
        )

        assert result.status_code == status.HTTP_200_OK
        assert len(result.json()["results"]) == 2
    def test_failed_ocr_on_create(self, client: Client,
                                  settings: SettingsWrapper) -> None:
        """Verify that a new submission completes the OCR process."""
        settings.ENABLE_OCR = True
        settings.IMAGE_DOMAINS = ["example.com"]
        assert Transcription.objects.count() == 0

        client, headers, _ = setup_user_client(client)
        source = get_default_test_source()
        data = {
            "original_id": "spaaaaace",
            "source": source.pk,
            "content_url": "http://example.com/a.jpg",
        }

        with patch("api.models.process_image", return_value=None) as mock:
            result = client.post(
                reverse("submission-list"),
                data,
                content_type="application/json",
                **headers,
            )
            mock.assert_called_once()

        assert result.status_code == status.HTTP_201_CREATED
        assert Transcription.objects.count() == 0
        assert result.json().get("cannot_ocr") is True
    def test_create(self, client: Client) -> None:
        """Test whether the creation functions correctly when invoked correctly."""
        client, headers, user = setup_user_client(client)
        submission = create_submission()
        data = {
            "submission_id": submission.id,
            "username": user.username,
            "original_id": "ABC",
            "source": submission.source.name,
            "url": "https://example.com",
            "text": "test content",
        }

        result = client.post(
            reverse("transcription-list"),
            json.dumps(data),
            content_type="application/json",
            **headers,
        )

        assert result.status_code == status.HTTP_201_CREATED
        transcription = Transcription.objects.get(id=result.json()["id"])
        assert transcription.submission == submission
        assert transcription.source == submission.source
        assert transcription.author == user
        assert transcription.original_id == data["original_id"]
        assert transcription.url == data["url"]
        assert transcription.text == data["text"]
    def test_rate_count_aggregation(
        self,
        client: Client,
        data: List[Dict[str, Union[str, int]]],
        url_additions: str,
        different_result: List[Dict],
    ) -> None:
        """Test if the number of transcriptions per day is aggregated correctly."""
        client, headers, user = setup_user_client(client, id=123456)

        for obj in data:
            date = make_aware(
                datetime.strptime(obj.get("date"), "%Y-%m-%dT%H:%M:%SZ"))
            for _ in range(obj.get("count")):
                create_transcription(
                    create_submission(completed_by=user, complete_time=date),
                    user,
                    create_time=date,
                )
        if not url_additions:
            url_additions = "?completed_by=123456"
        else:
            url_additions += "&completed_by=123456"
        result = client.get(
            reverse("submission-rate") + url_additions,
            content_type="application/json",
            **headers,
        )
        assert result.status_code == status.HTTP_200_OK
        rates = result.json()["results"]
        if different_result:
            assert rates == different_result
        else:
            assert rates == data
    def test_create_with_tz_aware_timestamp(self, client: Client) -> None:
        """Test whether the creation functions correctly when invoked correctly."""
        # TODO: Remove me when we remove the ability to create with create_time variable
        client, headers, user = setup_user_client(client)
        submission = create_submission()
        timestamp = "2021-11-28T13:00:05.985314+00:00"
        data = {
            "submission_id": submission.id,
            "username": user.username,
            "original_id": "ABC",
            "create_time": timestamp,
            "source": submission.source.name,
            "url": "https://example.com",
            "text": "test content",
        }

        result = client.post(
            reverse("transcription-list"),
            json.dumps(data),
            content_type="application/json",
            **headers,
        )

        assert result.status_code == status.HTTP_201_CREATED
        transcription = Transcription.objects.get(id=result.json()["id"])
        assert transcription.create_time.isoformat() == timestamp
Beispiel #23
0
    def test_filtered_leaderboard(self, client: Client,) -> None:
        """Test if the submissions for the rate is calculated on are filtered."""
        BlossomUser.objects.all().delete()
        date_joined = datetime(2021, 11, 3, tzinfo=pytz.UTC)
        client, headers, user = setup_user_client(
            client, id=1, username="******", date_joined=date_joined, is_volunteer=True
        )

        # Submissions before filter
        for _ in range(4):
            create_submission(
                completed_by=user, complete_time=make_aware(datetime(2021, 11, 3))
            )
        # Submissions after filter
        for _ in range(7):
            create_submission(
                completed_by=user, complete_time=make_aware(datetime(2021, 11, 5))
            )

        results = client.get(
            reverse("submission-leaderboard")
            + "?user_id=1&complete_time__gte=2021-11-04T00:00:00Z",
            content_type="application/json",
            **headers,
        )

        assert results.status_code == status.HTTP_200_OK
        results = results.json()
        assert results["user"] == {
            "id": 1,
            "username": "******",
            "gamma": 7,
            "rank": 1,
            "date_joined": "2021-11-03T00:00:00Z",
        }
    def test_search_with_ordering_filter(
        self,
        client: Client,
        ordering: str,
        create_times: List[datetime],
        expected_times: List[datetime],
    ) -> None:
        """Verify that listing items with specified orderings works correctly."""
        client, headers, user = setup_user_client(client)

        for time in create_times:
            create_transcription(create_time=make_aware(time),
                                 submission=create_submission(),
                                 user=user)

        result = client.get(
            reverse("transcription-list") + f"?ordering={ordering}",
            content_type="application/json",
            **headers,
        )
        assert result.status_code == status.HTTP_200_OK

        result_times = [
            datetime.strptime(obj.get("create_time"), "%Y-%m-%dT%H:%M:%SZ")
            for obj in result.json()["results"]
        ]
        assert result_times == expected_times
Beispiel #25
0
    def test_list_with_filters(self, client: Client) -> None:
        """Verify that listing all submissions works correctly."""
        Source.objects.all().delete()  # clear out system ones for test
        client, headers, _ = setup_user_client(client)

        Source.objects.get_or_create(name="AAA")
        Source.objects.get_or_create(name="BBB")
        Source.objects.get_or_create(name="CCC")

        result = client.get(reverse("source-list"),
                            content_type="application/json",
                            **headers)

        assert result.status_code == status.HTTP_200_OK
        assert len(result.json()["results"]) == 3

        result = client.get(
            reverse("source-list") + "?name=AAA",
            content_type="application/json",
            **headers,
        )

        assert result.status_code == status.HTTP_200_OK
        assert len(result.json()["results"]) == 1
        assert result.json()["results"][0]["name"] == "AAA"
    def test_in_progress_custom_time(self, client: Client) -> None:
        """Verify that passing a different time changes the returned submissions."""
        client, headers, user = setup_user_client(client)
        reddit, _ = Source.objects.get_or_create(name="reddit")

        submission = create_submission(
            claimed_by=user,
            claim_time=timezone.now() - timezone.timedelta(hours=2),
            source=reddit,
        )

        # will default to four hours, should return nothing
        result = client.get(
            reverse("submission-in-progress") + "?source=reddit",
            content_type="application/json",
            **headers,
        )
        assert result.status_code == status.HTTP_200_OK
        assert len(result.json()) == 0

        # we'll set a custom hour and now we should get the submission
        result = client.get(
            reverse("submission-in-progress") + "?source=reddit&hours=1",
            content_type="application/json",
            **headers,
        )
        assert result.status_code == status.HTTP_200_OK
        assert len(result.json()) == 1
        assert result.json()[0]["id"] == submission.id
Beispiel #27
0
def test_find_in_progress(client: Client, url: str, expected: bool) -> None:
    """Verify that an in-progress posts can be found by its URLs."""
    client, headers, user = setup_user_client(client,
                                              id=123,
                                              username="******")

    submission = create_submission(
        claimed_by=user,
        url="https://reddit.com/r/antiwork/comments/q1tlcf/work_is_work/",
        tor_url=
        "https://reddit.com/r/TranscribersOfReddit/comments/q1tnhc/antiwork_image_work_is_work/",
        content_url="https://i.redd.it/upwchc4bqhr71.jpg",
        title="Work is work",
    )

    result = client.get(
        reverse("find") + f"?url={url}",
        content_type="application/json",
        **headers,
    )

    if expected:
        assert result.status_code == status.HTTP_200_OK
        actual = result.json()

        assert actual["submission"]["id"] == submission.id
        assert actual["author"]["id"] == user.id
    else:
        assert result.status_code == status.HTTP_404_NOT_FOUND
Beispiel #28
0
    def test_transcribot_limit_param(self, client: Client) -> None:
        """Verify that adding the `limit` QSP modifies the results."""
        client, headers, _ = setup_user_client(client)
        user_model = get_user_model()
        transcribot = user_model.objects.get(username="******")

        submission1 = create_submission(source="reddit", original_id="A")
        submission2 = create_submission(source="reddit", original_id="B")
        submission3 = create_submission(source="reddit", original_id="C")

        create_transcription(submission1, transcribot, original_id=None)
        create_transcription(submission2, transcribot, original_id=None)
        create_transcription(submission3, transcribot, original_id=None)

        result = client.get(
            reverse("submission-get-transcribot-queue") +
            "?source=reddit&limit=none",
            content_type="application/json",
            **headers,
        ).json()

        assert len(result["data"]) == 3

        result = client.get(
            reverse("submission-get-transcribot-queue") +
            "?source=reddit&limit=1",
            content_type="application/json",
            **headers,
        ).json()

        assert len(result["data"]) == 1
        assert result["data"][0]["id"] == submission1.id
Beispiel #29
0
    def test_get_transcribot_queue(self, client: Client) -> None:
        """Test that the OCR queue endpoint returns the correct data."""
        client, headers, _ = setup_user_client(client)
        user_model = get_user_model()
        transcribot = user_model.objects.get(username="******")

        result = client.get(
            reverse("submission-get-transcribot-queue") + "?source=reddit",
            content_type="application/json",
            **headers,
        ).json()

        assert len(result["data"]) == 0  # there are no posts to work on

        submission = create_submission(source="reddit")

        result = client.get(
            reverse("submission-get-transcribot-queue") + "?source=reddit",
            content_type="application/json",
            **headers,
        ).json()

        # now there's a submission without a transcribot transcription
        assert len(result["data"]) == 0
        create_transcription(submission, transcribot, original_id=None)

        result = client.get(
            reverse("submission-get-transcribot-queue") + "?source=reddit",
            content_type="application/json",
            **headers,
        ).json()

        # now the submission has a transcribot entry
        assert len(result["data"]) == 1
Beispiel #30
0
    def test_yeet_with_no_user(self, client: Client) -> None:
        """Verify that yeeting without a count only deletes one."""
        client, headers, user = setup_user_client(client)

        response = client.post(reverse("submission-yeet"),
                               content_type="application/json",
                               **headers)
        assert response.status_code == 400