@eidra-umain/greenlight 0.7.6 → 0.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -51
- package/package.json +66 -66
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="assets/greenlight_banner.png" alt="GreenLight
|
|
2
|
+
<img src="assets/greenlight_banner.png" alt="GreenLight: AI-driven E2E Testing" width="500">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
# GreenLight
|
|
@@ -13,7 +13,7 @@ No selectors. No XPaths. No test IDs, drivers or glue code. Just describe what a
|
|
|
13
13
|
> [!WARNING]
|
|
14
14
|
> GreenLight is very new and not battle tested yet. YMMV.
|
|
15
15
|
|
|
16
|
-
**[How it works](#how-it-works)** | **[Quick start](#quick-start)** | **[Project configuration](#project-configuration)** | **[CLI](#cli)** | **[Test syntax](#test-syntax)** | **[Writing test steps](#writing-test-steps)** | **[Cached plans](#cached-plans)** | **[LLM setup](#llm-setup)** | **[Architecture](#architecture)** | **[Avoiding side effects](#avoiding-side-effects-in-your-app)** | **[CI/CD](#cicd)**
|
|
16
|
+
**[How it works](#how-it-works)** | **[Quick start](#quick-start)** | **[Project configuration](#project-configuration)** | **[CLI](#cli)** | **[Test syntax](#test-syntax)** | **[Writing test steps](#writing-test-steps)** | **[Cached plans](#cached-plans)** | **[LLM setup](#llm-setup)** | **[Architecture](#architecture)** | **[Avoiding side effects](#avoiding-side-effects-in-your-app)** | **[CI/CD](#cicd)** | **[Contributing](#contributing)**
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
@@ -39,7 +39,7 @@ tests:
|
|
|
39
39
|
GreenLight understands form wizards, custom dropdowns, autocomplete fields, checkbox consent flows, complex date pickers and interactive maps. It fills in forms with realistic test data, handles before/after value comparisons, and works with any UI framework.
|
|
40
40
|
|
|
41
41
|
The first run uses the LLM Pilot to discover the right actions (the **pilot** run).
|
|
42
|
-
After that, GreenLight caches a concrete action plan and replays it without LLM calls
|
|
42
|
+
After that, GreenLight caches a concrete action plan and replays it without LLM calls, making subsequent runs fast and deterministic.
|
|
43
43
|
|
|
44
44
|
## Quick start
|
|
45
45
|
|
|
@@ -165,20 +165,20 @@ greenlight run --on-drift rerun # re-run with pilot on cached plan drift
|
|
|
165
165
|
|
|
166
166
|
## GreenLight philosophy compared to Gherkin/Cucumber
|
|
167
167
|
|
|
168
|
-
Traditional BDD tools like Cucumber use **Gherkin
|
|
168
|
+
Traditional BDD tools like Cucumber use **Gherkin**, a structured `Given/When/Then` syntax where every step requires a developer-written **step definition** (glue code) that maps the English phrase to actual browser automation with CSS selectors or XPaths.
|
|
169
169
|
|
|
170
170
|
GreenLight takes a different approach:
|
|
171
171
|
|
|
172
172
|
| | GreenLight | Gherkin (Cucumber) |
|
|
173
173
|
|---|---|---|
|
|
174
174
|
| **Test language** | Freeform plain English | Structured `Given/When/Then` keywords |
|
|
175
|
-
| **Element targeting** | AI resolves via accessibility tree
|
|
175
|
+
| **Element targeting** | AI resolves via accessibility tree, no selectors | Developers write glue code with selectors/XPaths |
|
|
176
176
|
| **Maintenance** | Tests survive UI refactors that don't change behavior | Selector changes break tests, requiring glue code updates |
|
|
177
177
|
| **Authoring** | Non-technical testers, no code required | Readable specs, but developers must write step definitions |
|
|
178
|
-
| **Determinism** | Cached plans are deterministic; discovery runs have LLM variability | Fully deterministic
|
|
178
|
+
| **Determinism** | Cached plans are deterministic; discovery runs have LLM variability | Fully deterministic, same input, same execution path |
|
|
179
179
|
| **Maturity** | New, LLM-dependent | Battle-tested (15+ years), broad ecosystem |
|
|
180
180
|
|
|
181
|
-
**In short:** Gherkin requires developers to bridge English and browser automation via step definitions. GreenLight uses AI as that bridge
|
|
181
|
+
**In short:** Gherkin requires developers to bridge English and browser automation via step definitions. GreenLight uses AI as that bridge, eliminating the glue code layer at the cost of introducing LLM-dependent variability.
|
|
182
182
|
|
|
183
183
|
## Test syntax
|
|
184
184
|
|
|
@@ -217,9 +217,9 @@ This section covers how GreenLight interprets your plain-English steps, what hap
|
|
|
217
217
|
|
|
218
218
|
When you write a step like `click the "Add to Cart" button`, GreenLight's **planner** (an LLM) converts it into a structured action before any browser interaction happens. Understanding this pipeline helps you write clearer steps:
|
|
219
219
|
|
|
220
|
-
1. **Planning
|
|
221
|
-
2. **Execution
|
|
222
|
-
3. **Caching
|
|
220
|
+
1. **Planning:** The LLM reads all your steps and classifies each one into an action type
|
|
221
|
+
2. **Execution:** The pilot executes each action against the live browser page
|
|
222
|
+
3. **Caching:** Successful runs are saved so future runs skip the LLM entirely
|
|
223
223
|
|
|
224
224
|
### Navigation
|
|
225
225
|
|
|
@@ -232,7 +232,7 @@ steps:
|
|
|
232
232
|
- navigate to About from the main menu # click a link (uses the live page)
|
|
233
233
|
```
|
|
234
234
|
|
|
235
|
-
**Tip:** Use quoted paths starting with `/` or `http` for direct navigation. For anything that requires finding and clicking a link, describe it naturally
|
|
235
|
+
**Tip:** Use quoted paths starting with `/` or `http` for direct navigation. For anything that requires finding and clicking a link, describe it naturally. GreenLight will resolve it against the live page.
|
|
236
236
|
|
|
237
237
|
### Clicking and interacting
|
|
238
238
|
|
|
@@ -282,7 +282,7 @@ steps:
|
|
|
282
282
|
- clear the category selection # dropdown: finds the reset/clear button
|
|
283
283
|
```
|
|
284
284
|
|
|
285
|
-
GreenLight automatically detects the element type and applies the right clearing strategy. For text inputs, it selects all and deletes. For filter chips, dropdowns, and multi-select tag inputs, it finds and clicks the nearest clear/remove/reset button
|
|
285
|
+
GreenLight automatically detects the element type and applies the right clearing strategy. For text inputs, it selects all and deletes. For filter chips, dropdowns, and multi-select tag inputs, it finds and clicks the nearest clear/remove/reset button, looking inside the element and at sibling elements for buttons matching common clear patterns (including localized labels like "Rensa").
|
|
286
286
|
|
|
287
287
|
### Typing and form fields
|
|
288
288
|
|
|
@@ -301,7 +301,7 @@ steps:
|
|
|
301
301
|
- select "Canada" from "Country" # works with native <select> and custom dropdowns
|
|
302
302
|
```
|
|
303
303
|
|
|
304
|
-
A single `select` step handles both opening the dropdown and choosing the option
|
|
304
|
+
A single `select` step handles both opening the dropdown and choosing the option. Don't split it into two steps.
|
|
305
305
|
|
|
306
306
|
### Autocomplete fields
|
|
307
307
|
|
|
@@ -321,7 +321,7 @@ steps:
|
|
|
321
321
|
- uncheck the "Newsletter" checkbox
|
|
322
322
|
```
|
|
323
323
|
|
|
324
|
-
Use `check`/`uncheck` instead of `click` for checkboxes
|
|
324
|
+
Use `check`/`uncheck` instead of `click` for checkboxes. This ensures correct toggle behavior for both native and custom checkbox implementations.
|
|
325
325
|
|
|
326
326
|
### Form filling
|
|
327
327
|
|
|
@@ -344,11 +344,11 @@ steps:
|
|
|
344
344
|
- Select Red - Green - Blue in the color picker # three sequential clicks
|
|
345
345
|
```
|
|
346
346
|
|
|
347
|
-
Each value becomes a separate click action. Use this for tabs, radio cards, multi-select UIs
|
|
347
|
+
Each value becomes a separate click action. Use this for tabs, radio cards, multi-select UIs, anything where you're clicking multiple items in sequence.
|
|
348
348
|
|
|
349
349
|
### Assertions
|
|
350
350
|
|
|
351
|
-
Any step starting with "check that" or "verify" is treated as an assertion
|
|
351
|
+
Any step starting with "check that" or "verify" is treated as an assertion. It validates page state without interacting:
|
|
352
352
|
|
|
353
353
|
```yaml
|
|
354
354
|
steps:
|
|
@@ -372,7 +372,7 @@ steps:
|
|
|
372
372
|
- verify there are at least 5 results
|
|
373
373
|
```
|
|
374
374
|
|
|
375
|
-
**Important:** Assertions with quoted text (like `"Order Confirmed"`) are resolved at plan time
|
|
375
|
+
**Important:** Assertions with quoted text (like `"Order Confirmed"`) are resolved at plan time, no LLM call needed at runtime. Assertions without quotes (like `check that the form is present`) require the live page to resolve.
|
|
376
376
|
|
|
377
377
|
### Random test data
|
|
378
378
|
|
|
@@ -385,11 +385,11 @@ steps:
|
|
|
385
385
|
- fill the "Description" field with some test data
|
|
386
386
|
```
|
|
387
387
|
|
|
388
|
-
For full forms with multiple fields, use the form filling syntax (`fill in the form with some test data`)
|
|
388
|
+
For full forms with multiple fields, use the form filling syntax (`fill in the form with some test data`). GreenLight inspects each field's label, type, and placeholder to generate appropriate data. The literal word "***random***" will trigger actual random data generation which is different for every run, even if the run is cached.
|
|
389
389
|
|
|
390
390
|
### Date and time pickers
|
|
391
391
|
|
|
392
|
-
GreenLight has built-in support for date/time pickers
|
|
392
|
+
GreenLight has built-in support for date/time pickers, including native HTML5 inputs and component-library widgets like MUI DateTimePicker with sectioned spinbuttons. No special syntax is needed; just describe what time to set using natural language:
|
|
393
393
|
|
|
394
394
|
```yaml
|
|
395
395
|
steps:
|
|
@@ -403,15 +403,15 @@ steps:
|
|
|
403
403
|
**How it works:**
|
|
404
404
|
|
|
405
405
|
1. The planner identifies date/time steps and extracts the time expression (e.g., "10 minutes from now")
|
|
406
|
-
2. [chrono-node](https://github.com/wanasit/chrono) parses the expression into an exact timestamp
|
|
406
|
+
2. [chrono-node](https://github.com/wanasit/chrono) parses the expression into an exact timestamp, no LLM needed for time math
|
|
407
407
|
3. GreenLight inspects the page's accessibility tree to find the picker elements
|
|
408
408
|
4. Values are filled into the correct fields automatically
|
|
409
409
|
|
|
410
410
|
**Supported picker types:**
|
|
411
411
|
|
|
412
|
-
- **Native HTML5** (`<input type="date">`, `datetime-local`, `time`)
|
|
413
|
-
- **Sectioned pickers** (MUI v7, etc.)
|
|
414
|
-
- **Multiple pickers on one page
|
|
412
|
+
- **Native HTML5** (`<input type="date">`, `datetime-local`, `time`): Filled with `YYYY-MM-DD`, `YYYY-MM-DDTHH:mm`, or `HH:mm`
|
|
413
|
+
- **Sectioned pickers** (MUI v7, etc.): Individual spinbutton sections (Day, Month, Year, Hours, Minutes) are each filled with the correct value
|
|
414
|
+
- **Multiple pickers on one page**: GreenLight matches "start" / "end" in the step text against picker group names to target the right one
|
|
415
415
|
|
|
416
416
|
**Supported time expressions:**
|
|
417
417
|
|
|
@@ -425,7 +425,7 @@ steps:
|
|
|
425
425
|
| `2026-06-15` | Explicit date |
|
|
426
426
|
| `2026-06-15 14:30` | Explicit date and time |
|
|
427
427
|
|
|
428
|
-
Date picker steps are always computed fresh
|
|
428
|
+
Date picker steps are always computed fresh. Even on cached plan replay, the timestamp is recalculated from the current time. This means tests with relative times like "10 minutes from now" never fail due to stale cached dates.
|
|
429
429
|
|
|
430
430
|
### Counting elements
|
|
431
431
|
|
|
@@ -448,7 +448,7 @@ steps:
|
|
|
448
448
|
- count the number of rows in the results table
|
|
449
449
|
```
|
|
450
450
|
|
|
451
|
-
**How it works:** GreenLight inspects the live page's accessibility tree to identify all elements matching the description. The LLM determines a common denominator (role, text pattern, or accessible name) that uniquely identifies the target elements, then counts all matches using exact text matching to avoid false positives from headings or breadcrumbs. The count is stored as a number in the value store
|
|
451
|
+
**How it works:** GreenLight inspects the live page's accessibility tree to identify all elements matching the description. The LLM determines a common denominator (role, text pattern, or accessible name) that uniquely identifies the target elements, then counts all matches using exact text matching to avoid false positives from headings or breadcrumbs. The count is stored as a number in the value store, the same mechanism used by `remember`, so it works seamlessly with `check that ... has decreased/increased` comparisons.
|
|
452
452
|
|
|
453
453
|
When a step checks that the number of visible elements equals a remembered value, GreenLight automatically splits it into a count + compare: first count the elements, then compare the count against the stored variable.
|
|
454
454
|
|
|
@@ -479,7 +479,7 @@ This flow generates a random value, captures it, performs an action, and then ve
|
|
|
479
479
|
|
|
480
480
|
### Conditional steps
|
|
481
481
|
|
|
482
|
-
Conditional steps let you handle pages that may look different between runs
|
|
482
|
+
Conditional steps let you handle pages that may look different between runs: cookie banners, feature flags, A/B tests, or optional UI elements.
|
|
483
483
|
|
|
484
484
|
#### Inline conditionals
|
|
485
485
|
|
|
@@ -509,7 +509,7 @@ steps:
|
|
|
509
509
|
- search for "headphones"
|
|
510
510
|
```
|
|
511
511
|
|
|
512
|
-
The `else` block is optional. Block conditionals are flattened to inline conditionals at load time
|
|
512
|
+
The `else` block is optional. Block conditionals are flattened to inline conditionals at load time. The planner and pilot handle them the same way.
|
|
513
513
|
|
|
514
514
|
#### Supported conditions
|
|
515
515
|
|
|
@@ -521,7 +521,7 @@ If the condition is false and there's no `else`, the step is simply skipped (not
|
|
|
521
521
|
|
|
522
522
|
### Map testing
|
|
523
523
|
|
|
524
|
-
GreenLight has built-in support for testing interactive WebGL maps. When a step mentions maps, markers, layers, or zoom levels, GreenLight detects the map library, attaches to its instance, and queries rendered features directly
|
|
524
|
+
GreenLight has built-in support for testing interactive WebGL maps. When a step mentions maps, markers, layers, or zoom levels, GreenLight detects the map library, attaches to its instance, and queries rendered features directly, bypassing the DOM (WebGL canvas content is invisible to the accessibility tree).
|
|
525
525
|
|
|
526
526
|
```yaml
|
|
527
527
|
steps:
|
|
@@ -531,16 +531,16 @@ steps:
|
|
|
531
531
|
- check that the "hospitals" layer is visible on the map
|
|
532
532
|
```
|
|
533
533
|
|
|
534
|
-
Currently supported: **MapLibre GL JS**. The architecture is pluggable
|
|
534
|
+
Currently supported: **MapLibre GL JS**. The architecture is pluggable. Mapbox GL and Leaflet adapters can be added.
|
|
535
535
|
|
|
536
|
-
**How it works:** When a step mentions map-related content, GreenLight automatically inserts a map detection step. Map assertions query the actual rendered vector tile features (place names, road labels, etc.) and viewport state (center, zoom, bounds, layers)
|
|
536
|
+
**How it works:** When a step mentions map-related content, GreenLight automatically inserts a map detection step. Map assertions query the actual rendered vector tile features (place names, road labels, etc.) and viewport state (center, zoom, bounds, layers), not the DOM.
|
|
537
537
|
|
|
538
538
|
**Map instance detection** works automatically for most setups:
|
|
539
539
|
|
|
540
|
-
1. **React apps** (react-map-gl, etc.)
|
|
541
|
-
2. **Vue apps
|
|
542
|
-
3. **Global variables
|
|
543
|
-
4. **Explicit exposure
|
|
540
|
+
1. **React apps** (react-map-gl, etc.): Walks the React fiber tree
|
|
541
|
+
2. **Vue apps**: Checks `__vue_app__` / `__vue__` component trees
|
|
542
|
+
3. **Global variables**: Scans `window.map`, `window.mapInstance`, etc.
|
|
543
|
+
4. **Explicit exposure**: Set `window.__greenlight_map = map` for maximum reliability
|
|
544
544
|
|
|
545
545
|
### Reusable steps
|
|
546
546
|
|
|
@@ -563,25 +563,25 @@ tests:
|
|
|
563
563
|
|
|
564
564
|
### Tips for reliable tests
|
|
565
565
|
|
|
566
|
-
- **Be specific with quotes
|
|
567
|
-
- **One action per step
|
|
568
|
-
- **Use assertions liberally
|
|
569
|
-
- **Don't over-specify DOM structure
|
|
570
|
-
- **Conditional steps for flaky UI
|
|
566
|
+
- **Be specific with quotes.** `click "Submit"` is more reliable than `click the submit button` because it matches exact text.
|
|
567
|
+
- **One action per step.** Each step should describe one thing a user does. GreenLight splits compound steps, but explicit single-action steps are more predictable.
|
|
568
|
+
- **Use assertions liberally.** After key actions, add a `check that` step to verify the expected outcome. This catches failures early and makes the test report more readable.
|
|
569
|
+
- **Don't over-specify DOM structure.** Say `click "Add to Cart"` not `click the button inside the product card div`. GreenLight uses the accessibility tree, not CSS selectors.
|
|
570
|
+
- **Conditional steps for flaky UI.** If a cookie banner or popup sometimes appears, use `click "Accept" if visible` instead of making it a required step.
|
|
571
571
|
|
|
572
572
|
### Robustness features
|
|
573
573
|
|
|
574
574
|
GreenLight includes several built-in mechanisms to handle real-world complexity:
|
|
575
575
|
|
|
576
|
-
- **Planner model escalation
|
|
577
|
-
- **Context length recovery
|
|
578
|
-
- **Large page handling
|
|
576
|
+
- **Planner model escalation.** When the fast pilot model fails to resolve a step, GreenLight automatically retries with the more capable planner model before giving up. This catches cases where the cheaper model can't make a tricky element mapping.
|
|
577
|
+
- **Context length recovery.** If the LLM's context window is exceeded (common on pages with large DOM trees), GreenLight clears conversation history and retries with a fresh context instead of aborting the test run.
|
|
578
|
+
- **Large page handling.** Pages with many repeated elements (e.g. a list of many product cards with lots of detail) get an automatically compressed accessibility tree: the first few items are shown in full, and the rest are summarized as one-liners. This keeps the input within token limits while preserving all element names for targeting.
|
|
579
579
|
|
|
580
580
|
## Cached plans
|
|
581
581
|
|
|
582
582
|
The first run of a test uses LLM calls to discover the right browser actions (**discovery run**). After a successful run, GreenLight caches the concrete action sequence as a **heuristic plan** in `.greenlight/plans/`.
|
|
583
583
|
|
|
584
|
-
Subsequent runs replay the cached plan directly via Playwright
|
|
584
|
+
Subsequent runs replay the cached plan directly via Playwright, no LLM calls, no API costs, significantly faster. If you change the test steps in YAML, the hash changes and GreenLight automatically re-discovers.
|
|
585
585
|
|
|
586
586
|
```bash
|
|
587
587
|
greenlight run # uses cached plans where available
|
|
@@ -622,14 +622,14 @@ provider: openai
|
|
|
622
622
|
greenlight run --provider gemini
|
|
623
623
|
```
|
|
624
624
|
|
|
625
|
-
Only one provider is active at a time. OpenRouter is the default
|
|
625
|
+
Only one provider is active at a time. OpenRouter is the default. It lets you access models from all vendors through a single API key, which is the easiest way to get started.
|
|
626
626
|
|
|
627
627
|
### Model selection
|
|
628
628
|
|
|
629
629
|
GreenLight uses the LLM in two distinct roles with different requirements:
|
|
630
630
|
|
|
631
|
-
- **Planner
|
|
632
|
-
- **Pilot
|
|
631
|
+
- **Planner**: Interprets the test steps, splits compound actions, and expands form-filling steps. This runs once per test case and benefits from a more capable model for consistent, correct results.
|
|
632
|
+
- **Pilot**: Resolves individual steps against the live page (picking which element to click/type). This runs many times per test and should use a fast, inexpensive model to keep costs and execution time low.
|
|
633
633
|
|
|
634
634
|
Configure both in `greenlight.yaml`:
|
|
635
635
|
|
|
@@ -726,14 +726,14 @@ flowchart TD
|
|
|
726
726
|
orchestrator --> output
|
|
727
727
|
```
|
|
728
728
|
|
|
729
|
-
**Discovery run:**
|
|
729
|
+
**Discovery run:** Capture page state (a11y tree with stable refs) → LLM determines action → execute via Playwright → record for cache.
|
|
730
730
|
|
|
731
|
-
**Cached run:**
|
|
731
|
+
**Cached run:** Replay stored actions directly via Playwright, no LLM calls, no API costs.
|
|
732
732
|
|
|
733
733
|
## Documentation
|
|
734
734
|
|
|
735
|
-
- [Specifications](docs/specifications.md)
|
|
736
|
-
- [Implementation Plan](docs/implementation.md)
|
|
735
|
+
- [Specifications](docs/specifications.md): Full feature spec, technology decisions, MCP strategy
|
|
736
|
+
- [Implementation Plan](docs/implementation.md): Step-by-step build plan
|
|
737
737
|
|
|
738
738
|
## Avoiding side effects in your app
|
|
739
739
|
|
|
@@ -770,7 +770,7 @@ if (!req.isE2ETest) {
|
|
|
770
770
|
}
|
|
771
771
|
```
|
|
772
772
|
|
|
773
|
-
The header is only added to same-origin requests
|
|
773
|
+
The header is only added to same-origin requests. Cross-origin requests to CDNs, tile servers, and third-party APIs are not affected. This avoids triggering CORS preflight requests on external services.
|
|
774
774
|
|
|
775
775
|
## CI/CD
|
|
776
776
|
|
|
@@ -782,3 +782,13 @@ The header is only added to same-origin requests — cross-origin requests to CD
|
|
|
782
782
|
```
|
|
783
783
|
|
|
784
784
|
Exit code 0 on all-pass, non-zero on any failure.
|
|
785
|
+
|
|
786
|
+
## Contributing
|
|
787
|
+
|
|
788
|
+
GreenLight is an internal project at [Umain AB](https://umain.com) and is still in alpha. Things move fast and APIs may change. That said, we'd love contributions from anyone who finds the project useful or interesting.
|
|
789
|
+
|
|
790
|
+
**Pull requests are welcome.** Whether it's a bug fix, a new feature, improved docs, or a wild idea: Open a PR and we'll take a look. We don't have a formal contributing guide yet, so just keep your changes focused and include a short description of what you changed and why.
|
|
791
|
+
|
|
792
|
+
**A note on issues:** We've disabled the issue tracker for now. If you run into a problem or have an idea, the best way forward is to submit a PR. We're a small team and would rather review code than triage tickets at this stage.
|
|
793
|
+
|
|
794
|
+
Thanks for checking out GreenLight. We're excited to see where it goes.
|
package/package.json
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
2
|
+
"name": "@eidra-umain/greenlight",
|
|
3
|
+
"version": "0.7.7",
|
|
4
|
+
"description": "E2E web testing tool. Write tests as plain English, no selectors or glue code.",
|
|
5
|
+
"license": "GPL-3.0-only",
|
|
6
|
+
"author": "umain.com",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/cli/index.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./dist/cli/index.js",
|
|
11
|
+
"./*": "./dist/*"
|
|
12
|
+
},
|
|
13
|
+
"bin": {
|
|
14
|
+
"greenlight": "dist/cli/index.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"keywords": [
|
|
21
|
+
"e2e",
|
|
22
|
+
"testing",
|
|
23
|
+
"ai",
|
|
24
|
+
"llm",
|
|
25
|
+
"playwright",
|
|
26
|
+
"natural-language",
|
|
27
|
+
"accessibility",
|
|
28
|
+
"automation",
|
|
29
|
+
"end-to-end"
|
|
30
|
+
],
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/eidra-umain/greenlight"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc",
|
|
37
|
+
"dev": "tsc --watch",
|
|
38
|
+
"greenlight": "node dist/cli/index.js",
|
|
39
|
+
"lint": "eslint src/",
|
|
40
|
+
"lint:fix": "eslint src/ --fix",
|
|
41
|
+
"format": "prettier --write .",
|
|
42
|
+
"format:check": "prettier --check .",
|
|
43
|
+
"prepublishOnly": "npm run build",
|
|
44
|
+
"test": "vitest run",
|
|
45
|
+
"test:watch": "vitest"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"chrono-node": "^2.9.0",
|
|
49
|
+
"commander": "^13.0.0",
|
|
50
|
+
"dotenv": "^17.3.1",
|
|
51
|
+
"fuse.js": "^7.1.0",
|
|
52
|
+
"human-id": "^4.1.3",
|
|
53
|
+
"playwright": "^1.58.2",
|
|
54
|
+
"playwright-zoom": "^1.1.0",
|
|
55
|
+
"yaml": "^2.8.2",
|
|
56
|
+
"zod": "^4.3.6"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@eslint/js": "^10.0.1",
|
|
60
|
+
"@types/node": "^22.0.0",
|
|
61
|
+
"eslint": "^10.0.3",
|
|
62
|
+
"eslint-config-prettier": "^10.1.8",
|
|
63
|
+
"prettier": "^3.8.1",
|
|
64
|
+
"typescript": "^5.7.0",
|
|
65
|
+
"typescript-eslint": "^8.57.0",
|
|
66
|
+
"vitest": "^4.1.0"
|
|
67
|
+
}
|
|
68
68
|
}
|