def test_done_random_checks( self, client: Client, settings: SettingsWrapper, probability: float, gamma: int, message: bool, tor_url: [str, None], trans_url: [str, None], ) -> None: """Test whether the random checks for the done process are invoked correctly.""" # Mock both the gamma property and the random.random function. with patch("authentication.models.BlossomUser.gamma", new_callable=PropertyMock) as mock, patch( "api.views.submission._is_returning_transcriber", return_value=False), patch("random.random", lambda: probability): mock.return_value = gamma # Mock the Slack client to catch the sent messages by the function under test. slack_client.chat_postMessage = MagicMock() client, headers, user = setup_user_client(client) submission = create_submission(tor_url=tor_url, claimed_by=user) create_transcription(submission, user, url=trans_url) result = client.patch( reverse("submission-done", args=[submission.id]), json.dumps({"username": user.username}), content_type="application/json", **headers, ) slack_message = ( f"Please check the following transcription of u/{user.username}: " f"{trans_url if trans_url else tor_url}.") assert result.status_code == status.HTTP_201_CREATED if message: assert (call( channel=settings.SLACK_TRANSCRIPTION_CHECK_CHANNEL, text=slack_message, ) in slack_client.chat_postMessage.call_args_list) else: assert slack_client.chat_postMessage.call_count == 0
def test_list_with_filters(self, client: Client) -> None: """Verify that listing all submissions works correctly.""" client, headers, _ = setup_user_client(client) aaa, _ = Source.objects.get_or_create(name="AAA") bbb, _ = Source.objects.get_or_create(name="BBB") create_submission(source=aaa) create_submission(source=aaa) create_submission(source=bbb) create_submission(source=bbb) result = client.get( reverse("submission-list"), content_type="application/json", **headers ) assert result.status_code == status.HTTP_200_OK assert len(result.json()["results"]) == 4 result = client.get( reverse("submission-list") + "?source=AAA", content_type="application/json", **headers, ) assert result.status_code == status.HTTP_200_OK assert len(result.json()["results"]) == 2 assert "AAA" in result.json()["results"][0]["source"] # it will be a full link result = client.get( reverse("submission-list") + "?source=AAA&id=1", content_type="application/json", **headers, ) assert result.status_code == status.HTTP_200_OK assert len(result.json()["results"]) == 1 assert "AAA" in result.json()["results"][0]["source"] # it will be a full link assert result.json()["results"][0]["id"] == 1
def test_nsfw_no_change(self, client: Client) -> None: """Verify that setting a submission NSFW twice doesn't change anything.""" client, headers, user = setup_user_client(client) submission = create_submission(id=3, nsfw=True) assert submission.nsfw data = {} result = client.patch( reverse("submission-nsfw", args=[submission.id]), json.dumps(data), content_type="application/json", **headers ) submission.refresh_from_db() assert result.status_code == status.HTTP_200_OK assert submission.nsfw
def test_reported_post_is_removed(self, client: Client) -> None: """Verify that a reported post is not brought back to the page.""" client, _, user = setup_user_client(client) add_social_auth_to_user(user) submission = create_submission( original_id=int(random.random() * 1000), title="a", content_url="http://imgur.com", ) response = client.get(reverse("choose_transcription")) assert submission in response.context["options"] # Now we'll report it and verify that it's not rolled anymore client.get( reverse("app_report", kwargs={"submission_id": submission.id})) response = client.get(reverse("choose_transcription")) assert submission not in response.context["options"]
def test_remove_param_true(self, client: Client) -> None: """Verify that marking a submission as NSFW works with parameters.""" client, headers, user = setup_user_client(client) submission = create_submission(id=3) assert not submission.nsfw data = {"nsfw": True} result = client.patch( reverse("submission-nsfw", args=[submission.id]), json.dumps(data), content_type="application/json", **headers ) submission.refresh_from_db() assert result.status_code == status.HTTP_200_OK assert submission.nsfw
def test_unarchived_old_unarchived(self, client: Client) -> None: """Test whether an unarchived old post is returned correctly.""" client, headers, user = setup_user_client(client) reddit, _ = Source.objects.get_or_create(name="reddit") submission = create_submission( completed_by=user, complete_time=timezone.now() - timezone.timedelta(hours=1), archived=False, source=reddit, ) result = client.get( reverse("submission-unarchived") + "?source=reddit", 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
def test_yeet_also_removes_linked_transcription(self, client: Client) -> None: """Verify that a linked transcription also gets yeeted.""" client, headers, user = setup_user_client(client) submission = create_submission(original_id=str(uuid4()), completed_by=user) create_transcription(submission, user) assert Submission.objects.count() == 1 assert Transcription.objects.count() == 1 data = {"username": user.username} client.post(reverse("submission-yeet"), json.dumps(data), content_type="application/json", **headers) assert Submission.objects.count() == 0 assert Transcription.objects.count() == 0
def test_post_formatting_errors(self, client: Client) -> None: """Verify that correctable formatting issues are handled.""" 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, ) client.post( reverse("transcribe_submission", kwargs={"submission_id": submission.id}), data={ "transcription": "u/aaa ! Check this out!\n```\nabcde\n```\n\nayy" }, ) assert "`" not in Transcription.objects.first().text assert "\\/" in Transcription.objects.first().text
def test_report_already_removed(self, client: Client) -> None: """Verify that reporting an already removed submission doesn't do anything.""" slack_client.chat_postMessage = MagicMock() client, headers, user = setup_user_client(client) submission = create_submission(id=3, removed_from_queue=True) assert submission.removed_from_queue 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 submission.removed_from_queue assert slack_client.chat_postMessage.call_count == 0
def test_list(self, client: Client) -> None: """Test that the primary API page for transcriptions works correctly.""" client, headers, user = setup_user_client(client) submission = create_submission() result = client.get(reverse("transcription-list"), content_type="application/json", **headers) assert result.status_code == status.HTTP_200_OK assert result.json()["count"] == 0 create_transcription(submission, user) result = client.get(reverse("transcription-list"), content_type="application/json", **headers) assert result.status_code == status.HTTP_200_OK assert result.json()["count"] == 1 assert result.json()["results"][0]["id"] == 1
def test_approve_reverting_removal(self, client: Client) -> None: """Verify that approving a submission reverts its removal.""" client, headers, user = setup_user_client(client) submission = create_submission(id=3, removed_from_queue=True) assert not submission.approved assert submission.removed_from_queue data = {} result = client.patch(reverse("submission-approve", args=[submission.id]), json.dumps(data), content_type="application/json", **headers) submission.refresh_from_db() assert result.status_code == status.HTTP_200_OK assert submission.approved assert not submission.removed_from_queue
def test_completed_ocr_transcriptions(self, client: Client) -> None: """Test that a completed transcription removes the submission from the queue.""" client, headers, _ = setup_user_client(client) user_model = get_user_model() transcribot = user_model.objects.get(username="******") submission = create_submission(source="reddit") result = client.get( reverse("submission-get-transcribot-queue") + "?source=reddit", content_type="application/json", **headers, ).json() assert len(result["data"]) == 0 transcription = create_transcription(submission, transcribot, original_id=None) result = client.get( reverse("submission-get-transcribot-queue") + "?source=reddit", content_type="application/json", **headers, ).json() # now there's a transcription that needs work assert len(result["data"]) == 1 # transcribot works on it transcription.original_id = "AAA" transcription.save() result = client.get( reverse("submission-get-transcribot-queue") + "?source=reddit", content_type="application/json", **headers, ).json() # Queue goes back to 0. assert len(result["data"]) == 0
def test_image_proxies(self, client: Client) -> None: """Verify that the transcription page loads as expected.""" client, _, user = setup_user_client(client) add_social_auth_to_user(user) # Imgur direct link submission = create_submission( original_id=int(random.random() * 1000), content_url="http://imgur.com/aaa.png", title="a", ) response = client.get( reverse("transcribe_submission", kwargs={"submission_id": submission.id})) assert "imgur_content_url" in response.context assert response.context["imgur_content_url"] == "aaa.png" # Imgur post link submission.claimed_by = None submission.content_url = "http://imgur.com/aaa" submission.save() response = client.get( reverse("transcribe_submission", kwargs={"submission_id": submission.id})) assert "imgur_content_url" in response.context assert response.context["imgur_content_url"] == "aaa.jpg" # Reddit link submission.claimed_by = None submission.content_url = "i.redd.it/bbb" submission.save() response = client.get( reverse("transcribe_submission", kwargs={"submission_id": submission.id})) assert "ireddit_content_url" in response.context assert response.context["ireddit_content_url"] == "bbb"
def test_unclaim_errors(client: Client, error: int, expected_redirect: str) -> None: """Verify that errors redirect as they should.""" client, _, user = setup_user_client(client) add_social_auth_to_user(user) submission = create_submission(claimed_by=user) class Response: ... response = Response() response.status_code = error with patch("api.views.submission.SubmissionViewSet.unclaim", lambda a, b, c: response): response = client.get( reverse("app_unclaim", kwargs={"submission_id": submission.id})) assert reverse(expected_redirect) in response.url # the unclaim should not have succeeded assert submission.claimed_by == user
def test_pagination(self, client: Client) -> None: """Verify that pagination parameters properly change response.""" client, headers, user = setup_user_client(client, id=123456) for day in range(1, 4): date = make_aware(datetime(2021, 6, day)) create_transcription( create_submission(completed_by=user, complete_time=date), user, create_time=date, ) result = client.get( reverse("submission-rate") + "?page_size=1&page=2&completed_by=123456", content_type="application/json", **headers, ) assert result.status_code == status.HTTP_200_OK response = result.json() assert len(response["results"]) == 1 assert response["results"][0]["date"] == "2021-06-02T00:00:00Z" assert response["previous"] is not None assert response["next"] is not None
def test_done_no_coc(self, client: Client) -> None: """# noqa Test that a submission isn't marked as done when the CoC hasn't been accepted. """ client, headers, user = setup_user_client(client) submission = create_submission(claimed_by=user) user.accepted_coc = False user.save() create_transcription(submission, user) data = {"username": user.username} result = client.patch( reverse("submission-done", args=[submission.id]), json.dumps(data), content_type="application/json", **headers, ) submission.refresh_from_db() assert result.status_code == status.HTTP_403_FORBIDDEN assert submission.claimed_by == user assert submission.completed_by is None
def test_post_session(self, client: Client) -> None: """Verify that the session gets set appropriately if errors arise.""" 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, ) response = client.post( reverse("transcribe_submission", kwargs={"submission_id": submission.id}), data={"transcription": "#aaa"}, ) assert (reverse("transcribe_submission", kwargs={"submission_id": submission.id}) in response.url) assert response.wsgi_request.session["transcription"] == "#aaa" assert response.wsgi_request.session["submission_id"] == submission.id assert response.wsgi_request.session["heading"] is None
def test_post(self, client: Client) -> None: """Verify that posting a valid transcription completes the process.""" 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/aaa", title="a", claimed_by=user, ) assert submission.completed_by is None response = client.post( reverse("transcribe_submission", kwargs={"submission_id": submission.id}), data={"transcription": "AAA"}, ) submission.refresh_from_db() assert reverse("choose_transcription") in response.url assert submission.completed_by == user assert Transcription.objects.count() == 1
def test_get_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", ) class Response: ... response = Response() response.status_code = error with patch("api.views.submission.SubmissionViewSet.claim", lambda a, b, c: response): response = client.get( reverse("transcribe_submission", kwargs={"submission_id": submission.id})) assert reverse(expected_redirect) in response.url
def test_normal_transcriptions_dont_affect_ocr_queue( self, client: Client) -> None: """Verify that a human-completed transcription doesn't affect the OCR queue.""" client, headers, user = setup_user_client(client) submission = create_submission(source="reddit") result = client.get( reverse("submission-get-transcribot-queue") + "?source=reddit", content_type="application/json", **headers, ).json() assert len(result["data"]) == 0 create_transcription(submission, user) result = client.get( reverse("submission-get-transcribot-queue") + "?source=reddit", content_type="application/json", **headers, ).json() # there should be no change to the OCR queue assert len(result["data"]) == 0
def test_list_with_contains_filters( self, client: Client, filter_str: str, result_count: int ) -> None: """Verify that the title can be searched.""" client, headers, user = setup_user_client(client, id=123) create_submission( id=1, title="This is a title", ) create_submission( id=2, title="Another title", ) create_submission( id=3, title="TITLE IS GOOD", ) 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
def test_send_transcription_to_slack(self, client: Client, settings: SettingsWrapper) -> None: """Verify that a new user gets a different welcome message.""" # Mock both the gamma property and the random.random function. with patch("authentication.models.BlossomUser.gamma", new_callable=PropertyMock) as mock: mock.return_value = 0 # Mock the Slack client to catch the sent messages by the function under test. slack_client.chat_postMessage = MagicMock() client, headers, user = setup_user_client(client) submission = create_submission(tor_url="asdf", claimed_by=user) create_transcription(submission, user, url=None) result = client.patch( reverse("submission-done", args=[submission.id]), json.dumps({"username": user.username}), content_type="application/json", **headers, ) first_slack_message = ( f":rotating_light: First transcription! :rotating_light:" f" Please check the following transcription of u/{user.username}:" f" asdf.") second_slack_message = ( f"Please check the following transcription of u/{user.username}:" f" asdf.") check_slack_message = ( f"Please check the following transcription of u/{user.username}:" f" asdf.\n\nThis user is being watched with a chance of 100%.\n" f"Undo this using the `unwatch {user.username}` command.") assert result.status_code == status.HTTP_201_CREATED assert (call( channel=settings.SLACK_TRANSCRIPTION_CHECK_CHANNEL, text=first_slack_message, ) == slack_client.chat_postMessage.call_args_list[0]) submission.refresh_from_db() submission.completed_by = None submission.save() mock.return_value = 1 result = client.patch( reverse("submission-done", args=[submission.id]), json.dumps({"username": user.username}), content_type="application/json", **headers, ) assert result.status_code == status.HTTP_201_CREATED assert (call( channel=settings.SLACK_TRANSCRIPTION_CHECK_CHANNEL, text=second_slack_message, ) == slack_client.chat_postMessage.call_args_list[-1]) submission.refresh_from_db() submission.completed_by = None submission.save() user.overwrite_check_percentage = 1 user.save() result = client.patch( reverse("submission-done", args=[submission.id]), json.dumps({"username": user.username}), content_type="application/json", **headers, ) assert result.status_code == status.HTTP_201_CREATED assert (call( channel=settings.SLACK_TRANSCRIPTION_CHECK_CHANNEL, text=check_slack_message, ) == slack_client.chat_postMessage.call_args_list[-1])