Skip to content

Comments

feat: add minimal Playwright smoke test#534

Merged
rolznz merged 6 commits intogetAlby:masterfrom
DSanich:feat/e2e-minimal
Feb 20, 2026
Merged

feat: add minimal Playwright smoke test#534
rolznz merged 6 commits intogetAlby:masterfrom
DSanich:feat/e2e-minimal

Conversation

@DSanich
Copy link
Contributor

@DSanich DSanich commented Feb 17, 2026

Summary

Adds a minimal Playwright smoke test to verify the bundled SDK loads and runs correctly in a browser.

Changes

  • Playwright setup — Single smoke test instead of a full E2E suite
  • Smoke test — Loads /dist/esm/lnclient.js, runs SATS(10) and resolveAmount(), asserts the result
  • CI — New E2E step: yarn test:e2e (Chromium)
  • Dependencies@playwright/test, serve

What the smoke test validates

  • Build and bundle work correctly
  • ESM module loads in a real browser
  • SATS and resolveAmount execute without errors

How to run

yarn test:e2e:install # one-time setup
yarn test:e2e

Summary by CodeRabbit

  • Tests

    • Added end-to-end browser testing with Playwright configuration
    • Implemented smoke tests to validate SDK functionality in browser environments
    • Updated CI workflow to execute browser-based tests
  • Chores

    • Added testing infrastructure dependencies
    • Updated project configuration for end-to-end test support
    • Added test documentation

Co-authored-by: Cursor <cursoragent@cursor.com>
@socket-security
Copy link

socket-security bot commented Feb 17, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedserve@​14.2.5991009987100
Added@​playwright/​test@​1.58.210010010099100

View full report

@socket-security
Copy link

socket-security bot commented Feb 17, 2026

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm registry-auth-token is 94.0% likely obfuscated

Confidence: 0.94

Location: Package overview

From: ?npm/registry-auth-token@3.3.2

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/registry-auth-token@3.3.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@coderabbitai
Copy link

coderabbitai bot commented Feb 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This pull request adds Playwright-based end-to-end browser testing infrastructure to the project. It includes configuration files, test scripts, CI integration, documentation, and a smoke test that validates SDK functionality in actual browser environments.

Changes

Cohort / File(s) Summary
E2E Testing Framework Setup
playwright.config.ts, jest.config.ts
New Playwright configuration with chromium, firefox, and webkit projects; webServer running on localhost:3000 with 2 retries in CI. Jest config updated to exclude e2e/browser tests from Jest execution.
E2E Test Assets
e2e/browser/smoke.spec.ts, e2e/browser/fixtures/smoke.html
New Playwright smoke test that validates SDK loading and runtime behavior in browsers. HTML fixture performs basic SDK checks (SATS conversion, amount resolution) and reports status.
Documentation and Ignore Patterns
e2e/README.md, .gitignore
New README documenting e2e test setup and execution. .gitignore entries added for test-results and playwright-report directories.
Package and Script Configuration
package.json
Added @playwright/test and serve devDependencies. New scripts: test:e2e:browser, test:e2e:browser:install, test:e2e:browser:ui, test:e2e:browser:headed. Format scripts updated to include e2e and playwright.config.ts.
CI Workflow Integration
.github/workflows/ci.yml
Added steps to install Playwright browsers and run e2e tests in CI pipeline.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

Poem

🐰 Through chromium tunnels, firefox fields I bound,
Webkit whiskers twitching—SDK tests all around,
Playwright magic weaves the e2e delight,
Browser smoke clears—the SDK shines bright! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: adding a minimal Playwright smoke test for browser verification of the bundled SDK.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
playwright.config.ts (1)

14-18: Firefox and WebKit projects are defined but never exercised in CI.

CI runs playwright test --project=chromium only. The extra project definitions are fine for local use, but if there's no intention to run them in CI, consider adding a comment to clarify — or remove them to keep the config minimal and aligned with the "minimal smoke test" goal.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@playwright.config.ts` around lines 14 - 18, The projects array in
playwright.config.ts declares "firefox" and "webkit" projects (names: "firefox",
"webkit") but CI only runs --project=chromium; either remove these extra project
entries to keep the config minimal for the CI smoke test, or add a one-line
comment above projects explaining that firefox and webkit are kept for local
testing only and intentionally not executed in CI; update the projects block
accordingly (or add the clarifying comment) so intent is explicit.
package.json (1)

54-55: Minor glob inconsistency in format vs format:fix.

format uses 'examples/**/*.(js|jsx)' but format:fix uses 'examples/**/*.(js|jsx|ts)' — the |ts extension is only in format:fix. This appears to be a pre-existing inconsistency but worth noting since these lines were touched.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 54 - 55, The npm scripts "format" and "format:fix"
have inconsistent example file globs: "format" uses 'examples/**/*.(js|jsx)'
while "format:fix" uses 'examples/**/*.(js|jsx|ts)'; update the "format" script
to include TypeScript ('examples/**/*.(js|jsx|ts)') so both "format" and
"format:fix" use the same glob pattern, ensuring consistency between the two
scripts.
.github/workflows/ci.yml (1)

20-25: Double build in CI.

yarn build runs at Line 20, and then the Playwright webServer.command (yarn build && serve . -p 3000) triggers a second build. Consider splitting the webServer command so CI can skip the redundant build — e.g., use serve . -p 3000 as the webServer command and add a separate prerequisite or guard:

command: process.env.CI ? "serve . -p 3000" : "yarn build && serve . -p 3000",

This would cut CI time, especially as the project grows.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 20 - 25, CI runs `yarn build` then
Playwright's webServer.command rebuilds the app, causing a redundant build;
update the Playwright `webServer.command` to skip the build in CI by using
`process.env.CI` to choose `serve . -p 3000` when CI is set and keep `yarn build
&& serve . -p 3000` locally, and keep the existing `yarn build` step in the CI
workflow so artifacts are built before starting the server.
e2e/smoke.spec.ts (1)

7-15: Prefer locator-based assertions over waitForSelector.

Modern Playwright recommends the Locator API with web-first assertions. This gives better error messages and auto-retry semantics:

♻️ Suggested refactor
 test("bundled SDK loads and runs in browser", async ({ page }) => {
   await page.goto("/e2e/fixtures/smoke.html");
-  await page.waitForSelector("#status:has-text('ok')", { timeout: 10000 });
+  await expect(page.locator("#status")).toHaveText("ok", { timeout: 10_000 });
 
   const result = await page.evaluate(() => {
     return (window as { __sdkReady?: boolean }).__sdkReady;
   });
 
   expect(result).toBe(true);
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/smoke.spec.ts` around lines 7 - 15, The test "bundled SDK loads and runs
in browser" currently uses page.waitForSelector; replace that with a
locator-based assertion using Playwright's Locator API and web-first assertions:
locate the element (e.g., page.locator('#status')) and assert its text content
with expect(...).toHaveText('ok', { timeout: 10000 }) so you get auto-retry and
better errors; update the block around the page.waitForSelector call in the test
function to use the locator+expect pattern before evaluating window.__sdkReady.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@playwright.config.ts`:
- Around line 19-24: The webServer command uses the wrong flag for the Vercel
serve binary so it won't bind to the intended port; update the webServer.command
string in the Playwright config (the webServer object) to use the listen flag
(-l or --listen) instead of -p, e.g., replace "yarn build && serve . -p 3000"
with "yarn build && serve . -l 3000" so the server binds to port 3000 and tests
can start.

---

Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 20-25: CI runs `yarn build` then Playwright's webServer.command
rebuilds the app, causing a redundant build; update the Playwright
`webServer.command` to skip the build in CI by using `process.env.CI` to choose
`serve . -p 3000` when CI is set and keep `yarn build && serve . -p 3000`
locally, and keep the existing `yarn build` step in the CI workflow so artifacts
are built before starting the server.

In `@e2e/smoke.spec.ts`:
- Around line 7-15: The test "bundled SDK loads and runs in browser" currently
uses page.waitForSelector; replace that with a locator-based assertion using
Playwright's Locator API and web-first assertions: locate the element (e.g.,
page.locator('#status')) and assert its text content with
expect(...).toHaveText('ok', { timeout: 10000 }) so you get auto-retry and
better errors; update the block around the page.waitForSelector call in the test
function to use the locator+expect pattern before evaluating window.__sdkReady.

In `@package.json`:
- Around line 54-55: The npm scripts "format" and "format:fix" have inconsistent
example file globs: "format" uses 'examples/**/*.(js|jsx)' while "format:fix"
uses 'examples/**/*.(js|jsx|ts)'; update the "format" script to include
TypeScript ('examples/**/*.(js|jsx|ts)') so both "format" and "format:fix" use
the same glob pattern, ensuring consistency between the two scripts.

In `@playwright.config.ts`:
- Around line 14-18: The projects array in playwright.config.ts declares
"firefox" and "webkit" projects (names: "firefox", "webkit") but CI only runs
--project=chromium; either remove these extra project entries to keep the config
minimal for the CI smoke test, or add a one-line comment above projects
explaining that firefox and webkit are kept for local testing only and
intentionally not executed in CI; update the projects block accordingly (or add
the clarifying comment) so intent is explicit.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
package.json (1)

91-92: Minor: serve breaks alphabetical order of devDependencies.

"serve" (line 91) appears before "qrcode-terminal" (line 92). Most tooling and conventions expect devDependencies sorted alphabetically. Not blocking, but worth noting.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 91 - 92, DevDependencies are out of alphabetical
order: move the "serve" entry so keys are sorted alphabetically (place
"qrcode-terminal" before "serve") in package.json's devDependencies section, or
run a sorting tool to ensure all keys (including "qrcode-terminal" and "serve")
follow alphabetical order.
.github/workflows/ci.yml (1)

22-25: Double build in CI — consider optimizing.

The yarn build on line 20 already produces dist/. The webServer.command in Playwright config runs yarn build && serve ... again, rebuilding unnecessarily. You could split the webServer command to skip the build when artifacts already exist, or use a serve-only command in CI.

One approach: change the webServer command to just serve . -l 3000 and document that yarn build must run first (which CI already guarantees). Alternatively, keep it self-contained if you value simplicity over CI speed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 22 - 25, The CI currently builds the
app twice because the workflow runs `yarn build` (producing dist/) but
Playwright's webServer.command triggers `yarn build && serve ...` again; update
the Playwright config's webServer.command to serve the already-built artifact
(e.g., use a serve-only command like `serve . -l 3000` or a conditional that
skips `yarn build` when `dist/` exists) so that CI step names like "Run E2E
tests" and "Install Playwright browsers" can rely on the prior `yarn build` and
avoid redundant builds.
playwright.config.ts (1)

14-17: Consider removing unused browser projects.

The PR objective is a minimal Chromium-only smoke test, and CI runs --project=chromium. The Firefox and WebKit projects add no value here and will confuse contributors who run playwright test without --project (triggering all three browsers, which requires installing extra browser binaries).

Suggested simplification
-  projects: [
-    { name: "chromium", use: { ...devices["Desktop Chrome"] } },
-    { name: "firefox", use: { ...devices["Desktop Firefox"] } },
-    { name: "webkit", use: { ...devices["Desktop Safari"] } },
-  ],
+  projects: [
+    { name: "chromium", use: { ...devices["Desktop Chrome"] } },
+  ],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@playwright.config.ts` around lines 14 - 17, Remove the unused Firefox and
WebKit project entries from the projects array so only the Chromium project
remains; specifically delete the objects with name: "firefox" and name: "webkit"
and keep { name: "chromium", use: { ...devices["Desktop Chrome"] } } in the
projects array (projects) to ensure running playwright test defaults to the
single Chromium smoke test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@playwright.config.ts`:
- Around line 19-24: The webServer command in the Playwright config uses the
wrong flag for the serve package; update the command string in the webServer
config (the webServer object in playwright.config.ts) to use serve's listen flag
(either -l 3000 or --listen 3000) instead of -p 3000 so the server binds to port
3000 and tests don't time out.

---

Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 22-25: The CI currently builds the app twice because the workflow
runs `yarn build` (producing dist/) but Playwright's webServer.command triggers
`yarn build && serve ...` again; update the Playwright config's
webServer.command to serve the already-built artifact (e.g., use a serve-only
command like `serve . -l 3000` or a conditional that skips `yarn build` when
`dist/` exists) so that CI step names like "Run E2E tests" and "Install
Playwright browsers" can rely on the prior `yarn build` and avoid redundant
builds.

In `@package.json`:
- Around line 91-92: DevDependencies are out of alphabetical order: move the
"serve" entry so keys are sorted alphabetically (place "qrcode-terminal" before
"serve") in package.json's devDependencies section, or run a sorting tool to
ensure all keys (including "qrcode-terminal" and "serve") follow alphabetical
order.

In `@playwright.config.ts`:
- Around line 14-17: Remove the unused Firefox and WebKit project entries from
the projects array so only the Chromium project remains; specifically delete the
objects with name: "firefox" and name: "webkit" and keep { name: "chromium",
use: { ...devices["Desktop Chrome"] } } in the projects array (projects) to
ensure running playwright test defaults to the single Chromium smoke test.

@DSanich
Copy link
Contributor Author

DSanich commented Feb 17, 2026

@rolznz In continuation of this #533 (comment) I've created a separate PR with the minimum required test for Playwright integration. All the tests I created earlier will also be distributed across separate pull requests using Jest.

Copy link
Contributor

@rolznz rolznz left a comment

Choose a reason for hiding this comment

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

tACK, can you address the minor comments and I'll merge it.

Thanks for the PR!

@DSanich
Copy link
Contributor Author

DSanich commented Feb 18, 2026

@rolznz added your suggestion in this commit 969acaf 🙏

@rolznz
Copy link
Contributor

rolznz commented Feb 19, 2026

@DSanich can you check the build error?

@DSanich
Copy link
Contributor Author

DSanich commented Feb 19, 2026

@rolznz pushed fix for CI build 🙏

@rolznz
Copy link
Contributor

rolznz commented Feb 19, 2026

I don't understand, how is that a fix?

@DSanich
Copy link
Contributor Author

DSanich commented Feb 20, 2026

@rolznz hello!

Yarn test (Jest) tried to run e2e/smoke.spec.ts, which is written for Playwright. Jest and Playwright are different runners, so the test failed. What I did: I added testPathIgnorePatterns: ['/e2e/'] to Jest so that Jest doesn't run tests from e2e/.

@rolznz
Copy link
Contributor

rolznz commented Feb 20, 2026

@DSanich ah, thanks for the explanation. We might need to change the folder then since in your other PR it uses jest for e2e. https://github.com/getAlby/js-sdk/pull/535/changes

Can you move the browser tests into /e2e/browser and only ignore that folder in jest? then I think we won't have issues. What do you think?

@DSanich
Copy link
Contributor Author

DSanich commented Feb 20, 2026

@rolznz Yes, that's a great idea. I'm working on that.

@DSanich
Copy link
Contributor Author

DSanich commented Feb 20, 2026

@rolznz d0bbe35 - here I have made the suggested changes.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
e2e/browser/smoke.spec.ts (1)

9-9: Prefer web-first assertion over waitForSelector for the status check.

page.waitForSelector() is now discouraged in favour of Playwright's Locator API and built-in auto-waiting. Using Locator objects and assertions makes the code "wait-for-selector-free." The DOM-ready check can be replaced with a single web-first assertion that auto-waits and retries:

♻️ Proposed refactor
-  await page.waitForSelector("#status:has-text('ok')", { timeout: 10000 });
+  await expect(page.locator("#status")).toContainText("ok", { timeout: 10000 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/browser/smoke.spec.ts` at line 9, Replace the page.waitForSelector call
with a web-first Locator assertion: create a Locator for "#status" (e.g., status
= page.locator('#status')) and await a Playwright expect assertion such as
expect(status).toHaveText('ok', { timeout: 10000 }) or
expect(status).toContainText('ok', { timeout: 10000 }) so the test uses the
Locator API's auto-waiting instead of waitForSelector.
playwright.config.ts (2)

9-9: Consider adding a terminal reporter alongside "html" for CI diagnostics.

reporter: "html" alone produces no terminal output; CI failures require downloading and opening the HTML artefact. Adding "list" (or "github" for GitHub Actions annotations) alongside keeps logs readable without extra tooling.

♻️ Proposed refactor
-  reporter: "html",
+  reporter: process.env.CI ? [["github"], ["html"]] : "html",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@playwright.config.ts` at line 9, The Playwright config currently sets
reporter: "html" which yields no terminal output; change the reporter property
in playwright.config.ts to an array to include a terminal reporter alongside
HTML (e.g., ["list", "html"] or ["github", "html"] for Actions). Update the
reporter value used in the exported config object (the reporter field) to an
array and, if using "html", optionally add the html options object to set
outputFolder/artifact naming so CI still uploads the artifact while terminal
logs remain visible.

22-22: reuseExistingServer: !CI silently skips yarn build in local dev.

When a process is already listening on port 3000 locally, the entire webServer.command — including yarn build — is bypassed, so tests silently run against a potentially stale bundle. Consider documenting this behaviour in the e2e README, or restructure the command so the build step runs unconditionally (e.g. a separate prebuild phase).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@playwright.config.ts` at line 22, The current Playwright setting
reuseExistingServer (in playwright.config.ts) can skip webServer.command
including yarn build when a process already listens on the port; to fix, ensure
the build always runs by either (a) moving the build step out of the start
command into a separate prebuild script invoked unconditionally (e.g., add a
"prestart:e2e" npm script that runs yarn build and call that before starting the
server), or (b) make webServer.command run the build unconditionally (e.g.,
"yarn build && yarn start") and/or set reuseExistingServer to false in non-CI
environments so tests never run against a stale bundle; update e2e README to
document this behaviour and the chosen approach so developers know why build
runs or why reuseExistingServer is disabled.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@playwright.config.ts`:
- Around line 19-24: The webServer command uses the wrong flag for the serve
CLI; update the command string in the webServer config (the "command" property)
to use the correct listen flag (either "-l 3000" or "--listen 3000") instead of
"-p 3000" so the local server starts on port 3000; ensure the change is applied
to the command value referenced in playwright.config.ts (webServer.command).

---

Nitpick comments:
In `@e2e/browser/smoke.spec.ts`:
- Line 9: Replace the page.waitForSelector call with a web-first Locator
assertion: create a Locator for "#status" (e.g., status =
page.locator('#status')) and await a Playwright expect assertion such as
expect(status).toHaveText('ok', { timeout: 10000 }) or
expect(status).toContainText('ok', { timeout: 10000 }) so the test uses the
Locator API's auto-waiting instead of waitForSelector.

In `@playwright.config.ts`:
- Line 9: The Playwright config currently sets reporter: "html" which yields no
terminal output; change the reporter property in playwright.config.ts to an
array to include a terminal reporter alongside HTML (e.g., ["list", "html"] or
["github", "html"] for Actions). Update the reporter value used in the exported
config object (the reporter field) to an array and, if using "html", optionally
add the html options object to set outputFolder/artifact naming so CI still
uploads the artifact while terminal logs remain visible.
- Line 22: The current Playwright setting reuseExistingServer (in
playwright.config.ts) can skip webServer.command including yarn build when a
process already listens on the port; to fix, ensure the build always runs by
either (a) moving the build step out of the start command into a separate
prebuild script invoked unconditionally (e.g., add a "prestart:e2e" npm script
that runs yarn build and call that before starting the server), or (b) make
webServer.command run the build unconditionally (e.g., "yarn build && yarn
start") and/or set reuseExistingServer to false in non-CI environments so tests
never run against a stale bundle; update e2e README to document this behaviour
and the chosen approach so developers know why build runs or why
reuseExistingServer is disabled.

@rolznz rolznz merged commit 395a550 into getAlby:master Feb 20, 2026
4 checks passed
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.

2 participants