Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/open-the-nightwatch-dashboard-over-webdriver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@wdio/nightwatch-devtools': patch
---

Open the dashboard window over WebDriver and stop requiring the `devtools` package. The plugin opened it with `automationProtocol: 'devtools'`, which loads the `devtools` package, so `devtools` `^8.42.0` was a peer and npm installed it and an old Puppeteer into every project. Without it the dashboard window did not open (`Couldn't find automation protocol "devtools"`). The window now opens through chromedriver, still without the "controlled by automated test software" bar, and `devtools` is no longer a peer.
1 change: 0 additions & 1 deletion packages/nightwatch-devtools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
"typescript": "^6.0.3"
},
"peerDependencies": {
"devtools": "^8.42.0",
"nightwatch": ">=3.0.0"
}
}
15 changes: 4 additions & 11 deletions packages/nightwatch-devtools/src/run-lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,25 +135,18 @@ export async function openDevtoolsBrowser(
}
ctx.devtoolsBrowser = await remote({
logLevel: 'info',
automationProtocol: 'devtools',
capabilities: {
browserName: 'chrome',
'goog:chromeOptions': {
excludeSwitches: ['enable-automation'],
args: [
'--window-size=1600,1200',
`--user-data-dir=${ctx.userDataDir}`,
'--no-first-run',
'--no-default-browser-check'
]
},
// Dashboard uses the Puppeteer-based 'devtools' protocol; drop the
// "controlled by automated test software" infobar by ignoring
// Puppeteer's --enable-automation default. (Runtime-valid capability
// not present in the type.)
'wdio:devtoolsOptions': {
ignoreDefaultArgs: ['--enable-automation']
}
} as WebdriverIO.Capabilities
}
})
await ctx.devtoolsBrowser.url(url)
} catch (err) {
Expand Down Expand Up @@ -201,7 +194,7 @@ export async function waitForDevtoolsBrowserClose(
return
}
;(logger as { setLevel: (ns: string, lvl: string) => void }).setLevel(
'devtools',
'webdriver',
'warn'
)
let exitBySignal = false
Expand Down Expand Up @@ -229,7 +222,7 @@ export async function waitForDevtoolsBrowserClose(
process.removeListener('SIGINT', signalHandler)
process.removeListener('SIGTERM', signalHandler)
;(logger as { setLevel: (ns: string, lvl: string) => void }).setLevel(
'devtools',
'webdriver',
'info'
)
try {
Expand Down
65 changes: 65 additions & 0 deletions packages/nightwatch-devtools/tests/runLifecycle.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import * as fs from 'node:fs'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { remote } from 'webdriverio'

import {
openDevtoolsBrowser,
type RunLifecycleCtx
} from '../src/run-lifecycle.js'

vi.mock('webdriverio', () => ({ remote: vi.fn() }))
vi.mock('@wdio/devtools-backend', () => ({ start: vi.fn(), stop: vi.fn() }))

function makeCtx(): RunLifecycleCtx {
// openDevtoolsBrowser reads only these fields; the managers and reporter are irrelevant here.
return {
options: { hostname: 'localhost', port: 3000 },
devtoolsBrowser: undefined,
userDataDir: undefined
} as unknown as RunLifecycleCtx
}

describe('openDevtoolsBrowser', () => {
const browser = { url: vi.fn().mockResolvedValue(undefined) }
let ctx: RunLifecycleCtx

beforeEach(() => {
vi.mocked(remote).mockResolvedValue(browser as never)
ctx = makeCtx()
})

afterEach(() => {
if (ctx.userDataDir) {
fs.rmSync(ctx.userDataDir, { recursive: true, force: true })
}
vi.clearAllMocks()
})

it('opens the dashboard over WebDriver, which needs no `devtools` package', async () => {
await openDevtoolsBrowser(ctx, 'http://localhost:3000')

const [params] = vi.mocked(remote).mock.calls[0]
expect(params).not.toHaveProperty('automationProtocol')
expect(params.capabilities).not.toHaveProperty('wdio:devtoolsOptions')
expect(params.capabilities).toEqual(
expect.objectContaining({
browserName: 'chrome',
'goog:chromeOptions': expect.objectContaining({
excludeSwitches: ['enable-automation'],
args: expect.arrayContaining([`--user-data-dir=${ctx.userDataDir}`])
})
})
)
expect(browser.url).toHaveBeenCalledWith('http://localhost:3000')
expect(ctx.devtoolsBrowser).toBe(browser)
})

it('leaves the run going when the window cannot be opened', async () => {
vi.mocked(remote).mockRejectedValue(new Error('no chromedriver'))

await expect(
openDevtoolsBrowser(ctx, 'http://localhost:3000')
).resolves.toBeUndefined()
expect(ctx.devtoolsBrowser).toBeUndefined()
})
})
3 changes: 0 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading