feat: multi-module improvements across merchant, store, i18n, and customer systems
All checks were successful
All checks were successful
- Fix platform-grouped merchant sidebar menu with core items at root level - Add merchant store management (detail page, create store, team page) - Fix store settings 500 error by removing dead stripe/API tab - Move onboarding translations to module-owned locale files - Fix onboarding banner i18n with server-side rendering + context inheritance - Refactor login language selectors to use languageSelector() function (LANG-002) - Move HTTPException handling to global exception handler in merchant routes (API-003) - Add language selector to all login pages and portal headers - Fix customer module: drop order stats from customer model, add to orders module - Fix admin menu config visibility for super admin platform context - Fix storefront auth and layout issues - Add missing i18n translations for onboarding steps (en/fr/de/lb) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -263,34 +263,49 @@ class TestMerchantMenuModuleGating:
|
||||
|
||||
def test_loyalty_appears_when_module_enabled(
|
||||
self, client, db, menu_auth, menu_merchant, menu_subscription,
|
||||
menu_loyalty_module,
|
||||
menu_loyalty_module, menu_platform,
|
||||
):
|
||||
"""Loyalty section appears when loyalty module is enabled on subscribed platform."""
|
||||
"""Loyalty items appear under platform section when module is enabled."""
|
||||
response = client.get(BASE, headers=menu_auth)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
# Loyalty now appears under a platform-{code} section
|
||||
platform_section_id = f"platform-{menu_platform.code}"
|
||||
section_ids = {s["id"] for s in data["sections"]}
|
||||
assert "loyalty" in section_ids
|
||||
assert platform_section_id in section_ids
|
||||
# Check loyalty item exists in that platform section
|
||||
platform_section = next(
|
||||
s for s in data["sections"] if s["id"] == platform_section_id
|
||||
)
|
||||
item_ids = {i["id"] for i in platform_section["items"]}
|
||||
assert "loyalty-overview" in item_ids
|
||||
|
||||
def test_loyalty_hidden_when_module_not_enabled(
|
||||
self, client, db, menu_auth, menu_merchant, menu_subscription,
|
||||
menu_platform,
|
||||
):
|
||||
"""Loyalty section is hidden when loyalty module is NOT enabled."""
|
||||
"""No platform section when no non-core modules are enabled."""
|
||||
response = client.get(BASE, headers=menu_auth)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
platform_section_id = f"platform-{menu_platform.code}"
|
||||
section_ids = {s["id"] for s in data["sections"]}
|
||||
assert "loyalty" not in section_ids
|
||||
assert platform_section_id not in section_ids
|
||||
|
||||
def test_loyalty_item_has_correct_route(
|
||||
self, client, db, menu_auth, menu_merchant, menu_subscription,
|
||||
menu_loyalty_module,
|
||||
menu_loyalty_module, menu_platform,
|
||||
):
|
||||
"""Loyalty overview item has the correct URL."""
|
||||
response = client.get(BASE, headers=menu_auth)
|
||||
data = response.json()
|
||||
loyalty = next(s for s in data["sections"] if s["id"] == "loyalty")
|
||||
overview = next(i for i in loyalty["items"] if i["id"] == "loyalty-overview")
|
||||
platform_section_id = f"platform-{menu_platform.code}"
|
||||
platform_section = next(
|
||||
s for s in data["sections"] if s["id"] == platform_section_id
|
||||
)
|
||||
overview = next(
|
||||
i for i in platform_section["items"] if i["id"] == "loyalty-overview"
|
||||
)
|
||||
assert overview["url"] == "/merchants/loyalty/overview"
|
||||
|
||||
|
||||
@@ -352,7 +367,8 @@ class TestMerchantMenuSubscriptionStatus:
|
||||
response = client.get(BASE, headers=menu_auth)
|
||||
assert response.status_code == 200
|
||||
section_ids = {s["id"] for s in response.json()["sections"]}
|
||||
assert "loyalty" in section_ids
|
||||
platform_section_id = f"platform-{menu_platform.code}"
|
||||
assert platform_section_id in section_ids
|
||||
|
||||
def test_expired_subscription_hides_non_core_modules(
|
||||
self, client, db, menu_auth, menu_merchant, menu_platform, menu_tier,
|
||||
@@ -374,8 +390,9 @@ class TestMerchantMenuSubscriptionStatus:
|
||||
response = client.get(BASE, headers=menu_auth)
|
||||
assert response.status_code == 200
|
||||
section_ids = {s["id"] for s in response.json()["sections"]}
|
||||
# Loyalty should NOT appear because subscription is expired
|
||||
assert "loyalty" not in section_ids
|
||||
platform_section_id = f"platform-{menu_platform.code}"
|
||||
# Platform section should NOT appear because subscription is expired
|
||||
assert platform_section_id not in section_ids
|
||||
# Core sections always appear
|
||||
assert "main" in section_ids
|
||||
assert "billing" in section_ids
|
||||
@@ -468,9 +485,20 @@ class TestMerchantMenuMultiPlatform:
|
||||
|
||||
response = client.get(BASE, headers=menu_auth)
|
||||
assert response.status_code == 200
|
||||
section_ids = {s["id"] for s in response.json()["sections"]}
|
||||
# Loyalty enabled on Platform A should appear in the union
|
||||
assert "loyalty" in section_ids
|
||||
data = response.json()
|
||||
section_ids = {s["id"] for s in data["sections"]}
|
||||
# Loyalty enabled on Platform A appears under platform-a's section
|
||||
platform_a_section_id = f"platform-{platform_a.code}"
|
||||
assert platform_a_section_id in section_ids
|
||||
# Platform B has no non-core modules, so no section
|
||||
platform_b_section_id = f"platform-{platform_b.code}"
|
||||
assert platform_b_section_id not in section_ids
|
||||
# Check loyalty item exists in Platform A section
|
||||
pa_section = next(
|
||||
s for s in data["sections"] if s["id"] == platform_a_section_id
|
||||
)
|
||||
item_ids = {i["id"] for i in pa_section["items"]}
|
||||
assert "loyalty-overview" in item_ids
|
||||
# Core sections always present
|
||||
assert "main" in section_ids
|
||||
assert "billing" in section_ids
|
||||
|
||||
Reference in New Issue
Block a user