Skip to content
Open
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
51 changes: 43 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ Tests can be executed via different helpers.
This is a playground for your first steps in testing, so instead of installing it from NPM it is recommended to clone it from repo instead and then install the dependencies:

```
git clone git@github.com:codecept-js/examples.git codeceptjs-examples && cd codeceptjs-examples && npm i
git clone git@github.com:codeceptjs/examples.git codeceptjs-examples && cd codeceptjs-examples && npm i
```

This will install CodeceptJS with Puppeteer, WebdriverIO & TestCafe packages.
This will install CodeceptJS 4.x with Playwright, Puppeteer & WebdriverIO packages.

# Running Tests

Expand All @@ -30,26 +30,61 @@ npx codeceptjs run --steps
Use `codecept.puppeteer.conf.js` to run tests with Puppeteer:

```
npx codeceptjs run --steps -c codecept.puppeteer.conf.js
npx codeceptjs run --steps -c codecept.puppeteer.conf.js
```


## WebdriverIO

Use `codecept.webdriver.conf.js` to run tests with WebdriverIO in Chrome:

```
npx codeceptjs run -c codecept.webdriver.conf.js --steps
npx codeceptjs run -c codecept.webdriver.conf.js --steps
```

## TestCafe
## Alternative browsers

CodeceptJS 4.x can drive lightweight alternative browsers over the Chrome DevTools Protocol.
They are much faster and smaller than Chrome, at the cost of some features — pick the one that fits your suite:

| Helper | Browser | Renders screenshots | JavaScript | Best for |
| --- | --- | --- | --- | --- |
| `Playwright` / `Puppeteer` / `WebDriver` | Chrome/Chromium | ✅ | ✅ V8 | everything, full compatibility |
| `Obscura` | [Obscura](https://github.com/h4ckf0r0day/obscura) | ✅ | ✅ | fast smoke tests with screenshots |
| `Lightpanda` | [Lightpanda](https://lightpanda.io) | ❌ | ✅ V8 | fastest smoke tests, CI-friendly |
| `Moli` | [Moli](https://github.com/lexmount/moli) | ❌ | ✅ V8 + Servo styles | fast smoke tests, real CSS |

**Known limitations on this TodoMVC (React) app:**

- Alternative browsers use synthetic input: React checkbox toggling (`checkOption`) and hover-revealed controls (delete buttons appear on hover) may not work. Such tests are tagged `@full-browser` and excluded from the alternative-browser configs via `grep` — copy that pattern to your own suite.
- No screenshots on Lightpanda/Moli: `I.saveScreenshot()` is a no-op (a debug message is printed).
- Lightpanda has no Windows binary yet — on Windows run it via WSL or Docker and point the helper at the running server (`endpoint` config option). Moli ships Windows builds.

Use `codecept.testcafe.conf.js` to run tests with TestCafe in Chrome:
### Obscura

Install the [Obscura binary](https://github.com/h4ckf0r0day/obscura/releases) and run:

```
npx codeceptjs run -c codecept.testcafe.conf.js --steps
OBSCURA_PATH=/path/to/obscura npx codeceptjs run --steps -c codecept.obscura.conf.js
```

### Lightpanda

Install [Lightpanda](https://lightpanda.io/docs/open-source/installation) and run:

```
LIGHTPANDA_PATH=/path/to/lightpanda npx codeceptjs run --steps -c codecept.lightpanda.conf.js
```

### Moli

Install [Moli](https://github.com/lexmount/moli#direct-installation) and run:

```
MOLI_PATH=/path/to/moli npx codeceptjs run --steps -c codecept.moli.conf.js
```

The Moli helper ships with CodeceptJS versions after 4.2.1.

## Headless Mode

Run tests in headless mode:
Expand Down
34 changes: 34 additions & 0 deletions chromedriver-hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Starts a local chromedriver instance for the WebDriver helper (bootstrap)
// and stops it when the test run finishes (teardown).
const { spawn } = require('child_process')
const http = require('http')
const chromedriver = require('chromedriver')

let chromedriverProcess = null

function waitForStatus(url, retries = 30) {
return new Promise((resolve, reject) => {
const attempt = remaining => {
const req = http.get(url, res => {
res.resume()
if (res.statusCode === 200) return resolve()
retry(remaining)
})
req.on('error', () => retry(remaining))
}
const retry = remaining => {
if (remaining <= 0) return reject(new Error('chromedriver did not start'))
setTimeout(() => attempt(remaining - 1), 500)
}
attempt(retries)
})
}

exports.bootstrap = async function () {
chromedriverProcess = spawn(chromedriver.path, ['--port=9515'], { stdio: 'ignore' })
await waitForStatus('http://127.0.0.1:9515/status')
}

exports.teardown = async function () {
if (chromedriverProcess) chromedriverProcess.kill()
}
45 changes: 45 additions & 0 deletions codecept.lightpanda.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const { setHeadlessWhen } = require('@codeceptjs/configure');

setHeadlessWhen(process.env.HEADLESS);

// Lightpanda (https://lightpanda.io) — a headless browser built from scratch for automation.
// Runs real JavaScript in V8 but never paints a page: no screenshots, no coordinate clicks.
// Perfect for fast smoke tests; keep a Playwright job for rendering-sensitive checks.
//
// Requirements: `lightpanda` binary from https://lightpanda.io/docs/open-source/installation
// on your PATH, or pointed to by LIGHTPANDA_PATH / binaryPath below.
// The helper starts `lightpanda serve` per run and stops it automatically.

exports.config = {
tests: './todomvc-tests/**/*_test.js',
// exclude tests that need a full browser (hover, real pointer input)
grep: '^(?!.*@full-browser).*',
output: './output',
helpers: {
Lightpanda: {
url: 'https://todomvc.com',
// binaryPath: 'C:/tools/lightpanda', // or set LIGHTPANDA_PATH env variable
},

REST: {},

CustomHelper: {
require: './todomvc-tests/helpers/custom.helper.js'
}
},

gherkin: {
features: './todomvc-tests/features/*.feature',
steps: [
'./todomvc-tests/step-definitions/create-todos.steps.js'
]
},

include: {
TodosPage: './todomvc-tests/pages/todos.page.js'
},
bootstrap: null,
mocha: {},
plugins: {},
name: 'codecept demo tests (Lightpanda)'
}
49 changes: 49 additions & 0 deletions codecept.moli.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const { setHeadlessWhen } = require('@codeceptjs/configure');

setHeadlessWhen(process.env.HEADLESS);

// Moli (https://github.com/lexmount/moli) — an open-source headless browser written in Rust.
// Runs real JavaScript and computes real CSS, but skips layout and painting:
// no screenshots, no coordinate-based clicks. Very fast startup, tiny footprint.
//
// Requirements:
// - `moli` binary from https://github.com/lexmount/moli#direct-installation on your PATH,
// or pointed to by MOLI_PATH / binaryPath below
// - CodeceptJS with the Moli helper (added after 4.2.1; use codeceptjs from the 4.x branch
// until the next release: npm i codeceptjs@codeceptjs/CodeceptJS#4.x)
//
// The helper starts `moli serve` per run and stops it automatically.

exports.config = {
tests: './todomvc-tests/**/*_test.js',
// exclude tests that need a full browser (hover, real pointer input)
grep: '^(?!.*@full-browser).*',
output: './output',
helpers: {
Moli: {
url: 'https://todomvc.com',
// binaryPath: 'C:/tools/moli/moli.exe', // or set MOLI_PATH env variable
},

REST: {},

CustomHelper: {
require: './todomvc-tests/helpers/custom.helper.js'
}
},

gherkin: {
features: './todomvc-tests/features/*.feature',
steps: [
'./todomvc-tests/step-definitions/create-todos.steps.js'
]
},

include: {
TodosPage: './todomvc-tests/pages/todos.page.js'
},
bootstrap: null,
mocha: {},
plugins: {},
name: 'codecept demo tests (Moli)'
}
44 changes: 44 additions & 0 deletions codecept.obscura.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const { setHeadlessWhen } = require('@codeceptjs/configure');

setHeadlessWhen(process.env.HEADLESS);

// Obscura (https://github.com/h4ckf0r0day/obscura) — a lightweight open-source browser
// exposed over CDP. Renders real screenshots, much smaller footprint than Chrome.
//
// Requirements: `obscura` binary from https://github.com/h4ckf0r0day/obscura/releases
// on your PATH, or pointed to by OBSCURA_PATH / binaryPath below.
// The helper starts `obscura` per run and stops it automatically.

exports.config = {
tests: './todomvc-tests/**/*_test.js',
// exclude tests that need a full browser (hover, real pointer input)
grep: '^(?!.*@full-browser).*',
output: './output',
helpers: {
Obscura: {
url: 'https://todomvc.com',
// binaryPath: 'C:/tools/obscura/obscura.exe', // or set OBSCURA_PATH env variable
},

REST: {},

CustomHelper: {
require: './todomvc-tests/helpers/custom.helper.js'
}
},

gherkin: {
features: './todomvc-tests/features/*.feature',
steps: [
'./todomvc-tests/step-definitions/create-todos.steps.js'
]
},

include: {
TodosPage: './todomvc-tests/pages/todos.page.js'
},
bootstrap: null,
mocha: {},
plugins: {},
name: 'codecept demo tests (Obscura)'
}
35 changes: 0 additions & 35 deletions codecept.testcafe.conf.js

This file was deleted.

19 changes: 9 additions & 10 deletions codecept.webdriver.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ const { setHeadlessWhen } = require('@codeceptjs/configure');

setHeadlessWhen(process.env.HEADLESS);

// WebDriver (Selenium protocol) via a locally started chromedriver.
// The bootstrap script starts chromedriver on port 9515 and stops it after the run.

exports.config = {
tests: './todomvc-tests/**/*_test.js',
output: './output',
helpers: {
WebDriver: {
url: 'http://localhost',
url: 'https://todomvc.com',
browser: 'chrome',
host: '127.0.0.1',
port: 9515,
path: '/',
},

REST: {},
Expand All @@ -28,15 +34,8 @@ exports.config = {
include: {
TodosPage: './todomvc-tests/pages/todos.page.js'
},

plugins: {
wdio: {
enabled: true,
services: ['selenium-standalone']
}
},

bootstrap: null,
bootstrap: require('./chromedriver-hooks').bootstrap,
teardown: require('./chromedriver-hooks').teardown,
mocha: {},
name: 'codecept demo tests'
}
24 changes: 14 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
{
"name": "@codeceptjs/examples",
"version": "1.2.4",
"version": "2.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "npx codeceptjs run --steps",
"test:playwright": "npx codeceptjs run --steps -c codecept.conf.js",
"test:puppeteer": "npx codeceptjs run --steps -c codecept.puppeteer.conf.js",
"test:webdriver": "npx codeceptjs run --steps -c codecept.webdriver.conf.js",
"test:lightpanda": "npx codeceptjs run --steps -c codecept.lightpanda.conf.js",
"test:obscura": "npx codeceptjs run --steps -c codecept.obscura.conf.js",
"test:moli": "npx codeceptjs run --steps -c codecept.moli.conf.js"
},
"keywords": [],
"author": "kaflan, davert",
Expand All @@ -19,15 +25,13 @@
"url": "https://github.com/codeceptjs/examples.git/issues"
},
"homepage": "https://github.com/codeceptjs/examples.git#readme",
"description": "",
"description": "TodoMVC tests demonstrating every CodeceptJS browser helper, including alternative no-render browsers",
"devDependencies": {
"@codeceptjs/configure": "^0.5.0",
"@codeceptjs/ui": "^0.2.0",
"@wdio/selenium-standalone-service": "^5.16.10",
"codeceptjs": "3.5.12",
"playwright": "1.41.2",
"puppeteer": "^2.0.0",
"testcafe": "^1.7.0",
"webdriverio": "^5.16.11"
"codeceptjs": "^4.2.1",
"playwright": "^1.63.0",
"puppeteer": "24.36.0",
"webdriverio": "9.23.0",
"chromedriver": "155.0.2"
}
}
3 changes: 2 additions & 1 deletion todomvc-tests/edit-todos_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ Scenario.skip('Edited todo is saved on blur', async ({ I, TodosPage }) => {
I.saveScreenshot('edited-todo-saved-on-blur.png')
})

Scenario('Delete todos', async ({ I, TodosPage }) => {
// @full-browser: the delete button is revealed on hover, which alternative browsers can't do
Scenario('Delete todos @full-browser', async ({ I, TodosPage }) => {
I.say('Given I have some todos')
I.say('When I delete the first todo')
TodosPage.deleteNthTodo(1)
Expand Down
2 changes: 1 addition & 1 deletion todomvc-tests/pages/todos.page.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ module.exports = {
todos = [todos]
}

assert(todos[nthTodo - 1] === todo, `Expected "${todo}" but got "${todos[nthTodo - 1]}"`)
assert(todos[nthTodo - 1].trim() === todo, `Expected "${todo}" but got "${todos[nthTodo - 1]}"`)
return todos
},

Expand Down
Loading
Loading