Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 27 additions & 61 deletions buzz/api/account/test_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from frappe.utils import set_request

from buzz.api.account import (
get_enabled_languages,
get_translations,
get_user_info,
update_user_language,
Expand All @@ -17,14 +16,7 @@


class LanguageTestCase(IntegrationTestCase):
"""Base for the tests that exercise language resolution.

`get_language` reads cookies and headers off the live request, which a test
process does not have until one is installed.
"""

def tearDown(self):
frappe.set_user("Administrator")
"""`get_language` reads cookies and headers off the live request, which a test process lacks."""

def install_request(self, cookies: dict[str, str] | None = None, accept_language: str = ""):
headers = {}
Expand All @@ -37,11 +29,7 @@ def install_request(self, cookies: dict[str, str] | None = None, accept_language
self.addCleanup(setattr, frappe.local, "request", None)

def other_enabled_language(self) -> str:
"""An enabled language that is not the site default.

Plain codes only: a regional one like `pt-BR` comes back as a different
string once werkzeug has parsed the Accept-Language header.
"""
"""Plain codes only: werkzeug rewrites a regional one like `pt-BR` when it parses the header."""
for language in get_all_languages():
if language != get_default_language() and language.isalpha():
return language
Expand All @@ -57,24 +45,24 @@ def set_user_language(self, language: str | None):
class TestGetUserInfo(LanguageTestCase):
def test_guest_payload_keys(self):
self.install_request()
frappe.set_user("Guest")
info = get_user_info().__json__()
with self.set_user("Guest"):
info = get_user_info().__json__()

self.assertEqual(set(info), {"is_logged_in", "brand_image", "language"})
self.assertFalse(info["is_logged_in"])

def test_guest_language_follows_the_preferred_language_cookie(self):
language = self.other_enabled_language()
self.install_request(cookies={"preferred_language": language})
frappe.set_user("Guest")

self.assertEqual(get_user_info().__json__()["language"], language)
with self.set_user("Guest"):
self.assertEqual(get_user_info().__json__()["language"], language)

def test_guest_language_falls_back_to_the_site_default(self):
self.install_request()
frappe.set_user("Guest")

self.assertEqual(get_user_info().__json__()["language"], get_default_language())
with self.set_user("Guest"):
self.assertEqual(get_user_info().__json__()["language"], get_default_language())

def test_logged_in_payload_shape(self):
info = get_user_info().__json__()
Expand All @@ -99,20 +87,8 @@ def test_logged_in_payload_shape(self):
self.assertTrue(info["is_logged_in"])
self.assertEqual(info["name"], "Administrator")

def test_roles_stay_child_table_rows(self):
roles = get_user_info().__json__()["roles"]

self.assertTrue(roles)
self.assertTrue(any(row.role == "Administrator" for row in roles))


class TestLanguages(LanguageTestCase):
def test_enabled_languages_shape(self):
languages = [language.__json__() for language in get_enabled_languages()]

self.assertTrue(languages)
self.assertEqual(set(languages[0]), {"name", "language_name", "language_code"})

def test_update_rejects_unknown_language(self):
frappe.clear_messages()

Expand All @@ -123,9 +99,6 @@ def test_update_rejects_unknown_language(self):
self.assertEqual(message["title"], "Language Not Available")
self.assertIn("not-a-language", message["message"])

def test_unknown_language_maps_to_400(self):
self.assertEqual(UnknownLanguage.http_status_code, 400)

def test_update_persists_language(self):
self.set_user_language(None)

Expand All @@ -139,14 +112,6 @@ def test_update_stays_closed_to_guests(self):


class TestTimezones(IntegrationTestCase):
def tearDown(self):
frappe.set_user("Administrator")

def set_user_timezone(self, time_zone: str | None):
original = frappe.db.get_value("User", "Administrator", "time_zone")
self.addCleanup(frappe.db.set_value, "User", "Administrator", "time_zone", original)
frappe.db.set_value("User", "Administrator", "time_zone", time_zone)

def test_update_rejects_unknown_timezone(self):
frappe.clear_messages()

Expand All @@ -157,9 +122,6 @@ def test_update_rejects_unknown_timezone(self):
self.assertEqual(message["title"], "Timezone Not Available")
self.assertIn("Mars/Olympus_Mons", message["message"])

def test_unknown_timezone_maps_to_400(self):
self.assertEqual(UnknownTimezone.http_status_code, 400)

def test_update_persists_timezone(self):
self.set_user_timezone(None)

Expand All @@ -168,7 +130,6 @@ def test_update_persists_timezone(self):
self.assertEqual(frappe.db.get_value("User", "Administrator", "time_zone"), "Asia/Kolkata")

def test_update_accepts_utc(self):
"""The dashboard's picker puts UTC at the top of the list."""
self.set_user_timezone(None)

update_user_timezone("UTC")
Expand All @@ -179,35 +140,32 @@ def test_update_stays_closed_to_guests(self):
self.assertIn(update_user_timezone, frappe.whitelisted)
self.assertNotIn(update_user_timezone, frappe.guest_methods)

def set_user_timezone(self, time_zone: str | None):
original = frappe.db.get_value("User", "Administrator", "time_zone")
self.addCleanup(frappe.db.set_value, "User", "Administrator", "time_zone", original)
frappe.db.set_value("User", "Administrator", "time_zone", time_zone)

class TestGetTranslations(LanguageTestCase):
def resolved_language(self) -> str:
"""The language get_translations picked, without loading any."""
with patch("buzz.api.account.get_all_translations", return_value={}) as translations:
get_translations()

translations.assert_called_once()
return translations.call_args.args[0]

class TestGetTranslations(LanguageTestCase):
def test_guest_translations_follow_the_preferred_language_cookie(self):
language = self.other_enabled_language()
self.install_request(cookies={"preferred_language": language})
frappe.set_user("Guest")

self.assertEqual(self.resolved_language(), language)
with self.set_user("Guest"):
self.assertEqual(self.resolved_language(), language)

def test_guest_translations_fall_back_to_the_accept_language_header(self):
language = self.other_enabled_language()
self.install_request(accept_language=language)
frappe.set_user("Guest")

self.assertEqual(self.resolved_language(), language)
with self.set_user("Guest"):
self.assertEqual(self.resolved_language(), language)

def test_guest_translations_fall_back_to_the_site_default(self):
self.install_request()
frappe.set_user("Guest")

self.assertEqual(self.resolved_language(), get_default_language())
with self.set_user("Guest"):
self.assertEqual(self.resolved_language(), get_default_language())

def test_logged_in_translations_follow_the_user_document(self):
language = self.other_enabled_language()
Expand All @@ -219,3 +177,11 @@ def test_a_user_without_a_language_gets_the_site_default(self):
self.set_user_language(None)

self.assertEqual(self.resolved_language(), get_default_language())

def resolved_language(self) -> str:
"""The language get_translations picked, without loading any."""
with patch("buzz.api.account.get_all_translations", return_value={}) as translations:
get_translations()

translations.assert_called_once()
return translations.call_args.args[0]
38 changes: 6 additions & 32 deletions buzz/api/auth/test_auth.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,17 @@
import frappe
from frappe.tests import IntegrationTestCase

from buzz.api.auth import get_login_context


class TestGetLoginContext(IntegrationTestCase):
def tearDown(self):
frappe.set_user("Administrator")

def test_returns_expected_keys(self):
context = get_login_context().__json__()
self.assertEqual(
set(context),
{
"disable_signup",
"disable_user_pass_login",
"login_with_email_link",
"login_banner",
"provider_logins",
},
)

def test_settings_flags_stay_integers(self):
context = get_login_context().__json__()
for key in ("disable_signup", "disable_user_pass_login", "login_with_email_link"):
self.assertIsInstance(context[key], int)

def test_banner_is_rendered_as_html(self):
frappe.db.set_single_value("Buzz Settings", "login_banner", "# Welcome")
self.addCleanup(frappe.db.set_single_value, "Buzz Settings", "login_banner", None)

self.assertIn("<h1", get_login_context().__json__()["login_banner"])
with self.change_settings("Buzz Settings", login_banner="# Welcome"):
self.assertIn("<h1", get_login_context().__json__()["login_banner"])

def test_banner_is_none_when_unset(self):
frappe.db.set_single_value("Buzz Settings", "login_banner", None)

self.assertIsNone(get_login_context().__json__()["login_banner"])
with self.change_settings("Buzz Settings", login_banner=None):
self.assertIsNone(get_login_context().__json__()["login_banner"])

def test_available_to_guest(self):
frappe.set_user("Guest")

self.assertIsInstance(get_login_context().__json__()["provider_logins"], list)
with self.set_user("Guest"):
self.assertIsInstance(get_login_context().__json__()["provider_logins"], list)
34 changes: 3 additions & 31 deletions buzz/api/campaigns/test_campaigns.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,22 @@
from frappe.tests import IntegrationTestCase

from buzz.api.campaigns import get_campaign_details
from buzz.api.campaigns.exceptions import AlreadyRegistered, CampaignNotActive, CRMNotAvailable
from buzz.api.campaigns.exceptions import CampaignNotActive
from buzz.tests.factories.events.buzz_campaign_factory import BuzzCampaignFactory
from buzz.utils import is_app_installed


def make_campaign(enabled: int = 1) -> str:
# Buzz Campaign uses autoname "prompt" -> name set explicitly.
campaign = frappe.new_doc("Buzz Campaign")
campaign.name = f"Campaign {frappe.generate_hash(length=6)}"
campaign.title = campaign.name
campaign.description = "Interest list for the next edition"
campaign.enabled = enabled
campaign.insert(ignore_permissions=True)
return campaign.name


class TestCampaignErrors(IntegrationTestCase):
def test_unknown_campaign_raises_not_found(self):
with self.assertRaises(frappe.DoesNotExistError):
get_campaign_details("no-such-campaign")

def test_status_codes(self):
self.assertEqual(CampaignNotActive.http_status_code, 409)
self.assertEqual(AlreadyRegistered.http_status_code, 409)
self.assertEqual(CRMNotAvailable.http_status_code, 400)

def test_each_error_carries_its_own_copy(self):
titles = {str(error.title) for error in (CampaignNotActive, AlreadyRegistered, CRMNotAvailable)}

self.assertEqual(len(titles), 3)


# Buzz Campaign refuses to save unless Frappe CRM is installed.
@unittest.skipUnless(is_app_installed("crm"), "requires the crm app")
class TestGetCampaignDetails(IntegrationTestCase):
def tearDown(self):
frappe.set_user("Administrator")

def test_returns_expected_keys(self):
details = get_campaign_details(make_campaign()).__json__()

self.assertEqual(set(details), {"title", "description", "event"})

def test_disabled_campaign_reports_its_message(self):
campaign = make_campaign(enabled=0)
campaign = BuzzCampaignFactory.create(enabled=0).name
frappe.clear_messages()

with self.assertRaises(CampaignNotActive):
Expand Down
Loading
Loading