sadpandajoe opened a new pull request, #39925:
URL: https://github.com/apache/superset/pull/39925

   ### SUMMARY
   
   Skeleton commit for a TDD-driven refactor that makes subdirectory 
deployments (`SUPERSET_APP_ROOT`) decision-free for frontend developers. After 
the full PR lands, every URL in the codebase is router-relative; the channel-3 
helpers (`openInNewTab`, `redirect`, `getShareableUrl`, `<AppLink>`) wrap 
internally, and a backend response normaliser strips the application root on 
the way in so frontend code only ever speaks one shape.
   
   This PR is intentionally just the scaffolding so the framing can be reviewed 
before ~30-60 call sites get migrated.
   
   #### What's in this PR
   
   **Frameworks (implemented)**
   - `spec/helpers/withApplicationRoot.ts` — fixture that sets 
`application_root` in the bootstrap data, resets the module cache, and tears 
down on completion. Replaces an inline ritual that pathUtils.test.ts repeats 
per test.
   - `spec/helpers/sourceTreeScanner.ts` — line-by-line regex scanner over the 
source tree with allow-list support. Reports workspace-relative `file:line` for 
each violation.
   
   **Stubs (throw "not implemented")**
   - `src/utils/navigationUtils.ts` — `openInNewTab`, `redirect`, 
`redirectReplace`, `getShareableUrl`, `AppLink`. Each documents the channel 
rule it enforces. Existing `navigateTo` / `navigateWithState` stay as legacy 
multi-mode helpers and are scheduled for replacement.
   - `packages/superset-ui-core/src/connection/normalizeBackendUrls.ts` — 
conservative URL field normaliser. Ships a curated `NORMALIZED_URL_FIELDS` set 
(initially empty pending per-endpoint audit) and a documented 
`NORMALIZER_EXCLUSIONS` list explaining why fields like `bug_report_url`, 
`thumbnail_url`, and `user_login_url` are deliberately not normalised.
   
   **Layered tests (one example each; expanded in follow-up commits on this 
PR)**
   
   | Layer | What it covers | Example file | State on day 1 |
   |---|---|---|---|
   | 1 | Per-helper unit behaviour under empty / single / nested app roots | 
`navigationUtils.test.ts` (`openInNewTab`) | 🔴 red — helper throws |
   | 2 | Static invariant: no `ensureAppRoot` / `makeUrl` import outside 
`navigationUtils.ts` | `navigationUtils.invariants.test.ts` | 🟢 green — 
allow-list seeded with the 19 current call sites |
   | 3 | Backend URL normaliser: positive strip + negative passthrough cases | 
`normalizeBackendUrls.test.ts` | 🔴 red — normaliser throws |
   | 4 | `SupersetClient × applicationRoot` contract: root applied exactly once 
| `SupersetClientAppRootContract.test.ts` | 🟢 green — formalises existing 
behaviour |
   | 5 | Per-site regression for `SliceHeaderControls` Cmd-click "Edit chart" | 
`SliceHeaderControls.subdirectory.test.tsx` | 🔴 red — `index.tsx:266` calls 
`window.open(props.exploreUrl)` without prefixing |
   
   #### Why this approach
   
   The codebase has three URL channels — React Router, `SupersetClient`, and 
browser-direct sinks (`window.open`, `window.location.href`, `<a href>`). Today 
each has its own convention for whether the caller pre-applies the application 
root, and bugs come from mixing them up:
   
   - **Double-prefix**: passing an `ensureAppRoot(...)` value into a router or 
`SupersetClient` channel that already applies the prefix internally.
   - **Missing-prefix**: passing a raw `/path` to a browser-direct sink that 
does not.
   
   The fix makes router-relative the **canonical shape** — the one developers 
always write — and pushes the wrapping decision into helpers so individual call 
sites never need to think about it. Combined with the response normaliser, 
backend-supplied URLs (`explore_url`, `permalink`, etc.) speak the same shape, 
and `ensureAppRoot` / `makeUrl` become module-private inside 
`navigationUtils.ts`.
   
   #### Strategy
   
   Each subsequent commit on this PR fans out one layer to its full coverage 
and migrates the corresponding call sites, shrinking the Layer 2 allow-list in 
lockstep. Final commit lands an ESLint rule that complements the 
static-invariant tests.
   
   When the in-flight subdirectory branches (`origin/subdirectory-bugs`, 
`origin/subdirectory-export`) merge to master, this branch rebases onto them 
and adapts.
   
   ### TESTING INSTRUCTIONS
   
   Run the test suite from `superset-frontend/`:
   
   ```bash
   npm run test -- spec/helpers/withApplicationRoot \
                   src/utils/navigationUtils.invariants.test.ts \
                   
packages/superset-ui-core/test/connection/SupersetClientAppRootContract.test.ts
   ```
   
   Layers 2 and 4 should pass on day one. Layers 1, 3, and 5 are intentionally 
red — they describe the behaviour the green commit will deliver.
   
   ### ADDITIONAL INFORMATION
   - [ ] Has associated issue:
   - [ ] Required feature flags:
   - [ ] Changes UI
   - [ ] Includes DB Migration
   - [ ] Introduces new feature or API
   - [ ] Removes existing feature or API
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to