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

@decocms/qa

v0.3.0

Published

E2E QA test runner for deco.cx ecommerce stores. Runs a deterministic purchase journey against data-qa-marked DOM and emits JUnit XML + JSON report.

Readme

@decocms/qa

E2E QA test runner for deco.cx ecommerce stores. Runs a deterministic 10-step purchase journey (home → PLP → PDP → cart → /checkout) against a single URL and emits JUnit XML + a JSON report + screenshots. The journey asserts cart state — quantity, variant, price, and that the cart isn't empty — so a broken add-to-cart fails the run instead of passing green.

Selectors are resolved from data-qa-* attributes on the store's JSX, with a configurable override fallback in .qarc.json. No LLM discovery, no visual diff — deterministic by design. The marking is consumed by the setup-deco-ecommerce-qa Claude Code skill that scaffolds GitHub Actions workflows in store repos.

Quickstart

bunx @decocms/qa journey \
  --url https://mystore.example.com \
  --junit junit.xml \
  --github \
  --viewports desktop,mobile

The journey clicks through:

  1. visit-home — load the URL
  2. navigate-plp — click the first visible [data-qa-category-link]. If no visible match exists and [data-qa-menu-trigger] is present, the engine clicks the trigger (e.g. a hamburger button) to open the menu drawer, then clicks the category link.
  3. enter-pdp — click the first [data-qa-product-card], extract [data-qa-pdp-title] and (optional) [data-qa-pdp-price]
  4. shipping-calc-pdp (optional) — fill [data-qa-cep-input] + click [data-qa-cep-submit]
  5. add-to-cart — click [data-qa-buy-button]. If the click opens a size/variant modal (common on mobile), the engine picks the first in-stock [data-qa-variant-option], clicks [data-qa-variant-confirm] if present, then verifies via [data-qa-cart-count] (soft — never fails the step).
  6. open-minicart — dismiss sticky overlays (Escape), click [data-qa-cart-icon], wait for [data-qa-minicart], then assert the cart line (see "Cart-state assertions" below)
  7. cart-persists-reload (optional) — reload the page, reopen the minicart, assert the cart line still has ≥1 [data-qa-minicart-item]
  8. shipping-calc-cart (optional) — same as step 4 but in the cart context
  9. go-checkout — click [data-qa-minicart-checkout], assert [data-qa-checkout-page], verify the PDP title persisted in the cart DOM (preferring [data-qa-minicart-item-name] when present)
  10. cart-controls (optional) — click [data-qa-quantity-increment] and assert [data-qa-quantity-value] becomes 2, then click [data-qa-minicart-item-remove] and assert the cart empties

Optional steps are skipped silently when their slugs aren't on the page.

After every navigation the engine waits for the network to settle and scrolls the page to trigger IntersectionObserver-driven lazy content (product grids), and polls for each required selector for up to 10s — so lazily-hydrated storefronts don't flake.

The variant slugs (data-qa-variant-option, data-qa-variant-confirm) and the badge slug (data-qa-cart-count) are optional: add them only on stores where buying requires picking a size or where you want add-to-cart verified by the cart badge.

Cart-state assertions

Once the minicart is open (step 6), the engine validates the cart line — but only for the markers a store has actually added. A missing marker means "not verified" (skipped), never a failure, so stores adopt the checks incrementally:

| Marker | Assertion | |---|---| | data-qa-minicart-items | The cart-line list wrapper (rendered even when empty). When present and it contains zero data-qa-minicart-item rows → fail (empty cart — add-to-cart didn't persist). Also scopes the line queries below, so a recommendation carousel can't be mistaken for a cart line. | | data-qa-minicart-item | One element per cart line. | | data-qa-quantity-value | Must read 1 after a single add. | | data-qa-minicart-item-variant | Must contain the size picked in step 5 (exact token match). | | data-qa-minicart-item-price + data-qa-pdp-price | Line price must be > 0 and the PDP "from" price. | | data-qa-minicart-item-name | Used at go-checkout to confirm the right product reached the checkout; a mismatch here (and only here) escalates step 9 to a failure. |

Additional optional markers: data-qa-minicart-subtotal, data-qa-minicart-total, data-qa-quantity-increment, data-qa-quantity-decrement, data-qa-minicart-item-remove (the last three drive the cart-controls step).

Commands

| Command | Purpose | |---|---| | qa journey --url <url> | Run the 10-step purchase journey | | qa doctor --url <url> | Report which data-qa-* slugs are present on a URL | | qa list-slugs | Print the 27 canonical slugs as JSON |

qa journey flags

| Flag | Type | Purpose | |---|---|---| | --url <url> | string | Target URL (required) | | --junit <file> | string | Emit JUnit XML to this path | | --github | boolean | Emit GitHub Actions ::group:: / ::error:: annotations | | --viewports <list> | string | Comma-separated: desktop,mobile,tablet. Default: desktop. | | --cep <cep> | string | Override the CEP used in shipping-calc steps | | --smoke | boolean | Run only steps 1,2,3,5 (skips shipping, minicart, checkout) | | --headed | boolean | Run with a visible browser (local debug) | | --debug | boolean | Pause for inspection (implies --headed) |

.qarc.json config

Lives at the root of the store repo. All fields except url are optional.

{
  "url": "https://farmrio.com.br",
  "cep": "01310-100",
  "viewports": ["desktop", "mobile"],
  "selectors": {
    "data-qa-buy-button": "button.custom-add-to-cart"
  },
  "features": {
    "checkoutUrlPattern": "**/checkout**"
  }
}
  • selectors — per-slug CSS override used when [data-qa-<slug>] is missing. Keys are restricted to the 27 canonical slug names (Zod-enforced).
  • features.checkoutUrlPattern — a Playwright URL glob (e.g. **/checkout**) that the post-click checkout URL must match. When set, the engine drops the [data-qa-checkout-page] assertion and validates by URL match instead — works for both same-origin and cross-origin (external VTEX) checkouts. On a local base (localhost/127.0.0.1) where the click never reaches a matching URL, the step is skipped (verdict stays pass) rather than failing. Takes precedence over checkoutCrossOrigin.
  • features.checkoutCrossOrigin — set to true for VTEX legacy stores where the checkout opens on checkout.vtex.com.br. The engine drops the [data-qa-checkout-page] assertion and validates by URL change instead; the PDP-title persistence sweep still runs on the VTEX DOM. Prefer checkoutUrlPattern for new configs.

CLI flags take precedence over .qarc.json.

Output

qa-output/<runId>/
├── report.json            # full structured report (validated against the v0.1 Zod schema)
└── screenshots/
    ├── 1-visit-home.png
    ├── 2-navigate-plp.png
    └── ...

When --junit <file> is passed, a separate JUnit XML file is written for dorny/test-reporter@v2 or similar CI parsers.

Exit codes

| Code | Meaning | |---|---| | 0 | Journey passed (all required steps OK; optional steps OK or deliberately skipped) | | 1 | Assertion failure (a required step failed — the standard red-test case) | | 2 | Setup failure (URL invalid, .qarc.json broken, browser couldn't launch) | | 3 | Global timeout (journey exceeded its deadline; pages were force-closed) |

Development

bun install
bunx playwright install chromium
bun run check    # tsc --noEmit
bun run lint     # biome lint
bun run test     # vitest run
bun run build    # bundle dist/cli.js for npm

Tests use a local HTTP server (tests/harness/server.ts) plus HTML fixtures. They run against real Chromium — no mocks for browser interactions.

License

MIT.