Skip to content

Commit f32bcb0

Browse files
DavertMikclaude
andcommitted
feat(helpers): add experimental Moli CDP helper
Moli (https://github.com/lexmount/moli) is a Rust headless browser with V8 and Stylo, served over CDP. The helper is a thin CDPBrowser subclass like Lightpanda: it self-launches `moli serve` on a free port, or attaches to an explicit endpoint. Moli runs without --layout on purpose: with --layout element geometry is frozen on first read and only a screenshot refreshes it, which breaks waitForVisible/waitForText. Presets pin synthetic input, layout 'real' and no screenshots, since the runtime probe would otherwise pick coordinate input that Moli rejects in this mode. - shared webapi suite: 289 passing, 50 pending; 6 tests skipped with verified reasons (clickXY, upload MIME type, link color) - 19 acceptance scenarios tagged @Moli, including gherkin features - CI workflow pinned to v1.1.17 with SHA256 check - docs: alternative browsers, installation, README, helper reference Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent b3ef767 commit f32bcb0

22 files changed

Lines changed: 2445 additions & 21 deletions

‎.github/workflows/moli.yml‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Moli Helper Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- 4.x
7+
pull_request:
8+
branches:
9+
- '**'
10+
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
13+
cancel-in-progress: true
14+
15+
permissions:
16+
contents: read
17+
18+
env:
19+
CI: true
20+
FORCE_COLOR: 1
21+
MOLI_VERSION: v1.1.17
22+
MOLI_SHA256: e338cdd2ab6e3e6262117e56aba625bf6c71c44fd72ac3870bbd9c0e6c1ec351
23+
24+
jobs:
25+
build:
26+
runs-on: ubuntu-22.04
27+
timeout-minutes: 15
28+
29+
strategy:
30+
matrix:
31+
node-version: [22.x]
32+
33+
steps:
34+
- uses: actions/checkout@v6
35+
with:
36+
persist-credentials: false
37+
- name: Use Node.js ${{ matrix.node-version }}
38+
uses: actions/setup-node@v6
39+
with:
40+
node-version: ${{ matrix.node-version }}
41+
- uses: shivammathur/setup-php@v2
42+
with:
43+
php-version: 8.0
44+
- name: npm install
45+
run: npm i --force
46+
- name: Cache Moli tarball
47+
uses: actions/cache@v6
48+
with:
49+
path: ~/moli-bin/moli.tar.gz
50+
key: moli-${{ env.MOLI_VERSION }}-x86_64-linux
51+
- name: Download Moli
52+
run: |
53+
mkdir -p ~/moli-bin
54+
if [ ! -f ~/moli-bin/moli.tar.gz ]; then
55+
curl -sfL --retry 3 -o ~/moli-bin/moli.tar.gz https://github.com/lexmount/moli/releases/download/${MOLI_VERSION}/moli-x86_64-unknown-linux-gnu.tar.gz
56+
fi
57+
echo "${MOLI_SHA256} $HOME/moli-bin/moli.tar.gz" | sha256sum -c -
58+
tar xzf ~/moli-bin/moli.tar.gz -C ~/moli-bin --strip-components=1
59+
~/moli-bin/moli --version
60+
- name: start test server
61+
run: |
62+
php -S 127.0.0.1:8000 -t test/data/app &
63+
sleep 1
64+
curl -sf http://127.0.0.1:8000/info > /dev/null
65+
- name: run moli helper tests
66+
run: |
67+
export MOLI_PATH="$HOME/moli-bin/moli"
68+
npm run test:unit:webbapi:moli
69+
- name: run moli acceptance tests
70+
run: |
71+
export MOLI_PATH="$HOME/moli-bin/moli"
72+
./bin/codecept.js run -c test/acceptance/codecept.Moli.js --grep @Moli --debug

‎Bunoshfile.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ const inheritedHelperDocs = {
400400
},
401401
Obscura: { parent: 'CDPBrowser' },
402402
Lightpanda: { parent: 'CDPBrowser' },
403+
Moli: { parent: 'CDPBrowser' },
403404
Kitesurf: { parent: 'CDPBrowser', excludeConfig: ['endpoint', 'headers'] },
404405
}
405406

‎README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
| 🌐 Web | WebDriver | [![WebDriver Tests](https://github.com/codeceptjs/CodeceptJS/actions/workflows/webdriver.yml/badge.svg)](https://github.com/codeceptjs/CodeceptJS/actions/workflows/webdriver.yml) |
1313
| 🌐 Web | Obscura | [![Obscura Helper Tests](https://github.com/codeceptjs/CodeceptJS/actions/workflows/obscura.yml/badge.svg)](https://github.com/codeceptjs/CodeceptJS/actions/workflows/obscura.yml) |
1414
| 🌐 Web | Lightpanda | [![Lightpanda Helper Tests](https://github.com/codeceptjs/CodeceptJS/actions/workflows/lightpanda.yml/badge.svg)](https://github.com/codeceptjs/CodeceptJS/actions/workflows/lightpanda.yml) |
15+
| 🌐 Web | Moli | [![Moli Helper Tests](https://github.com/codeceptjs/CodeceptJS/actions/workflows/moli.yml/badge.svg)](https://github.com/codeceptjs/CodeceptJS/actions/workflows/moli.yml) |
1516
| 📱 Mobile | Appium | [![Appium Tests - Android](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appium_Android.yml/badge.svg)](https://github.com/codeceptjs/CodeceptJS/actions/workflows/appium_Android.yml) |
1617

1718
# CodeceptJS [![Made in Ukraine](https://img.shields.io/badge/made_in-ukraine-ffd700.svg?labelColor=0057b7)](https://stand-with-ukraine.pp.ua)
@@ -46,6 +47,7 @@ CodeceptJS uses **Helper** modules to provide actions to `I` object. Currently,
4647
- [**WebDriver**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/WebDriver.md) - uses [webdriverio](http://webdriver.io/) to run tests via WebDriver or Devtools protocol.
4748
- [**Obscura**](https://codecept.io/helpers/Obscura) - drives the lightweight Obscura browser through Chrome DevTools Protocol. See [Alternative Browser Engines](https://codecept.io/alternative-browsers).
4849
- [**Lightpanda**](https://codecept.io/helpers/Lightpanda) - drives the Lightpanda headless browser through Chrome DevTools Protocol. See [Alternative Browser Engines](https://codecept.io/alternative-browsers).
50+
- [**Moli**](https://codecept.io/helpers/Moli) - drives the Moli headless browser through Chrome DevTools Protocol. See [Alternative Browser Engines](https://codecept.io/alternative-browsers).
4951
- [**Appium**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Appium.md) - for **mobile testing** with Appium
5052
- [**Detox**](https://github.com/codeceptjs/CodeceptJS/blob/master/docs/helpers/Detox.md) - This is a wrapper on top of Detox library, aimed to unify testing experience for CodeceptJS framework. Detox provides a grey box testing for mobile applications, playing especially well for React Native apps.
5153

‎docs/alternative-browsers.md‎

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ title: Alternative Browser Engines
66
# Alternative Browser Engines
77

88
::: warning Experimental
9-
The `Obscura`, `Lightpanda` and `Kitesurf` helpers are experimental. Keep a Playwright or WebDriver job for compatibility-critical tests.
9+
The `Obscura`, `Lightpanda`, `Moli` and `Kitesurf` helpers are experimental. Keep a Playwright or WebDriver job for compatibility-critical tests.
1010
:::
1111

1212
Playwright drives full Chromium, Firefox and WebKit: the most accurate way to test what users see, at the cost of a heavy browser per worker. Alternative engines trade part of that accuracy for speed, a small footprint, or cloud scale. They are a good fit for functional tests (text appears, form submits, redirect happens, cookie is set) and a poor one for anything visual.
@@ -143,6 +143,61 @@ Lightpanda: {
143143

144144
All options: [Lightpanda helper reference](/helpers/Lightpanda).
145145

146+
## Moli
147+
148+
[Moli](https://github.com/lexmount/moli) is an open-source headless browser built in Rust for automation. It runs your app's JavaScript in V8 and computes real CSS, but skips layout and painting, so it starts fast and stays small. Visibility checks such as `seeElement` and `waitForVisible` work.
149+
150+
Limitations:
151+
152+
- No screenshots: `saveScreenshot`, failure screenshots and the `screencast` plugin do not work.
153+
- `clickXY` does not work.
154+
- `attachFile` uploads files without a MIME type; the server receives `application/octet-stream`.
155+
- Links have no default color: `a` computes `color: rgb(0, 0, 0)`.
156+
157+
### Setup
158+
159+
Install Moli following the [official instructions](https://github.com/lexmount/moli#direct-installation) and put `moli` on `PATH`. Then enable the helper:
160+
161+
```js
162+
// codecept.conf.js
163+
export const config = {
164+
helpers: {
165+
Moli: {
166+
url: 'http://localhost:3000',
167+
},
168+
},
169+
}
170+
```
171+
172+
If the binary is not on `PATH`, set `binaryPath` in the config or the `MOLI_PATH` environment variable.
173+
174+
### Usage
175+
176+
```sh
177+
npx codeceptjs run
178+
```
179+
180+
The helper starts `moli serve` on a free port before the first test and stops it after the last one. Each worker gets its own instance:
181+
182+
```sh
183+
npx codeceptjs run-workers 8
184+
```
185+
186+
To connect to a Moli you started yourself, set `endpoint`; the helper then never starts or stops it:
187+
188+
```sh
189+
moli serve --host 127.0.0.1 --port 9222
190+
```
191+
192+
```js
193+
Moli: {
194+
url: 'http://localhost:3000',
195+
endpoint: 'http://127.0.0.1:9222',
196+
}
197+
```
198+
199+
All options: [Moli helper reference](/helpers/Moli).
200+
146201
## Kitesurf
147202

148203
[Kitesurf](https://blog.cloudflare.com/kitesurf/) is Cloudflare's browser running on Cloudflare Workers, with a real layout and rendering pipeline. Sessions start in about a second and nothing runs on your machine, so the number of parallel browsers is limited only by how far your suite splits.

0 commit comments

Comments
 (0)