From f98483f5c56d39be9197be1d1c2d9ee7e73390bc Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Mon, 9 Nov 2026 18:11:50 +0100 Subject: [PATCH 1/2] fix(E2E): Lift the E2E organisation's plan limits on SaaS On SaaS, plan limits such as audit log visibility come from the subscription information cache, which the seed left on free plan limits. The E2E organisation therefore saw no audit logs. Upgrade the cache to enterprise limits when one exists. --- api/e2etests/e2e_seed_data.py | 18 ++++++++++- api/tests/unit/e2etests/__init__.py | 0 .../e2etests/test_unit_e2etests_seed_data.py | 31 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 api/tests/unit/e2etests/__init__.py create mode 100644 api/tests/unit/e2etests/test_unit_e2etests_seed_data.py diff --git a/api/e2etests/e2e_seed_data.py b/api/e2etests/e2e_seed_data.py index f00717c897de..2a3aec35b666 100644 --- a/api/e2etests/e2e_seed_data.py +++ b/api/e2etests/e2e_seed_data.py @@ -15,7 +15,12 @@ from environments.identities.models import Identity from environments.models import Environment from environments.permissions.models import UserEnvironmentPermission -from organisations.models import Organisation, OrganisationRole, Subscription +from organisations.models import ( + Organisation, + OrganisationRole, + OrganisationSubscriptionInformationCache, + Subscription, +) from organisations.permissions.models import UserOrganisationPermission from organisations.permissions.permissions import ( CREATE_PROJECT, @@ -143,6 +148,17 @@ def seed_data() -> None: Subscription.objects.filter(organisation__in=org_admin.organisations.all()).update( max_seats=8, plan=ENTERPRISE, subscription_id="test_subscription_id" ) + # On SaaS, plan limits such as audit log visibility come from the + # subscription information cache, which starts with free plan limits. + for subscription_cache in OrganisationSubscriptionInformationCache.objects.filter( + organisation__in=org_admin.organisations.all() + ).select_related("organisation__subscription"): + subscription = subscription_cache.organisation.subscription + subscription_cache.upgrade_to_enterprise( + seats=subscription.max_seats, + api_calls=subscription.max_api_calls, + ) + subscription_cache.save() # Create projects and environments projects = [] diff --git a/api/tests/unit/e2etests/__init__.py b/api/tests/unit/e2etests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/api/tests/unit/e2etests/test_unit_e2etests_seed_data.py b/api/tests/unit/e2etests/test_unit_e2etests_seed_data.py new file mode 100644 index 000000000000..e8d24f382d50 --- /dev/null +++ b/api/tests/unit/e2etests/test_unit_e2etests_seed_data.py @@ -0,0 +1,31 @@ +import pytest +from django.conf import settings + +from e2etests.e2e_seed_data import seed_data +from organisations.models import OrganisationSubscriptionInformationCache +from users.models import FFAdminUser + + +@pytest.mark.saas_mode +@pytest.mark.django_db +def test_seed_data__saas__lifts_e2e_organisation_plan_limits() -> None: + # Given / When + seed_data() + + # Then + e2e_user = FFAdminUser.objects.get(email=settings.E2E_USER) + organisation = e2e_user.organisations.get() + subscription_cache = organisation.subscription_information_cache + assert subscription_cache.allowed_seats == 8 + assert subscription_cache.allowed_projects is None + assert subscription_cache.audit_log_visibility_days is None + assert subscription_cache.feature_history_visibility_days is None + + +@pytest.mark.django_db +def test_seed_data__self_hosted__creates_no_subscription_information_cache() -> None: + # Given / When + seed_data() + + # Then + assert not OrganisationSubscriptionInformationCache.objects.exists() From 41913d9f02f4cd5ebe6ca143bbe9d5f4a9e85c8a Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Mon, 9 Nov 2026 18:11:50 +0100 Subject: [PATCH 2/2] test(Segments): Skip the segment audit log E2E test on SaaS Until the seed fix is deployed, the E2E organisation can't see audit logs on SaaS, which blocks the production frontend deploy. --- frontend/e2e/helpers/utils.playwright.ts | 8 ++++++++ frontend/e2e/tests/segment-test.pw.ts | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/frontend/e2e/helpers/utils.playwright.ts b/frontend/e2e/helpers/utils.playwright.ts index f8818aba7b2a..310be38d1707 100644 --- a/frontend/e2e/helpers/utils.playwright.ts +++ b/frontend/e2e/helpers/utils.playwright.ts @@ -40,3 +40,11 @@ export const getFlagsmith = async function (): Promise { await initProm; return flagsmith as IFlagsmith; }; + +// Whether the API under test is a SaaS deployment, per its `/version/` endpoint. +export const isSaas = async function (): Promise { + const api = process.env.FLAGSMITH_API_URL || Project.api; + const res = await fetch(`${api.replace(/api\/v1\/$/, '')}version/`); + const version = (await res.json()) as { is_saas?: boolean }; + return !!version.is_saas; +}; diff --git a/frontend/e2e/tests/segment-test.pw.ts b/frontend/e2e/tests/segment-test.pw.ts index cccb3555d525..71eb628762a5 100644 --- a/frontend/e2e/tests/segment-test.pw.ts +++ b/frontend/e2e/tests/segment-test.pw.ts @@ -1,5 +1,5 @@ import { test, expect } from '../test-setup'; -import { byId, log, createHelpers, visualSnapshot, getFlagsmith } from '../helpers'; +import { byId, log, createHelpers, visualSnapshot, getFlagsmith, isSaas } from '../helpers'; import { E2E_USER, PASSWORD, E2E_TEST_IDENTITY, E2E_SEGMENT_PROJECT_1, E2E_SEGMENT_PROJECT_2, E2E_SEGMENT_PROJECT_3 } from '../config' const REMOTE_CONFIG_FEATURE = 'remote_config' @@ -477,6 +477,10 @@ test('Segment test 4 - Create ANY rule type segment and verify match changes whe }) test('Segment test 5 - Audit log shows segment rule changes @enterprise', async ({ page }) => { + test.skip( + await isSaas(), + 'The E2E organisation has no audit log visibility on SaaS until the seeded subscription is deployed', + ) const { click, createSegment,