Skip to content

Experiments Portlet — UVE integration behind FEATURE_FLAG_EXPERIMENTS_PORTLET + variant Edit Content round-trip #37005

Description

@oidacra

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 Content on 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).
  • Build the URL from the experiment's page data in the store — do not copy the current getUrl() that parses window.location.href (dot-experiments-configuration-variants.component.ts:187-234).
  • Returning from UVE lands back in the portlet, on /experiments/:id/configuration for the experiment the editor came from — resolved by experiment identity, not by page, since a page can host more than one experiment.
  • Control variant and locked experiments open UVE read-only (Preview), per the design.
  • No "edited" indicator. No edited/revision signal exists on the variant model on either side of the wire (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.
  • One consequence: the new Variants card renders the fixed string No content changes yet for 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 explicitly false in dotmarketing-config.properties, with a matching FeaturedFlags entry and an allow-list entry in ConfigurationResource so the frontend can read it.

  • Do not reuse FEATURE_FLAG_EXPERIMENTS. It is already read by ConfigExperimentUtil.isExperimentEnabled() and gates experiment JS injection (ExperimentWebAPIImpl:338) and experiment resolution during page render (HTMLPageAssetRenderedAPIImpl:176,239). Setting it to false — 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.
  • The explicit false is required, not optional: DotPropertiesService.getFeatureFlags() and withFlags() both map an absent flag (NOT_FOUND) to enabled. A flag that is merely declared ships on.
  • The unused frontend enum entry 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.

  • Flag on: the UVE experiments nav item routes to the portlet's site-wide list, filtered to the page in hand — not an unfiltered list, and not straight to a single experiment. Must behave for zero (empty state scoped to the page, with a way to create one), one, and many experiments; the filter is visible and clearable.
  • Flag off (default): byte-identical behavior to today — nav item, per-page list, deep-links.
  • Mechanism: withFlags([...]) / DotPropertiesService.getFeatureFlags(); precedent: FEATURE_FLAG_EDIT_CONTENT_SIDE_PANEL in dot-content-drive and edit-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 spec dot-ema-shell.component.spec.ts:117-120.

Acceptance Criteria

  • With the flag off, the UVE experiments experience is unchanged (specs + E2E regression).
  • With the flag off — including on a build where an operator never set it — experiments still serve to site visitors; FEATURE_FLAG_EXPERIMENTS is untouched by this work.
  • The new flag resolves to off when unset, and is reversible in both directions without a redeploy.
  • With the flag on, the UVE entry point lands on the site-wide list filtered to the page, correct for zero, one and many experiments.
  • Edit Content on a non-control variant opens UVE for that variant; Save/back returns to /experiments/:id/configuration for the originating experiment, including on a page with more than one experiment.
  • Control variant / locked experiment opens UVE in preview mode, and returns to the same place as the editable case.
  • No window.location.href parsing — the deep-link is built from store data.
  • The Variants card makes no claim about whether a variant's content has been modified.

Priority

Medium.

Additional Context

Activity

  1. added theissue type on Aug 11, 2026
  2. moved this from New to Current Sprint Backlog in dotCMS - Product Planningon Aug 11, 2026
  3. moved this from Current Sprint Backlog to In Progress in dotCMS - Product Planningon Aug 26, 2026
  4. 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
  5. github-actions commented on Aug 27, 2026

    @github-actions
    Contributor
  6. 49 remaining items

  7. moved this from In Review to QA in dotCMS - Product Planningon Sep 16, 2026
  8. removed their assignment
    on Sep 16, 2026
  9. jcastro-dotcms commented on Sep 16, 2026

    @jcastro-dotcms
    Member

    🧪 Post-Merge Test Plan

    Source PR: #37256
    Related issues: #37005

    Ownership 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_PORTLET switch (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 by ConfigurationResourceTest/ConfigExperimentUtilTest added 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.
    
  10. jcastro-dotcms commented on Sep 17, 2026

    @jcastro-dotcms
    Member

    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.

  11. removed their assignment
    on Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions