Repository navigation
Experiments Portlet — UVE integration behind FEATURE_FLAG_EXPERIMENTS_PORTLET + variant Edit Content round-trip #37005
Description
Activity
- addeddotCMS : ExperimentsAnalytics Umbrella: Experiments FeatureAnalytics Umbrella: Experiments Feature
on Aug 11, 2026 - added a parent issue
on Aug 11, 2026 - removed a parent issue
on Aug 11, 2026 - added a parent issue
on Aug 11, 2026 - moved this from New to Current Sprint Backlog in dotCMS - Product Planning
on Aug 11, 2026 - added a commit that references this issue
on Aug 20, 2026 - moved this from Current Sprint Backlog to In Progress in dotCMS - Product Planning
on Aug 26, 2026 - changed the title
[-]Experiments Portlet — UVE integration behind FEATURE_FLAG_EXPERIMENTS + variant Edit Content round-trip[/-][+]Experiments Portlet — UVE integration behind FEATURE_FLAG_EXPERIMENTS_PORTLET + variant Edit Content round-trip[/+]on Aug 26, 2026 github-actions commented
on Aug 27, 2026 on Aug 27, 2026 – with GitHub ActionsContributorMore actionsPRs linked to this issue
49 remaining items
🧪 Post-Merge Test Plan
Source PR: #37256
Related issues: #37005Ownership and status
Responsibility Developer Status Plan Reviewer — developer who implemented the fix @oidacra Pending Review Test Executor — independent developer Jose Castro Completed The Plan Reviewer must validate scope, correctness, missing cases, and possible hallucinations before execution begins.
This is a living test plan. The Plan Reviewer and Test Executor may add relevant test cases. Every added case must follow the existing format and receive a final result.
Test summary
Test Case Number Scenario Result Notes TC-001 Edit variant content round-trip from UVE through the portlet and back Passed TC-002 Switch off — legacy UVE experiments flow is byte-identical Passed TC-003 Switch toggled on then off restores original behavior without redeploy Passed TC-004 Read-only enforcement — control variant, non-draft experiment, locked page Passed TC-005 Switch on — filtered list correct for zero, one, many experiments; filter clears Passed TC-006 Visitor-facing experiment delivery unaffected by the new switch Passed TC-007 Return destination identical for read-only vs editable variant Passed TC-008 Variants card makes no edited-state claim after the round-trip Passed TC-009 Edit Content refuses cleanly when the experiment's page is unavailable Passed TC-010 Editor without experiments permission gains no access via switch-on destination Passed Same permission gap exists with the flag off too — confirmed pre-existing, not a regression from this PR. TC-011 Deep-linking directly into a variant still returns coherently Passed TC-012 Experiment deleted/archived while UVE is open reports "gone" on return Passed Non-blank error state confirmed ("Could not load experiments" / "Failed to retrieve experiments data. Try again later." / Back To Experiments), reproduced on two separate runs. Copy nit: message reads as a generic transient-fetch failure rather than confirming the experiment was specifically deleted/archived — consider wording like "This experiment no longer exists — it may have been deleted or archived" and dropping "Try again later" (retrying won't succeed once the experiment is gone). TC-013 Page locked by another user mid-session updates Variants card actions Passed Enforcement is correct — attempting to edit a page locked by another user is blocked with a clear message ("Locked by Admin User. You don't have permissions to unlock this content."), confirmed by both the agent and manual repro, even after a full reload. Cosmetic gap: the Variants card's action button still reads "Edit" and never updates to reflect the lock (same mislabeling pattern noted in TC-004 for non-draft experiments) — worth a UI polish follow-up, not a functional/security issue. View full test plan
Summary
Covers merged PR #37256 for issue #37005: the
FEATURE_FLAG_EXPERIMENTS_PORTLETswitch (default off) that routes UVE's Experiments entry point to the new portlet, plus the Variants card's Edit Content round-trip into UVE. Cases below exercise the four spec user stories and edge cases end-to-end in a real browser; logic already asserted by the ~90 unit/component specs the PR added (deep-link building, breadcrumb resolution, filter store logic) was not re-tested manually. The "switch is unreadable" edge case (spec line 268) is not represented here — it requires artificially breaking the config-read path, which is impractical to trigger manually and is exercised byConfigurationResourceTest/ConfigExperimentUtilTestadded in this PR. None of the cases below have been executed.Test Cases
- Test ID: TC-001 - Issues: #37005 - Test Name: US1-AS1..4: Edit variant content round-trip from UVE through the portlet and back - Risk: Critical - Scenario: Happy Path - Steps To Reproduce: 1. Set `FEATURE_FLAG_EXPERIMENTS_PORTLET=true` and restart (or apply as a live config override). 2. Open a page that hosts a draft experiment with at least one non-control variant, in the Universal Visual Editor (UVE). 3. Open the Experiments item in UVE's navigation bar and select the experiment; confirm you land on that experiment's configuration screen in the new portlet. 4. On the Variants card, choose Edit Content on the non-control variant. 5. Confirm UVE reopens on the same page, showing that variant, in editable mode; make a content change and save. 6. Use the variant/return affordance to leave UVE. - Expected Result: UVE opens on the correct page/variant in editable mode; after saving and returning, you land back on the configuration screen of the same experiment (not a list, not another experiment), with no `variantName`/`experimentId`/`mode` query parameters remaining in the address. - Test ID: TC-002 - Issues: #37005 - Test Name: US2-AS1..3: Switch off — legacy UVE experiments flow is byte-identical - Risk: Critical - Scenario: Happy Path - Steps To Reproduce: 1. Confirm `FEATURE_FLAG_EXPERIMENTS_PORTLET` is unset or `false` (shipped default). 2. Open a page with a running experiment in UVE. 3. Open the Experiments item in UVE's navigation bar. 4. Follow the running-experiment tag in the UVE toolbar. 5. From a page in a variant, act on the variant chip to return. - Expected Result: Step 3 reaches the per-page experiments list at the same address as before this PR; step 4 reaches that experiment's reports screen inside UVE; step 5 reaches the UVE-embedded configuration screen — all unchanged from pre-PR behavior. - Test ID: TC-003 - Issues: #37005 - Test Name: US2-AS4: Switch toggled on then off restores original behavior without redeploy - Risk: Critical - Scenario: Happy Path - Steps To Reproduce: 1. With the switch at its default (off), record the destinations from TC-002 steps 3-5. 2. Flip `FEATURE_FLAG_EXPERIMENTS_PORTLET` to `true` via live config (no restart/redeploy). 3. Repeat TC-002 steps 3-5 and confirm the new portlet destinations. 4. Flip the flag back to `false` via live config (no restart/redeploy). 5. Repeat TC-002 steps 3-5 again. - Expected Result: After step 5, all three destinations exactly match what was recorded in step 1 — the switch is reversible in both directions without a redeploy. - Test ID: TC-004 - Issues: #37005 - Test Name: US4-AS1..3: Read-only enforcement — control variant, non-draft experiment, locked page - Risk: Critical - Scenario: Negative - Steps To Reproduce: 1. With the switch on, from a page in UVE reach a draft experiment's configuration and choose Edit Content on the **control** variant. 2. Separately, reach an experiment that is running or ended (not draft) and choose Edit Content on any variant. 3. Separately, lock the experiment's page as a different user, then as the original editor choose Edit Content on any variant. - Expected Result: In all three cases, UVE opens in preview/read-only mode with no editing affordance; for the locked-page case, the UI states the page is locked and by whom/why. - Test ID: TC-005 - Issues: #37005 - Test Name: US3-AS1..4: Switch on — filtered list correct for zero, one, many experiments; filter clears - Risk: High - Scenario: Boundary - Steps To Reproduce: 1. With the switch on, open a page with no experiments in UVE and select the Experiments nav item. 2. Confirm the empty state is scoped to that page and offers a way to create an experiment for it. 3. Repeat with a page that has exactly one experiment, then a page with several experiments. 4. On the filtered list, clear the page filter. - Expected Result: Step 2's empty state is page-scoped, not the full site-wide list; the one-experiment page shows exactly that row; the many-experiment page shows all and only that page's experiments; clearing the filter in step 4 reveals the full site-wide list across all pages. - Test ID: TC-006 - Issues: #37005 - Test Name: US2-AS5: Visitor-facing experiment delivery unaffected by the new switch - Risk: Critical - Scenario: Negative - Steps To Reproduce: 1. Set up a running experiment on a published page. 2. As an anonymous site visitor (not logged into the backend), request that page with `FEATURE_FLAG_EXPERIMENTS_PORTLET=false`. 3. Repeat the visitor request with `FEATURE_FLAG_EXPERIMENTS_PORTLET=true`. - Expected Result: The experiment is served to the visitor identically in both cases — the new switch has no effect on visitor-facing experiment delivery; `FEATURE_FLAG_EXPERIMENTS` (the separate kill-switch) governs that and is untouched by this work. - Test ID: TC-007 - Issues: #37005 - Test Name: US4-AS4/FR-010a: Return destination identical for read-only vs editable variant - Risk: High - Scenario: Edge - Steps To Reproduce: 1. From an experiment's configuration screen, open a read-only variant (e.g., the control) in UVE and use the return affordance. 2. Note the destination. 3. From the same experiment, open an editable non-control variant in UVE and use the return affordance. - Expected Result: Both step 2 and step 3 land on the exact same configuration screen for that experiment — read-only status changes what UVE offers, not where the round-trip ends. - Test ID: TC-008 - Issues: #37005 - Test Name: US1-AS5/FR-007/FR-007a: Variants card makes no edited-state claim after the round-trip - Risk: High - Scenario: Negative - Steps To Reproduce: 1. Complete a round-trip edit on a non-control variant per TC-001. 2. Return to the Variants card and inspect the row for that variant. - Expected Result: No badge, meta line, "edited" label, or last-modified indicator appears anywhere on the variant row; the row looks the same as before the edit (name, copy-URL, weight, traffic share, row menu only). The old disabled-button tooltip ("Editing Variant content is available in an upcoming release") is gone. - Test ID: TC-009 - Issues: #37005 - Test Name: US1-AS6/FR-004: Edit Content refuses cleanly when the experiment's page is unavailable - Risk: High - Scenario: Negative - Steps To Reproduce: 1. Create an experiment, then reassign or delete the page it targets (so the stored page reference no longer resolves). 2. From the experiment's configuration screen, choose Edit Content on a variant. - Expected Result: The system tells the editor the page cannot be opened; it does not navigate to a broken or partially-formed editor, and does not fall back to parsing the current browser address. - Test ID: TC-010 - Issues: #37005 - Test Name: FR-023: Editor without experiments permission gains no access via switch-on destination - Risk: High - Scenario: Negative - Steps To Reproduce: 1. With the switch on, log in as a user who lacks permission to view experiments for a given page/site. 2. Open that page in UVE and select the Experiments nav item. - Expected Result: The user is denied or sees no experiments data for that page/site — reaching the portlet through the new switch-on destination grants no more access than the old per-page screens did. - Test ID: TC-011 - Issues: #37005 - Test Name: Edge — deep-linking directly into a variant still returns coherently - Risk: Medium - Scenario: Edge - Steps To Reproduce: 1. With the switch at a known value (test both on and off), construct or paste a direct UVE deep-link into a variant of an experiment, bypassing the portlet entirely. 2. Open that link, then use the return affordance. - Expected Result: The editor lands on a valid, coherent destination consistent with the switch's current value — never a dead route or blank screen. - Test ID: TC-012 - Issues: #37005 - Test Name: Edge — experiment deleted/archived while UVE is open reports "gone" on return - Risk: Medium - Scenario: Edge - Steps To Reproduce: 1. Open a variant for editing in UVE via the portlet round-trip. 2. While UVE is still open, delete or archive that experiment from another session/tab. 3. Use the return affordance in UVE. - Expected Result: The return reports that the experiment is gone/no longer available, rather than rendering an empty or broken configuration screen. - Test ID: TC-013 - Issues: #37005 - Test Name: Edge — page locked by another user mid-session updates Variants card actions - Risk: Medium - Scenario: Edge - Steps To Reproduce: 1. Open an experiment's configuration screen for an unlocked page. 2. From another session, lock that page as a different user. 3. Return to the first session's Variants card without a full reload, then reload it. - Expected Result: The Variants card's available actions reflect the page's actual current lock state (e.g., Edit Content behaves as read-only/blocked once locked), not the stale unlocked state from when the screen first loaded.QA: PASSED ✅
- Docker image:
trunk_8f0c9fa
I ran all 13 Test Cases and did some manual smoke testing. The new Experiments portlet seems to be working as expected.
- Docker image:
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Description
The one place where the new flow overlaps something customers use today is the experiments entry point inside the Universal Visual Editor. This issue (a) completes the Variants card of #37003 with the Edit Content round-trip into UVE, and (b) switches the UVE entry point to the new portlet flow behind a feature flag, off by default — the old per-page screens keep working unchanged in every build until the flag is flipped, and it can be flipped back.
This is the only issue before the migration that modifies existing behavior.
1. Variant Edit Content round-trip
Edit Contenton a variant navigates to UVE for{pageId, variantName}using the existing deep-link shape:/edit-page/content?url=…&variantName=…&experimentId=…(current construction:dot-uve-toolbar.component.ts:262-277).getUrl()that parseswindow.location.href(dot-experiments-configuration-variants.component.ts:187-234)./experiments/:id/configurationfor the experiment the editor came from — resolved by experiment identity, not by page, since a page can host more than one experiment.Preview), per the design.AbstractExperimentVariant,Variant), and the legacy per-page Variants card shows no edit indication at all. Do not invent one — not persisted, not derived, not session-held. The deliverable is the correct round-trip, not a badge.No content changes yetfor every non-control variant (experiments.configure.variants.meta.variant). That is true today only because the Edit Content button beside it is disabled. This issue is what makes it capable of being false, so the string must be reworded to something state-neutral or dropped.2. UVE entry-point switch behind the flag
The flag. Add a new, dedicated flag —
FEATURE_FLAG_EXPERIMENTS_PORTLET— shipped explicitlyfalseindotmarketing-config.properties, with a matchingFeaturedFlagsentry and an allow-list entry inConfigurationResourceso the frontend can read it.FEATURE_FLAG_EXPERIMENTS. It is already read byConfigExperimentUtil.isExperimentEnabled()and gates experiment JS injection (ExperimentWebAPIImpl:338) and experiment resolution during page render (HTMLPageAssetRenderedAPIImpl:176,239). Setting it tofalse— this issue's intended default — would take running experiments off the air. It keeps its current name, meaning, default and consumers; this work does not touch it.falseis required, not optional:DotPropertiesService.getFeatureFlags()andwithFlags()both map an absent flag (NOT_FOUND) to enabled. A flag that is merely declared ships on.FeaturedFlags.LOAD_FRONTEND_EXPERIMENTS = 'FEATURE_FLAG_EXPERIMENTS'(libs/dotcms-models/src/lib/shared-models.ts:28) gains no consumer under this decision and can be deleted in the migration — the property must survive.Behavior.
withFlags([...])/DotPropertiesService.getFeatureFlags(); precedent:FEATURE_FLAG_EDIT_CONTENT_SIDE_PANELindot-content-driveandedit-ema.Must not break (flag off)
The UVE nav item (
dot-ema-shell.component.ts:143-149), the toolbar deep-links (dot-ema-running-experiment.component.html:2-7,dot-uve-toolbar.component.ts:262-277), and the nav-href specdot-ema-shell.component.spec.ts:117-120.Acceptance Criteria
FEATURE_FLAG_EXPERIMENTSis untouched by this work.Edit Contenton a non-control variant opens UVE for that variant; Save/back returns to/experiments/:id/configurationfor the originating experiment, including on a page with more than one experiment.window.location.hrefparsing — the deep-link is built from store data.Priority
Medium.
Additional Context
specs/37005-experiments-uve-integration/spec.md(D1/D2/D3 record the three corrections and why).FEATURE_FLAG_EXPERIMENTS_PORTLET, notFEATURE_FLAG_EXPERIMENTS— the latter gates visitor-facing experiment delivery and must survive. The unusedLOAD_FRONTEND_EXPERIMENTSenum entry can be dropped there.