From 7384394cc1789fcfc7369fa6f2c4274e87f91947 Mon Sep 17 00:00:00 2001 From: kovalch Date: Mon, 1 Jul 2024 11:28:56 +0200 Subject: [PATCH 1/3] fix: Temporary remove recaptcha tests --- ckanext/subscribe/tests/test_action.py | 97 -------------------------- 1 file changed, 97 deletions(-) diff --git a/ckanext/subscribe/tests/test_action.py b/ckanext/subscribe/tests/test_action.py index b4ff683..985d108 100644 --- a/ckanext/subscribe/tests/test_action.py +++ b/ckanext/subscribe/tests/test_action.py @@ -223,103 +223,6 @@ def test_dataset_and_group_at_same_time(self, send_request_email): assert not send_request_email.called - # Adding the reCAPTCHA tests - @mock.patch("requests.post") - def test_verify_recaptcha_success(self, mock_post): - mock_post.return_value = mock.Mock(status_code=200) - mock_post.return_value.json.return_value = {"success": True} - - response = helpers.call_action( - "subscribe_signup", - {}, - email="bob@example.com", - dataset_id=factories.Dataset()["id"], - __extras={"g-recaptcha-response": "test-recaptcha-response"}, - ) - assert "email" in response - - @mock.patch("requests.post") - def test_verify_recaptcha_failure(self, mock_post): - mock_post.return_value = mock.Mock(status_code=200) - mock_post.return_value.json.return_value = {"success": False} - - with assert_raises(ValidationError): - helpers.call_action( - "subscribe_signup", - {}, - email="bob@example.com", - dataset_id=factories.Dataset()["id"], - __extras={"g-recaptcha-response": "test-recaptcha-response"}, - ) - - @mock.patch("requests.post") - @mock.patch("ckanext.subscribe.email_verification.send_request_email") - def test_recaptcha_frontend_form(self, mock_post, send_request_email): - mock_post.return_value = mock.Mock(status_code=200) - mock_post.return_value.json.return_value = {"success": True} - - dataset = factories.Dataset() - - subscription = helpers.call_action( - "subscribe_signup", - {}, - email="bob@example.com", - dataset_id=dataset["id"], - __extras={"g-recaptcha-response": "test-recaptcha-response"}, - ) - - send_request_email.assert_called_once() - eq(send_request_email.call_args[0][0].object_type, "dataset") - eq(send_request_email.call_args[0][0].object_id, dataset["id"]) - eq(send_request_email.call_args[0][0].email, "bob@example.com") - eq(subscription["object_type"], "dataset") - eq(subscription["object_id"], dataset["id"]) - eq(subscription["email"], "bob@example.com") - eq(subscription["verified"], False) - assert "verification_code" not in subscription - subscription_obj = model.Session.query(Subscription).get(subscription["id"]) - assert subscription_obj - - # Verify that 'g-recaptcha-response' was passed in __extras - extras = subscription["__extras"] - assert "g-recaptcha-response" in extras - eq(extras["g-recaptcha-response"], "test-recaptcha-response") - - -@mock.patch("requests.post") -@mock.patch("ckanext.subscribe.email_verification.send_request_email") -@mock.patch("ckan.plugins.toolkit.request") -def test_recaptcha_backend_form(self, mock_request, mock_post, send_request_email): - mock_post.return_value = mock.Mock(status_code=200) - mock_post.return_value.json.return_value = {"success": True} - - # Mock the request parameters to include g-recaptcha-response - mock_request.params = {"g-recaptcha-response": "test-recaptcha-response"} - - dataset = factories.Dataset() - - subscription = helpers.call_action( - "subscribe_signup", - {}, - email="bob@example.com", - dataset_id=dataset["id"], - ) - - send_request_email.assert_called_once() - eq(send_request_email.call_args[0][0].object_type, "dataset") - eq(send_request_email.call_args[0][0].object_id, dataset["id"]) - eq(send_request_email.call_args[0][0].email, "bob@example.com") - eq(subscription["object_type"], "dataset") - eq(subscription["object_id"], dataset["id"]) - eq(subscription["email"], "bob@example.com") - eq(subscription["verified"], False) - assert "verification_code" not in subscription - subscription_obj = model.Session.query(Subscription).get(subscription["id"]) - assert subscription_obj - - # Verify that 'g-recaptcha-response' was passed in request params - eq(mock_request.params.get("g-recaptcha-response"), "test-recaptcha-response") - class TestSubscribeVerify(object): def setup(self): From e27cb2a46359a028068de4f75f5801a75b002602 Mon Sep 17 00:00:00 2001 From: kovalch Date: Mon, 1 Jul 2024 13:46:25 +0200 Subject: [PATCH 2/3] fix: For tests handle potential transient issues --- .github/workflows/test.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5d1e1af..02adaa2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -73,4 +73,9 @@ jobs: run: | # Upgrade certi to fix SSL error due to the version installed in CKAN-2.8 image pip install --upgrade certifi - coveralls + # Run coveralls command with retry logic to handle potential transient issues + for attempt in 1 2 3; do + coveralls && break + echo "Attempt $attempt: Failed to submit coverage, retrying in 10 seconds..." + sleep 10 + done From e6bfac9e009c81cb15f722b13bac2726bdd69f4e Mon Sep 17 00:00:00 2001 From: kovalch Date: Mon, 1 Jul 2024 19:51:08 +0200 Subject: [PATCH 3/3] feat: Add tests for recaptcha_failure and recaptcha_success Create a new class and set apply_recaptcha to true Add teardown to not use apply_recaptcha in next tests --- ckanext/subscribe/tests/test_action.py | 81 ++++++++++++++++++++++++++ test.ini | 2 +- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/ckanext/subscribe/tests/test_action.py b/ckanext/subscribe/tests/test_action.py index 985d108..f2d8e08 100644 --- a/ckanext/subscribe/tests/test_action.py +++ b/ckanext/subscribe/tests/test_action.py @@ -2,6 +2,7 @@ import datetime +import ckan.plugins.toolkit as tk import mock from ckan import model from ckan.plugins.toolkit import ValidationError @@ -224,6 +225,86 @@ def test_dataset_and_group_at_same_time(self, send_request_email): assert not send_request_email.called +# The reCAPTCHA tests +class TestRecaptchaOfSubscribeSignup(object): + def setup(self): + helpers.reset_db() + tk.config["ckanext.subscribe.apply_recaptcha"] = "true" + + def teardown(self): + tk.config["ckanext.subscribe.apply_recaptcha"] = "false" + + # mock the _verify_recaptcha function and test both + # successful and unsuccessful reCAPTCHA verification scenarios + @mock.patch("requests.post") + @mock.patch("ckanext.subscribe.email_verification.send_request_email") + @mock.patch("ckanext.subscribe.action._verify_recaptcha") + def test_verify_recaptcha_success( + self, mock_verify_recaptcha, send_request_email, mock_post + ): + # Mocking the reCAPTCHA verification to return True + mock_verify_recaptcha.return_value = True + mock_post.return_value = mock.Mock( + status_code=200, json=lambda: {"success": True} + ) + + dataset = factories.Dataset() + + # Calling the subscribe_signup action with a mock reCAPTCHA response + subscription = helpers.call_action( + "subscribe_signup", + {}, + email="bob@example.com", + dataset_id=dataset["id"], + g_recaptcha_response="test-recaptcha-response", + ) + + # Asserting that the email verification function was called once + send_request_email.assert_called_once() + eq(send_request_email.call_args[0][0].object_type, "dataset") + eq(send_request_email.call_args[0][0].object_id, dataset["id"]) + eq(send_request_email.call_args[0][0].email, "bob@example.com") + + # Asserting that the subscription was created with the correct details + eq(subscription["object_type"], "dataset") + eq(subscription["object_id"], dataset["id"]) + eq(subscription["email"], "bob@example.com") + eq(subscription["verified"], False) + assert "verification_code" not in subscription + + # Checking that the subscription object exists in the database + subscription_obj = model.Session.query(subscribe_model.Subscription).get( + subscription["id"] + ) + assert subscription_obj + + @mock.patch("ckanext.subscribe.email_verification.send_request_email") + @mock.patch("ckanext.subscribe.action._verify_recaptcha") + def test_verify_recaptcha_failure(self, mock_verify_recaptcha, send_request_email): + # Mocking the reCAPTCHA verification to return False + mock_verify_recaptcha.return_value = False + + dataset = factories.Dataset() + + # Attempting to call subscribe_signup action with an invalid reCAPTCHA + try: + helpers.call_action( + "subscribe_signup", + {}, + email="bob@example.com", + dataset_id=dataset["id"], + g_recaptcha_response="wrong_recaptcha", + ) + except ValidationError as e: + # Asserting that the error is raised with the correct message + assert "Invalid reCAPTCHA. Please try again." in str(e.error_dict) + + # Ensuring the email is not sent due to invalid reCAPTCHA + assert not send_request_email.called + else: + assert False, "ValidationError not raised" + + class TestSubscribeVerify(object): def setup(self): helpers.reset_db() diff --git a/test.ini b/test.ini index 2d61a4e..6f784b3 100644 --- a/test.ini +++ b/test.ini @@ -9,7 +9,7 @@ host = 0.0.0.0 port = 5000 [app:main] -use = config:/usr/lib/ckan/venv/src/ckan/test-core.ini +use = config:../ckan/test-core.ini # Insert any custom config settings to be used when running your extension's # tests here.