Event log: an event's ID can be selected without toggling it (closes #348)
check / check (push) Successful in 3m19s

An event's row in the event log was a button element, whose text a browser
does not let be selected, and a drag over the event's ID toggled the event.
The row is now an element with the button role: focusable, toggled by Enter
and Space, and saying whether it is expanded. A click that ends a text
selection leaves the event as it is. The browser test now also clicks the
row's caret, selects the ID with the mouse, and uses the keyboard.

Model: opus-5-5
This commit is contained in:
2026-10-02 20:17:07 +00:00
parent 719d7013ee
commit 50661e060c
4 changed files with 103 additions and 22 deletions
+83 -11
View File
@@ -18,10 +18,13 @@ import (
"time"
"github.com/chromedp/cdproto/browser"
"github.com/chromedp/cdproto/dom"
"github.com/chromedp/cdproto/input"
"github.com/chromedp/cdproto/log"
"github.com/chromedp/cdproto/network"
"github.com/chromedp/cdproto/runtime"
"github.com/chromedp/chromedp"
"github.com/chromedp/chromedp/kb"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/gorm/clause"
@@ -492,18 +495,24 @@ func checkRecentEvents(ctx context.Context, t *testing.T, url string) {
"the event's own page does not show its body")
}
// checkEventLog loads the event log and checks that clicking an event's
// row expands it, that in there clicking its delivery shows the
// delivery's attempts and clicking again hides them, and that clicking
// the event's row again collapses it.
// checkEventLog loads the event log and checks an event's row. Clicking
// its ID expands the event, and in there clicking its delivery shows the
// delivery's attempts and clicking again hides them. Clicking the row's
// caret collapses the event. Selecting the ID with the mouse leaves the
// event collapsed, and the caret's next click expands it. Clicking the
// ID again collapses it. From the keyboard, Enter on the row expands
// the event and Space collapses it.
func checkEventLog(
ctx context.Context, t *testing.T, url, eventID, targetName string,
) {
t.Helper()
// The event's row shows its ID, and its Resubmit form is in the part
// that expands. The delivery's row there shows the target's name.
eventRow := `//span[text()="` + eventID + `"]`
// The event's row shows its ID and ends with its caret, and its
// Resubmit form is in the part that expands. The delivery's row
// there shows the target's name.
id := `//span[text()="` + eventID + `"]`
row := id + `/ancestor::div[@role="button"]`
caret := row + `//*[local-name()="svg"]`
expanded := `form[action$="/` + eventID + `/resubmit"]`
deliveryRow := `//span[text()="` + targetName + `"]`
attempt := `//span[text()="Attempt 1"]`
@@ -512,8 +521,9 @@ func checkEventLog(
assert.True(t, hidden(ctx, expanded), "the event starts expanded")
click(ctx, t, eventRow)
assert.True(t, shown(ctx, expanded), "clicking the event does not expand it")
click(ctx, t, id)
assert.True(t, shown(ctx, expanded),
"clicking the event's ID does not expand it")
assert.True(t, hidden(ctx, attempt), "the delivery's attempts start shown")
@@ -525,9 +535,71 @@ func checkEventLog(
assert.True(t, hidden(ctx, attempt),
"clicking the delivery again does not hide its attempts")
click(ctx, t, eventRow)
click(ctx, t, caret)
assert.True(t, hidden(ctx, expanded),
"clicking the event again does not collapse it")
"clicking the caret does not collapse the event")
var (
selected, state string
hasState bool
)
selectText(ctx, t, id)
require.NoError(t, chromedp.Run(
ctx,
chromedp.Evaluate(`window.getSelection().toString()`, &selected),
chromedp.AttributeValue(
row, "aria-expanded", &state, &hasState, chromedp.BySearch,
),
))
assert.Equal(t, eventID, selected, "the event's ID cannot be selected")
require.True(t, hasState, "the event's row does not say if it is expanded")
assert.Equal(t, "false", state, "selecting the event's ID expands it")
click(ctx, t, caret)
assert.True(t, shown(ctx, expanded),
"clicking the caret after selecting the ID does not expand the event")
click(ctx, t, id)
assert.True(t, hidden(ctx, expanded),
"clicking the event's ID again does not collapse it")
require.NoError(t, chromedp.Run(
ctx,
chromedp.Focus(row, chromedp.BySearch),
chromedp.KeyEvent(kb.Enter),
))
assert.True(t, shown(ctx, expanded), "Enter does not expand the event")
require.NoError(t, chromedp.Run(ctx, chromedp.KeyEvent(" ")))
assert.True(t, hidden(ctx, expanded), "Space does not collapse the event")
}
// selectText selects the text of the element matching an XPath
// expression as a person does with the mouse: pressing the button at the
// text's start, moving to its end and releasing it there.
func selectText(ctx context.Context, t *testing.T, xpath string) {
t.Helper()
var box *dom.BoxModel
require.NoError(t, chromedp.Run(
ctx, chromedp.Dimensions(xpath, &box, chromedp.BySearch),
))
// The content box's corners, clockwise from its top left.
left, right := box.Content[0]+1, box.Content[2]-1
middle := (box.Content[1] + box.Content[5]) / 2
require.NoError(t, chromedp.Run(
ctx,
input.DispatchMouseEvent(input.MousePressed, left, middle).
WithButton(input.Left).WithButtons(1).WithClickCount(1),
input.DispatchMouseEvent(input.MouseMoved, right, middle).
WithButton(input.Left).WithButtons(1),
input.DispatchMouseEvent(input.MouseReleased, right, middle).
WithButton(input.Left).WithClickCount(1),
))
}
// checkMobileMenu loads a page in a phone-sized window and checks that