Skip to content

Commit 35987fd

Browse files
author
DavidQ
committed
Move Session Inspector V2 detail scrollbars onto output pre elements - PR_26128_024-session-inspector-v2-output-scrollbars
1 parent 5d28773 commit 35987fd

4 files changed

Lines changed: 120 additions & 19 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Playwright Session Inspector V2 Output Scrollbars
2+
3+
## Command
4+
`npm run test:workspace-v2`
5+
6+
## Result
7+
- Passed: 15/15
8+
- Runtime: about 1.5 minutes
9+
10+
## Targeted Coverage
11+
- Verified `#sessionInspectorV2JsonOutput` scrolls vertically and horizontally with long JSON content.
12+
- Verified `#sessionInspectorV2DataOutput` scrolls vertically and horizontally with long Data content.
13+
- Verified `#sessionInspectorV2DirtyOutput` scrolls vertically and horizontally when Dirty content overflows.
14+
- Verified JSON/Data/Dirty accordion content wrappers do not own the primary scrollbars.
15+
- Verified JSON/Data/Dirty output heights remain bounded.
16+
- Verified Dirty and Status headers remain visible/reachable.
17+
- Verified Copy All still copies the JSON/Data/Dirty payload.
18+
- Verified Dirty header values remain covered for false, true, and unknown states.
19+
20+
## Skipped
21+
- Full samples smoke test was skipped by request. The relevant output scrollbar, detail panel, Dirty header, and Copy All coverage is in `tests/playwright/tools/WorkspaceManagerV2.spec.mjs`.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Session Inspector V2 Output Scrollbars
2+
3+
## Scope
4+
- Moved Session Inspector V2 detail scrolling onto the output `<pre>` elements.
5+
- Ensured these outputs own their vertical and horizontal scroll behavior:
6+
- `#sessionInspectorV2JsonOutput`
7+
- `#sessionInspectorV2DataOutput`
8+
- `#sessionInspectorV2DirtyOutput`
9+
- Kept JSON/Data/Dirty accordion containers bounded so long content does not hide lower headers.
10+
11+
## Implementation Notes
12+
- Detail accordion content wrappers now hide overflow instead of owning the primary scrollbars.
13+
- JSON/Data/Dirty output `<pre>` elements use internal scrolling and preserve unwrapped text for horizontal overflow.
14+
- Dirty and Status headers remain visible/reachable with long JSON/Data content.
15+
16+
## Preserved Behavior
17+
- Dirty header values remain:
18+
- `Dirty: false`
19+
- `Dirty: true`
20+
- `Dirty: unknown`
21+
- Copy All still copies the labeled JSON/Data/Dirty payload.
22+
- Clear Status behavior was preserved.
23+
- JSON/Data/Dirty/Status accordion behavior was preserved.
24+
- Normalized session object shape was not changed.
25+
26+
## Guardrails
27+
- No cross-tool communication was added.
28+
- No sample JSON was modified.
29+
- No roadmap content was modified.
30+
31+
## Validation
32+
- Passed `npm run test:workspace-v2` with 15/15 tests.
33+
- Verified JSON scrollbar ownership is inside `#sessionInspectorV2JsonOutput`.
34+
- Verified Data scrollbar ownership is inside `#sessionInspectorV2DataOutput`.
35+
- Verified Dirty scrollbar ownership is inside `#sessionInspectorV2DirtyOutput` when Dirty content overflows.
36+
- Verified accordion containers do not grow uncontrollably.
37+
- Verified Dirty and Status headers remain visible/reachable.
38+
- Verified Copy All still works.
39+
40+
## Skipped
41+
- Full samples smoke test was skipped by request. The changed surface is Session Inspector V2 output scrolling and is covered by `npm run test:workspace-v2`.

tests/playwright/tools/WorkspaceManagerV2.spec.mjs

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,7 @@ test.describe("Workspace Manager V2 bootstrap", () => {
745745
source: "test-fixture"
746746
}];
747747
}));
748+
const longHorizontalToken = "session-inspector-v2-horizontal-scroll-probe".repeat(8);
748749
window.sessionStorage.setItem("workspace.tools.preview-generator-v2", JSON.stringify({
749750
schema: {
750751
source: "workspace-manager-v2",
@@ -785,7 +786,10 @@ test.describe("Workspace Manager V2 bootstrap", () => {
785786
assetsPath: "games/Asteroids/assets",
786787
repoReferenceKey: "workspace.repo.reference"
787788
},
788-
data: { assets: { "assets.image.preview.preview": { path: "assets/images/preview.png" }, ...longAssetMap } },
789+
data: {
790+
assets: { "assets.image.preview.preview": { path: "assets/images/preview.png" }, ...longAssetMap },
791+
horizontalProbe: longHorizontalToken
792+
},
789793
dirty: {
790794
isDirty: false,
791795
reason: null,
@@ -809,9 +813,9 @@ test.describe("Workspace Manager V2 bootstrap", () => {
809813
},
810814
dirty: {
811815
isDirty: true,
812-
reason: "test dirty flag",
816+
reason: longHorizontalToken,
813817
changedAt: "2026-05-08T12:00:00.000Z",
814-
changedKeys: ["data.note"]
818+
changedKeys: Array.from({ length: 70 }, (_, index) => `${longHorizontalToken}.${index}`)
815819
}
816820
}));
817821
window.sessionStorage.setItem("workspace.tools.no-data-test", JSON.stringify({
@@ -891,28 +895,40 @@ test.describe("Workspace Manager V2 bootstrap", () => {
891895
const detailPanelState = await page.evaluate(() => {
892896
const jsonContent = document.querySelector("#sessionInspectorV2JsonContent");
893897
const dataContent = document.querySelector("#sessionInspectorV2DataContent");
898+
const jsonOutput = document.querySelector("#sessionInspectorV2JsonOutput");
899+
const dataOutput = document.querySelector("#sessionInspectorV2DataOutput");
894900
const dirtyHeader = document.querySelector(".session-inspector-v2__dirty-accordion-header");
895901
const statusHeader = document.querySelector(".session-inspector-v2__status-accordion-header");
896902
const rightPanel = document.querySelector(".session-inspector-v2__panel--right");
903+
const jsonContentStyle = getComputedStyle(jsonContent);
904+
const dataContentStyle = getComputedStyle(dataContent);
897905
const rectFor = (element) => element.getBoundingClientRect();
898906
const rightRect = rectFor(rightPanel);
899907
const dirtyHeaderRect = rectFor(dirtyHeader);
900908
const statusHeaderRect = rectFor(statusHeader);
901909
return {
902-
dataContentScrolls: dataContent.scrollHeight > dataContent.clientHeight + 1,
903-
dataHeightBounded: rectFor(dataContent).height <= 170,
910+
dataContentDoesNotOwnScrollbar: dataContentStyle.overflowY === "hidden" && dataContentStyle.overflowX === "hidden",
911+
dataOutputScrollsHorizontally: dataOutput.scrollWidth > dataOutput.clientWidth + 1,
912+
dataOutputScrollsVertically: dataOutput.scrollHeight > dataOutput.clientHeight + 1,
913+
dataOutputHeightBounded: rectFor(dataOutput).height <= 170,
904914
dirtyHeaderReachable: dirtyHeaderRect.top >= rightRect.top && dirtyHeaderRect.bottom <= rightRect.bottom,
905-
jsonContentScrolls: jsonContent.scrollHeight > jsonContent.clientHeight + 1,
906-
jsonHeightBounded: rectFor(jsonContent).height <= 170,
915+
jsonContentDoesNotOwnScrollbar: jsonContentStyle.overflowY === "hidden" && jsonContentStyle.overflowX === "hidden",
916+
jsonOutputScrollsHorizontally: jsonOutput.scrollWidth > jsonOutput.clientWidth + 1,
917+
jsonOutputScrollsVertically: jsonOutput.scrollHeight > jsonOutput.clientHeight + 1,
918+
jsonOutputHeightBounded: rectFor(jsonOutput).height <= 170,
907919
statusHeaderReachable: statusHeaderRect.top >= rightRect.top && statusHeaderRect.bottom <= rightRect.bottom
908920
};
909921
});
910922
expect(detailPanelState).toEqual({
911-
dataContentScrolls: true,
912-
dataHeightBounded: true,
923+
dataContentDoesNotOwnScrollbar: true,
924+
dataOutputScrollsHorizontally: true,
925+
dataOutputScrollsVertically: true,
926+
dataOutputHeightBounded: true,
913927
dirtyHeaderReachable: true,
914-
jsonContentScrolls: true,
915-
jsonHeightBounded: true,
928+
jsonContentDoesNotOwnScrollbar: true,
929+
jsonOutputScrollsHorizontally: true,
930+
jsonOutputScrollsVertically: true,
931+
jsonOutputHeightBounded: true,
916932
statusHeaderReachable: true
917933
});
918934
await page.locator("#copySessionInspectorV2AllButton").click();
@@ -930,6 +946,24 @@ test.describe("Workspace Manager V2 bootstrap", () => {
930946
await page.locator('[data-session-inspector-v2-entry-id="sessionStorage:workspace.tools.dirty-test"]').click();
931947
await expect(page.locator("#sessionInspectorV2DirtyHeaderValue")).toHaveText("Dirty: true");
932948
await expect(page.locator("#sessionInspectorV2DirtyOutput")).toContainText('"isDirty": true');
949+
const dirtyOutputScrollState = await page.evaluate(() => {
950+
const dirtyContent = document.querySelector("#sessionInspectorV2DirtyContent");
951+
const dirtyOutput = document.querySelector("#sessionInspectorV2DirtyOutput");
952+
const dirtyContentStyle = getComputedStyle(dirtyContent);
953+
const rect = dirtyOutput.getBoundingClientRect();
954+
return {
955+
dirtyContentDoesNotOwnScrollbar: dirtyContentStyle.overflowY === "hidden" && dirtyContentStyle.overflowX === "hidden",
956+
dirtyOutputScrollsHorizontally: dirtyOutput.scrollWidth > dirtyOutput.clientWidth + 1,
957+
dirtyOutputScrollsVertically: dirtyOutput.scrollHeight > dirtyOutput.clientHeight + 1,
958+
dirtyOutputHeightBounded: rect.height <= 170
959+
};
960+
});
961+
expect(dirtyOutputScrollState).toEqual({
962+
dirtyContentDoesNotOwnScrollbar: true,
963+
dirtyOutputScrollsHorizontally: true,
964+
dirtyOutputScrollsVertically: true,
965+
dirtyOutputHeightBounded: true
966+
});
933967
await page.locator('[data-session-inspector-v2-entry-id="sessionStorage:workspace.tools.no-data-test"]').click();
934968
await expect(page.locator("#sessionInspectorV2DataOutput")).toContainText("No data section is present for sessionStorage:workspace.tools.no-data-test.");
935969
await page.locator('[data-session-inspector-v2-entry-id="sessionStorage:workspace.tools.no-dirty-test"]').click();

tools/session-inspector-v2/styles/sessionInspectorV2.css

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,9 @@ button:hover {
173173
}
174174

175175
.session-inspector-v2__accordion--detail.is-open {
176-
flex: 1 1 0;
176+
flex: 0 1 auto;
177177
min-height: 0;
178+
max-height: clamp(126px, 24vh, 190px);
178179
}
179180

180181
.session-inspector-v2__accordion--detail-scroll.is-open {
@@ -245,17 +246,21 @@ button:hover {
245246
}
246247

247248
.session-inspector-v2__detail-scroll-content {
248-
max-height: clamp(86px, 17vh, 142px);
249-
overflow: auto;
249+
overflow: hidden;
250250
}
251251

252-
.session-inspector-v2__accordion--detail .session-inspector-v2__output {
253-
min-height: 0;
252+
.session-inspector-v2__accordion--detail > .accordion-v2__content {
253+
overflow: hidden;
254254
}
255255

256-
.session-inspector-v2__detail-scroll-content > .session-inspector-v2__output {
257-
flex: 0 0 auto;
258-
overflow: visible;
256+
.session-inspector-v2__accordion--detail .session-inspector-v2__output {
257+
flex: 1 1 auto;
258+
max-height: clamp(86px, 17vh, 142px);
259+
min-height: 0;
260+
overflow: auto;
261+
overflow-wrap: normal;
262+
white-space: pre;
263+
word-break: normal;
259264
}
260265

261266
.session-inspector-v2__actions {

0 commit comments

Comments
 (0)