Skip to content

feat: add mobilewright inspect command with browser-based element inspector#213

Open
marcomaes wants to merge 1 commit into
mobile-next:mainfrom
marcomaes:feat/inspector
Open

feat: add mobilewright inspect command with browser-based element inspector#213
marcomaes wants to merge 1 commit into
mobile-next:mainfrom
marcomaes:feat/inspector

Conversation

@marcomaes

Copy link
Copy Markdown

Summary

  • Adds @mobilewright/inspector as a new workspace package: an Express server with a plain HTML/CSS/JS frontend (no build step) that shows a live device screenshot alongside an annotated element list
  • Each element is annotated with its best mobilewright locator (testId > role > label > text), mirroring @mobilewright/core's query engine priority order exactly
  • Clicking a locator highlights its bounding box on the screenshot; clicking a box selects the matching row; duplicate locators get a "dup" badge
  • Adds mobilewright inspect CLI subcommand that starts the server and opens the browser automatically

Architecture

  • packages/inspector: standalone package, no dependency on mobilewright (avoids circular dep). Launchers (ios, android) are injected via start({ ios, android, port? }) from the CLI
  • packages/mobilewright: inspect command imports @mobilewright/inspector and injects the real launchers
  • Frontend: private class fields, O(1) index maps for highlight/row sync, user visibility overrides persisted across refreshes

Test plan

  • npx playwright test --config=tests/mobilewright.config.ts packages/inspector — 83 tests (locator derivation, DeviceManager, HTTP routes including 503)
  • mobilewright inspect opens browser, lists connected devices, screenshot + elements load on device select
  • Clicking element in list highlights bounding box on screenshot and vice versa
  • Auto-refresh works; stops after 3 consecutive failures
  • mobilewright inspect --port 5000 binds to correct port

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Walkthrough

Adds a new @mobilewright/inspector package with device management, locator derivation, HTTP routes, and a browser-based inspector UI. It also adds a mobilewright inspect CLI command that starts the inspector and opens it in the browser, plus workspace dependency, test, and TypeScript reference updates.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: a new mobilewright inspect command with a browser-based inspector.
Description check ✅ Passed The description is directly related to the changeset and accurately describes the new inspector package and CLI command.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 12

🧹 Nitpick comments (2)
packages/inspector/src/lib/device-manager.test.ts (1)

135-148: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make this test assert that the first device was actually closed.

Right now it only proves that the second device became active. The test still passes if await this.#activeDevice.close() disappears, so it does not cover the behavior named in the test.

Suggested change
   test('closes previous device before connecting new one', async () => {
+    let firstClosed = false
+    const first = fakeDevice({ close: async () => { firstClosed = true } })
     const second = fakeDevice()
     const dm = new DeviceManager({
       ios: {
         devices: async () => [],
         launch: async (opts: { deviceId: string }) =>
-          (opts.deviceId === 'sim-2' ? second : fakeDevice()) as unknown as Device,
+          (opts.deviceId === 'sim-2' ? second : first) as unknown as Device,
       },
       android: { devices: async () => [], launch: async () => { throw new Error() } },
     })
     await dm.select('sim-1', 'ios')
     await dm.select('sim-2', 'ios')
+    expect(firstClosed).toBe(true)
     expect(dm.device).toBe(second)
   })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/inspector/src/lib/device-manager.test.ts` around lines 135 - 148,
Update the DeviceManager test so it verifies the previous device is actually
closed, not just that the new one becomes active. In the "closes previous device
before connecting new one" test in DeviceManager.select, make the first fake
device a tracked mock/spied Device with a close method assertion, then after the
second select assert that the first device’s close was called while still
checking the active device is the second one. Use the existing fakeDevice helper
and the DeviceManager.device/select flow to locate the right spot.
packages/inspector/src/routes.test.ts (1)

138-157: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a wrong-platform regression case for POST /api/devices/:id/select.

The suite checks invalid platforms and unknown ids, but not the case where the id exists on one platform and the request specifies the other. A dedicated test here would lock in the 404 behavior once the route matches on both fields.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/inspector/src/routes.test.ts` around lines 138 - 157, Add a
regression test in routes.test.ts for POST /api/devices/:id/select that covers
an existing device id requested with the wrong platform, and assert it returns
404. Use the existing post helper and mirror the current select route tests so
the case is verified alongside the platform validation and unknown id checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/inspector/public/css/app.css`:
- Line 412: The font-family declaration is using quote styles that violate
stylelint’s font-family-name-quotes rule. Update the font-family in the
stylesheet to use the quote style expected by the linter for the named fonts in
this declaration, keeping the monospace fallback unchanged, and adjust the
app.css rule containing the SF Mono / Menlo / Monaco stack accordingly.

In `@packages/inspector/public/index.html`:
- Around line 11-28: The header selects `#device-select` and
`#auto-refresh-interval` are missing accessible names, so update the markup in the
header to associate each select with a clear label or an
aria-label/aria-labelledby using the existing device-picker and
auto-refresh-controls structure. Make sure the device selector and refresh
interval control each have distinct, descriptive names that assistive
technologies can announce.

In `@packages/inspector/public/js/app.js`:
- Around line 202-206: The visibility toggle in updateRowVisibility() updates
the button glyph, title, and aria-pressed, but leaves aria-label stale, so
screen readers announce the wrong action after toggles. Update the .vis-btn
handling in updateRowVisibility() to also set aria-label to match the current
hidden state, keeping it in sync with the existing textContent and title values.
- Around line 377-383: Clear stale inspect state when `#fetchDevices`() receives
no active device. In the app.js device refresh flow, detect when
this.#state.activeId becomes null after fetching /api/devices, and explicitly
reset the current inspect data so the old screenshot and locator list do not
remain visible. Update the `#fetchDevices` method and any related state/render
helpers in the inspector app to clear the selected device/inspect view before
calling `#renderDevicePicker`().

In `@packages/inspector/src/lib/device-manager.ts`:
- Around line 68-73: The `DeviceManager` is clearing `#activeDevice` and
`#activeDeviceInfo` even when `close()` rejects, which can leave a live session
orphaned while allowing `select()` to start another one. Update the cleanup
logic in both the previous-device block and `DeviceManager.close()` so the state
is only nulled after a successful `await this.#activeDevice.close()`, and
preserve the existing active-device references when `close()` fails so callers
can retry or handle the error.

In `@packages/inspector/src/lib/logger.ts`:
- Around line 1-9: The new TypeScript files in this package violate the enforced
semicolon style, and the logger.ts snippet shows the same formatting pattern.
Run the formatter/linter fix on logger.ts and the other new TS files so the
exported logger methods and related code conform to `@stylistic/semi` and CI
passes.

In `@packages/inspector/src/routes/devices.ts`:
- Around line 28-33: The precheck in the devices route only matches on id, but
listDevices() returns platform-specific entries, so update the existence check
in the route handler around deviceManager.listDevices() / deviceManager.select()
to require both id and platform before proceeding. If no entry matches both
fields, return the same 404 response instead of calling deviceManager.select(),
so the wrong platform for an existing device id does not fall through to a 500.

In `@packages/inspector/src/routes/inspect.ts`:
- Around line 35-41: The iOS scaling logic in inspect() is guessing logical size
from screenshot width bands, which breaks iPad overlays when it falls back to
scale 1. Update the platform handling in inspect.ts to use Device.screenSize()
for iOS logical dimensions instead of the current 300-520pt heuristic, so
screen.width/height stay aligned with the view tree and box highlights. Keep the
existing Android path unchanged and make the scale/screen size calculation
consistent with the inspect route’s returned metadata.
- Around line 29-30: The inspect retry flow in
attemptWithRetry/getScreenshotTree is leaving timed-out device work running in
the background, so the next retry can overlap on the same shared device. Update
the inspect route logic around attemptWithRetry, withTimeout, screenshot(),
viewTree(), and endInspect() so a timed-out attempt is actually canceled or
prevented from continuing before retrying, and ensure the manager lock is not
cleared until all in-flight driver calls from that attempt have fully settled.

In `@packages/inspector/tsconfig.json`:
- Around line 7-11: The inspector tsconfig currently includes all of src, which
causes test files like the *.test.ts specs to be compiled into the build and
then published from dist. Update the package’s TypeScript config so the build
only picks up production sources for the inspector package, excluding test-only
files while preserving the existing references to protocol and
mobilewright-core. Use the tsconfig include/exclude setup in this package to
narrow what tsc -b emits, and verify the generated dist no longer contains the
test artifacts.

In `@packages/mobilewright/src/cli.ts`:
- Around line 311-331: The new inspector action in cli.ts is missing required
semicolons and will fail the repo’s `@stylistic/semi` lint rule. Update the
statements in the inspector startup/shutdown flow around start, open, console
output, shutdown, and the SIGINT/SIGTERM handlers in the cli action so they
follow the existing semicolon style used elsewhere in the file.
- Around line 321-331: The `mobilewright inspect` flow in `cli.ts` currently
awaits `open(inspector.url)` directly, so a launch failure can abort startup
before the `SIGINT`/`SIGTERM` handlers in `shutdown()` are registered. Wrap the
`open()` call in `try/catch` inside the `start`/`inspector` setup path, log or
ignore the failure as appropriate, and continue so the server stays running and
controllable even when no browser/app can be launched.

---

Nitpick comments:
In `@packages/inspector/src/lib/device-manager.test.ts`:
- Around line 135-148: Update the DeviceManager test so it verifies the previous
device is actually closed, not just that the new one becomes active. In the
"closes previous device before connecting new one" test in DeviceManager.select,
make the first fake device a tracked mock/spied Device with a close method
assertion, then after the second select assert that the first device’s close was
called while still checking the active device is the second one. Use the
existing fakeDevice helper and the DeviceManager.device/select flow to locate
the right spot.

In `@packages/inspector/src/routes.test.ts`:
- Around line 138-157: Add a regression test in routes.test.ts for POST
/api/devices/:id/select that covers an existing device id requested with the
wrong platform, and assert it returns 404. Use the existing post helper and
mirror the current select route tests so the case is verified alongside the
platform validation and unknown id checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0fbad740-3ab8-4243-8667-51917a1bc9bb

📥 Commits

Reviewing files that changed from the base of the PR and between 8f7b44c and 3882020.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json

Comment thread packages/inspector/public/css/app.css Outdated
Comment thread packages/inspector/public/index.html
Comment thread packages/inspector/public/js/app.js
Comment thread packages/inspector/public/js/app.js
Comment thread packages/inspector/src/lib/device-manager.ts
Comment thread packages/inspector/src/routes/inspect.ts Outdated
Comment thread packages/inspector/src/routes/inspect.ts Outdated
Comment thread packages/inspector/tsconfig.json
Comment thread packages/mobilewright/src/cli.ts Outdated
Comment thread packages/mobilewright/src/cli.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
packages/inspector/src/routes.test.ts (1)

16-39: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add a timeout to the test HTTP helper.

If a route hangs, this promise waits until the whole Playwright test timeout. A small request timeout makes failures faster and easier to diagnose.

Suggested fix
     });
     req.on('error', reject);
+    req.setTimeout(5000, () => {
+      req.destroy(new Error(`${method} ${parsed.pathname} timed out`));
+    });
     if (payload) req.write(payload);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/inspector/src/routes.test.ts` around lines 16 - 39, The test HTTP
helper in request should enforce a short timeout so hung routes fail quickly
instead of waiting for the full Playwright timeout. Update the request()
implementation to set a timeout on the http.request instance and reject/abort
with a clear error when it expires, keeping the existing resolve/reject behavior
intact for normal responses.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/inspector/public/js/app.js`:
- Around line 281-283: The user visibility override storage in the inspector app
is keyed only by locatorKey, so duplicate rows share the same persisted state
and all get toggled together. Update the override handling in app.js, especially
the `#userOverrides` map and the refresh/application logic around the element
list, to persist only when a locator key is unique or to add a stable
per-element disambiguator for duplicates. Ensure the code that records and
reapplies overrides distinguishes duplicate elements instead of treating every
row with the same locatorKey as one entry.
- Around line 420-438: The `#connectDevice`() flow leaves the screenshot pane
stuck in the loading state on failure because the catch path only updates the
status bar. In the `#connectDevice`(device) method, clear or reset the
`#screenshotPane` placeholder when the fetch/select request fails, alongside the
existing error status update, so the pane no longer shows “Connecting...” after
a failed connection.
- Around line 480-490: Guard the auto-refresh loop in `#applyAutoRefresh` so a new
tick cannot start while a previous async refresh is still running. Add an
in-flight flag around the setInterval callback that wraps `#fetchDevices` and
refresh, skip the body when a refresh is already active, and clear the flag in a
finally block so overlapping ticks cannot race or leave stale UI state.

In `@packages/inspector/src/index.ts`:
- Around line 47-53: Bind the inspector server to loopback only in the startup
logic around server.listen and the assignedPort/url setup in index.ts. Update
the listen call so it explicitly binds to the localhost loopback interface
rather than all interfaces, and keep the returned URL consistent with that
binding. Use the existing server and assignedPort flow to ensure the inspector
remains reachable only via localhost.

---

Nitpick comments:
In `@packages/inspector/src/routes.test.ts`:
- Around line 16-39: The test HTTP helper in request should enforce a short
timeout so hung routes fail quickly instead of waiting for the full Playwright
timeout. Update the request() implementation to set a timeout on the
http.request instance and reject/abort with a clear error when it expires,
keeping the existing resolve/reject behavior intact for normal responses.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: febfb87a-bb16-4497-977b-1910ee7762c1

📥 Commits

Reviewing files that changed from the base of the PR and between 3882020 and 9ec743d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
✅ Files skipped from review due to trivial changes (5)
  • packages/mobilewright/tsconfig.json
  • README.md
  • packages/mobilewright/package.json
  • tsconfig.json
  • packages/inspector/tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (10)
  • packages/inspector/package.json
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/public/index.html
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/mobilewright/src/cli.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/public/css/app.css

Comment thread packages/inspector/public/js/app.js
Comment thread packages/inspector/public/js/app.js
Comment thread packages/inspector/src/index.ts Outdated
@marcomaes marcomaes force-pushed the feat/inspector branch 2 times, most recently from 6401c95 to a2bc11c Compare June 26, 2026 10:26

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/inspector/public/js/app.js`:
- Around line 258-263: The row keyboard shortcut currently reacts to bubbled
Enter/Space events from the child visibility button, causing accidental row
selection. Update the keydown handler on the row to only trigger when the event
target is the row itself, and keep the existing `#onClickCb`(el.index) behavior
for direct row keyboard interaction. Use the row.addEventListener('keydown',
...) handler and the el.index callback path to locate and adjust the guard.

In `@packages/inspector/src/lib/device-manager.ts`:
- Around line 73-98: The `DeviceManager.select()` flow can still finish
`launcher.launch(...)` after `close()` has started, which may leave a newly
assigned active device after shutdown. Add a closing/closed guard in
`DeviceManager` and check it in `select()` before and after
`launcher.launch(...)`; if shutdown has begun, abort or immediately close the
launched device and avoid setting `#activeDevice`/`#activeDeviceInfo`. Also
update `close()` to mark the manager as closing/closed and ensure any in-flight
`select()` uses that state to skip cleanup-safe assignment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7a134331-59a2-4deb-9679-6f183b566f66

📥 Commits

Reviewing files that changed from the base of the PR and between 9ec743d and a2bc11c.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
✅ Files skipped from review due to trivial changes (3)
  • tsconfig.json
  • README.md
  • packages/inspector/public/index.html
🚧 Files skipped from review as they are similar to previous changes (12)
  • packages/inspector/tsconfig.json
  • packages/inspector/package.json
  • packages/mobilewright/tsconfig.json
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/lib/logger.ts
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/package.json
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/public/css/app.css
  • packages/inspector/src/lib/locator-derivation.test.ts

Comment thread packages/inspector/public/js/app.js
Comment thread packages/inspector/src/lib/device-manager.ts
@marcomaes marcomaes force-pushed the feat/inspector branch 2 times, most recently from 0dbf0ba to 40826bc Compare June 26, 2026 15:25

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/inspector/public/js/app.js`:
- Around line 441-444: The failed-connect path in app.js leaves the device
picker out of sync because the select element still shows the attempted device
while `#state.activeId` remains unchanged. In the connect flow around the
catch/finally handling, restore the picker selection back to the current active
device when the POST fails, using the existing state managed by `#state.activeId`
and the picker update logic so the UI matches the real device and reselecting
the same option can trigger change again.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: af4db7f9-4482-4587-a414-51b6abe7e206

📥 Commits

Reviewing files that changed from the base of the PR and between a2bc11c and 40826bc.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
✅ Files skipped from review due to trivial changes (3)
  • packages/inspector/public/index.html
  • README.md
  • packages/inspector/tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (13)
  • packages/inspector/package.json
  • packages/mobilewright/src/cli.ts
  • packages/inspector/public/css/app.css
  • tsconfig.json
  • packages/inspector/src/lib/logger.ts
  • packages/mobilewright/package.json
  • packages/mobilewright/tsconfig.json
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/lib/locator-derivation.test.ts

Comment thread packages/inspector/public/js/app.js
@marcomaes marcomaes force-pushed the feat/inspector branch 2 times, most recently from 98f884b to bfece5d Compare June 26, 2026 21:36

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (3)
packages/inspector/src/index.ts (1)

56-60: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Return the same loopback address that the server binds to.

Line 56 listens only on 127.0.0.1, but Line 60 still returns http://localhost:.... On hosts where localhost resolves to ::1 first, the CLI can open a URL the server is not actually listening on.

Suggested fix
-  const url = `http://localhost:${assignedPort}`;
+  const url = `http://127.0.0.1:${assignedPort}`;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/inspector/src/index.ts` around lines 56 - 60, The URL returned from
the inspector startup should use the same loopback address that server.listen
binds to, instead of hardcoding localhost. Update the logic in the startup path
around server.listen and the assignedPort/url निर्माण so the returned URL uses
127.0.0.1 consistently, preventing mismatches when localhost resolves to ::1
first.
packages/inspector/public/js/app.js (2)

475-483: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Ignore saved overrides once a locator key becomes duplicated.

#toggleHidden() now skips writing new duplicate keys, but Lines 479-480 still read any older override for that key. If a locator was unique when the user hid it and becomes duplicated on a later refresh, every duplicate row will inherit that stale override again.

Suggested fix
   `#computeHiddenIndices`() {
+    const dupes = buildDuplicateSet(this.#state.elements)
     return new Set(
       this.#state.elements
         .filter(el => {
           const key = el.locator ? locatorKey(el.locator) : null
-          const override = key ? this.#userOverrides.get(key) : undefined
+          const override = key && !dupes.has(key) ? this.#userOverrides.get(key) : undefined
           if (override === 'visible') return false
           if (override === 'hidden') return true
           return el.locator?.kind === 'testId' && DEFAULT_HIDDEN_TESTIDS.has(el.locator.value)
         })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/inspector/public/js/app.js` around lines 475 - 483, The hidden-state
lookup in `#computeHiddenIndices` is still applying stale user overrides for
locator keys that are now duplicated. Update the locatorKey-based override
handling in this method so it only honors overrides for keys that are still
unique in the current `#state.elements` set, and ignore any saved override when
the same key appears more than once. Keep the existing DEFAULT_HIDDEN_TESTIDS
fallback and the override checks aligned with `#toggleHidden`’s duplicate-key
behavior.

456-462: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Look up the toggled element by el.index, not by array offset.

The rest of this file treats index as the element identifier, but Line 457 reads this.#state.elements[index] as if it were the current array position. If those ever diverge, the toggle will compute the locator key/dup state from the wrong element and the override will not survive the next refresh.

Suggested fix
   `#toggleHidden`(index) {
-    const el = this.#state.elements[index]
+    const el = this.#state.elements.find(el => el.index === index)
     const key = el?.locator ? locatorKey(el.locator) : null
     const nowHidden = this.#state.hiddenIndices.has(index)
     // Only persist overrides for unique locator keys — shared keys would affect all duplicates.
     const isDupe = key ? buildDuplicateSet(this.#state.elements).has(key) : false
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/inspector/public/js/app.js` around lines 456 - 462, In
`#toggleHidden`, the element should be resolved by its stable identifier rather
than treating index as an array offset. Update the lookup around this method to
find the matching element by el.index in this.#state.elements before computing
locatorKey, nowHidden, and the duplicate-set check, so the toggle operates on
the same element identity used elsewhere in the file and survives refreshes
correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packages/inspector/public/js/app.js`:
- Around line 475-483: The hidden-state lookup in `#computeHiddenIndices` is still
applying stale user overrides for locator keys that are now duplicated. Update
the locatorKey-based override handling in this method so it only honors
overrides for keys that are still unique in the current `#state.elements` set, and
ignore any saved override when the same key appears more than once. Keep the
existing DEFAULT_HIDDEN_TESTIDS fallback and the override checks aligned with
`#toggleHidden`’s duplicate-key behavior.
- Around line 456-462: In `#toggleHidden`, the element should be resolved by its
stable identifier rather than treating index as an array offset. Update the
lookup around this method to find the matching element by el.index in
this.#state.elements before computing locatorKey, nowHidden, and the
duplicate-set check, so the toggle operates on the same element identity used
elsewhere in the file and survives refreshes correctly.

In `@packages/inspector/src/index.ts`:
- Around line 56-60: The URL returned from the inspector startup should use the
same loopback address that server.listen binds to, instead of hardcoding
localhost. Update the logic in the startup path around server.listen and the
assignedPort/url निर्माण so the returned URL uses 127.0.0.1 consistently,
preventing mismatches when localhost resolves to ::1 first.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: aac6d8a6-eb81-4c72-93c6-e7935f26a093

📥 Commits

Reviewing files that changed from the base of the PR and between 40826bc and bfece5d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
✅ Files skipped from review due to trivial changes (5)
  • packages/inspector/tsconfig.json
  • tsconfig.json
  • README.md
  • packages/inspector/package.json
  • packages/mobilewright/tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (11)
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/mobilewright/src/cli.ts
  • packages/inspector/public/index.html
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/mobilewright/package.json
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/public/css/app.css

@marcomaes marcomaes force-pushed the feat/inspector branch 2 times, most recently from 3ef9869 to c3473b6 Compare June 26, 2026 21:53
@marcomaes

Copy link
Copy Markdown
Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/inspector/public/js/app.js`:
- Around line 282-284: The visibility override state in InspectorApp is
currently shared across devices because `#userOverrides` is keyed only by locator
and reused by refresh/prune logic in the inspect/update flow. Update the
override storage and lookup in InspectorApp (including the map definition and
the code paths that read/write it, such as the refresh pruning and toggle
handlers) so overrides are scoped by activeId, or clear `#userOverrides` whenever
the selected device changes. Make sure the pruning logic only retains entries
for the current device’s activeId and locator combination.
- Around line 12-24: The locator snippet builder in locatorLabel() currently
produces invalid single-quoted JavaScript when locator values contain line
breaks or Unicode separators because escQ() only escapes backslashes and
apostrophes. Update escQ() to also escape \r, \n, \u2028, and \u2029 so all
callers in locatorLabel() (testId, role, label, text) generate valid inspector
snippets.

In `@packages/inspector/src/index.ts`:
- Around line 63-69: The close() shutdown sequence in inspector/src/index.ts
needs to stop accepting new connections before forcefully dropping existing
ones. Update the close() function so server.close() is called and awaited before
server.closeAllConnections(), keeping the existing deviceManager.close()
handling intact and preserving the same close() symbol for easy location.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: da1b73f7-df35-4640-8e17-308d5dc10ca5

📥 Commits

Reviewing files that changed from the base of the PR and between 40826bc and c3473b6.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
✅ Files skipped from review due to trivial changes (5)
  • packages/inspector/tsconfig.json
  • tsconfig.json
  • packages/mobilewright/tsconfig.json
  • README.md
  • packages/inspector/public/index.html
🚧 Files skipped from review as they are similar to previous changes (11)
  • packages/mobilewright/package.json
  • packages/inspector/package.json
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/public/css/app.css
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/mobilewright/src/cli.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/routes/inspect.ts

Comment thread packages/inspector/public/js/app.js
Comment thread packages/inspector/public/js/app.js
Comment thread packages/inspector/src/index.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
packages/inspector/src/routes.test.ts (1)

49-55: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Mirror the production error middleware in buildApp().

start() installs a JSON 500 handler, but this test app does not. A thrown route error here will exercise Express's default HTML error page instead of the response contract the real server ships.

Proposed fix
 function buildApp(dm: DeviceManager) {
   const app = express();
   app.use(express.json());
   app.get('/health', (_req, res) => res.json({ ok: true }));
   app.use('/api/devices', createDevicesRouter(dm));
   app.use('/api', createInspectRouter(dm));
+  app.use((err: Error, _req: express.Request, res: express.Response, _next: express.NextFunction) => {
+    res.status(500).json({ error: err.message });
+  });
   return app;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/inspector/src/routes.test.ts` around lines 49 - 55, Mirror the
production error handling in buildApp() so this test app matches the real
server’s response contract. The app currently sets up routes in buildApp() but
never installs the JSON 500 error middleware that start() uses, so thrown errors
fall back to Express’s default HTML handler. Add the same final error-handling
middleware after createDevicesRouter() and createInspectRouter() in buildApp(),
using the existing production middleware pattern so route failures return JSON
here too.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/inspector/public/js/app.js`:
- Around line 18-19: The regex literals in the app.js string replacement chain
use raw U+2028/U+2029 characters, which breaks parsing. Update the replacement
expressions in the inspector app bootstrap to use escaped Unicode code points
instead, keeping the existing replace calls but changing the pattern literals so
the file can load correctly.

---

Nitpick comments:
In `@packages/inspector/src/routes.test.ts`:
- Around line 49-55: Mirror the production error handling in buildApp() so this
test app matches the real server’s response contract. The app currently sets up
routes in buildApp() but never installs the JSON 500 error middleware that
start() uses, so thrown errors fall back to Express’s default HTML handler. Add
the same final error-handling middleware after createDevicesRouter() and
createInspectRouter() in buildApp(), using the existing production middleware
pattern so route failures return JSON here too.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9d62d4cb-88f1-443f-af6f-0beb7e5b897c

📥 Commits

Reviewing files that changed from the base of the PR and between c3473b6 and 4925db4.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
✅ Files skipped from review due to trivial changes (3)
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • README.md
🚧 Files skipped from review as they are similar to previous changes (13)
  • packages/inspector/package.json
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/mobilewright/tsconfig.json
  • packages/mobilewright/src/cli.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/public/index.html
  • packages/inspector/public/css/app.css
  • tsconfig.json
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/device-manager.ts

Comment thread packages/inspector/public/js/app.js Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/inspector/public/js/app.js`:
- Around line 309-315: The device selection flow can start multiple overlapping
calls to `#connectDevice`(), allowing later selections to race with earlier POSTs
and overwrite `#state.activeId` incorrectly. Update the device connect path in
`#connectDevice` and the change handler on `#deviceSelect` to serialize or ignore
stale in-flight connections so only the latest selection can complete and
trigger refresh logic. Use the existing `#connectDevice`, `#state.activeId`, and
device change listener as the key spots to guard against out-of-order responses.

In `@packages/inspector/src/index.ts`:
- Around line 63-71: The close() shutdown flow in index.ts keeps the HTTP server
accepting requests while deviceManager.close() is draining, which allows
/api/inspect and /api/devices/:id/select to race teardown. Update the close()
sequence so server.close() (and server.closeAllConnections()) runs before
waiting on deviceManager.close(), using the close() helper and
deviceManager.close() symbols to keep the shutdown order deterministic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 582608f5-912c-4999-b7b0-55be4ff4a731

📥 Commits

Reviewing files that changed from the base of the PR and between 4925db4 and 4d9c880.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
✅ Files skipped from review due to trivial changes (2)
  • README.md
  • packages/inspector/tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (14)
  • packages/inspector/package.json
  • tsconfig.json
  • packages/mobilewright/tsconfig.json
  • packages/inspector/src/routes/devices.ts
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/public/index.html
  • packages/inspector/public/css/app.css
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/lib/locator-derivation.test.ts

Comment thread packages/inspector/public/js/app.js
Comment thread packages/inspector/src/index.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/inspector/public/js/app.js`:
- Around line 311-316: Disable the device picker while a connect request is in
flight so the UI can’t drift from the actual active device. Update the change
handling around `#deviceSelect` and `#connectDevice` to set the select disabled
before starting the request and re-enable it when the request finishes, while
still honoring `#connectInFlight`. Ensure the picker state stays aligned with
`#state.activeId` after a successful connect so a second selection cannot be
silently dropped and leave the wrong device shown.
- Around line 333-366: The refresh flow in the inspector UI does not clear stale
data when /api/inspect returns 409, so the previous screenshot and element list
can remain visible after a disconnect. Update the fetch handling in the app’s
inspect refresh method to detect the 409 “no device connected” response and
reset the last snapshot state, including elements, hidden indices, highlights,
and screenshot display, before setting the disconnected status. Use the existing
state and rendering symbols in this path such as this.#state,
this.#screenshotPane, this.#elementsPane, and this.#setStatus so the UI no
longer looks current after a disconnect.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cba47de2-a798-48e0-b60f-da621a0e4d15

📥 Commits

Reviewing files that changed from the base of the PR and between 4d9c880 and ed79260.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
✅ Files skipped from review due to trivial changes (3)
  • packages/inspector/tsconfig.json
  • README.md
  • packages/inspector/public/index.html
🚧 Files skipped from review as they are similar to previous changes (13)
  • tsconfig.json
  • packages/mobilewright/tsconfig.json
  • packages/mobilewright/package.json
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/src/routes/devices.ts
  • packages/mobilewright/src/cli.ts
  • packages/inspector/public/css/app.css
  • packages/inspector/package.json
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts

Comment thread packages/inspector/public/js/app.js
Comment thread packages/inspector/public/js/app.js
@marcomaes

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
packages/inspector/public/js/app.js (2)

291-293: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Lock the whole auto-refresh tick, not just refresh().

#refreshInFlight only serializes /api/inspect. Overlapping intervals can still issue concurrent /api/devices requests, and an older response can rewind #state.activeId after a newer selection has already won.

Suggested fix
   `#autoRefreshTimer` = null
+  `#autoRefreshTickInFlight` = false
   `#refreshInFlight` = false
   `#connectInFlight` = false
@@
   `#applyAutoRefresh`() {
     clearInterval(this.#autoRefreshTimer)
     this.#autoRefreshTimer = null
+    this.#autoRefreshTickInFlight = false
     this.#autoRefreshInterval.disabled = !this.#autoRefreshToggle.checked
     this.#consecutiveErrors = 0  // reset when user manually reconfigures auto-refresh
     if (this.#autoRefreshToggle.checked) {
       const ms = Number(this.#autoRefreshInterval.value)
       this.#autoRefreshTimer = setInterval(async () => {
-        await this.#fetchDevices().catch(() => {})
-        await this.refresh()
+        if (this.#autoRefreshTickInFlight) return
+        this.#autoRefreshTickInFlight = true
+        try {
+          await this.#fetchDevices().catch(() => {})
+          await this.refresh()
+        } finally {
+          this.#autoRefreshTickInFlight = false
+        }
       }, ms)
     }
   }

Also applies to: 516-526

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/inspector/public/js/app.js` around lines 291 - 293, The auto-refresh
flow in the inspector app needs a single lock around the entire tick, not only
around `refresh()`. Update the `#autoRefreshTimer`-driven logic and the related
`refresh()`/devices fetch path so overlapping intervals cannot start concurrent
`/api/devices` requests or let an older response overwrite `#state.activeId`.
Use a whole-tick guard in the `app.js` auto-refresh code to skip a new tick
while the previous one is still running, and keep the state update tied to the
latest successful refresh in the existing `#refreshInFlight`-related flow.

406-409: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Clear visibility overrides when /api/devices switches the active device.

#userOverrides is only reset in #connectDevice(). If another inspector tab/process changes the shared active device, #fetchDevices() updates #state.activeId but reuses the previous device's locator overrides on the next refresh.

Suggested fix
   async `#fetchDevices`() {
     const res = await fetch('/api/devices')
     if (!res.ok) throw new Error(`Device list failed: ${res.status}`)
     const data = await res.json()
     const prevActiveId = this.#state.activeId
     this.#state.devices = data.devices ?? []
     this.#state.activeId = data.activeId ?? null
+    if (prevActiveId !== this.#state.activeId) {
+      this.#userOverrides.clear()
+    }
     this.#renderDevicePicker()
     if (prevActiveId && !this.#state.activeId) {

Also applies to: 461-463

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/inspector/public/js/app.js` around lines 406 - 409, The device
refresh path in `#fetchDevices`() and the active-device switch path around
`#connectDevice`() leave stale `#userOverrides` in place when `#state.activeId`
changes externally. Update the state change handling so that when the active
device returned by /api/devices differs from the previous activeId, the
inspector clears `#userOverrides` before the next render/refresh, using the
existing `#state.activeId`, `#fetchDevices`(), and `#renderDevicePicker`() flow to
locate the fix.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/inspector/public/js/app.js`:
- Around line 420-441: Render a placeholder option in `#renderDevicePicker` when
`#state.activeId` is null so the first real device is not auto-selected; this is
causing the picker to appear connected and suppressing change events for
retrying the same device. Update the device-select rendering logic to add a
disabled/placeholder option for the no-active-device state before appending the
entries, and ensure the selected value only maps to a real device when
`#state.activeId` is set.

---

Duplicate comments:
In `@packages/inspector/public/js/app.js`:
- Around line 291-293: The auto-refresh flow in the inspector app needs a single
lock around the entire tick, not only around `refresh()`. Update the
`#autoRefreshTimer`-driven logic and the related `refresh()`/devices fetch path
so overlapping intervals cannot start concurrent `/api/devices` requests or let
an older response overwrite `#state.activeId`. Use a whole-tick guard in the
`app.js` auto-refresh code to skip a new tick while the previous one is still
running, and keep the state update tied to the latest successful refresh in the
existing `#refreshInFlight`-related flow.
- Around line 406-409: The device refresh path in `#fetchDevices`() and the
active-device switch path around `#connectDevice`() leave stale `#userOverrides` in
place when `#state.activeId` changes externally. Update the state change handling
so that when the active device returned by /api/devices differs from the
previous activeId, the inspector clears `#userOverrides` before the next
render/refresh, using the existing `#state.activeId`, `#fetchDevices`(), and
`#renderDevicePicker`() flow to locate the fix.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d3b9dcca-1936-44bc-b729-b8c5a47c1555

📥 Commits

Reviewing files that changed from the base of the PR and between ed79260 and ceb1f8c.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
✅ Files skipped from review due to trivial changes (2)
  • README.md
  • packages/mobilewright/package.json
🚧 Files skipped from review as they are similar to previous changes (14)
  • packages/inspector/tsconfig.json
  • packages/mobilewright/tsconfig.json
  • packages/inspector/src/routes/devices.ts
  • packages/mobilewright/src/cli.ts
  • tsconfig.json
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/public/css/app.css
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/public/index.html
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/package.json
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/device-manager.ts

Comment thread packages/inspector/public/js/app.js
@marcomaes

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/inspector/public/js/app.js`:
- Around line 389-396: Stop auto-selecting the first device in `#loadDevices`. The
current branch in `#loadDevices`() immediately calls
`#connectDevice`(this.#state.devices[0]) when `#state.activeId` is unset, which
bypasses the new “Select a device” state and picks an arbitrary target. Update
the initial-load flow so `#fetchDevices`() can leave activeId as null, and only
call `#connectDevice` or refresh() when there is an explicit activeId; otherwise
let the UI stay unconnected until the user chooses a device.
- Around line 333-336: The refresh flow in app.js leaves the UI stuck in
“Loading…” when `/api/inspect` returns 503 because the early return skips
resetting state. Update `refresh()` so the 503 branch clears the loading
indicator before returning, using the same loading-state handling already used
elsewhere in the function (and keep the existing `fetch('/api/inspect')` and
status checks intact).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 704c890d-f97a-4940-b300-eec34e35ec5f

📥 Commits

Reviewing files that changed from the base of the PR and between ceb1f8c and 1eeaa40.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
✅ Files skipped from review due to trivial changes (2)
  • packages/mobilewright/package.json
  • README.md
🚧 Files skipped from review as they are similar to previous changes (14)
  • tsconfig.json
  • packages/inspector/package.json
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/tsconfig.json
  • packages/inspector/src/routes/devices.ts
  • packages/mobilewright/tsconfig.json
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/mobilewright/src/cli.ts
  • packages/inspector/public/css/app.css
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/public/index.html
  • packages/inspector/src/lib/device-manager.ts

Comment thread packages/inspector/public/js/app.js
Comment thread packages/inspector/public/js/app.js
@marcomaes

Copy link
Copy Markdown
Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

@marcomaes

Copy link
Copy Markdown
Author

@coderabbitai approve

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
✅ Action performed

Comments resolved. Approval is disabled; enable reviews.request_changes_workflow to allow explicit top-level @coderabbitai resolve or @coderabbitai approve commands.

@marcomaes

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
packages/inspector/public/js/app.js (2)

530-533: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

The interval still allows overlapping device polls.

This guard only blocks the refresh() part. A second tick can still enter while the first #fetchDevices() is awaiting, so device list and activeId updates can race and briefly desync the picker/state.

Suggested fix
   `#autoRefreshTimer` = null
+  `#autoRefreshTickInFlight` = false
   `#refreshInFlight` = false
@@
       const ms = Number(this.#autoRefreshInterval.value)
       this.#autoRefreshTimer = setInterval(async () => {
-        if (this.#refreshInFlight) return
-        await this.#fetchDevices().catch(() => {})
-        await this.refresh()
+        if (this.#autoRefreshTickInFlight) return
+        this.#autoRefreshTickInFlight = true
+        try {
+          await this.#fetchDevices().catch(() => {})
+          await this.refresh()
+        } finally {
+          this.#autoRefreshTickInFlight = false
+        }
       }, ms)
     }
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/inspector/public/js/app.js` around lines 530 - 533, The auto-refresh
loop in app.js still allows overlapping device polls because the
`#refreshInFlight` guard is only checked before `#fetchDevices`() starts, so a
second setInterval tick can enter while the first fetch is still awaiting.
Update the auto-refresh flow around `#autoRefreshTimer`, `#fetchDevices`(), and
refresh() so the in-flight guard covers the entire poll sequence (including the
fetchDevices await), and ensure the flag is set/reset consistently to prevent
concurrent device list and activeId updates.

Source: Linters/SAST tools


333-335: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reintroduces the 503 loading-state bug.

refresh() already swaps the pane into a loading placeholder before this fetch. This early return clears only the status text, so a skipped inspect can leave the UI stuck on “Loading screenshot…” when the screenshot was hidden.

Suggested fix
       const res = await fetch('/api/inspect')
-      if (res.status === 503) { this.#setStatus('', ''); return }  // another inspect in flight, skip this tick
+      if (res.status === 503) {
+        this.#setStatus('Inspect already in progress')
+        if (this.#screenshotPane.isScreenshotHidden) {
+          this.#screenshotPane.showPlaceholder('Inspect already in progress', 'Retry in a moment')
+        }
+        return
+      }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/inspector/public/js/app.js` around lines 333 - 335, The early return
in refresh() after fetch('/api/inspect') is clearing only the status text, which
can leave the pane stuck in the loading placeholder. Update the 503 handling in
refresh() so it fully restores the prior UI state instead of just calling
`#setStatus`('', ''), using the same state-reset path that runs when inspection is
skipped or cancelled. Keep the fix localized to refresh() and its loading/state
transition logic so the screenshot pane does not remain on “Loading
screenshot…”.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packages/inspector/public/js/app.js`:
- Around line 530-533: The auto-refresh loop in app.js still allows overlapping
device polls because the `#refreshInFlight` guard is only checked before
`#fetchDevices`() starts, so a second setInterval tick can enter while the first
fetch is still awaiting. Update the auto-refresh flow around `#autoRefreshTimer`,
`#fetchDevices`(), and refresh() so the in-flight guard covers the entire poll
sequence (including the fetchDevices await), and ensure the flag is set/reset
consistently to prevent concurrent device list and activeId updates.
- Around line 333-335: The early return in refresh() after fetch('/api/inspect')
is clearing only the status text, which can leave the pane stuck in the loading
placeholder. Update the 503 handling in refresh() so it fully restores the prior
UI state instead of just calling `#setStatus`('', ''), using the same state-reset
path that runs when inspection is skipped or cancelled. Keep the fix localized
to refresh() and its loading/state transition logic so the screenshot pane does
not remain on “Loading screenshot…”.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1a9f66cb-be07-462e-9618-aed42083af32

📥 Commits

Reviewing files that changed from the base of the PR and between ceb1f8c and 0814512.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
✅ Files skipped from review due to trivial changes (2)
  • README.md
  • packages/inspector/public/index.html
🚧 Files skipped from review as they are similar to previous changes (14)
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
  • packages/inspector/package.json
  • packages/inspector/src/lib/logger.ts
  • packages/mobilewright/src/cli.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/tsconfig.json
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/mobilewright/package.json
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/public/css/app.css
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/routes/devices.ts

…pector

Adds a new `@mobilewright/inspector` workspace package and a `mobilewright inspect`
CLI subcommand that opens a browser-based element inspector for connected devices.

The inspector shows a live screenshot on the left and an annotated element list on the
right. Each element is annotated with the best mobilewright locator (testId > role >
label > text), mirroring the priority order of @mobilewright/core's query engine.
Clicking a locator highlights its bounding box on the screenshot; clicking a box
selects the matching row. Duplicate locators get a "dup" badge.

Architecture:
- packages/inspector: standalone Express server, plain HTML/CSS/JS frontend (no build
  step), locator derivation pure function, DeviceManager with injected launchers (DIP)
- packages/mobilewright: inspect CLI command injects ios/android launchers into start()
  to avoid a circular dependency; open is an explicit dependency here

Hardening and review fixes:
- Logs to stderr so the URL line on stdout is uncluttered
- Port validated as integer in [0, 65535]
- Node 18 compatible server close (no Symbol.asyncDispose)
- 4-arg Express error handler returns JSON on unexpected throws
- escQ escapes backslashes in addition to single quotes
- open() wrapped in try/catch so headless environments print URL and continue
- device.screenSize() replaces PNG IHDR heuristic for correct iPad support
- 404 check in select route matches by id AND platform
- Test files excluded from tsconfig (not shipped in dist)
- Stale screenshot cleared when active device disconnects
- aria-label on device picker and interval selects; vis-btn aria-label kept in sync
- Passes ESLint @stylistic/semi throughout
- 83 tests (@playwright/test): locator derivation, DeviceManager, HTTP routes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@marcomaes

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
packages/inspector/src/routes.test.ts (1)

49-69: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a start() smoke test instead of duplicating the server assembly here.

buildApp()/startServer() copy the bootstrap logic from packages/inspector/src/index.ts, so these tests can still pass if the real startup path drifts. A narrow integration test around start() would cover the exported URL/binding/shutdown contract and keep this wiring from diverging.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/inspector/src/routes.test.ts` around lines 49 - 69, The test setup
in buildApp() and startServer() duplicates the server bootstrap from the real
startup path, so replace this with a narrow smoke test for start() instead. Use
the exported start() entrypoint from packages/inspector/src/index.ts and assert
the URL/binding/shutdown contract rather than assembling Express and listen
logic directly in routes.test.ts. Keep the existing router coverage focused on
behavior, but remove the copied bootstrap wiring so the test stays aligned with
the production startup flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/inspector/public/js/app.js`:
- Around line 337-346: The 409 handling in app.js is rebuilding the picker from
stale cached devices, so refresh the device list before calling
`#renderDevicePicker`. Update the device-disconnected branch to fetch the latest
devices or otherwise sync this.#state.devices first, then rebuild the picker so
removed devices disappear and new ones can appear immediately. Use the existing
state and rendering flow around this.#state.devices and `#renderDevicePicker` to
keep the UI consistent.

---

Nitpick comments:
In `@packages/inspector/src/routes.test.ts`:
- Around line 49-69: The test setup in buildApp() and startServer() duplicates
the server bootstrap from the real startup path, so replace this with a narrow
smoke test for start() instead. Use the exported start() entrypoint from
packages/inspector/src/index.ts and assert the URL/binding/shutdown contract
rather than assembling Express and listen logic directly in routes.test.ts. Keep
the existing router coverage focused on behavior, but remove the copied
bootstrap wiring so the test stays aligned with the production startup flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 60521e32-ab33-4b39-b008-e4929b16d88d

📥 Commits

Reviewing files that changed from the base of the PR and between 0814512 and e83d721.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md
  • packages/inspector/package.json
  • packages/inspector/public/css/app.css
  • packages/inspector/public/index.html
  • packages/inspector/public/js/app.js
  • packages/inspector/src/index.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/lib/device-manager.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/logger.ts
  • packages/inspector/src/routes.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/tsconfig.json
  • packages/mobilewright/package.json
  • packages/mobilewright/src/cli.ts
  • packages/mobilewright/tsconfig.json
  • tsconfig.json
✅ Files skipped from review due to trivial changes (3)
  • README.md
  • packages/mobilewright/tsconfig.json
  • packages/inspector/tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (13)
  • packages/inspector/public/index.html
  • packages/inspector/package.json
  • tsconfig.json
  • packages/inspector/src/lib/logger.ts
  • packages/mobilewright/src/cli.ts
  • packages/inspector/src/routes/inspect.ts
  • packages/inspector/public/css/app.css
  • packages/mobilewright/package.json
  • packages/inspector/src/lib/locator-derivation.ts
  • packages/inspector/src/lib/device-manager.test.ts
  • packages/inspector/src/routes/devices.ts
  • packages/inspector/src/lib/locator-derivation.test.ts
  • packages/inspector/src/lib/device-manager.ts

Comment thread packages/inspector/public/js/app.js
@marcomaes

Copy link
Copy Markdown
Author

@coderabbitai resolve

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
✅ Action performed

Comments resolved. Approval is disabled; enable reviews.request_changes_workflow to allow explicit top-level @coderabbitai resolve or @coderabbitai approve commands.

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