npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@devant-net/maestro-reporter

v0.1.5

Published

Streams Maestro test runs into devq-cloud — reads the JUnit XML report Maestro emits with --format junit, plus the screenshots/video/logs from --test-output-dir.

Downloads

599

Readme

@devant-net/maestro-reporter

Streams Maestro test runs into Devant Cloud.

Maestro doesn't expose a programmatic reporter API, so this package consumes Maestro's own JUnit XML output (--format junit) plus the screenshot / video / log directory it writes (--test-output-dir, --debug-output).

Install

bun add -D @devant-net/maestro-reporter
# or
npm i -D @devant-net/maestro-reporter

Use

# 1. Run Maestro and tell it to emit JUnit + keep its artifact dirs.
maestro test \
  --format junit \
  --output build/maestro-report.xml \
  --test-output-dir build/maestro-results \
  --debug-output build/maestro-debug \
  ./flows

# 2. Upload to Devant Cloud.
devq-maestro-upload \
  --junit build/maestro-report.xml \
  --test-output-dir build/maestro-results \
  --debug-output build/maestro-debug \
  --run-name "PR #${{ github.event.number }}"

The uploader exits 0 whenever the upload itself succeeds — it does not re-fail on test failures. Maestro's own exit code already encodes that, so your CI step can treat them independently.

Connecting to Devant Cloud

Either pass flags inline (--api-url, --api-token, --project-id) or set the same env vars our other reporters read:

| Var | Default | Notes | |-------------------|--------------------------|------------------------------------------------| | DEVQ_API_URL | http://localhost:32124 | Your tenant's URL. | | DEVQ_TOKEN | dev-admin-token | CI token (dq_ci_…) from Settings → CI/CD. | | DEVQ_PROJECT_ID | 1 | Numeric project id. | | DEVQ_RUN_NAME | Maestro — <ISO date> | Display name on the run. | | DEVQ_RUN_ID | unset | If set, skip create/complete (orchestration). |

How tests bind to test cases

The reporter resolves each Maestro flow against a Devant Cloud test_case row in this order:

  1. <property name="devq-key">DEF-AB12</property> — explicit override. Maestro supports custom properties on flows.
  2. <property name="testCaseId">…</property> or xray-test-key — common conventions; only used if the value matches the [A-Z]+-[A-Z0-9]+ shape.
  3. @KEY token anywhere in the flow name, classname, or property values.
  4. Exact name match in the project, then auto-create. The reporter prints the new key:
    [devq] minted DEF-XYZ9 for "Login Flow"
           — add '@DEF-XYZ9' to the flow's name or a property to bind it

In Maestro YAML you bind a key with the name: field at the top of the flow:

name: Login Flow @DEF-XYZ9
appId: com.example.app
---
- launchApp
- tapOn: "Sign in"

…or as a property:

name: Login Flow
appId: com.example.app
---
- launchApp
- tapOn: "Sign in"
# Properties live in a separate `# tags:`, `# properties:` section under the
# flow header — see the Maestro docs for the exact syntax.

Status mapping

Maestro emits a non-standard status= attribute on each <testcase>:

| Maestro status | Devant Cloud status | Notes | |------------------|---------------------|--------------------------------| | SUCCESS | pass | | | WARNING | pass | Soft fail — flow ran but the agent flagged a concern. | | ERROR | fail | | | CANCELED | blocked | Run aborted before this flow finished. | | STOPPED | blocked | |

For frameworks that emit standard JUnit (<failure>, <error>, <skipped/>) the reporter also handles those — same parser is used by other Devant Cloud JUnit consumers.

What gets uploaded

Per Maestro flow (<testcase>):

| Source | Maps to in Devant Cloud | |--------------------------------|----------------------------------------| | <testcase status="..." time="..."> | One test_result + one test_result_attempt | | <failure message="..." /> | error_message + error_stack | | <system-out> / <system-err> | stdout / stderr on the attempt | | screenshot-…-(<flow>).png | Artifact (image/png) | | commands-(<flow>).json | Artifact (application/json) | | ai-(<flow>).json | Artifact (application/json) | | *.mp4 (video) tagged (<flow>) | Artifact (video/mp4) | | maestro.log (debug) | Attached to every flow as a shared log |

Artifact path safety: the uploader refuses any file whose realpath escapes the --test-output-dir / --debug-output roots, so a malicious flow can't trick it into uploading /etc/passwd.

Recording video

maestro test doesn't record video — its LocalVideoRenderer classes are only exercised by maestro record / maestro cloud. To get a video into Devant Cloud, wrap the test run with the bundled devq-maestro-record helper, which uses xcrun simctl io recordVideo (iOS) or adb shell screenrecord (Android) under the hood:

devq-maestro-record \
  --output build/maestro-results/recording.mp4 \
  --device booted \
  -- maestro test \
       --format junit --output build/maestro-report.xml \
       --test-output-dir build/maestro-results \
       ./flows

Then run the uploader as usual. Any mp4 / mov / webm at the top of --test-output-dir whose name doesn't include a (<flow>) tag is treated as a run-scoped recording and attached to every flow's last attempt — same pattern as maestro.log.

devq-maestro-upload \
  --junit build/maestro-report.xml \
  --test-output-dir build/maestro-results

devq-maestro-record mirrors the child's exit code, so CI jobs that decide pass/fail from maestro test keep working unchanged. Android tip: screenrecord caps each invocation at 180s — split very long suites across multiple flow runs.

Limitations

  • No retries. Maestro's JUnit output reports a single execution per flow; we always emit one attempt. If you re-run a failing flow, run the uploader twice.
  • No per-step trees. Maestro doesn't put step / command details in JUnit XML; the commands-*.json file holds them, but parsing it into Devant Cloud steps would be a future enhancement.
  • time precision. Maestro reports seconds with millisecond precision (time="421.573"); the uploader rounds to whole milliseconds for storage.
  • AI report files named by file stem (ai-(01-launch-settings).json) rather than the flow's name: field aren't yet matched per-flow — they'll be picked up by a future enhancement that consults the file path. The ai-(<flow.name>).json files Maestro 1.x emits do match.