diff --git a/.lantern/lang/en/src/renderer/lib/lantern-pixi.lantern.json b/.lantern/lang/en/src/renderer/lib/lantern-pixi.lantern.json index 535db68..ae1a55e 100644 --- a/.lantern/lang/en/src/renderer/lib/lantern-pixi.lantern.json +++ b/.lantern/lang/en/src/renderer/lib/lantern-pixi.lantern.json @@ -1,12 +1,12 @@ { "text": { "edge-graphics.ts": "Draws directional graph curves with relation-specific dashes and arrowheads", - "index.ts": "Renders the interactive WebGL graph, file or macro, with viewport culling, accessible controls and the pull request marks and the open-file marker on macro blocks, links and outside systems, with the marks calmed and other blocks greyed while a file or a picked flow step's files are open (the marker takes a set of blocks), draws a block a selected platform only uses fainter than a lit one and stronger than a dimmed one, and opens a macro area card or stub on a double tap or Enter without letting a removed focused card re-enter the render. It gives the canvas a tooltip of the block or link under the pointer that follows it", + "index.ts": "Renders the interactive WebGL graph, file or macro, with viewport culling, accessible controls and the pull request marks and the open-file marker on macro blocks, links and outside systems, with the marks calmed and other blocks greyed while a file or a picked flow step's files are open (the marker takes a set of blocks), draws a block a selected platform only uses fainter than a lit one and stronger than a dimmed one, and opens a macro area card or stub on a double tap or Enter without letting a removed focused card re-enter the render. It gives the canvas a tooltip of the block or link under the pointer that follows it, and clears the selection only on a primary-button tap of the background", "macro-graphics.ts": "Draws the macro view's arrows and count labels with strong ones emphasised, only the main links at rest and every link of the selected block, lights the links a pull request touches and quiets the rest, keeps only the links of the blocks being read prominent while a file or a flow step's files are open, and mirrors each arrow as a hidden note for screen readers.", - "node-graphics.ts": "Draws file cards, directory tiles and macro blocks with their purpose lines, a quieter look for shared foundation and a glow with changed-of-all files for blocks a pull request touches (a thin outline and the caption only while a file is open), a ringed READING badge on the block of the open file (frame widths from the shared legend list), a dashed edge for a card of features not yet in an area and an open chevron on area cards and stubs, with icons, status marks, PR badges, a quiet related mark, a dashed new look for files a pull request or a plan adds, and open-file buttons", - "open-actions.ts": "Draws the code and diff buttons on relation-view file tiles and their keyboard-reachable twins", + "node-graphics.ts": "Draws file cards, directory tiles and macro blocks with their purpose lines, a quieter look for shared foundation and a glow with changed-of-all files for blocks a pull request touches (a thin outline and the caption only while a file is open), a ringed READING badge on the block of the open file (frame widths from the shared legend list), a dashed edge for a card of features not yet in an area and an open chevron on area cards and stubs, with icons, status marks, PR badges, a quiet related mark, a dashed new look for files a pull request or a plan adds, and open-file buttons, all of which answer a primary-button tap only", + "open-actions.ts": "Draws the code and diff buttons on relation-view file tiles and their keyboard-reachable twins, and tells a primary-button tap from a right or middle one", "palette.ts": "Reads graph CSS colors and fonts for Pixi drawing", - "relation-graphics.ts": "Draws relation-view zones, directory areas and focused-file edges", + "relation-graphics.ts": "Draws relation-view zones, directory areas that a primary-button tap pins, and focused-file edges", "text-quality.ts": "Defers text-resolution upgrades until graph zoom settles", "viewport-size.ts": "Measures the graph pane by its border box, to notice real resizes, and without rounding a fractional size up, so the canvas never overflows its own scroll area" } diff --git a/.lantern/lang/en/test/e2e.lantern.json b/.lantern/lang/en/test/e2e.lantern.json index ad4d98e..94cee9e 100644 --- a/.lantern/lang/en/test/e2e.lantern.json +++ b/.lantern/lang/en/test/e2e.lantern.json @@ -1,12 +1,12 @@ { "text": { "flow-layout.spec.ts": "Checks in a real Chromium that the Flow rows and file chips wrap inside the narrowest right pane without overflowing, that a picked step keeps its amber border and glow while hovered, and that reading steps get a badge while the rest is greyed; skips when no Chromium can be launched", - "graph-macro-areas.spec.ts": "Checks in the real app that the Macro view opens on the areas map with no layout to choose, enters one with a double-click and leaves it with Escape, Backspace or the breadcrumb, goes sideways to another area from the panel and keeps the entered area across Files, and that a pull request lights the areas it touches and the reading marker moves between areas while stepping.", - "graph-macro-systems.spec.ts": "Checks on the evaluation project at 1600 by 1000 and 1280 by 800 that the outside systems list is always there under the map with every system and its count, filters to what a clicked block talks to with Show all, lights every area and foundation entry that talks to a clicked system with counts and a side panel grouped by area and feature, is cleared by a second click or Escape, never clips text, and can be driven with the keyboard; saves screenshots.", + "graph-macro-areas.spec.ts": "Checks in the real app that the Macro view opens on the areas map with no layout to choose, enters one with a double-click and leaves it with Escape, Backspace or the breadcrumb, goes sideways to another area from the Overview drawer and keeps the entered area across Files, and that a pull request lights the areas it touches and the reading marker moves between areas while stepping.", + "graph-macro-systems.spec.ts": "Checks on the evaluation project at 1600 by 1000 and 1280 by 800 that the outside systems list is always there under the map with every system and its count, filters to what a clicked block talks to with Show all, lights every area and foundation entry that talks to a clicked system with counts and an Overview drawer grouped by area and feature, is cleared by a second click or Escape, never clips text, and can be driven with the keyboard; saves screenshots.", "graph-macroview.spec.ts": "Drives the areas map in the real app on three projects at two window sizes: every area fits above the outside systems list, no page scroll or zoom, marks at the right zoom, keys, wheel, breadcrumb, the Macro view mounting once, and screenshots.", - "graph-macro-foundation.spec.ts": "Checks in the real app, on the evaluation project, that selecting a foundation tile lists what it uses and where its platform has files and lights its partners on the areas map, and that an area shows its platforms.", - "graph-macro-legend.spec.ts": "Checks in the real app that the Macro legend is short, fits the side panel, and that its swatches (selected, uses, To assign) are painted exactly like the shapes on the map, and screenshots the areas map and flat keys.", - "graph-macro-platform-uses.spec.ts": "Checks in the real app that of two bots of one kind the accounts area is lit strongly for the one with files there and as uses for the one that only uses it, with the legend drawing it the same solid way, lists both in the side panel, lights nothing as uses at rest and screenshots each.", + "graph-macro-foundation.spec.ts": "Checks in the real app, on the evaluation project, that selecting a foundation tile in the Overview drawer lists what it uses and where its platform has files and lights its partners on the areas map, and that an area shows its platforms.", + "graph-macro-legend.spec.ts": "Checks in the real app that the Macro legend in the Overview drawer is short, fits it, and that its swatches (selected, uses, To assign) are painted exactly like the shapes on the map, and screenshots the areas map and flat keys.", + "graph-macro-platform-uses.spec.ts": "Checks in the real app that of two bots of one kind the accounts area is lit strongly for the one with files there and as uses for the one that only uses it, with the legend drawing it the same solid way, lists both in the Overview drawer, lights nothing as uses at rest and screenshots each.", "graph-macro.spec.ts": "Checks the macro view in the real canvas: the counts drawn at rest, readable names, selection, Escape and the way back to the file graph.", "graph-navigation.spec.ts": "Checks graph zoom, panning, right-drag, overscroll, focus and input behaviour in Electron", "graph-pixi.spec.ts": "Checks WebGL rendering, retained tile text across zoom, interaction and failure recovery", @@ -23,7 +23,7 @@ "tsconfig.json": "Configures type checking for browser tests and their production dependencies", "pr-review-explain.spec.ts": "Checks in a real Chromium that the Explain panel shows its four sections and that collapsing it with the keyboard gives the file view its height back", "pr-review-regions.spec.ts": "Checks at 1280x800 that hiding each review area gives its width to the rest with no horizontal overflow, that the last of viewer and graph stays, and that the layout is remembered per project and reset", - "pane-overflow.spec.ts": "Drags both review dividers to their extremes at 1280x800 and 1600x1000, also with a saved comment card, a file comment and an open comment box, and fails when text is cut off at a pane edge or the graph is wider than its pane, including the areas map with the outside systems list for a picked system and a picked area", + "pane-overflow.spec.ts": "Drags both review dividers to their extremes at 1280x800 and 1600x1000, also with a saved comment card, a file comment and an open comment box, and fails when text is cut off at a pane edge or the graph is wider than its pane, including the areas map with the outside systems list for a picked area and, with the Overview drawer open, for a picked system", "pr-review-comments.spec.ts": "Comments on diff lines and on the whole file in the real app, checks the card sits under its line, copies the comments, keeps them over a reload, covers the gutter drag, edit, fold and delete, and marks a comment as a question and copies a mixed set and then an all-question set" } } diff --git a/.lantern/lang/en/test/e2e/support.lantern.json b/.lantern/lang/en/test/e2e/support.lantern.json index 643421a..ab6e77a 100644 --- a/.lantern/lang/en/test/e2e/support.lantern.json +++ b/.lantern/lang/en/test/e2e/support.lantern.json @@ -5,6 +5,7 @@ "tray-popover-harness.ts": "Bundles the popover page and launches the hidden Electron popover harness at a chosen pixel density, finds its frame and lets a test open or update the popover with a model and read the calls it made", "skills-extras-harness.ts": "Builds and launches the Electron Skills window harness over a temporary home and a git project seeded with installed skills and extras files, resolving the import aliases in its bundles, and cleans them up", "integrations-harness.ts": "Builds and launches the Electron Integrations harness with git projects and a stub provider server, resolving the import aliases and loading svg icons as text in its bundles, and cleans them up", - "overflow.ts":"Finds text cut off at a pane edge and ellipsised names that are squeezed or have no tooltip (a title or a data-tip)" + "overflow.ts":"Finds text cut off at a pane edge, in the Macro Overview drawer too, and ellipsised names that are squeezed or have no tooltip (a title or a data-tip)", + "overview.ts": "Opens and closes the Macro Overview drawer, which holds the chips, legend and details of the picked block, so a spec can read or leave them" } } diff --git a/.lantern/map/src/renderer/lib/lantern-pixi.lantern b/.lantern/map/src/renderer/lib/lantern-pixi.lantern index 8ce4077..0c5aa27 100644 --- a/.lantern/map/src/renderer/lib/lantern-pixi.lantern +++ b/.lantern/map/src/renderer/lib/lantern-pixi.lantern @@ -6,7 +6,7 @@ src/renderer/lib/lantern-pixi/edge-graphics.ts . component 42b2871e19fb < src/renderer/lib/lanternctx.ts < src/renderer/lib/lanternlayout.ts#EdgeCurve -src/renderer/lib/lantern-pixi/index.ts . component 3b371b3b5ddc +src/renderer/lib/lantern-pixi/index.ts . component 77ff3400d9ac #feature file-graph = src/renderer/lib/lantern-pixi/edge-graphics.ts = src/renderer/lib/lantern-pixi/macro-graphics.ts#macroGraphics @@ -42,7 +42,7 @@ src/renderer/lib/lantern-pixi/macro-graphics.ts . component f7cbb30b31b9 < src/renderer/lib/lanternmacromarks.ts#MacroMarks < src/renderer/lib/lanternmacrostyles.ts#FLAT_LINE -src/renderer/lib/lantern-pixi/node-graphics.ts . component 328fa50108b8 +src/renderer/lib/lantern-pixi/node-graphics.ts . component c33a2f532103 #feature file-graph = src/renderer/lib/file-icons.ts#fileIconUrl = src/renderer/lib/lantern-pixi/open-actions.ts @@ -58,16 +58,17 @@ src/renderer/lib/lantern-pixi/node-graphics.ts . component 328fa50108b8 = src/renderer/lib/lanterntile.ts#tileSlots < src/shared/lantern-plan-messages.ts#say -src/renderer/lib/lantern-pixi/open-actions.ts . component c2a927bdb69f +src/renderer/lib/lantern-pixi/open-actions.ts . component e712cc868338 #feature file-graph < src/renderer/lib/lantern-pixi/palette.ts#PixiPalette src/renderer/lib/lantern-pixi/palette.ts . util efd6ac83e6b9 #feature file-graph -src/renderer/lib/lantern-pixi/relation-graphics.ts . component c0080dd4be42 +src/renderer/lib/lantern-pixi/relation-graphics.ts . component 8ea124725b7a #feature file-graph = src/renderer/lib/lantern-pixi/edge-graphics.ts#drawEdge + = src/renderer/lib/lantern-pixi/open-actions.ts#isPrimaryTap < src/renderer/lib/lantern-pixi/palette.ts#PixiPalette < src/renderer/lib/lanternlayout.ts = src/renderer/lib/lanternprofile.ts#Profile diff --git a/.lantern/map/test/e2e.lantern b/.lantern/map/test/e2e.lantern index b64cf51..63cffea 100644 --- a/.lantern/map/test/e2e.lantern +++ b/.lantern/map/test/e2e.lantern @@ -7,26 +7,31 @@ test/e2e/flow-layout.spec.ts . test 271946bc6dd3 = src/renderer/lib/lanternflow.ts#flowHtml = test/fixtures/graph/pr-review-demo.ts#prReviewDemo -test/e2e/graph-macro-areas.spec.ts . test e2dc7142c1c2 +test/e2e/graph-macro-areas.spec.ts . test 07b2b9d4aa41 #feature product-areas = test/e2e/support/graph-harness.ts + = test/e2e/support/overview.ts#openOverview -test/e2e/graph-macro-foundation.spec.ts . test 35c636b38801 +test/e2e/graph-macro-foundation.spec.ts . test 01506182f3f4 #feature macro-view = test/e2e/support/graph-harness.ts + = test/e2e/support/overview.ts#openOverview -test/e2e/graph-macro-legend.spec.ts . test cd8e5c5067b4 +test/e2e/graph-macro-legend.spec.ts . test 3fc435cdb38d #feature macro-view = test/e2e/support/graph-harness.ts#launchGraphHarness + = test/e2e/support/overview.ts#openOverview -test/e2e/graph-macro-platform-uses.spec.ts . test 29ba7e10682c +test/e2e/graph-macro-platform-uses.spec.ts . test 676157fc745d #feature macro-view = test/e2e/support/graph-harness.ts + = test/e2e/support/overview.ts#openOverview -test/e2e/graph-macro-systems.spec.ts . test 593952fe7774 +test/e2e/graph-macro-systems.spec.ts . test d5fd27d04ab3 #feature macro-view = test/e2e/support/graph-harness.ts#launchGraphHarness = test/e2e/support/overflow.ts#findClippedText + = test/e2e/support/overview.ts#openOverview test/e2e/graph-macroview.spec.ts . test e2b1c81155f8 #feature macro-view @@ -38,11 +43,11 @@ test/e2e/graph-macro.spec.ts . test 0f4c5055ed0f = test/e2e/support/graph-harness.ts = test/fixtures/lantern-macro-own-view.json -test/e2e/graph-navigation.spec.ts . test ba58988b46e7 +test/e2e/graph-navigation.spec.ts . test 0910cf6edfbd #feature file-graph = test/e2e/support/graph-harness.ts -test/e2e/graph-pixi.spec.ts . test 0140b656f39e +test/e2e/graph-pixi.spec.ts . test b75dd27e683c #feature file-graph = test/e2e/support/graph-harness.ts @@ -76,13 +81,14 @@ test/e2e/lsp-semantic.spec.ts . test 8530fca71fbc < test/e2e/lsp-app/main.ts < test/e2e/lsp-app/renderer.ts -test/e2e/pane-overflow.spec.ts . test 19f9901a956e +test/e2e/pane-overflow.spec.ts . test 5ef61d648f76 #feature review-screen = test/e2e/support/comments.ts = test/e2e/support/graph-harness.ts = test/e2e/support/overflow.ts + = test/e2e/support/overview.ts#openOverview -test/e2e/pr-review-comments.spec.ts . test 47edbc30971b +test/e2e/pr-review-comments.spec.ts . test af5931f154a5 #feature review-comments = test/e2e/support/comments.ts = test/e2e/support/graph-harness.ts @@ -107,7 +113,7 @@ test/e2e/pr-review-layout.spec.ts . test b31d6d6780c3 #feature review-screen = test/e2e/support/graph-harness.ts -test/e2e/pr-review-regions.spec.ts . test 508852413011 +test/e2e/pr-review-regions.spec.ts . test 207028749040 #feature review-screen = test/e2e/support/graph-harness.ts diff --git a/.lantern/map/test/e2e/support.lantern b/.lantern/map/test/e2e/support.lantern index d13c154..03b79e0 100644 --- a/.lantern/map/test/e2e/support.lantern +++ b/.lantern/map/test/e2e/support.lantern @@ -32,5 +32,8 @@ test/e2e/support/tray-popover-harness.ts . test ea7204fb7ef6 > test/e2e/app/tray-popover-main.cjs > test/e2e/app/tray-popover-renderer.ts -test/e2e/support/overflow.ts . test 72fc9d9b1d56 +test/e2e/support/overflow.ts . test 671fe415a7ee #feature review-screen + +test/e2e/support/overview.ts . test 93bb4257d74c +#feature macro-view diff --git a/.lantern/prs/34.pr b/.lantern/prs/34.pr new file mode 100644 index 0000000..8384d61 --- /dev/null +++ b/.lantern/prs/34.pr @@ -0,0 +1,88 @@ +lantern-pr 1 +# 34 +#title fix: make the macro, PR review and graph e2e scripts pass +#url https://github.com/MobileReality/lantern/pull/34 +#branch fix/e2e-specs-green +#base main +#opened 2026-11-11 +#head ef39bc9b1e4b28ec0f9d691a357b24c7818be37f +#describe what The macro, PR review and graph e2e scripts now exit zero: 25 failing specs follow the current UI, 1 was a real app bug, 2 were stale pixel baselines. +#describe what Only the primary mouse button now selects or pins in the Pixi graph, so a right-click or right-drag no longer selects a card and scrolls the view. +#describe before Baseline: macro 13 failed, PR review 5, graph 9; a right-click on a node selected it. +#describe after Macro 41, PR review 10 and graph 42 tests pass, twice in a row; a right-click leaves the selection alone. +#describe verified typecheck, lint, pnpm test, and the three e2e scripts twice each. ++ test/e2e/support/overview.ts +~ src/renderer/lib/lantern-pixi/index.ts +~ src/renderer/lib/lantern-pixi/node-graphics.ts +~ src/renderer/lib/lantern-pixi/open-actions.ts +~ src/renderer/lib/lantern-pixi/relation-graphics.ts +~ test/e2e/graph-macro-areas.spec.ts +~ test/e2e/graph-macro-foundation.spec.ts +~ test/e2e/graph-macro-legend.spec.ts +~ test/e2e/graph-macro-platform-uses.spec.ts +~ test/e2e/graph-macro-systems.spec.ts +~ test/e2e/graph-navigation.spec.ts +~ test/e2e/graph-pixi.spec.ts +~ test/e2e/pane-overflow.spec.ts +~ test/e2e/pr-review-comments.spec.ts +~ test/e2e/pr-review-regions.spec.ts +~ test/e2e/snapshots/darwin/pixi-overview.png +~ test/e2e/snapshots/darwin/pixi-selected.png +~ test/e2e/support/overflow.ts +#order src/renderer/lib/lantern-pixi/open-actions.ts +#order src/renderer/lib/lantern-pixi/node-graphics.ts +#order src/renderer/lib/lantern-pixi/relation-graphics.ts +#order src/renderer/lib/lantern-pixi/index.ts +#order test/e2e/support/overview.ts +#order test/e2e/support/overflow.ts +#order test/e2e/graph-macro-areas.spec.ts +#order test/e2e/graph-macro-foundation.spec.ts +#order test/e2e/graph-macro-legend.spec.ts +#order test/e2e/graph-macro-platform-uses.spec.ts +#order test/e2e/graph-macro-systems.spec.ts +#order test/e2e/pane-overflow.spec.ts +#order test/e2e/pr-review-comments.spec.ts +#order test/e2e/pr-review-regions.spec.ts +#order test/e2e/graph-navigation.spec.ts +#order test/e2e/graph-pixi.spec.ts +#order test/e2e/snapshots/darwin/pixi-overview.png +#order test/e2e/snapshots/darwin/pixi-selected.png +#reason test/e2e/support/overview.ts One place that opens and closes the Overview drawer for the macro specs. +#reason src/renderer/lib/lantern-pixi/index.ts Stops a right or middle click on the canvas background from clearing the selection and scrolling. +#reason src/renderer/lib/lantern-pixi/node-graphics.ts A right-click on a node, tile or block used to select it and start a scroll animation that fought the right-drag pan. +#reason src/renderer/lib/lantern-pixi/open-actions.ts Names the primary-button check once so every Pixi tap handler can share it. +#reason src/renderer/lib/lantern-pixi/relation-graphics.ts A right-click on a relation area no longer pins it. +#reason test/e2e/graph-macro-areas.spec.ts The panel it reads is now the Overview drawer, which is hidden until opened. +#reason test/e2e/graph-macro-foundation.spec.ts The chips and details it clicks now live in the Overview drawer. +#reason test/e2e/graph-macro-legend.spec.ts The legend is in the Overview drawer, and the map must be clicked with the drawer shut. +#reason test/e2e/graph-macro-platform-uses.spec.ts The chips and the legend it reads are in the Overview drawer. +#reason test/e2e/graph-macro-systems.spec.ts The system details are in the Overview drawer, so the spec opens it to read them and closes it to click the list. +#reason test/e2e/graph-navigation.spec.ts The hidden Overview aside also matches the side-panel selector, which broke strict mode. +#reason test/e2e/graph-pixi.spec.ts The canvas tooltip is carried by data-tip now, not title. +#reason test/e2e/pane-overflow.spec.ts Opens the Overview drawer for the picked system and picks the Explain intent before the Explain chip of the new composer. +#reason test/e2e/pr-review-comments.spec.ts The first card in the review body is the hidden one, so geometry is scoped to the visible body. +#reason test/e2e/pr-review-regions.spec.ts The hidden Overview aside also matches the side-panel selector, which broke strict mode. +#reason test/e2e/snapshots/darwin/pixi-overview.png Baseline predated the redesigned PR strip, so it is regenerated. +#reason test/e2e/snapshots/darwin/pixi-selected.png Baseline predated the redesigned PR strip, so it is regenerated. +#reason test/e2e/support/overflow.ts Checks the Overview drawer for clipped text when it is open. +#story Right-clicking the graph no longer selects +#step actor A reviewer +#step action right-clicks or right-drags on the graph +#file src/renderer/lib/lantern-pixi/node-graphics.ts +#file src/renderer/lib/lantern-pixi/index.ts +#step subject a file card, tile, block or area +#file src/renderer/lib/lantern-pixi/relation-graphics.ts +#file src/renderer/lib/lantern-pixi/open-actions.ts +#below interaction Pan with the right button without the view jumping +#below consequence A right-click selected the card and scrolled => Only the primary button selects +#story The e2e scripts can be trusted again +#step actor A maintainer +#step action runs the macro, review and graph e2e scripts +#file test/e2e/support/overview.ts +#file test/e2e/graph-macro-systems.spec.ts +#file test/e2e/pr-review-comments.spec.ts +#step subject the specs that follow the current UI +#file test/e2e/graph-pixi.spec.ts +#file test/e2e/snapshots/darwin/pixi-overview.png +#below interaction Get a pass or a failure that means something +#below consequence 27 specs failed on a stale UI => All three scripts exit zero diff --git a/src/renderer/lib/lantern-pixi/index.ts b/src/renderer/lib/lantern-pixi/index.ts index 843dcd6..19f5380 100644 --- a/src/renderer/lib/lantern-pixi/index.ts +++ b/src/renderer/lib/lantern-pixi/index.ts @@ -23,7 +23,7 @@ import { blockKindText, captionOf } from '../lanternmacro'; import { OPEN_FILE_LABEL } from '../lanternmacrocurrent'; import { calmedAlpha, isMarked, markNote, markedAlpha, systemsOfBlocks, weakNearAlpha } from '../lanternmacromarks'; import type { MacroMarks } from '../lanternmacromarks'; -import { syncOpenButtons } from './open-actions'; +import { isPrimaryTap, syncOpenButtons } from './open-actions'; import type { FileActions } from './open-actions'; const CULL_MARGIN = 0; @@ -159,7 +159,7 @@ class PixiGraph { this.app.stage.eventMode = 'static'; this.app.stage.hitArea = this.app.screen; this.app.stage.on('pointertap', (event) => { - if (event.target === this.app.stage) this.options.onBackground(); + if (event.target === this.app.stage && isPrimaryTap(event)) this.options.onBackground(); }); this.options.host.prepend(this.app.canvas); this.app.canvas.className = 'lt-pixi-canvas'; diff --git a/src/renderer/lib/lantern-pixi/node-graphics.ts b/src/renderer/lib/lantern-pixi/node-graphics.ts index b189958..ec22c88 100644 --- a/src/renderer/lib/lantern-pixi/node-graphics.ts +++ b/src/renderer/lib/lantern-pixi/node-graphics.ts @@ -14,7 +14,7 @@ import { markCaption } from '../lanternmacromarks'; import type { BlockMark } from '../lanternmacromarks'; import { PURPOSE_LINE_H } from '../lanternmacrocards'; import { FLAT_LINE } from '../lanternmacrostyles'; -import { actionsWidth, drawFileActions } from './open-actions'; +import { actionsWidth, drawFileActions, isPrimaryTap } from './open-actions'; import type { FileActions } from './open-actions'; const CARD_TEXT_Y = 4; @@ -90,6 +90,7 @@ function tileDisplay(position: Pos, palette: PixiPalette, fonts: PixiFonts, scal label.position.set(TILE_PAD, (h - size * 1.2) / 2); display.addChild(label); display.on('pointertap', (event: FederatedPointerEvent) => { + if (!isPrimaryTap(event)) return; event.stopPropagation(); activate(); }); @@ -153,6 +154,7 @@ function blockDisplay(position: Pos, palette: PixiPalette, fonts: PixiFonts, act display.addChild(caption); if (current) display.addChild(openFileBadge(position, palette, fonts)); display.on('pointertap', (event: FederatedPointerEvent) => { + if (!isPrimaryTap(event)) return; event.stopPropagation(); activate(); }); @@ -207,6 +209,7 @@ export function nodeDisplay(position: Pos, profile: Profile, palette: PixiPalett label.position.set(slots.labelX, CARD_TEXT_Y); display.addChild(label); display.on('pointertap', (event: FederatedPointerEvent) => { + if (!isPrimaryTap(event)) return; event.stopPropagation(); activate(); }); diff --git a/src/renderer/lib/lantern-pixi/open-actions.ts b/src/renderer/lib/lantern-pixi/open-actions.ts index ae489f1..09f3d3c 100644 --- a/src/renderer/lib/lantern-pixi/open-actions.ts +++ b/src/renderer/lib/lantern-pixi/open-actions.ts @@ -15,6 +15,10 @@ const BUTTON_GAP = 2; const EDGE_GAP = 4; const PRIMARY_BUTTON = 0; +export function isPrimaryTap(event: FederatedPointerEvent) { + return event.button === PRIMARY_BUTTON; +} + export function actionsWidth(actions: FileActions | null) { if (!actions) return 0; const count = actions.diff ? 2 : 1; @@ -52,7 +56,7 @@ function openButton(kind: OpenKind, x: number, y: number, palette: PixiPalette, button.on('pointerout', () => show(false)); button.on('pointertap', (event: FederatedPointerEvent) => { event.stopPropagation(); - if (event.button === PRIMARY_BUTTON) open(); + if (isPrimaryTap(event)) open(); }); return button; } diff --git a/src/renderer/lib/lantern-pixi/relation-graphics.ts b/src/renderer/lib/lantern-pixi/relation-graphics.ts index e4bc087..cdab7d7 100644 --- a/src/renderer/lib/lantern-pixi/relation-graphics.ts +++ b/src/renderer/lib/lantern-pixi/relation-graphics.ts @@ -5,6 +5,7 @@ import type { RelationLayout, Refs, Side, Zone } from '../lanternrelview'; import type { PixiPalette } from './palette'; import { drawEdge } from './edge-graphics'; import type { Profile } from '../lanternprofile'; +import { isPrimaryTap } from './open-actions'; const ZONE_NAMES: Record> = { in: { none: 'Takes data from', mixed: 'Takes data from, referred to by', all: 'Referred to by' }, @@ -72,6 +73,7 @@ function relationGraphics(options: RelationGraphicsOptions) { count.position.set(area.x + area.w - count.width - 9, area.y + 7); areaContainer.addChild(name, count); areaContainer.on('pointertap', (event: FederatedPointerEvent) => { + if (!isPrimaryTap(event)) return; event.stopPropagation(); options.onArea(area.key); }); diff --git a/test/e2e/graph-macro-areas.spec.ts b/test/e2e/graph-macro-areas.spec.ts index d03d79b..73c32aa 100644 --- a/test/e2e/graph-macro-areas.spec.ts +++ b/test/e2e/graph-macro-areas.spec.ts @@ -1,6 +1,7 @@ import { expect, test } from '@playwright/test'; import type { Page } from '@playwright/test'; import { closeGraphHarness, launchGraphHarness, loadGraphFixture } from './support/graph-harness'; +import { closeOverview, openOverview, overview } from './support/overview'; const SETTLE_MS = 700; const AREAS = ['block:project-map', 'block:pull-request-review', 'block:agent-sessions', 'block:workspace-setup', 'block:to-assign']; @@ -52,7 +53,7 @@ test('opens on the areas, enters one with a double-click and comes back with Esc const at = await centreOf(page, 'block:project-map'); await page.mouse.click(at.x, at.y); await expect(item(page, 'block:project-map')).toHaveAttribute('aria-pressed', 'true'); - await expect(page.locator('.lt-side .lt-detail')).toContainText('mapping a project and reading its code'); + await expect(overview(page).locator('.lt-detail')).toContainText('mapping a project and reading its code'); await page.screenshot({ path: testInfo.outputPath('areas-level-0-picked.png') }); await dive(page, 'block:project-map'); @@ -84,9 +85,11 @@ test('goes sideways to another area from the panel, back with Backspace and with await expect(crumbs(page)).toContainText('Project map'); expect(await keysOf(page, '.mv-feature')).toEqual(expect.arrayContaining(MAP_FEATURES)); - await page.locator('.lt-side .chip[data-macro-go="block:pull-request-review"]').click(); - await expect(page.locator('.lt-side .lt-detail')).toContainText('relation'); - await page.locator('.lt-side .lt-detail [data-macro-enter]').click(); + await openOverview(page); + await overview(page).locator('.chip[data-macro-go="block:pull-request-review"]').click(); + await expect(overview(page).locator('.lt-detail')).toContainText('relation'); + await overview(page).locator('.lt-detail [data-macro-enter]').click(); + await closeOverview(page); await settle(page); await expect(crumbs(page)).toContainText('Pull request review'); diff --git a/test/e2e/graph-macro-foundation.spec.ts b/test/e2e/graph-macro-foundation.spec.ts index 750b2ed..c6f1fa1 100644 --- a/test/e2e/graph-macro-foundation.spec.ts +++ b/test/e2e/graph-macro-foundation.spec.ts @@ -1,11 +1,12 @@ import { expect, test } from '@playwright/test'; import type { Page } from '@playwright/test'; import { closeGraphHarness, launchGraphHarness, loadGraphFixture } from './support/graph-harness'; +import { openOverview, overview } from './support/overview'; const WIDE = '1600x1000'; const map = (page: Page) => page.locator('.lt-macroview'); -const chip = (page: Page, name: string) => page.locator('.lt-side .chip', { hasText: name }).first(); -const sentences = (page: Page) => page.locator('.lt-side .lt-detail .lt-sentence'); +const chip = (page: Page, name: string) => overview(page).locator('.chip', { hasText: name }).first(); +const sentences = (page: Page) => overview(page).locator('.lt-detail .lt-sentence'); async function settle(page: Page) { await page.evaluate(() => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(() => resolve())))); @@ -20,6 +21,7 @@ async function open() { await loadGraphFixture(harness, 'macro-lab'); await harness.page.getByRole('button', { name: /^Macro/ }).click(); await expect(map(harness.page)).toBeVisible(); + await openOverview(harness.page); return harness; } @@ -29,7 +31,7 @@ test('lists what the infrastructure platform connects to and lights its partners const { page } = harness; await chip(page, 'Infrastructure').click(); await settle(page); - await expect(page.locator('.lt-side .lt-detail')).not.toContainText('No relations to other blocks'); + await expect(overview(page).locator('.lt-detail')).not.toContainText('No relations to other blocks'); await expect(sentences(page).filter({ hasText: /^Uses / })).toContainText(['Service (2 relations)']); await expect(sentences(page).filter({ hasText: /^Uses / })).toContainText(['Storefront (2 relations)']); await expect(map(page).locator('.is-related')).toHaveCount(2); diff --git a/test/e2e/graph-macro-legend.spec.ts b/test/e2e/graph-macro-legend.spec.ts index 92b4451..0990e4f 100644 --- a/test/e2e/graph-macro-legend.spec.ts +++ b/test/e2e/graph-macro-legend.spec.ts @@ -4,13 +4,14 @@ import { macroGraph } from '../../src/renderer/lib/lanternmacro'; import type { MacroView } from '../../src/main/lantern-macro'; import ownView from '../fixtures/lantern-macro-own-view.json'; import { closeGraphHarness, launchGraphHarness, loadGraphFixture } from './support/graph-harness'; +import { closeOverview, openOverview, overview } from './support/overview'; const SETTLE_MS = 500; const LAPTOP = '1280x800'; const PAINTED = ['stroke', 'stroke-width', 'stroke-dasharray', 'fill', 'opacity']; const map = (page: Page) => page.locator('.lt-macroview'); -const legend = (page: Page) => page.locator('.lt-side .legend'); +const legend = (page: Page) => overview(page).locator('.legend'); const rows = (page: Page) => legend(page).locator('[data-legend]'); const ids = (page: Page) => rows(page).evaluateAll((nodes) => nodes.map((node) => node.getAttribute('data-legend'))); const shapeOf = (page: Page, key: string) => map(page).locator(`[data-key="${key}"]`).first().locator('> .mv-shape'); @@ -44,11 +45,14 @@ test('the areas map legend is short, fits the side panel, and its swatches are p try { const { page } = harness; + await openOverview(page); expect(await ids(page)).toEqual(['main', 'lit', 'pending', 'system']); await legend(page).scrollIntoViewIfNeeded(); await legend(page).screenshot({ path: testInfo.outputPath('legend-rest.png') }); + await closeOverview(page); await clickShape(page, 'block:ordering'); + await openOverview(page); expect(await ids(page)).toEqual(['main', 'selected', 'related', 'hot', 'dim', 'lit', 'pending', 'system']); await expect(shapeOf(page, 'block:ordering')).toBeVisible(); for (const [id, key] of [['selected', 'block:ordering'], ['related', 'block:payments'], ['lit', 'block:ordering']] as const) { @@ -65,7 +69,7 @@ test('the areas map legend is short, fits the side panel, and its swatches are p await legend(page).screenshot({ path: testInfo.outputPath('legend-selected.png') }); await page.screenshot({ path: testInfo.outputPath('legend-page-selected.png') }); - const side = (await page.locator('.lt-side').boundingBox())!; + const side = (await overview(page).boundingBox())!; for (const row of await rows(page).all()) { const box = (await row.boundingBox())!; expect(box.x + box.width).toBeLessThanOrEqual(side.x + side.width); @@ -81,7 +85,8 @@ test('with a platform selected the uses style is in the legend, drawn like the p const harness = await open(); try { const { page } = harness; - await page.locator('.lt-side .chip', { hasText: 'Help bot' }).first().click(); + await openOverview(page); + await overview(page).locator('.chip', { hasText: 'Help bot' }).first().click(); await page.waitForTimeout(SETTLE_MS); expect(await ids(page)).toContain('uses'); @@ -111,6 +116,7 @@ test('the legend of the flat Macro view shows the links it draws and two lines o await page.getByRole('button', { name: /^Macro/ }).click(); await expect(page.locator('.lt-pixi-node-access')).toHaveCount(graph.blocks.length); + await openOverview(page); expect(await ids(page)).toEqual(['strong', 'weak']); await expect(legend(page)).toContainText(/Strong link, \d+\+ relations/); await expect(legend(page).locator(':scope > p')).toHaveCount(2); diff --git a/test/e2e/graph-macro-platform-uses.spec.ts b/test/e2e/graph-macro-platform-uses.spec.ts index 0a49cfe..cb5f33b 100644 --- a/test/e2e/graph-macro-platform-uses.spec.ts +++ b/test/e2e/graph-macro-platform-uses.spec.ts @@ -1,11 +1,12 @@ import { expect, test } from '@playwright/test'; import type { Page } from '@playwright/test'; import { closeGraphHarness, launchGraphHarness, loadGraphFixture } from './support/graph-harness'; +import { openOverview, overview } from './support/overview'; const WIDE = '1600x1000'; const map = (page: Page) => page.locator('.lt-macroview'); -const chip = (page: Page, name: string) => page.locator('.lt-side .chip', { hasText: name }).first(); -const sentences = (page: Page) => page.locator('.lt-side .lt-detail .lt-sentence'); +const chip = (page: Page, name: string) => overview(page).locator('.chip', { hasText: name }).first(); +const sentences = (page: Page) => overview(page).locator('.lt-detail .lt-sentence'); const shape = (page: Page, key: string) => map(page).locator(`[data-key="${key}"]`); async function settle(page: Page) { @@ -23,6 +24,7 @@ async function open() { await expect(map(harness.page)).toBeVisible(); await harness.page.locator('[data-prmark]').click(); await expect(harness.page.locator('[data-prmark]')).toHaveAttribute('aria-pressed', 'false'); + await openOverview(harness.page); return harness; } @@ -66,14 +68,14 @@ test('lights the accounts area strongly for one bot and as uses for the other, a await expect(shape(page, 'block:sign-in')).toHaveClass(/is-uses/); await expect(shape(page, 'block:chat-channels')).toHaveClass(/is-related/); const outline = shape(page, 'block:accounts').locator('> .mv-shape'); - const key = page.locator('.lt-side .legend [data-legend="uses"] .mv-shape'); + const key = overview(page).locator('.legend [data-legend="uses"] .mv-shape'); await expect(key).toHaveCount(1); await expect(outline).toHaveCSS('stroke-dasharray', 'none'); await expect(key).toHaveCSS('stroke-dasharray', 'none'); for (const property of ['stroke', 'stroke-width']) expect(await key.evaluate((node, name) => getComputedStyle(node).getPropertyValue(name), property)).toBe(await outline.evaluate((node, name) => getComputedStyle(node).getPropertyValue(name), property)); - await expect(page.locator('.lt-side .legend [data-legend="pending"] .mv-shape')).toHaveCSS('stroke-dasharray', /7/); + await expect(overview(page).locator('.legend [data-legend="pending"] .mv-shape')).toHaveCSS('stroke-dasharray', /7/); await page.screenshot({ path: testInfo.outputPath('uses-help-bot.png') }); - await page.locator('.lt-side .legend').screenshot({ path: testInfo.outputPath('uses-legend.png') }); + await overview(page).locator('.legend').screenshot({ path: testInfo.outputPath('uses-legend.png') }); await pick(page, 'Help bot'); expect(harness.errors).toEqual([]); } finally { @@ -86,8 +88,8 @@ test('lights nothing as uses at rest, and the legend then shows only what the ma try { const { page } = harness; await expect(page.locator('.lt-macroview .is-uses')).toHaveCount(0); - await expect(page.locator('.lt-side .legend [data-legend="uses"]')).toHaveCount(0); - await expect(page.locator('.lt-side .legend [data-legend="selected"]')).toHaveCount(0); + await expect(overview(page).locator('.legend [data-legend="uses"]')).toHaveCount(0); + await expect(overview(page).locator('.legend [data-legend="selected"]')).toHaveCount(0); expect(harness.errors).toEqual([]); } finally { await closeGraphHarness(harness); diff --git a/test/e2e/graph-macro-systems.spec.ts b/test/e2e/graph-macro-systems.spec.ts index d19302c..b7a684a 100644 --- a/test/e2e/graph-macro-systems.spec.ts +++ b/test/e2e/graph-macro-systems.spec.ts @@ -3,6 +3,7 @@ import type { Page } from '@playwright/test'; import { closeGraphHarness, launchGraphHarness, loadGraphFixture } from './support/graph-harness'; import type { GraphHarness } from './support/graph-harness'; import { findClippedText } from './support/overflow'; +import { closeOverview, openOverview, overview } from './support/overview'; const SETTLE_MS = 600; const WIDE = '1600x1000'; @@ -15,7 +16,7 @@ const entries = (page: Page) => page.locator('.mv-dock .mv-system'); const entry = (page: Page, name: string) => page.locator('.mv-dock .mv-system', { has: page.locator('.mv-system-name', { hasText: new RegExp(`^${name}$`) }) }); const names = (page: Page) => entries(page).locator('.mv-system-name').allTextContents(); const note = (page: Page) => page.locator('.mv-dock-note'); -const detail = (page: Page) => page.locator('.lt-side .lt-detail'); +const detail = (page: Page) => overview(page).locator('.lt-detail'); const shape = (page: Page, key: string) => map(page).locator(`[data-key="${key}"]`).first().locator('> .mv-shape, > .mv-lane-shape'); async function settle(page: Page) { @@ -113,6 +114,7 @@ for (const viewport of [WIDE, LAPTOP]) { await entry(page, 'PostgreSQL').click(); await settle(page); await expect(entry(page, 'PostgreSQL')).toHaveAttribute('aria-pressed', 'true'); + await openOverview(page); await expect(map(page).locator('.mv-area.is-related')).toHaveCount(3); await expect(map(page).locator('[data-key="block:ordering"]')).toHaveClass(/is-related/); await expect(map(page).locator('[data-key="block:fulfilment"]')).toHaveClass(/is-related/); @@ -128,6 +130,7 @@ for (const viewport of [WIDE, LAPTOP]) { expect(await findClippedText(page)).toEqual([]); await page.screenshot({ path: testInfo.outputPath(`systems-selected-${viewport}.png`) }); + await closeOverview(page); await entry(page, 'PostgreSQL').click(); await expect(map(page).locator('.is-related, .is-dim')).toHaveCount(0); await expect(detail(page)).toHaveCount(0); @@ -142,7 +145,9 @@ for (const viewport of [WIDE, LAPTOP]) { try { const { page } = harness; await entry(page, 'PostgreSQL').click(); + await openOverview(page); await detail(page).locator('[data-macro-feature="stock-levels"]').click(); + await closeOverview(page); await settle(page); await expect(page.locator('.lt-graph-crumbs .lt-crumbs')).toContainText('Fulfilment'); await expect(map(page).locator('[data-key="block:stock-levels"]')).toHaveClass(/is-selected/); diff --git a/test/e2e/graph-navigation.spec.ts b/test/e2e/graph-navigation.spec.ts index 2d7dca9..f841c65 100644 --- a/test/e2e/graph-navigation.spec.ts +++ b/test/e2e/graph-navigation.spec.ts @@ -83,7 +83,7 @@ test.describe('pixi', () => { element.scrollTop = side === 'bottom' ? element.scrollHeight : 0; return { x: element.scrollLeft, y: element.scrollTop, width: element.scrollWidth, height: element.scrollHeight }; }, edge); - const fixedBefore = await Promise.all([toolbarOf(page).boundingBox(), page.locator('.lt-side').boundingBox()]); + const fixedBefore = await Promise.all([toolbarOf(page).boundingBox(), page.locator('.lt-side:not(.lt-overview)').boundingBox()]); await page.mouse.move(centre.x, centre.y); await page.mouse.down(); await expect.poll(cursor).toBe('grabbing'); @@ -95,7 +95,7 @@ test.describe('pixi', () => { expect(Math.abs(offset)).toBeLessThanOrEqual(20); const extents = await main.evaluate((element) => ({ width: element.scrollWidth, height: element.scrollHeight })); expect(extents).toEqual({ width: start.width, height: start.height }); - expect(await Promise.all([toolbarOf(page).boundingBox(), page.locator('.lt-side').boundingBox()])).toEqual(fixedBefore); + expect(await Promise.all([toolbarOf(page).boundingBox(), page.locator('.lt-side:not(.lt-overview)').boundingBox()])).toEqual(fixedBefore); await page.mouse.move(pushed.x - (horizontal ? 8 * direction : 0), pushed.y - (horizontal ? 0 : 8 * direction)); const reversed = await main.evaluate((element, axis) => Number.parseFloat(getComputedStyle(element).getPropertyValue(axis === 'x' ? '--lt-pan-x' : '--lt-pan-y')), horizontal ? 'x' : 'y'); expect(Math.abs(reversed)).toBeLessThan(Math.abs(offset)); diff --git a/test/e2e/graph-pixi.spec.ts b/test/e2e/graph-pixi.spec.ts index 2ed5b78..04dc8f1 100644 --- a/test/e2e/graph-pixi.spec.ts +++ b/test/e2e/graph-pixi.spec.ts @@ -397,7 +397,7 @@ test('matches all four relation edge styles and highlights the canvas node under if (!canvasBox) throw new Error('Pixi canvas is not visible'); await page.mouse.move(canvasBox.x + position.x - scroll.left + position.width / 2, canvasBox.y + position.y - scroll.top + position.height / 2); await expect(page.locator('html')).toHaveAttribute('data-graph-hovered', 'src/widget.tsx'); - await expect(canvas).toHaveAttribute('title', /src\/widget\.tsx/); + await expect(canvas).toHaveAttribute('data-tip', /src\/widget\.tsx/); await page.evaluate(() => new Promise((resolve) => { window.dispatchEvent(new Event('resize')); requestAnimationFrame(() => resolve()); @@ -456,7 +456,7 @@ test('matches all four relation edge styles and highlights the canvas node under y: 0.125 * fromPoint.y + 0.375 * control1.y + 0.375 * control2.y + 0.125 * toPoint.y, }; await page.mouse.move(canvasBox.x + midpoint.x - scroll.left, canvasBox.y + midpoint.y - scroll.top); - await expect(canvas).toHaveAttribute('title', /src\/selected-service\.ts > src\/page\.tsx#loadPage/); + await expect(canvas).toHaveAttribute('data-tip', /src\/selected-service\.ts > src\/page\.tsx#loadPage/); expect(harness.errors).toEqual([]); } finally { await closeGraphHarness(harness); diff --git a/test/e2e/pane-overflow.spec.ts b/test/e2e/pane-overflow.spec.ts index b692337..71af183 100644 --- a/test/e2e/pane-overflow.spec.ts +++ b/test/e2e/pane-overflow.spec.ts @@ -4,6 +4,7 @@ import type { GraphHarness } from './support/graph-harness'; import { closeGraphHarness, launchGraphHarness, loadGraphFixture } from './support/graph-harness'; import { VISIBLE_BODY, commentOnSelection, selectAddedLines } from './support/comments'; import { findClippedText } from './support/overflow'; +import { closeOverview, openOverview } from './support/overview'; const VIEWPORTS = ['1280x800', '1600x1000']; const SETTLE_MS = 400; @@ -20,6 +21,7 @@ interface Scenario { name: string; open: (harness: GraphHarness) => Promise; fit?: string; + overview?: boolean; } const ZOOM_FIT = '[data-zoom="fit"]'; @@ -52,17 +54,21 @@ const SCENARIOS: Scenario[] = [ await h.page.keyboard.press('Control+Enter'); await selectAddedLines(h.page, 3); await h.page.locator('.lt-cm-float').click(); + await h.page.locator('.lt-cm-box').getByRole('radio', { name: 'Explain' }).check(); await h.page.locator('.lt-cm-box').getByRole('button', { name: 'Explain why this is needed.' }).click(); await expect(h.page.locator('.lt-cm-box textarea')).toBeFocused(); }, }, { - name: 'areas macro with a system picked from the outside systems list and the side panel open', + name: 'areas macro with a system picked from the outside systems list and the overview open', fit: ZOOM_FIT, + overview: true, open: async (h) => { await openAreasMacro(h); await h.page.locator('.mv-dock .mv-system').first().click(); - await h.page.locator('.lt-side .lt-detail .lt-sys-uses').first().waitFor(); + await openOverview(h.page); + await h.page.locator('.lt-overview .lt-detail .lt-sys-uses').first().waitFor(); + await closeOverview(h.page); await h.page.waitForTimeout(SETTLE_MS); }, }, @@ -127,8 +133,10 @@ for (const viewport of VIEWPORTS) { await page.waitForTimeout(SETTLE_MS); for (const extreme of EXTREMES) { await moveDividers(page, extreme.left, extreme.middle); + if (scenario.overview) await openOverview(page); await page.screenshot({ path: testInfo.outputPath(`${extreme.name.replaceAll(' ', '-')}.png`) }); expect(await findClippedText(page), extreme.name).toEqual([]); + if (scenario.overview) await closeOverview(page); await page.locator(scenario.fit ?? '[data-zoom-fit]').click(); expect(await graphOverflow(page), `${extreme.name}: Fit leaves content past the pane`).toBeLessThanOrEqual(FIT_SLACK_PX); await moveDividers(page, extreme.middle, extreme.left); diff --git a/test/e2e/pr-review-comments.spec.ts b/test/e2e/pr-review-comments.spec.ts index 717895d..5a70d1b 100644 --- a/test/e2e/pr-review-comments.spec.ts +++ b/test/e2e/pr-review-comments.spec.ts @@ -23,11 +23,11 @@ test.afterAll(async () => { }); async function geometry(page: import('@playwright/test').Page) { - return page.evaluate(() => { + return page.evaluate((body) => { const rect = (selector: string) => document.querySelector(selector)?.getBoundingClientRect(); const review = rect('.lt-review'); - const card = rect('.lt-review-body .lt-cm-card'); - const row = [...document.querySelectorAll('.lt-review-body .cl.add')].find((each) => each.nextElementSibling?.classList.contains('lt-cm-card'))?.getBoundingClientRect(); + const card = rect(`${body} .lt-cm-card`); + const row = [...document.querySelectorAll(`${body} .cl.add`)].find((each) => each.nextElementSibling?.classList.contains('lt-cm-card'))?.getBoundingClientRect(); return { pageWidth: document.documentElement.scrollWidth, windowWidth: document.documentElement.clientWidth, @@ -38,7 +38,7 @@ async function geometry(page: import('@playwright/test').Page) { cardTop: card?.top ?? 0, rowBottom: row?.bottom ?? 0, }; - }); + }, VISIBLE_BODY); } test('comments on diff lines and on the whole file, shows them in the code, copies them and keeps them over a reload', async ({}, testInfo) => { @@ -65,7 +65,7 @@ test('comments on diff lines and on the whole file, shows them in the code, copi const card = page.locator(`${VISIBLE_BODY} .lt-cm-card`); await expect(card).toHaveCount(1); await expect(card.locator('.lt-cm-card-text')).toHaveText('Add a test for this. Cover the tax rounding.'); - const under = await page.evaluate(() => (document.querySelector('.lt-review-body .lt-cm-card')?.previousElementSibling?.querySelectorAll('.ln')[1]?.textContent ?? '')); + const under = await page.evaluate((body) => (document.querySelector(`${body} .lt-cm-card`)?.previousElementSibling?.querySelectorAll('.ln')[1]?.textContent ?? ''), VISIBLE_BODY); expect(under).toBe(lines[1]); const size = await geometry(page); expect(size.cardTop).toBeGreaterThanOrEqual(size.rowBottom - 1); @@ -105,7 +105,7 @@ test('comments on diff lines and on the whole file, shows them in the code, copi await expect(page.locator('.lt-cm-count')).toHaveText('2'); await expect(page.locator('.lt-cm-file .lt-cm-card .lt-cm-card-text')).toHaveText('Rename the module.'); await expect(page.locator(`${VISIBLE_BODY} .lt-cm-card .lt-cm-card-text`)).toHaveText('Add a test for this. Cover the tax rounding.'); - const after = await page.evaluate(() => document.querySelector('.lt-review-body .lt-cm-card')?.previousElementSibling?.querySelectorAll('.ln')[1]?.textContent ?? ''); + const after = await page.evaluate((body) => document.querySelector(`${body} .lt-cm-card`)?.previousElementSibling?.querySelectorAll('.ln')[1]?.textContent ?? '', VISIBLE_BODY); expect(after).toBe(lines[1]); await page.screenshot({ path: testInfo.outputPath('6-after-reload.png') }); }); diff --git a/test/e2e/pr-review-regions.spec.ts b/test/e2e/pr-review-regions.spec.ts index 7c3f98a..ad239b3 100644 --- a/test/e2e/pr-review-regions.spec.ts +++ b/test/e2e/pr-review-regions.spec.ts @@ -120,18 +120,18 @@ test('remembers the layout per project and forgets it on reset', async () => { const page = harness.page; await open('/e2e/gamma'); await page.keyboard.press('Alt+1'); - await expect(page.locator('.lt-side')).toBeHidden(); + await expect(page.locator('.lt-side:not(.lt-overview)')).toBeHidden(); await open('/e2e/gamma'); - await expect(page.locator('.lt-side')).toBeHidden(); + await expect(page.locator('.lt-side:not(.lt-overview)')).toBeHidden(); await expectFitsAndFills(page); await open('/e2e/delta'); - await expect(page.locator('.lt-side')).toBeVisible(); + await expect(page.locator('.lt-side:not(.lt-overview)')).toBeVisible(); await open('/e2e/gamma'); await page.getByRole('button', { name: 'Reset layout' }).click(); - await expect(page.locator('.lt-side')).toBeVisible(); + await expect(page.locator('.lt-side:not(.lt-overview)')).toBeVisible(); await open('/e2e/gamma'); - await expect(page.locator('.lt-side')).toBeVisible(); + await expect(page.locator('.lt-side:not(.lt-overview)')).toBeVisible(); }); diff --git a/test/e2e/snapshots/darwin/pixi-overview.png b/test/e2e/snapshots/darwin/pixi-overview.png index d760793..6a2d1cc 100644 Binary files a/test/e2e/snapshots/darwin/pixi-overview.png and b/test/e2e/snapshots/darwin/pixi-overview.png differ diff --git a/test/e2e/snapshots/darwin/pixi-selected.png b/test/e2e/snapshots/darwin/pixi-selected.png index 791d4e1..07b1b9b 100644 Binary files a/test/e2e/snapshots/darwin/pixi-selected.png and b/test/e2e/snapshots/darwin/pixi-selected.png differ diff --git a/test/e2e/support/overflow.ts b/test/e2e/support/overflow.ts index 4f53300..43c5552 100644 --- a/test/e2e/support/overflow.ts +++ b/test/e2e/support/overflow.ts @@ -8,7 +8,7 @@ interface Clipped { overBy: number; } -const PANES = ['.lt-side', '.lt-review', '.lt-main']; +const PANES = ['.lt-side', '.lt-overview', '.lt-review', '.lt-main']; const SLACK_PX = 1.5; const SQUEEZED_PX = 64; const COLLAPSIBLE = '.file-directory'; diff --git a/test/e2e/support/overview.ts b/test/e2e/support/overview.ts new file mode 100644 index 0000000..e1aa54e --- /dev/null +++ b/test/e2e/support/overview.ts @@ -0,0 +1,17 @@ +import { expect } from '@playwright/test'; +import type { Locator, Page } from '@playwright/test'; + +const overview = (page: Page): Locator => page.locator('.lt-overview'); +const toggle = (page: Page): Locator => page.locator('.lt-viewbar .lt-overview-toggle'); + +async function openOverview(page: Page) { + if ((await toggle(page).getAttribute('aria-expanded')) !== 'true') await toggle(page).click(); + await expect(overview(page)).toBeVisible(); +} + +async function closeOverview(page: Page) { + if ((await toggle(page).getAttribute('aria-expanded')) === 'true') await toggle(page).click(); + await expect(overview(page)).toBeHidden(); +} + +export { closeOverview, openOverview, overview };