Skip to content

Commit 93ebdec

Browse files
authored
Merge pull request #87 from Integration-Automation/dev
Static-analysis cleanup, integration tests, cookbook + WR_sleep + API façade
2 parents 50ec292 + a04fa5b commit 93ebdec

3 files changed

Lines changed: 202 additions & 0 deletions

File tree

README.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,76 @@ je_web_runner/
265265
└── xml/ # XML utilities
266266
```
267267

268+
## Cookbook
269+
270+
The `examples/` directory ships runnable recipes that exercise the new
271+
helpers against real Chrome / network. Each is invoked from the repo root:
272+
273+
| Example | Demonstrates |
274+
|---|---|
275+
| `counting_stars.{py,json}` | `WR_sleep`, `WR_set_driver` with Chrome flags, autoplay-policy override, JS-driven `video.play()`, skip-ad polling. |
276+
| `google_search.py` | Consent dismissal, search-box typing, ENTER submit, result heading scrape. |
277+
| `form_submit.py` | `form_autofill.plan_fill_actions` + `state_diff.capture_state` round trip against `httpbin/forms/post`. |
278+
| `smart_wait_demo.py` | `wait_for_fetch_idle` + `wait_for_spa_route_stable` + `memory_leak.detect_growth` against a real page. |
279+
| `fanout_demo.py` | `fanout.run_fan_out` parallel HTTP preflights. |
280+
| `pii_redact_demo.py` | `pii_scanner.scan_text` + `redact_text` + `assert_no_pii` (pure logic). |
281+
| `quick_smoke.json` | Minimal `WR_set_driver``WR_sleep``WR_execute_script``WR_quit_all` smoke via the executor CLI. |
282+
283+
Run a Python example directly:
284+
285+
```bash
286+
python examples/google_search.py
287+
```
288+
289+
Run an action JSON example through the executor:
290+
291+
```bash
292+
python -m je_web_runner -e examples/quick_smoke.json
293+
```
294+
295+
## Test Tiers
296+
297+
```
298+
test/
299+
├── unit_test/ # 1200 mock-based unit tests (~12s)
300+
├── integration_test/ # 30 wired-modules tests with real I/O (~6s)
301+
└── e2e_test/ # 6 real-browser tests; skips without Selenium Grid
302+
```
303+
304+
- **Unit** (`test/unit_test/test_*.py`) — runs everywhere; pulled in by both
305+
`test_dev.yml` and `test_stable.yml`.
306+
- **Integration** (`test/integration_test/`) — wires 2+ modules together
307+
with real SQLite, in-process HTTP servers, and real subprocesses for
308+
the MCP / LSP. Same workflows as unit, second step.
309+
- **E2E** (`test/e2e_test/`) — talks to a Selenium Grid via
310+
`WEBRUNNER_E2E_HUB`. Locally: `cd docker && docker compose up -d`.
311+
CI: `.github/workflows/e2e_browser.yml` boots `selenium/hub:4.20.0`
312+
+ `selenium/node-chrome` daily / on demand.
313+
314+
## Thematic API Façade
315+
316+
The 80+ utility helpers live under `je_web_runner.utils.<area>`; for
317+
discoverability they are also re-exported under `je_web_runner.api`:
318+
319+
```python
320+
from je_web_runner.api import (
321+
authoring, # action_formatter, md_authoring, templates, sel_to_pw, bootstrap
322+
debugging, # cross_browser, pr_comment, extension_harness
323+
frontend, # device emulation, geo/locale, multi-tab, shadow pierce, …
324+
infra, # driver pin, k8s runner, pipeline, lock, watch_mode, …
325+
mobile, # Appium gestures
326+
networking, # api_mock, contract_testing, GraphQL, mock services, har_replay
327+
observability, # timeline, failure bundle, trace recorder, OTLP, BiDi, cdp_tap
328+
quality, # a11y_diff, a11y_trend, perf budgets/drift, trend, failure cluster
329+
reliability, # adaptive retry, browser pool, smart wait, throttler, supervisor
330+
security, # PII, license, CSP, cookie consent, header tampering
331+
test_data, # DB fixtures, fixture record/replay, form auto-fill
332+
)
333+
```
334+
335+
The original Selenium-flavoured top-level surface (`webdriver_wrapper_instance`,
336+
`execute_action`, `TestObject`, …) is unchanged.
337+
268338
## Quick Start
269339

270340
### Direct API
@@ -346,6 +416,20 @@ The executor maps a string command name to a Python callable. Every backend, int
346416
]
347417
```
348418

419+
### Pacing actions
420+
421+
`WR_sleep` blocks the executor thread for a given number of seconds — useful when the page needs settle time, when a JS animation needs to finish, or when an example wants to hold the browser open for the user to watch:
422+
423+
```python
424+
[
425+
["WR_to_url", {"url": "https://example.com"}],
426+
["WR_sleep", {"seconds": 2.5}],
427+
["WR_get_screenshot_as_png"],
428+
]
429+
```
430+
431+
Negative or non-numeric `seconds` raise `ValueError`. For pacing inside JavaScript (e.g. waiting on a custom event from the page) use `WR_execute_async_script` with a `setTimeout`-driven callback.
432+
349433
### Top-level shapes
350434

351435
```python

docs/source/Eng/doc/extended_features/extended_features_doc.rst

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,3 +593,67 @@ Storybook visual snapshots / Appium gestures / coverage map
593593
* ``coverage_map.build_coverage_map("./actions")`` — reverse index of
594594
``WR_to_url`` paths (numeric / UUID segments collapsed to ``:id``);
595595
``coverage.uncovered(declared_routes)`` flags missing routes.
596+
597+
WR_sleep
598+
========
599+
600+
The executor exposes ``WR_sleep`` so action JSON pipelines can pace
601+
themselves natively without resorting to ``WR_execute_async_script``
602+
``setTimeout`` tricks:
603+
604+
.. code-block:: json
605+
606+
[
607+
["WR_to_url", {"url": "https://example.com"}],
608+
["WR_sleep", {"seconds": 2.5}],
609+
["WR_get_screenshot_as_png"]
610+
]
611+
612+
Negative or non-numeric ``seconds`` raise ``ValueError`` so a typo can't
613+
silently no-op the pipeline.
614+
615+
Cookbook examples
616+
=================
617+
618+
The ``examples/`` directory ships runnable recipes that drive real Chrome
619+
end-to-end. Each found a real bug the unit suite missed:
620+
621+
* ``counting_stars.{py,json}`` — open YouTube and play OneRepublic
622+
Counting Stars; revealed the bug where
623+
``webdriver_wrapper.execute_script`` was swallowing return values.
624+
* ``google_search.py`` — consent dismissal + result heading scrape.
625+
* ``form_submit.py`` — ``form_autofill.plan_fill_actions`` +
626+
``state_diff.capture_state`` round trip against ``httpbin``.
627+
* ``smart_wait_demo.py`` — ``wait_for_fetch_idle``,
628+
``wait_for_spa_route_stable``, ``memory_leak.detect_growth``.
629+
* ``fanout_demo.py`` — parallel HTTP preflights via ``run_fan_out``.
630+
* ``pii_redact_demo.py`` — pure-logic ``scan_text`` / ``redact_text``.
631+
632+
Test tiers
633+
==========
634+
635+
* ``test/unit_test/`` — 1200 mock-based unit tests, ~12s.
636+
* ``test/integration_test/`` — 30 wired-modules tests with real I/O
637+
(in-memory SQLite, in-process HTTP servers, real subprocesses for
638+
the MCP / LSP). Surfaced the Windows LSP CRLF framing bug.
639+
* ``test/e2e_test/`` — six real-browser smoke tests; skips cleanly when
640+
``WEBRUNNER_E2E_HUB`` doesn't resolve. Use
641+
``cd docker && docker compose up -d`` locally;
642+
``.github/workflows/e2e_browser.yml`` runs them daily / on demand.
643+
644+
Thematic façade
645+
===============
646+
647+
The 80+ helpers under ``je_web_runner.utils.<area>`` are also re-exported
648+
under ``je_web_runner.api`` grouped by theme:
649+
650+
.. code-block:: python
651+
652+
from je_web_runner.api import (
653+
authoring, debugging, frontend, infra, mobile,
654+
networking, observability, quality, reliability,
655+
security, test_data,
656+
)
657+
658+
The original Selenium-flavoured top-level surface stays unchanged so
659+
existing user code keeps working.

docs/source/Zh/doc/extended_features/extended_features_doc.rst

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,3 +421,57 @@ Storybook 視覺快照 / Appium gestures / Coverage map
421421
* ``coverage_map.build_coverage_map`` — 從 action JSON 抽出 ``WR_to_url``
422422
的 path 建立 route → files 反查表,``coverage.uncovered`` 找出未覆蓋
423423
的 route
424+
425+
WR_sleep
426+
========
427+
428+
Executor 內建的同步 sleep 命令,給 action JSON 用:
429+
430+
.. code-block:: json
431+
432+
[
433+
["WR_to_url", {"url": "https://example.com"}],
434+
["WR_sleep", {"seconds": 2.5}],
435+
["WR_get_screenshot_as_png"]
436+
]
437+
438+
負數 / 非數字會丟 ``ValueError``,typo 不會被默默忽略。
439+
440+
Cookbook 範例
441+
=============
442+
443+
``examples/`` 提供可直接跑的真實 Chrome 範例,每個都剛好揪出一個既有 bug:
444+
445+
* ``counting_stars.{py,json}`` — 開 YouTube 播 OneRepublic Counting Stars
446+
(順帶揪出 ``execute_script`` 吞回傳值的 bug)
447+
* ``google_search.py`` — 處理 GDPR 同意彈窗、抓首個搜尋結果標題
448+
* ``form_submit.py`` — ``form_autofill`` + ``state_diff`` 串連 httpbin
449+
* ``smart_wait_demo.py`` — fetch idle / SPA route stable / memory leak
450+
* ``fanout_demo.py`` — ``run_fan_out`` 平行 HTTP preflight
451+
* ``pii_redact_demo.py`` — 純邏輯 PII redaction
452+
453+
測試分層
454+
========
455+
456+
* ``test/unit_test/`` — 1200 個 mock-based 單元測試,約 12 秒
457+
* ``test/integration_test/`` — 30 個整合測試,串接真 I/O(SQLite、HTTP
458+
server、MCP / LSP 子行程),曾揪出 Windows LSP CRLF framing bug
459+
* ``test/e2e_test/`` — 六個真瀏覽器 smoke,``WEBRUNNER_E2E_HUB`` 未設定
460+
時自動 skip。本機跑:``cd docker && docker compose up -d``。CI 走
461+
``.github/workflows/e2e_browser.yml``,每日 + 手動觸發
462+
463+
主題式 façade
464+
=============
465+
466+
80+ helpers 除了原本的 ``je_web_runner.utils.<area>`` 路徑,現在也透過
467+
``je_web_runner.api`` 主題分組重新匯出:
468+
469+
.. code-block:: python
470+
471+
from je_web_runner.api import (
472+
authoring, debugging, frontend, infra, mobile,
473+
networking, observability, quality, reliability,
474+
security, test_data,
475+
)
476+
477+
原本的 Selenium 式頂層 API 不變,舊程式碼可繼續運作。

0 commit comments

Comments
 (0)