Skip to content

Commit a91eba9

Browse files
author
DavertMik
committed
updated docs generation
1 parent b6daa67 commit a91eba9

7 files changed

Lines changed: 1260 additions & 3430 deletions

File tree

‎Bunoshfile.js‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,11 +425,13 @@ async function docsHelperMarkdown(name, { parent, exclude = [], excludeConfig =
425425
const documentation = await import('documentation')
426426
const buildOptions = { shallow: true, sortOrder: ['alpha'] }
427427
const doc = await documentation.build([`docs/build/${name}.js`], buildOptions)
428+
doc.sort((a, b) => (b.kind === 'class') - (a.kind === 'class'))
428429
let members = doc[0].members.instance
429430

430431
if (parent) {
431432
const parentDoc = await documentation.build([`docs/build/${parent}.js`], buildOptions)
432-
for (const method of parentDoc[0].members.instance) {
433+
const parentClass = parentDoc.find(c => c.kind === 'class')
434+
for (const method of parentClass.members.instance) {
433435
if (exclude.some(f => method.name.match(f))) continue
434436
if (members.some(m => m.name === method.name)) continue
435437
members.push(method)

‎docs/helpers/Kitesurf.md‎

Lines changed: 551 additions & 923 deletions
Large diffs are not rendered by default.

‎docs/helpers/Obscura.md‎

Lines changed: 567 additions & 1002 deletions
Large diffs are not rendered by default.

‎lib/helper/CDPBrowser.js‎

Lines changed: 118 additions & 1390 deletions
Large diffs are not rendered by default.

‎lib/helper/Kitesurf.js‎

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import CDPBrowser from './CDPBrowser.js'
44
/**
55
* ## Configuration
66
*
7-
* This helper should be configured in codecept.conf.js. It accepts everything `CDPBrowser`
8-
* accepts (see its config table), plus:
7+
* This helper should be configured in codecept.conf.js
98
*
109
* @typedef KitesurfConfig
1110
* @type {object}
@@ -14,8 +13,8 @@ import CDPBrowser from './CDPBrowser.js'
1413
* @prop {string} [apiToken] - Cloudflare API token; defaults to CF_API_TOKEN env var
1514
* @prop {number} [keepAlive=240000] - session keep-alive time in milliseconds
1615
* @prop {string} [apiBase=https://api.cloudflare.com/client/v4] - Cloudflare API base URL
17-
* @prop {string} [input=cdp] - input method for user actions; defaults to 'cdp' for Kitesurf's real layout engine, but can be overridden
18-
* @prop {object} [capabilities] - pre-configured capabilities; Kitesurf uses { layout: 'real', screenshot: true }
16+
* @prop {string} [input=cdp] - how actions are dispatched: `cdp` (real mouse and keyboard events) or `synthetic` (DOM events).
17+
* @prop {object} [capabilities] - browser capabilities; Kitesurf sets `{ layout: 'real', screenshot: true }`.
1918
*/
2019
const config = {}
2120

@@ -90,14 +89,6 @@ class Kitesurf extends CDPBrowser {
9089
this.cloudSessionId = null
9190
}
9291

93-
/**
94-
* Acquires a Kitesurf browser session from the Cloudflare Browser Run API and resolves it to
95-
* the `wss://` debugger URL `CDPConnection` connects to. Overrides `CDPBrowser._resolveEndpoint`,
96-
* which resolves a fixed local endpoint instead of provisioning a cloud session per test.
97-
*
98-
* @returns {Promise<string>} a `wss://` debugger URL ready to be passed to `CDPConnection`.
99-
* @protected
100-
*/
10192
async _resolveEndpoint() {
10293
if (!this.options.accountId || !this.options.apiToken) {
10394
throw new Error('Kitesurf requires accountId and apiToken (or CF_ACCOUNT_ID / CF_API_TOKEN env vars)')
@@ -113,15 +104,6 @@ class Kitesurf extends CDPBrowser {
113104
return data.webSocketDebuggerUrl
114105
}
115106

116-
/**
117-
* Closes the target as `CDPBrowser._finishTest` does, then releases the cloud session acquired
118-
* in `_resolveEndpoint` via the Cloudflare API so it does not linger for the full `keepAlive`
119-
* window. The release runs in a `finally` so a rejection while closing the CDP connection still
120-
* frees the cloud session instead of leaving the browser alive until `keepAlive` expires; the
121-
* session id is cleared before the request, so a repeated call never releases it twice.
122-
*
123-
* @protected
124-
*/
125107
async _finishTest() {
126108
try {
127109
await super._finishTest()

‎lib/helper/Obscura.js‎

Lines changed: 15 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,20 @@ import { isFile, isWindows } from '../utils.js'
1313
*
1414
* @typedef ObscuraConfig
1515
* @type {object}
16-
* @prop {string} [endpoint] - explicit CDP endpoint. Setting this switches the helper to ATTACH
17-
* mode: it only connects, and never spawns or kills a process, no matter what else is configured.
18-
* Leave it unset for SELF-MANAGED mode (see below).
19-
* @prop {string} [binaryPath] - path to the `obscura` executable, used in SELF-MANAGED mode
20-
* (`endpoint` unset). Checked before `OBSCURA_PATH` and `PATH`.
21-
* @prop {number} [port] - port `obscura serve` listens on, in SELF-MANAGED mode. When unset, a
22-
* free port is picked automatically, which is what makes `run-workers` collision-free — every
23-
* worker gets its own instance on its own port with zero config.
24-
* @prop {number} [serverStartTimeout=15000] - milliseconds to wait for a spawned `obscura serve`
25-
* to answer `/json/version` before `_connect` gives up.
16+
* @prop {string} [endpoint] - connect to a running Obscura instead of starting one (ATTACH mode).
17+
* @prop {string} [binaryPath] - path to the `obscura` executable. Checked before `OBSCURA_PATH` and `PATH`.
18+
* @prop {number} [port] - port for `obscura serve`. A free port is picked when unset, so parallel workers never collide.
19+
* @prop {number} [serverStartTimeout=15000] - how long to wait for `obscura serve` to start, in milliseconds.
2620
*/
2721
const config = {}
2822

2923
/**
30-
* Obscura drives [Obscura](https://github.com/h4ckf0r0day/obscura), a minimal headless
31-
* browser exposed over the Chrome DevTools Protocol. From v0.2.0, default release builds ship a
32-
* real rendering engine (layout, paint, screenshots); `-no-render` variants and v0.1.x builds keep
33-
* the original single-V8-isolate, nothing-rendered mode. This helper does not hardcode which mode a
34-
* given binary is in — `CDPBrowser._probeCapabilities` detects `layout`/`screenshot` per binary at
35-
* runtime, so the same helper works against either.
24+
* Obscura drives [Obscura](https://github.com/h4ckf0r0day/obscura), a lightweight headless
25+
* browser controlled over the Chrome DevTools Protocol. Default builds from v0.2.0 render pages
26+
* (layout, screenshots); `-no-render` builds and v0.1.x run JavaScript and the DOM only. The helper
27+
* detects which build it runs against, so the same config works for both.
3628
*
37-
* This helper is a thin `CDPBrowser` subclass: it changes nothing about how locating or acting on
38-
* elements works, it only pins the config presets Obscura requires and manages the `obscura serve`
39-
* process lifecycle, the same way Playwright manages its own browser process.
29+
* The helper starts and stops `obscura serve` for you, the same way Playwright manages its browser.
4030
*
4131
* > Obscura support is experimental in CodeceptJS 4.2. Pin the browser version in CI and keep a
4232
* > Playwright/WebDriver job for browser-compatibility coverage.
@@ -56,8 +46,8 @@ const config = {}
5646
* - **SELF-LAUNCH** — `endpoint` is unset and a binary can be resolved, in order: `binaryPath` in
5747
* the config, then the `OBSCURA_PATH` environment variable, then `obscura` on `PATH`. The helper
5848
* spawns `obscura serve --port <port> --allow-private-network --allow-file-access` (`port` from
59-
* the config, or a free port picked automatically), waits for it to answer, connects, and kills
60-
* it in `_finishTest`.
49+
* the config, or a free port picked automatically), waits for it to answer, connects, and stops
50+
* it when tests finish.
6151
* - **COURTESY-ATTACH** — `endpoint` is unset and no binary can be resolved, but something already
6252
* answers `http://127.0.0.1:9222/json/version` (e.g. `obscura serve` started by hand, or by CI
6353
* before this process ever ran). The helper attaches to it and never kills it — it isn't the
@@ -96,13 +86,11 @@ const config = {}
9686
*
9787
* | option | value | why |
9888
* | --- | --- | --- |
99-
* | `input` | `synthetic` | coordinate-click navigation is unreliable over CDP on Obscura even on rendering builds (no `frameNavigated` event, stale `page.url()`); `click` always takes the `forceClick` path — on Obscura, `click` and `forceClick` are the same thing |
100-
* | `xpathPolyfill` | `auto` | probed per binary/page: Obscura's native `document.evaluate` still doesn't support attribute selection or `not()`, so the polyfill is used until that lands |
89+
* | `input` | `synthetic` | clicks that navigate are unreliable in Obscura, so `click` behaves like `forceClick` |
90+
* | `xpathPolyfill` | `auto` | Obscura's XPath lacks attribute selection and `not()`, so the polyfill is used when needed |
10191
*
102-
* `capabilities.layout`/`capabilities.screenshot`/`capabilities.xpath` are intentionally left
103-
* unset here — `CDPBrowser._probeCapabilities` detects them at runtime from the actual binary
104-
* (`'real'`/`true` on v0.2.0+ default builds, `'none'`/`false` on `-no-render` builds and v0.1.x).
105-
* Set them explicitly in your own config to skip probing or to force a mode.
92+
* `capabilities` are detected at runtime from the Obscura build. Set them in your config to skip
93+
* detection or to force a mode.
10694
*
10795
* ## Limitations
10896
*
@@ -168,17 +156,6 @@ class Obscura extends CDPBrowser {
168156
this._selfManagedResolved = false
169157
}
170158

171-
/**
172-
* In ATTACH mode, connects exactly as `CDPBrowser._connect` would. In SELF-MANAGED mode,
173-
* resolves and spawns `obscura serve` (or courtesy-attaches to an already-running one on
174-
* :9222) exactly once via `_resolveSelfManaged`, then connects.
175-
*
176-
* A spawn failure (e.g. a bad binary) is delivered asynchronously by Node as an `error`
177-
* event; it is recorded on `this.serverError` and surfaced as a rejection from `_waitForServer`
178-
* instead of crashing the process as an uncaught exception.
179-
*
180-
* @protected
181-
*/
182159
async _connect() {
183160
if (this.mode !== 'attach' && !this._selfManagedResolved) {
184161
await this._resolveSelfManaged()
@@ -187,14 +164,6 @@ class Obscura extends CDPBrowser {
187164
return super._connect()
188165
}
189166

190-
/**
191-
* Resolves how to reach Obscura when no explicit `endpoint` was configured, trying, in order:
192-
* spawn a binary (`binaryPath` config, then `OBSCURA_PATH` env, then `obscura` on `PATH`),
193-
* courtesy-attach to `http://127.0.0.1:9222` if something already answers there, or throw a
194-
* loud, actionable error. Sets `this.options.endpoint` as a side effect.
195-
*
196-
* @protected
197-
*/
198167
async _resolveSelfManaged() {
199168
const binaryPath = this._resolveBinary()
200169
if (binaryPath) {
@@ -225,15 +194,6 @@ class Obscura extends CDPBrowser {
225194
)
226195
}
227196

228-
/**
229-
* Resolves the `obscura` binary to spawn, in priority order: `options.binaryPath`, then the
230-
* `OBSCURA_PATH` environment variable, then `obscura` on `PATH`. The `PATH` lookup walks the
231-
* directories itself instead of shelling out to `which`, which does not exist on Windows: on
232-
* Windows every `PATHEXT` suffix is tried, so an `obscura.exe` on `PATH` is found too.
233-
*
234-
* @returns {string|null} an absolute or relative path to the binary, or null if none resolved.
235-
* @protected
236-
*/
237197
_resolveBinary() {
238198
if (this.options.binaryPath) return this.options.binaryPath
239199
if (process.env.OBSCURA_PATH) return process.env.OBSCURA_PATH
@@ -256,14 +216,6 @@ class Obscura extends CDPBrowser {
256216
return null
257217
}
258218

259-
/**
260-
* Picks a free TCP port on 127.0.0.1 by briefly listening on port 0 and reading back the OS-assigned
261-
* port. Used as the SELF-LAUNCH default when `options.port` isn't explicitly set, so multiple
262-
* `run-workers` workers never collide on the same port.
263-
*
264-
* @returns {Promise<number>} a free port.
265-
* @protected
266-
*/
267219
async _findFreePort() {
268220
return new Promise((resolve, reject) => {
269221
const srv = net.createServer()
@@ -276,13 +228,6 @@ class Obscura extends CDPBrowser {
276228
})
277229
}
278230

279-
/**
280-
* Probes a `/json/version`-style URL with a short timeout, used for the COURTESY-ATTACH check.
281-
*
282-
* @param {string} url
283-
* @returns {Promise<boolean>} true if the URL answered.
284-
* @protected
285-
*/
286231
async _probeUp(url) {
287232
try {
288233
await axios.get(url, { timeout: 1000 })
@@ -292,15 +237,6 @@ class Obscura extends CDPBrowser {
292237
}
293238
}
294239

295-
/**
296-
* Polls `http://127.0.0.1:<port>/json/version` until `obscura serve` responds, `this.serverError`
297-
* is set by the spawned process' `error` event, or `options.serverStartTimeout` elapses. The
298-
* process typically comes up within tens of milliseconds — a 20ms retry interval (down from a
299-
* previous 200ms) keeps the wasted tail after the server is actually ready small, since this cost
300-
* is paid once per run and counts directly toward real-world startup latency.
301-
*
302-
* @protected
303-
*/
304240
async _waitForServer() {
305241
const timeout = this.options.serverStartTimeout || 15000
306242
const deadline = Date.now() + timeout
@@ -321,19 +257,6 @@ class Obscura extends CDPBrowser {
321257
throw new Error(`obscura serve did not start on port ${this.options.port} within ${timeout}ms`)
322258
}
323259

324-
/**
325-
* Closes the CDP connection (via `CDPBrowser._finishTest`), then kills the `obscura serve`
326-
* process spawned by `_connect`, if any (never runs in ATTACH or COURTESY-ATTACH mode, since
327-
* `this.serverProcess` is only ever set in SELF-LAUNCH mode). Runs in a `finally` so the process
328-
* is always reaped even if closing the CDP connection throws. Sends `SIGTERM` first and waits for
329-
* the process to exit; a process that ignores `SIGTERM` is escalated to `SIGKILL` after 5s. The
330-
* promise only resolves once the child has actually exited (confirmed via the `exit` event, not
331-
* merely once `SIGKILL` was sent — the kernel needs a moment to reap it), with a final safety-net
332-
* timeout so a stuck child can never keep the event loop alive even if that confirmation is
333-
* somehow lost.
334-
*
335-
* @protected
336-
*/
337260
async _finishTest() {
338261
try {
339262
await super._finishTest()

‎runok.cjs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,11 +430,13 @@ title: ${name}
430430
const documentation = await import('documentation')
431431
const buildOptions = { shallow: true, sortOrder: ['alpha'] }
432432
const doc = await documentation.build([`docs/build/${name}.js`], buildOptions)
433+
doc.sort((a, b) => (b.kind === 'class') - (a.kind === 'class'))
433434
let members = doc[0].members.instance
434435

435436
if (parent) {
436437
const parentDoc = await documentation.build([`docs/build/${parent}.js`], buildOptions)
437-
for (const method of parentDoc[0].members.instance) {
438+
const parentClass = parentDoc.find(c => c.kind === 'class')
439+
for (const method of parentClass.members.instance) {
438440
if (exclude.some(f => method.name.match(f))) continue
439441
if (members.some(m => m.name === method.name)) continue
440442
members.push(method)

0 commit comments

Comments
 (0)