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
94 changes: 66 additions & 28 deletions Bunoshfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,10 +249,9 @@ export async function docsHelpers() {
const sharedPlaceholders = sharedPartials.map(file => `{{ ${path.basename(file, '.mustache')} }}`)
const sharedTemplates = sharedPartials.map(file => fs.readFileSync(`docs/shared/${file}`).toString()).map(template => `\n\n\n${template}`)

for (const file of files) {
const name = path.basename(file, '.js')
if (ignoreList.indexOf(name) >= 0) continue
say(`Writing documentation for ${name}`)
const helperFiles = files.filter(file => ignoreList.indexOf(path.basename(file, '.js')) < 0)

for (const file of helperFiles) {
copyFile(`lib/helper/${file}`, `docs/build/${file}`)
replaceInFile(`docs/build/${file}`, cfg => {
for (const i in placeholders) {
Expand Down Expand Up @@ -286,8 +285,14 @@ export async function docsHelpers() {
cfg.replace(/^export\s*\{\s*([^}]+)\s*\}/gm, 'module.exports = { $1 }')
cfg.replace(/^export\s+(class|function|const|let|var)\s+([^\s=]+)/gm, '$1 $2')
})
}

await shell`npx documentation build docs/build/${file} -o docs/helpers/${name}.md ${documentjsCliArgs}`
for (const file of helperFiles) {
const name = path.basename(file, '.js')
if (abstractHelpers.includes(name)) continue
say(`Writing documentation for ${name}`)

await docsHelperMarkdown(name, inheritedHelperDocs[name])
replaceInFile(helperMarkDownFile(name), cfg => {
cfg.replace(/\(optional, default.*?\)/gm, '')
cfg.replace(/\\*/gm, '')
Expand All @@ -309,10 +314,6 @@ export async function docsHelpers() {
cfg.replace(regex, '[1]')
})

if (name === 'Appium') {
await docsAppium()
}

await writeToFile(helperMarkDownFile(name), line => {
line`---
permalink: /helpers/${name}
Expand Down Expand Up @@ -392,28 +393,65 @@ export async function wiki() {
})
}

/**
* Generate docs for Appium by merging in public WebDriver methods.
*/
export async function docsAppium() {
const inheritedHelperDocs = {
Appium: {
parent: 'WebDriver',
exclude: [/Title/, /Popup/, /Cookie/, /Url/, /^press/, /^refreshPage/, /^resizeWindow/, /Script$/, /cursor/, /Css/, /Tab$/, /^wait/],
},
Obscura: { parent: 'CDPBrowser' },
Kitesurf: { parent: 'CDPBrowser', excludeConfig: ['endpoint', 'headers'] },
}

const abstractHelpers = ['CDPBrowser']

const helperHooks = [
'_init',
'_before',
'_after',
'_beforeStep',
'_afterStep',
'_beforeSuite',
'_afterSuite',
'_passed',
'_failed',
'_finishTest',
'_setConfig',
'_validateConfig',
'_test',
'_useTo',
]

async function docsHelperMarkdown(name, { parent, exclude = [], excludeConfig = [] } = {}) {
const documentation = await import('documentation')
const onlyWeb = [/Title/, /Popup/, /Cookie/, /Url/, /^press/, /^refreshPage/, /^resizeWindow/, /Script$/, /cursor/, /Css/, /Tab$/, /^wait/]
const webdriverDoc = await documentation.build(['docs/build/WebDriver.js'], {
shallow: true,
order: 'asc',
})
const doc = await documentation.build(['docs/build/Appium.js'], {
shallow: true,
order: 'asc',
})
const buildOptions = { shallow: true, sortOrder: ['alpha'] }
const doc = await documentation.build([`docs/build/${name}.js`], buildOptions)
let members = doc[0].members.instance

if (parent) {
const parentDoc = await documentation.build([`docs/build/${parent}.js`], buildOptions)
for (const method of parentDoc[0].members.instance) {
if (exclude.some(f => method.name.match(f))) continue
if (members.some(m => m.name === method.name)) continue
members.push(method)
}

for (const method of webdriverDoc[0].members.instance) {
if (onlyWeb.filter(f => method.name.match(f)).length) continue
if (doc[0].members.instance.filter(m => m.name === method.name).length) continue
doc[0].members.instance.push(method)
const config = doc.find(c => c.name === 'config')
const parentConfig = parentDoc.find(c => c.name === 'config')
if (config && parentConfig) {
for (const prop of parentConfig.properties) {
if (excludeConfig.includes(prop.name)) continue
if (config.properties.some(p => p.name === prop.name)) continue
config.properties.push(prop)
}
}
}
const output = await documentation.formats.md(doc)
fs.writeFileSync('docs/helpers/Appium.md', output)

members = members.filter(m => !helperHooks.includes(m.name))
members.sort((a, b) => a.name.startsWith('_') - b.name.startsWith('_') || a.name.localeCompare(b.name))
doc[0].members.instance = members

const output = await documentation.formats.md(doc, { markdownToc: false })
fs.writeFileSync(helperMarkDownFile(name), output)
}

/**
Expand Down
16 changes: 3 additions & 13 deletions docs/alternative-browsers.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ title: Alternative Browser Engines
# Alternative Browser Engines

::: warning Experimental
The `CDPBrowser`, `Obscura`, and `Kitesurf` helpers are experimental in CodeceptJS 4.2. Pin browser versions in CI and retain Playwright or WebDriver coverage for compatibility-critical tests.
The `Obscura` and `Kitesurf` helpers are experimental in CodeceptJS 4.2. Pin browser versions in CI and retain Playwright or WebDriver coverage for compatibility-critical tests.
:::

Playwright and Puppeteer drive full Chromium — the most accurate way to test what users see.
But a new class of lightweight, agent-era browsers has appeared, and CodeceptJS can drive them
through the `CDPBrowser` helper family:
through dedicated helpers:

- **[Obscura](https://github.com/h4ckf0r0day/obscura)** — an open-source Rust browser with a real
V8 engine. From v0.2.0, the default release build also renders — real layout, computed styles,
Expand Down Expand Up @@ -96,15 +96,6 @@ CodeceptJS 4.2 is tested in CI with Obscura 0.2.2. Obscura 0.2.x is recommended;
},
}

Any other CDP endpoint works through the base helper:

helpers: {
CDPBrowser: {
url: 'http://localhost:3000',
endpoint: 'http://127.0.0.1:9222',
},
}

### Obscura's three connection modes

Obscura manages its own `obscura serve` process, the same way Playwright manages its own browser
Expand Down Expand Up @@ -154,5 +145,4 @@ process — there is nothing to start by hand in the common case:
| Where it runs | local/grid | local | Cloudflare only |
| License / cost | open source | Apache-2.0 | proprietary, free beta |

See helper reference pages: [CDPBrowser](/helpers/CDPBrowser), [Obscura](/helpers/Obscura),
[Kitesurf](/helpers/Kitesurf).
See helper reference pages: [Obscura](/helpers/Obscura), [Kitesurf](/helpers/Kitesurf).
40 changes: 20 additions & 20 deletions docs/helpers/ApiDataFactory.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,26 +192,6 @@ By default `id` property of response is taken. This behavior can be changed by s

* `config` &#x20;

### _requestCreate

Executes request to create a record in API.
Can be replaced from a in custom helper.

#### Parameters

* `factory` **any**&#x20;
* `data` **any**&#x20;

### _requestDelete

Executes request to delete a record in API
Can be replaced from a custom helper.

#### Parameters

* `factory` **any**&#x20;
* `id` **any**&#x20;

### have

Generates a new record using factory and saves API request to store it.
Expand Down Expand Up @@ -256,6 +236,26 @@ I.haveMultiple('post', 3, { author: 'davert' }, { publish_date: '01.01.1997' });
* `params` **any?**&#x20;
* `options` **any?**&#x20;

### _requestCreate

Executes request to create a record in API.
Can be replaced from a in custom helper.

#### Parameters

* `factory` **any**&#x20;
* `data` **any**&#x20;

### _requestDelete

Executes request to delete a record in API
Can be replaced from a custom helper.

#### Parameters

* `factory` **any**&#x20;
* `id` **any**&#x20;

[1]: https://github.com/rosiejs/rosie

[2]: https://www.npmjs.com/package/faker
Expand Down
Loading
Loading