Skip to content

Commit 58f7971

Browse files
committed
Command capture enhancement
1 parent 2173496 commit 58f7971

File tree

17 files changed

+1006
-1062
lines changed

17 files changed

+1006
-1062
lines changed

packages/app/src/components/sidebar/explorer.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ import type { DevtoolsSidebarFilter } from './filter.js'
3131

3232
const EXPLORER = 'wdio-devtools-sidebar-explorer'
3333

34+
const STATE_MAP: Record<string, TestState> = {
35+
'running': TestState.RUNNING,
36+
'failed': TestState.FAILED,
37+
'passed': TestState.PASSED,
38+
'skipped': TestState.SKIPPED
39+
}
40+
3441
@customElement(EXPLORER)
3542
export class DevtoolsSidebarExplorer extends CollapseableEntry {
3643
#testFilter: DevtoolsSidebarFilter | undefined
@@ -364,18 +371,32 @@ export class DevtoolsSidebarExplorer extends CollapseableEntry {
364371
return entry.state === 'failed'
365372
}
366373

374+
#computeEntryState(entry: TestStats | SuiteStats): TestState {
375+
const state = (entry as any).state
376+
377+
// Check explicit state first
378+
const mappedState = STATE_MAP[state]
379+
if (mappedState) return mappedState
380+
381+
// For suites, compute state from children
382+
if ('tests' in entry) {
383+
if (this.#isRunning(entry)) return TestState.RUNNING
384+
if (this.#hasFailed(entry)) return TestState.FAILED
385+
return TestState.PASSED
386+
}
387+
388+
// For individual tests, check if still running
389+
return !entry.end ? TestState.RUNNING : TestState.PASSED
390+
}
391+
367392
#getTestEntry(entry: TestStats | SuiteStats): TestEntry {
368393
if ('tests' in entry) {
369394
const entries = [...entry.tests, ...entry.suites]
370395
return {
371396
uid: entry.uid,
372397
label: entry.title,
373398
type: 'suite',
374-
state: this.#isRunning(entry)
375-
? TestState.RUNNING
376-
: this.#hasFailed(entry)
377-
? TestState.FAILED
378-
: TestState.PASSED,
399+
state: this.#computeEntryState(entry),
379400
callSource: (entry as any).callSource,
380401
specFile: (entry as any).file,
381402
fullTitle: entry.title,
@@ -391,11 +412,7 @@ export class DevtoolsSidebarExplorer extends CollapseableEntry {
391412
uid: entry.uid,
392413
label: entry.title,
393414
type: 'test',
394-
state: !entry.end
395-
? TestState.RUNNING
396-
: entry.state === 'failed'
397-
? TestState.FAILED
398-
: TestState.PASSED,
415+
state: this.#computeEntryState(entry),
399416
callSource: (entry as any).callSource,
400417
specFile: (entry as any).file,
401418
fullTitle: (entry as any).fullTitle || entry.title,

packages/backend/src/index.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,17 @@ export function broadcastToClients(message: string) {
3030
})
3131
}
3232

33-
export async function start(opts: DevtoolsBackendOptions = {}) {
33+
export async function start(opts: DevtoolsBackendOptions = {}): Promise<{ server: FastifyInstance; port: number }> {
3434
const host = opts.hostname || 'localhost'
3535
// Use getPort to find an available port, starting with the preferred port
3636
const preferredPort = opts.port || DEFAULT_PORT
3737
const port = await getPort({ port: preferredPort })
38-
38+
3939
// Log if we had to use a different port
4040
if (opts.port && port !== opts.port) {
4141
log.warn(`Port ${opts.port} is already in use, using port ${port} instead`)
4242
}
43-
43+
4444
const appPath = await getDevtoolsApp()
4545

4646
server = Fastify({ logger: true })
@@ -99,22 +99,22 @@ export async function start(opts: DevtoolsBackendOptions = {}) {
9999
log.info(
100100
`received ${message.length} byte message from worker to ${clients.size} client${clients.size > 1 ? 's' : ''}`
101101
)
102-
102+
103103
// Parse message to check if it's a clearCommands message
104104
try {
105105
const parsed = JSON.parse(message.toString())
106-
106+
107107
// If this is a clearCommands message, transform it to clear-execution-data format
108108
if (parsed.scope === 'clearCommands') {
109109
const testUid = parsed.data?.testUid
110110
log.info(`Clearing commands for test: ${testUid || 'all'}`)
111-
111+
112112
// Create a synthetic message that DataManager will understand
113113
const clearMessage = JSON.stringify({
114114
scope: 'clearExecutionData',
115115
data: { uid: testUid }
116116
})
117-
117+
118118
clients.forEach((client) => {
119119
if (client.readyState === WebSocket.OPEN) {
120120
client.send(clearMessage)
@@ -125,7 +125,7 @@ export async function start(opts: DevtoolsBackendOptions = {}) {
125125
} catch (e) {
126126
// Not JSON or parsing failed, forward as-is
127127
}
128-
128+
129129
// Forward all other messages as-is
130130
clients.forEach((client) => {
131131
if (client.readyState === WebSocket.OPEN) {
@@ -138,7 +138,7 @@ export async function start(opts: DevtoolsBackendOptions = {}) {
138138

139139
log.info(`Starting WebdriverIO Devtools application on port ${port}`)
140140
await server.listen({ port, host })
141-
return server
141+
return { server, port }
142142
}
143143

144144
export async function stop() {
@@ -147,15 +147,15 @@ export async function stop() {
147147
}
148148

149149
log.info('Shutting down WebdriverIO Devtools application')
150-
150+
151151
// Close all WebSocket connections first
152152
clients.forEach((client) => {
153153
if (client.readyState === WebSocket.OPEN || client.readyState === WebSocket.CONNECTING) {
154154
client.terminate()
155155
}
156156
})
157157
clients.clear()
158-
158+
159159
await server.close()
160160
}
161161

packages/nightwatch-devtools/README.md

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Brings the powerful WebdriverIO DevTools visual debugging interface to Nightwatc
88

99
See everything in real-time:
1010
- 📋 **Commands** - Every action executed
11-
- 🖥️ **Console** - Browser console logs
11+
- 🖥️ **Console** - Browser console logs
1212
- 🌐 **Network** - HTTP requests/responses
1313
-**Tests** - Suite structure and results
1414
- 📁 **Sources** - Test file contents
@@ -28,16 +28,18 @@ Add to your Nightwatch config:
2828

2929
```javascript
3030
// nightwatch.conf.js
31+
const nightwatchDevtools = require('@wdio/nightwatch-devtools').default;
32+
3133
module.exports = {
3234
src_folders: ['tests'],
33-
34-
plugins: ['@wdio/nightwatch-devtools'],
35-
35+
3636
test_settings: {
3737
default: {
3838
desiredCapabilities: {
3939
browserName: 'chrome'
40-
}
40+
},
41+
// Add DevTools globals with lifecycle hooks
42+
globals: nightwatchDevtools()
4143
}
4244
}
4345
}
@@ -51,7 +53,7 @@ nightwatch
5153

5254
The DevTools UI will automatically:
5355
1. Start backend server on port 3000
54-
2. Open in a new browser window
56+
2. Open in a new browser window
5557
3. Stream test data in real-time
5658
4. Stay open after tests finish (close manually to exit)
5759

@@ -66,7 +68,6 @@ Run it:
6668
```bash
6769
cd packages/nightwatch-devtools
6870
pnpm build
69-
pnpm validate # Quick check
7071
pnpm example # Run tests with DevTools UI
7172
```
7273

@@ -81,43 +82,31 @@ This is a **thin adapter** (~210 lines) that:
8182

8283
Same backend, same UI, same capture as WDIO - just different framework hooks!
8384

84-
## Validation
85-
86-
Verify the plugin is working:
87-
88-
```bash
89-
pnpm validate
90-
```
91-
92-
Output:
93-
```
94-
✅ Plugin compiled (dist/ exists)
95-
✅ Plugin module loaded
96-
✅ Plugin exports default class
97-
✅ Plugin can be instantiated
98-
✅ All required lifecycle methods present
99-
✨ Plugin validation successful!
100-
```
101-
10285
## Options
10386

10487
```javascript
105-
plugins: [
106-
['@wdio/nightwatch-devtools', {
107-
port: 3000, // DevTools server port
108-
hostname: 'localhost' // DevTools server hostname
109-
}]
110-
]
88+
const nightwatchDevtools = require('@wdio/nightwatch-devtools').default;
89+
90+
module.exports = {
91+
test_settings: {
92+
default: {
93+
globals: nightwatchDevtools({
94+
port: 3000, // DevTools server port (default: 3000)
95+
hostname: 'localhost' // DevTools server hostname (default: 'localhost')
96+
})
97+
}
98+
}
99+
}
111100
```
112101

113102
## What Gets Captured
114103

115-
✅ Test suites and hierarchy
116-
✅ Test pass/fail status
117-
✅ Execution timing
118-
✅ Error messages and stack traces
119-
✅ Browser console logs (automatic)
120-
✅ Network requests (automatic)
104+
✅ Test suites and hierarchy
105+
✅ Test pass/fail status
106+
✅ Execution timing
107+
✅ Error messages and stack traces
108+
✅ Browser console logs (automatic)
109+
✅ Network requests (automatic)
121110
✅ DOM mutations (automatic)
122111

123112
Browser-side capture works automatically via `@wdio/devtools-script`.

0 commit comments

Comments
 (0)