Skip to content

fix(test): enable HTTP keep-alive on the global agent for backend tests#7852

Open
JohnMcLear wants to merge 1 commit into
developfrom
fix-ci-flake-supertest-keepalive
Open

fix(test): enable HTTP keep-alive on the global agent for backend tests#7852
JohnMcLear wants to merge 1 commit into
developfrom
fix-ci-flake-supertest-keepalive

Conversation

@JohnMcLear
Copy link
Copy Markdown
Member

Summary

One-line behaviour change in src/tests/backend/common.ts: set http.globalAgent.keepAlive = true at module load. Targeted at the Windows backend-test silent-ELIFECYCLE flake we've been chasing across #7838, #7842, #7846.

Smoking gun from PR #7846

The OS-level netstat sidecar in #7846 captured run 26419467467 Win-no-plugins. localhost server-side TIME_WAIT count on the Etherpad listening port [::1]:50398:

21:02:18.337       56
21:02:20.765      103
21:02:23.204      136
21:02:25.662      169
21:02:28.146      201
21:02:30.638      228   ← silent kill 37 ms later

~14 server-active-close TIME_WAITs per second, growing linearly. ESTABLISHED count is ~zero because each supertest request opens-and-closes a fresh TCP. The SERVER is the active closer (sends FIN after response), so the SERVER side enters TIME_WAIT — for ~120 s on Windows default TcpTimedWaitDelay.

228 half-dead sockets isn't enough to hit the Windows free-TCB cap (~2000), but it forces libuv's IOCP socket-table scan to walk a much larger working set on every TCP completion. The kill cluster is concentrated on tests that do rapid sequential HTTP roundtrips — importexportGetPost.ts > Import authorization checks, pad.ts > Tests, import.ts > DOCX export -> import round-trip, all of which match this profile.

The fix

http.globalAgent.keepAlive = true makes supertest's underlying http.request reuse a single TCP connection for sequential requests to the same origin. Each test no longer leaves a TIME_WAIT socket behind. Churn collapses from ~14/s to ~0.

Linux is unaffected by the flake because its TCP recycling and kernel half-dead socket handling are far more permissive. This change is a strict improvement there too (less socket churn = less work overall).

What this does NOT do

Test plan

  • Existing backend matrix passes (Linux ± plugins, Windows ± plugins). No tests assert on per-request connect/disconnect cycles, but the change is observable.
  • On the Win+plugins matrix, rerun the workflow 5-10x. Pre-fix flake rate was ~22%. Post-fix expectation: substantially lower (ideally near zero).
  • If test(ci): OS-level sidecar watcher for the Windows silent ELIFECYCLE #7846 is also landed, netstat.log on a failure should show TIME_WAIT count flat at 0-5 instead of climbing to 200+.

🤖 Generated with Claude Code

The Windows backend-test silent-ELIFECYCLE flake (silent exit 255 mid
test phase, no JS-handler trace, no native abort report; documented
by PRs #7838, #7842) correlates with localhost server-side TIME_WAIT
socket accumulation. The OS-level netstat sidecar added in PR #7846
captured the smoking gun in run 26419467467:

  netstat poll      server-side TIME_WAIT on [::1]:50398
  ----------------  -------------------------------------
  21:02:18.337       56
  21:02:20.765      103
  21:02:23.204      136
  21:02:25.662      169
  21:02:28.146      201
  21:02:30.638      228   ← silent kill 37 ms later

That's ~14 server-active-close TIME_WAITs per second growing linearly
toward the kill. All TIME_WAITs are on the Etherpad listening port —
the SERVER is the active closer, because supertest opens a fresh TCP
connection per request and the server sends FIN after the response.

The hard kernel TIME_WAIT cap (Windows default ~2000 free TCBs) was
not exceeded in this capture, but 228 half-dead handles forces libuv's
IOCP socket-table scan to walk a much larger working set on every
completion. The kill cluster is concentrated on tests that perform
rapid sequential HTTP roundtrips (importexportGetPost.ts, pad.ts,
import.ts DOCX round-trips) — exactly the pattern that grows TIME_WAIT
fastest.

Setting `http.globalAgent.keepAlive = true` in the backend-test common
bootstrap makes supertest's underlying http.request reuse a single
TCP connection for sequential requests to the same origin. Connection
reuse collapses the TIME_WAIT churn from ~14/s to nearly zero — each
test no longer leaves a half-dead socket behind. Linux's TCP recycling
is fast enough that the same load doesn't symptomize there, so this
keep-alive is a Windows-targeted mitigation that's also a strict
improvement on Linux (less socket churn = less work overall).

This is a real behavior change scoped to the test process — tests
share a long-lived connection rather than opening fresh ones — so the
shape of any race that depended on per-request connect/disconnect
cycles will shift. None of the existing backend tests assert on that,
but the change is observable and is being landed deliberately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Review Summary by Qodo

Enable HTTP keep-alive to fix Windows backend-test silent-ELIFECYCLE flake

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Enable HTTP keep-alive on global agent to fix Windows backend-test flake
• Prevents TIME_WAIT socket accumulation from rapid sequential requests
• Reduces IOCP socket-table scan overhead on Windows test execution
• Adds detailed diagnostic comments explaining root cause analysis
Diagram
flowchart LR
  A["Rapid sequential HTTP requests"] -->|"without keep-alive"| B["Fresh TCP per request"]
  B --> C["Server-side TIME_WAIT accumulation"]
  C --> D["Large IOCP socket-table scan"]
  D --> E["Silent ELIFECYCLE kill"]
  A -->|"with keep-alive=true"| F["TCP connection reuse"]
  F --> G["Minimal TIME_WAIT churn"]
  G --> H["Reduced IOCP overhead"]

Loading

File Changes

1. src/tests/backend/common.ts 🐞 Bug fix +25/-0

Enable HTTP keep-alive and add diagnostic documentation

• Import http module from node:http
• Set http.globalAgent.keepAlive = true at module load time
• Add comprehensive diagnostic comments explaining the Windows TIME_WAIT flake root cause
• Document the netstat sidecar findings and socket accumulation pattern

src/tests/backend/common.ts


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

qodo-free-for-open-source-projects Bot commented May 25, 2026

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0)

Grey Divider


Action required

1. Keep-alive breaks shutdown timeout 🐞 Bug ☼ Reliability
Description
Setting http.globalAgent.keepAlive=true can leave an idle HTTP connection open when backend test
teardown calls server.exit(), and server.stop() will fail if shutdown hooks exceed its 3s timeout.
express.closeServer() explicitly allows up to 5s before it forcibly destroys remaining sockets, so
this change can cause teardown to error with "Timed out waiting for shutdown tasks" and fail the
test run.
Code

src/tests/backend/common.ts[R22-45]

Evidence
The PR enables keep-alive globally, and common.ts teardown calls server.exit() without closing the
HTTP agent. server.exit() calls server.stop(), which times out shutdown hooks after 3s, but the HTTP
close path explicitly allows up to 5s before destroying remaining connections and notes that
server.close won’t resolve until existing connections close, so an idle keep-alive socket can push
shutdown beyond the 3s limit.

src/tests/backend/common.ts[22-45]
src/tests/backend/common.ts[156-161]
src/node/server.ts[195-233]
src/node/server.ts[240-267]
src/node/hooks/express.ts[32-55]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`src/tests/backend/common.ts` enables keep-alive on `http.globalAgent` at module load, but the test teardown does not close/destroy the agent’s sockets before calling `server.exit()`. Etherpad shutdown (`server.stop()`) enforces a 3s timeout for shutdown hooks, while the HTTP server shutdown path (`closeServer()`) may legitimately take up to 5s before it force-terminates remaining sockets.

This creates a new failure mode: an idle keep-alive connection can keep the HTTP server from fully closing within 3 seconds, causing `server.stop()` to throw `Timed out waiting for shutdown tasks` and the test process to exit non-zero.

## Issue Context
- Backend tests start a server and create a long-lived supertest client.
- With keep-alive enabled globally, it is normal for at least one connection to remain open briefly after the last request.
- The shutdown path already anticipates lingering connections (5s force-destroy), but the higher-level shutdown timeout is only 3s.

## Fix Focus Areas
- src/tests/backend/common.ts[156-161]
- src/tests/backend/common.ts[22-45]

### Suggested implementation direction
In the existing `after(async function () { ... })` teardown in `common.ts`, explicitly close keep-alive sockets before `await server.exit()`:
- Call `http.globalAgent.destroy()` (and optionally restore `http.globalAgent.keepAlive` to its previous value).

This keeps the keep-alive behavior during tests, but ensures shutdown hooks complete quickly and deterministically.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

Comment on lines +22 to +45
// Enable HTTP keep-alive on the global agent for the test process. Without
// this, every supertest request opens a fresh TCP connection and the server
// closes it on response — the server side then enters TIME_WAIT for the
// default Windows TcpTimedWaitDelay (~120 s) before the ephemeral port is
// freed.
//
// The Windows backend-test job's OS-level netstat sidecar (PR #7846)
// captured the smoking gun for the silent-ELIFECYCLE flake in run
// 26419467467: localhost server-side TIME_WAIT counts on the Etherpad
// listening port climbed linearly at ~14/s, reaching 228 active TIME_WAIT
// entries on `[::1]:50398` 37 ms before the kill — all server-active-close
// half-dead sockets, all from rapid sequential supertest requests with no
// connection reuse. The kill cluster on Windows + Node 24 + plugins
// correlates tightly with this TIME_WAIT accumulation: it gives libuv a
// large pool of half-dead handles to walk on every IOCP completion.
//
// Setting keepAlive=true on http.globalAgent makes supertest's underlying
// http.request reuse a single TCP connection for sequential requests to
// the same origin, collapsing TIME_WAIT churn from ~14/s to nearly zero.
// Linux is unaffected; the flake was Windows-only because Linux's
// TIME_WAIT recycling is much faster and the kernel can sustain higher
// half-dead-socket counts without symptom.
http.globalAgent.keepAlive = true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Keep-alive breaks shutdown timeout 🐞 Bug ☼ Reliability

Setting http.globalAgent.keepAlive=true can leave an idle HTTP connection open when backend test
teardown calls server.exit(), and server.stop() will fail if shutdown hooks exceed its 3s timeout.
express.closeServer() explicitly allows up to 5s before it forcibly destroys remaining sockets, so
this change can cause teardown to error with "Timed out waiting for shutdown tasks" and fail the
test run.
Agent Prompt
## Issue description
`src/tests/backend/common.ts` enables keep-alive on `http.globalAgent` at module load, but the test teardown does not close/destroy the agent’s sockets before calling `server.exit()`. Etherpad shutdown (`server.stop()`) enforces a 3s timeout for shutdown hooks, while the HTTP server shutdown path (`closeServer()`) may legitimately take up to 5s before it force-terminates remaining sockets.

This creates a new failure mode: an idle keep-alive connection can keep the HTTP server from fully closing within 3 seconds, causing `server.stop()` to throw `Timed out waiting for shutdown tasks` and the test process to exit non-zero.

## Issue Context
- Backend tests start a server and create a long-lived supertest client.
- With keep-alive enabled globally, it is normal for at least one connection to remain open briefly after the last request.
- The shutdown path already anticipates lingering connections (5s force-destroy), but the higher-level shutdown timeout is only 3s.

## Fix Focus Areas
- src/tests/backend/common.ts[156-161]
- src/tests/backend/common.ts[22-45]

### Suggested implementation direction
In the existing `after(async function () { ... })` teardown in `common.ts`, explicitly close keep-alive sockets before `await server.exit()`:
- Call `http.globalAgent.destroy()` (and optionally restore `http.globalAgent.keepAlive` to its previous value).

This keeps the keep-alive behavior during tests, but ensures shutdown hooks complete quickly and deterministically.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: Playwright Firefox

Failed stage: Run the frontend tests [❌]

Failed test name: [firefox] › tests/frontend-new/specs/clear_authorship_color.spec.ts:40:5 › clear authorship colors can be undone to restore author colors @feature:clear-authorship

Failure summary:

The action failed because a Playwright UI test failed in Firefox:
- Failed test:
tests/frontend-new/specs/clear_authorship_color.spec.ts:40:5 (clear authorship colors can be undone
to restore author colors @feature:clear-authorship).
- Assertion failure at
src/tests/frontend-new/specs/clear_authorship_color.spec.ts:70:53: expect(padBody.locator('div
span').first()).toHaveAttribute('class', /author-/, {timeout: 5000}).
- The located element <span
class="">Hello never gained a class matching /author-/ within 5s, so Playwright reported an
unexpected value of an empty string for the class attribute.
- The test retried twice (retry #1,
retry #2) and failed each time, causing pnpm run test-ui --project=firefox to exit with code 1
([ELIFECYCLE] Command failed with exit code 1).

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

229:  │   to run scripts.                                                            │
230:  │                                                                              │
231:  ╰──────────────────────────────────────────────────────────────────────────────╯
232:  Done in 2.1s using pnpm v11.1.2
233:  ##[group]Run cp ./src/tests/settings.json settings.json
234:  �[36;1mcp ./src/tests/settings.json settings.json�[0m
235:  shell: /usr/bin/bash -e {0}
236:  env:
237:  PNPM_HOME: /home/runner/setup-pnpm/node_modules/.bin
238:  ##[endgroup]
239:  ##[group]Run set -euo pipefail
240:  �[36;1mset -euo pipefail�[0m
241:  �[36;1mpnpm run prod > /tmp/etherpad-server.log 2>&1 &�[0m
242:  �[36;1m# Generous 90s budget so a slow runner (or, in the with-plugins�[0m
243:  �[36;1m# variant, plugin boot) doesn't lose the race against the test�[0m
244:  �[36;1m# phase. Fail loudly on timeout rather than silently falling�[0m
245:  �[36;1m# through to tests against a half-started server.�[0m
246:  �[36;1m# --max-time bounds each probe so a stuck server can't make a�[0m
247:  �[36;1m# single curl call eat the whole 90s budget.�[0m
248:  �[36;1mcan_connect() { curl --max-time 3 -sSfo /dev/null http://localhost:9001/; }�[0m
249:  �[36;1mfor i in $(seq 1 90); do can_connect && break; sleep 1; done�[0m
250:  �[36;1mif ! can_connect; then�[0m
251:  �[36;1m  echo "::error::Etherpad did not respond on :9001 within 90s"�[0m
252:  �[36;1m  echo "----- server log -----"�[0m
253:  �[36;1m  tail -n 200 /tmp/etherpad-server.log || true�[0m
254:  �[36;1m  exit 1�[0m
255:  �[36;1mfi�[0m
256:  �[36;1mcd src�[0m
257:  �[36;1mpnpm exec playwright install firefox  --with-deps�[0m
258:  �[36;1mpnpm run test-ui --project=firefox�[0m
259:  shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
260:  env:
261:  PNPM_HOME: /home/runner/setup-pnpm/node_modules/.bin
262:  ##[endgroup]
263:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
264:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
265:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
266:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
267:  curl: (7) Failed to connect to localhost port 9001 after 0 ms: Couldn't connect to server
268:  Installing dependencies...
...

672:  ✓   42 [firefox] › tests/frontend-new/specs/chat.spec.ts:152:5 › chat title bar lays out as a centred flex row with underscore minimize @feature:chat @feature:rtl-toggle (1.1s)
673:  ✓   43 [firefox] › tests/frontend-new/specs/chat.spec.ts:207:5 › chat icon click reliably opens the chat box @feature:chat (1.1s)
674:  ✓   44 [firefox] › tests/frontend-new/specs/clear_authorship_color.spec.ts:17:5 › clear authorship color @feature:clear-authorship (1.7s)
675:  ✓   46 [firefox] › tests/frontend-new/specs/clear_authorship_color.spec.ts:77:5 › clears authorship when first line has line attributes @feature:clear-authorship (1.7s)
676:  ✘   45 [firefox] › tests/frontend-new/specs/clear_authorship_color.spec.ts:40:5 › clear authorship colors can be undone to restore author colors @feature:clear-authorship (6.4s)
677:  ✓   47 [firefox] › tests/frontend-new/specs/collab_client.spec.ts:47:7 › Messages in the COLLABROOM › bug #4978 regression test (5.2s)
678:  ✓   49 [firefox] › tests/frontend-new/specs/delete.spec.ts:10:5 › delete keystroke (1.4s)
679:  ✓   50 [firefox] › tests/frontend-new/specs/editbar.spec.ts:9:5 › should go to home on pad (1.3s)
680:  ✓   51 [firefox] › tests/frontend-new/specs/embed_value.spec.ts:66:11 › embed links › read and write › the share link is the actual pad url (1.3s)
681:  ✓   52 [firefox] › tests/frontend-new/specs/embed_value.spec.ts:78:9 › embed links › read and write › is an iframe with the correct url parameters and correct size (1.4s)
682:  ✓   53 [firefox] › tests/frontend-new/specs/embed_value.spec.ts:97:11 › embed links › when read only option is set › the share link shows a read only url (1.3s)
683:  ✓   54 [firefox] › tests/frontend-new/specs/embed_value.spec.ts:114:11 › embed links › when read only option is set › the embed as iframe code is an iframe with the correct url parameters and correct size (1.5s)
684:  ✘   48 [firefox] › tests/frontend-new/specs/clear_authorship_color.spec.ts:40:5 › clear authorship colors can be undone to restore author colors @feature:clear-authorship (retry #1) (8.5s)
685:  ✓   55 [firefox] › tests/frontend-new/specs/enter.spec.ts:11:7 › enter keystroke › creates a new line & puts cursor onto a new line (1.1s)
686:  ✓   56 [firefox] › tests/frontend-new/specs/enter.spec.ts:33:7 › enter keystroke › enter is always visible after event (2.1s)
687:  ✓   58 [firefox] › tests/frontend-new/specs/error_sanitization.spec.ts:12:7 › error sanitization › production mode hides error details from gritter popup @feature:error-gritter (1.0s)
688:  ✓   59 [firefox] › tests/frontend-new/specs/error_sanitization.spec.ts:47:7 › error sanitization › development mode shows full error details in gritter popup @feature:error-gritter (905ms)
689:  ✓   60 [firefox] › tests/frontend-new/specs/error_sanitization.spec.ts:72:7 › error sanitization › duplicate errors are deduplicated in both modes @feature:error-gritter (775ms)
690:  ✓   61 [firefox] › tests/frontend-new/specs/error_sanitization.spec.ts:95:7 › error sanitization › errors before clientVars handshake default to hiding details @feature:error-gritter (668ms)
691:  ✓   62 [firefox] › tests/frontend-new/specs/font_type.spec.ts:14:7 › font select › makes text RobotoMono (1.5s)
692:  ✓   63 [firefox] › tests/frontend-new/specs/hide_menu_right.spec.ts:13:7 › showMenuRight URL parameter › without the parameter, .menu_right is visible (640ms)
693:  ##[error]  1) [firefox] › tests/frontend-new/specs/clear_authorship_color.spec.ts:40:5 › clear authorship colors can be undone to restore author colors @feature:clear-authorship 
694:      Error: expect(locator).toHaveAttribute(expected) failed
695:  
...

701:      Call log:
702:        - Expect "toHaveAttribute" with timeout 5000ms
703:        - waiting for locator('#innerdocbody').locator('div span').first()
704:          14 × locator resolved to <span class="">Hello</span>
705:             - unexpected value ""
706:  
707:  
708:        68 |
709:        69 |   // verify authorship is restored and user is not disconnected
710:      > 70 |   await expect(padBody.locator('div span').first()).toHaveAttribute('class', /author-/, {timeout: 5000});
711:           |                                                     ^
712:        71 |   const disconnected = page.locator('.disconnected, .unreachable');
713:        72 |   await expect(disconnected).not.toBeVisible();
714:        73 | });
715:          at /home/runner/work/etherpad/etherpad/src/tests/frontend-new/specs/clear_authorship_color.spec.ts:70:53
716:  ##[error]  1) [firefox] › tests/frontend-new/specs/clear_authorship_color.spec.ts:40:5 › clear authorship colors can be undone to restore author colors @feature:clear-authorship 
717:  
718:      Retry #1 ───────────────────────────────────────────────────────────────────────────────────────
719:      Error: expect(locator).toHaveAttribute(expected) failed
720:  
...

726:      Call log:
727:        - Expect "toHaveAttribute" with timeout 5000ms
728:        - waiting for locator('#innerdocbody').locator('div span').first()
729:          14 × locator resolved to <span class="">Hello</span>
730:             - unexpected value ""
731:  
732:  
733:        68 |
734:        69 |   // verify authorship is restored and user is not disconnected
735:      > 70 |   await expect(padBody.locator('div span').first()).toHaveAttribute('class', /author-/, {timeout: 5000});
736:           |                                                     ^
737:        71 |   const disconnected = page.locator('.disconnected, .unreachable');
738:        72 |   await expect(disconnected).not.toBeVisible();
739:        73 | });
740:          at /home/runner/work/etherpad/etherpad/src/tests/frontend-new/specs/clear_authorship_color.spec.ts:70:53
741:  ##[error]  1) [firefox] › tests/frontend-new/specs/clear_authorship_color.spec.ts:40:5 › clear authorship colors can be undone to restore author colors @feature:clear-authorship 
742:  
743:      Retry #2 ───────────────────────────────────────────────────────────────────────────────────────
744:      Error: expect(locator).toHaveAttribute(expected) failed
745:  
...

794:  ✓   91 [firefox] › tests/frontend-new/specs/language.spec.ts:76:7 › Language select and change › changes direction when picking an ltr lang (1.8s)
795:  ✓   92 [firefox] › tests/frontend-new/specs/line_ops.spec.ts:20:7 › Line ops (#6433) › Ctrl+Shift+D duplicates the current line below itself (1.8s)
796:  ✓   93 [firefox] › tests/frontend-new/specs/line_ops.spec.ts:41:7 › Line ops (#6433) › Ctrl+Shift+K deletes the current line (1.8s)
797:  ✓   95 [firefox] › tests/frontend-new/specs/list_wrap_indent.spec.ts:10:7 › numbered list wrapped line indentation › wrapped lines in a numbered list item are indented (1.2s)
798:  ✓   94 [firefox] › tests/frontend-new/specs/line_ops.spec.ts:65:7 › Line ops (#6433) › Ctrl+Shift+D duplicates every line in a multi-line selection (2.0s)
799:  ✓   96 [firefox] › tests/frontend-new/specs/ordered_list.spec.ts:11:9 › ordered_list.js › issue #4748 keeps numbers increment on OL (1.0s)
800:  ✓   97 [firefox] › tests/frontend-new/specs/ordered_list.spec.ts:34:9 › ordered_list.js › issue #1125 keeps the numbered list on enter for the new line (1.3s)
801:  ✓   98 [firefox] › tests/frontend-new/specs/ordered_list.spec.ts:59:7 › issue #5160 ordered list increments correctly after unordered list (2.1s)
802:  ✓   99 [firefox] › tests/frontend-new/specs/ordered_list.spec.ts:97:7 › issue #5718 consecutive numbering works after indented sub-bullets (1.5s)
803:  ✓  100 [firefox] › tests/frontend-new/specs/ordered_list.spec.ts:142:9 › Pressing Tab in an OL increases and decreases indentation › indent and de-indent list item with keypress (1.1s)
804:  ✓  101 [firefox] › tests/frontend-new/specs/ordered_list.spec.ts:169:9 › Pressing indent/outdent button in an OL increases and decreases indentation and bullet / ol formatting › indent and de-indent list item with indent button (1.3s)
805:  ✓  102 [firefox] › tests/frontend-new/specs/outdated_notice.spec.ts:43:7 › outdated notice (gritter-based) › outdated:null — no outdated-notice gritter is shown (1.2s)
806:  ✓  103 [firefox] › tests/frontend-new/specs/outdated_notice.spec.ts:54:7 › outdated notice (gritter-based) › outdated:minor, isFirstAuthor:false — no gritter shown (client guard) (1.0s)
807:  ✓  104 [firefox] › tests/frontend-new/specs/outdated_notice.spec.ts:66:7 › outdated notice (gritter-based) › outdated:minor, isFirstAuthor:true — gritter appears with correct text (1.1s)
808:  ✓  105 [firefox] › tests/frontend-new/specs/outdated_notice.spec.ts:82:7 › outdated notice (gritter-based) › user dismisses by clicking X — gritter disappears (1.5s)
809:  ✓  106 [firefox] › tests/frontend-new/specs/outdated_notice.spec.ts:96:7 › outdated notice (gritter-based) › server returns 500 — no gritter and no user-visible error (1.4s)
810:  ✓  108 [firefox] › tests/frontend-new/specs/pad_deletion_token.spec.ts:22:7 › pad deletion token › creator sees a token modal exactly once and can dismiss it (799ms)
...

847:  ✓  144 [firefox] › tests/frontend-new/specs/privacy_banner.spec.ts:162:7 › privacy banner (gritter-based) › javascript: learnMoreUrl is rejected — no anchor rendered (949ms)
848:  ✓  145 [firefox] › tests/frontend-new/specs/privacy_banner.spec.ts:175:7 › privacy banner (gritter-based) › data: learnMoreUrl is rejected — no anchor rendered (958ms)
849:  ✓  147 [firefox] › tests/frontend-new/specs/privacy_banner.spec.ts:210:7 › privacy banner (gritter-based) › mailto: learnMoreUrl is allowed (923ms)
850:  ✓  146 [firefox] › tests/frontend-new/specs/privacy_banner.spec.ts:187:7 › privacy banner (gritter-based) › unknown dismissal value is treated as dismissible (defense-in-depth) (1.3s)
851:  ✓  148 [firefox] › tests/frontend-new/specs/redo.spec.ts:12:7 › undo button then redo button › redo some typing with button (1.5s)
852:  ✓  149 [firefox] › tests/frontend-new/specs/redo.spec.ts:39:7 › undo button then redo button › redo some typing with keypress (1.5s)
853:  ✓  150 [firefox] › tests/frontend-new/specs/rtl_url_param.spec.ts:11:7 › RTL URL parameter › rtl=true enables RTL mode (1.5s)
854:  ✓  151 [firefox] › tests/frontend-new/specs/rtl_url_param.spec.ts:16:7 › RTL URL parameter › rtl=false disables RTL mode after rtl=true @feature:rtl-toggle (2.4s)
855:  ✓  152 [firefox] › tests/frontend-new/specs/rtl_url_param.spec.ts:26:7 › RTL URL parameter › no rtl param falls back to the pad setting after an RTL URL override @feature:rtl-toggle (2.1s)
856:  -  153 [firefox] › tests/frontend-new/specs/select_focus_restore.spec.ts:8:5 › toolbar select change returns focus to the pad editor (#7589)
857:  ✓  154 [firefox] › tests/frontend-new/specs/strikethrough.spec.ts:10:7 › strikethrough button › makes text strikethrough (1.1s)
858:  ✓  155 [firefox] › tests/frontend-new/specs/theme_color_dark_mode.spec.ts:10:7 › light color scheme › theme-color meta tracks the dark-mode toggle (1.7s)
859:  ✓  156 [firefox] › tests/frontend-new/specs/theme_color_dark_mode.spec.ts:33:7 › dark color scheme › theme-color meta follows the auto dark-mode switch on dark-OS clients (968ms)
860:  ✓  157 [firefox] › tests/frontend-new/specs/timeslider_follow.spec.ts:15:7 › timeslider follow › content as it's added to timeslider (3.1s)
861:  ✓  158 [firefox] › tests/frontend-new/specs/timeslider_follow.spec.ts:56:7 › timeslider follow › only to lines that exist in the pad view, regression test for #4389 (3.2s)
862:  ✓  160 [firefox] › tests/frontend-new/specs/timeslider_identity_changeset.spec.ts:61:7 › Timeslider with identity changesets (bug #5214) › timeslider can scrub through all revisions without error (5.0s)
863:  ✓  161 [firefox] › tests/frontend-new/specs/timeslider_line_numbers.spec.ts:9:7 › timeslider line numbers › shows line numbers aligned with the rendered document lines (3.2s)
...

914:  ✓  211 [firefox] › tests/frontend-new/specs/urls_become_clickable.spec.ts:48:9 › punctuation after URL is ignored › https://etherpad.org, (1.4s)
915:  ✓  212 [firefox] › tests/frontend-new/specs/urls_become_clickable.spec.ts:48:9 › punctuation after URL is ignored › https://etherpad.org; (1.4s)
916:  ✓  213 [firefox] › tests/frontend-new/specs/urls_become_clickable.spec.ts:48:9 › punctuation after URL is ignored › https://etherpad.org? (1.4s)
917:  ✓  214 [firefox] › tests/frontend-new/specs/urls_become_clickable.spec.ts:48:9 › punctuation after URL is ignored › https://etherpad.org! (1.3s)
918:  ✓  215 [firefox] › tests/frontend-new/specs/urls_become_clickable.spec.ts:48:9 › punctuation after URL is ignored › https://etherpad.org) (1.8s)
919:  ✓  216 [firefox] › tests/frontend-new/specs/urls_become_clickable.spec.ts:48:9 › punctuation after URL is ignored › https://etherpad.org] (1.6s)
920:  ✓  218 [firefox] › tests/frontend-new/specs/urls_become_clickable.spec.ts:48:9 › punctuation after URL is ignored › https://etherpad.org* (1.4s)
921:  ✓  217 [firefox] › tests/frontend-new/specs/urls_become_clickable.spec.ts:48:9 › punctuation after URL is ignored › https://etherpad.org' (1.5s)
922:  ✓  219 [firefox] › tests/frontend-new/specs/userlist_click_to_chat.spec.ts:33:7 › userlist click → chat prefill › clicking another user opens chat and prefills @<name> @feature:chat @feature:username (4.0s)
923:  ✓  220 [firefox] › tests/frontend-new/specs/userlist_click_to_chat.spec.ts:72:7 › userlist click → chat prefill › clicking the swatch opens the color picker, not chat @feature:chat @feature:username (4.2s)
924:  ✓  221 [firefox] › tests/frontend-new/specs/userlist_click_to_chat.spec.ts:104:7 › userlist click → chat prefill › clicking the rename input on an unnamed user does not steal focus @feature:chat @feature:username (3.6s)
925:  ✓  222 [firefox] › tests/frontend-new/specs/userlist_click_to_chat.spec.ts:140:7 › userlist click → chat prefill › partial message in chat input is preserved when prefilling @feature:chat @feature:username (4.1s)
926:  ✓  223 [firefox] › tests/frontend-new/specs/wcag_author_color.spec.ts:64:7 › WCAG author colour (issue #7377) › issue scenario: #9AB3FA renders >= AA against the author text @feature:authorship-bg-color (2.8s)
927:  ✓  224 [firefox] › tests/frontend-new/specs/wcag_author_color.spec.ts:73:7 › WCAG author colour (issue #7377) › pure red #ff0000 renders >= AA after the clamp @feature:authorship-bg-color (2.6s)
928:  ✓  225 [firefox] › tests/frontend-new/specs/wcag_author_color.spec.ts:82:7 › WCAG author colour (issue #7377) › already-AA-friendly #ffeedd is rendered unchanged @feature:authorship-bg-color (2.7s)
929:  ##[notice]  1 failed
930:      [firefox] › tests/frontend-new/specs/clear_authorship_color.spec.ts:40:5 › clear authorship colors can be undone to restore author colors @feature:clear-authorship 
931:    1 skipped
932:    221 passed (3.9m)
933:  1) [firefox] › tests/frontend-new/specs/clear_authorship_color.spec.ts:40:5 › clear authorship colors can be undone to restore author colors @feature:clear-authorship 
934:  Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoHaveAttribute�[2m(�[22m�[32mexpected�[39m�[2m)�[22m failed
935:  Locator: locator('#innerdocbody').locator('div span').first()
...

937:  Received string:  �[31m""�[39m
938:  Timeout: 5000ms
939:  Call log:
940:  �[2m  - Expect "toHaveAttribute" with timeout 5000ms�[22m
941:  �[2m  - waiting for locator('#innerdocbody').locator('div span').first()�[22m
942:  �[2m    14 × locator resolved to <span class="">Hello</span>�[22m
943:  �[2m       - unexpected value ""�[22m
944:  68 |
945:  69 |   // verify authorship is restored and user is not disconnected
946:  > 70 |   await expect(padBody.locator('div span').first()).toHaveAttribute('class', /author-/, {timeout: 5000});
947:  |                                                     ^
948:  71 |   const disconnected = page.locator('.disconnected, .unreachable');
949:  72 |   await expect(disconnected).not.toBeVisible();
950:  73 | });
951:  at /home/runner/work/etherpad/etherpad/src/tests/frontend-new/specs/clear_authorship_color.spec.ts:70:53
952:  Error Context: test-results/tests-frontend-new-specs-c-3f96a-ne-to-restore-author-colors-firefox/error-context.md
953:  Retry #1 ───────────────────────────────────────────────────────────────────────────────────────
954:  Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoHaveAttribute�[2m(�[22m�[32mexpected�[39m�[2m)�[22m failed
955:  Locator: locator('#innerdocbody').locator('div span').first()
...

960:  �[2m  - Expect "toHaveAttribute" with timeout 5000ms�[22m
961:  �[2m  - waiting for locator('#innerdocbody').locator('div span').first()�[22m
962:  �[2m    14 × locator resolved to <span class="">Hello</span>�[22m
963:  �[2m       - unexpected value ""�[22m
964:  68 |
965:  69 |   // verify authorship is restored and user is not disconnected
966:  > 70 |   await expect(padBody.locator('div span').first()).toHaveAttribute('class', /author-/, {timeout: 5000});
967:  |                                                     ^
968:  71 |   const disconnected = page.locator('.disconnected, .unreachable');
969:  72 |   await expect(disconnected).not.toBeVisible();
970:  73 | });
971:  at /home/runner/work/etherpad/etherpad/src/tests/frontend-new/specs/clear_authorship_color.spec.ts:70:53
972:  attachment #1: video (video/webm) ──────────────────────────────────────────────────────────────
973:  test-results/tests-frontend-new-specs-c-3f96a-ne-to-restore-author-colors-firefox-retry1/video.webm
974:  ────────────────────────────────────────────────────────────────────────────────────────────────
975:  Error Context: test-results/tests-frontend-new-specs-c-3f96a-ne-to-restore-author-colors-firefox-retry1/error-context.md
976:  attachment #3: trace (application/zip) ─────────────────────────────────────────────────────────
977:  test-results/tests-frontend-new-specs-c-3f96a-ne-to-restore-author-colors-firefox-retry1/trace.zip
978:  Usage:
979:  pnpm exec playwright show-trace test-results/tests-frontend-new-specs-c-3f96a-ne-to-restore-author-colors-firefox-retry1/trace.zip
980:  ────────────────────────────────────────────────────────────────────────────────────────────────
981:  Retry #2 ───────────────────────────────────────────────────────────────────────────────────────
982:  Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoHaveAttribute�[2m(�[22m�[32mexpected�[39m�[2m)�[22m failed
983:  Locator: locator('#innerdocbody').locator('div span').first()
...

985:  Received string:  �[31m""�[39m
986:  Timeout: 5000ms
987:  Call log:
988:  �[2m  - Expect "toHaveAttribute" with timeout 5000ms�[22m
989:  �[2m  - waiting for locator('#innerdocbody').locator('div span').first()�[22m
990:  �[2m    14 × locator resolved to <span class="">Hello</span>�[22m
991:  �[2m       - unexpected value ""�[22m
992:  68 |
993:  69 |   // verify authorship is restored and user is not disconnected
994:  > 70 |   await expect(padBody.locator('div span').first()).toHaveAttribute('class', /author-/, {timeout: 5000});
995:  |                                                     ^
996:  71 |   const disconnected = page.locator('.disconnected, .unreachable');
997:  72 |   await expect(disconnected).not.toBeVisible();
998:  73 | });
999:  at /home/runner/work/etherpad/etherpad/src/tests/frontend-new/specs/clear_authorship_color.spec.ts:70:53
1000:  Error Context: test-results/tests-frontend-new-specs-c-3f96a-ne-to-restore-author-colors-firefox-retry2/error-context.md
1001:  1 failed
1002:  [firefox] › tests/frontend-new/specs/clear_authorship_color.spec.ts:40:5 › clear authorship colors can be undone to restore author colors @feature:clear-authorship 
1003:  1 skipped
1004:  221 passed (3.9m)
1005:  [ELIFECYCLE] Command failed with exit code 1.
1006:  ##[error]Process completed with exit code 1.
1007:  ##[group]Run actions/upload-artifact@v7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant