Developer-Dashboard

 view release on metacpan or  search on metacpan

doc/testing.md  view on Meta::CPAN

# Testing

## Test Suite

Run the full test suite with:

```bash
prove -lr t
```

Run the fast saved-bookmark browser smoke check with:

```bash
integration/browser/run-bookmark-browser-smoke.pl
```

That host-side smoke runner creates an isolated temporary runtime, starts the
checkout-local dashboard, loads one saved bookmark page through headless
Chromium, and can assert page-source fragments, saved `/ajax/...` output, and
the final browser DOM. With no arguments it runs the built-in Ajax
`foo.bar` bookmark case.

For a real bookmark file, point it at the saved file and add the specific
browser assertions you care about:

```bash
integration/browser/run-bookmark-browser-smoke.pl \
  --bookmark-file ~/.developer-dashboard/dashboards/test \
  --expect-page-fragment "set_chain_value(foo,'bar','/ajax/foobar?type=text')" \
  --expect-ajax-path /ajax/foobar?type=text \
  --expect-ajax-body 123 \
  --expect-dom-fragment '<span class="display">123</span>'
```

For long-running saved bookmark Ajax handlers that would otherwise survive a
browser refresh, prefer `Ajax(..., singleton => 'NAME', ...)`. The runtime will
rename the Perl worker to `dashboard ajax: NAME`, terminate the older matching
Perl stream before it starts the refreshed one, and also tear down matching
singleton workers during `dashboard stop`, `dashboard restart`, and browser
`pagehide` cleanup beacons. For browser streaming checks, use `stream_data()`
or `stream_value()` against a finite saved Ajax handler and assert the final
DOM after incremental chunks land.

## Coverage

Install Devel::Cover in a local Perl library and generate the coverage report:

```bash
cpanm --notest --local-lib-contained ./.perl5 Devel::Cover
export PERL5LIB="$PWD/.perl5/lib/perl5${PERL5LIB:+:$PERL5LIB}"
export PATH="$PWD/.perl5/bin:$PATH"
cover -delete
HARNESS_PERL_SWITCHES=-MDevel::Cover prove -lr t
PERL5OPT=-MDevel::Cover prove -lr t
cover -report text -select_re '^lib/' -coverage statement -coverage subroutine
```

Developer Dashboard expects a reviewed `lib/` coverage report before release, and the current repository target is 100% statement and subroutine coverage for `lib/`.

The coverage-closure suite includes managed collector loop start/stop paths under `Devel::Cover`, including wrapped fork coverage in `t/14-coverage-closure-extra.t`, so the covered run stays green without breaking TAP from daemon-style child processe...
Managed collector children now scrub inherited `PERL5OPT` and `HARNESS_PERL_SWITCHES` coverage settings before their long-lived loop work begins, and the runtime manager widens its startup stability polls when the parent harness is running under `Dev...
GitHub workflow coverage gates must match the `Devel::Cover` `Total` summary
line by regex rather than one fixed-width spacing layout, because runner or
module upgrades can change column padding without changing the real
`100.0 / 100.0 / 100.0` result.
The `t/07-core-units.t` collector loop guard treats both `HARNESS_PERL_SWITCHES` and `PERL5OPT` as valid `Devel::Cover` signals, because this machine uses both launch styles during verification.
The runtime-manager coverage cases also use bounded child reaping for stubborn process shutdown scenarios, so `Devel::Cover` runs do not stall indefinitely after the escalation path has already been exercised.
The focused skill regression in `t/19-skill-system.t` now also exercises `PathRegistry::installed_skill_docker_roots()` directly, including the default enabled-only view and the explicit `include_disabled => 1` path, so skill docker layering changes ...
That same focused skill regression now also locks the same-repo
`DD-OOP-LAYERS` fallback contract inside one skill name, including inherited
fallback for missing `cli/<command>` files, missing bookmark files, missing
`dashboards/nav/` folders, and missing skill config keys.
The release-metadata checks also reject repeated FULL-POD-DOC template prose in shipped Perl assets, so contributors have to document the actual responsibility of each module or staged helper instead of pasting one generic block across the tree. The ...
The tarball release gate now also includes `t/36-release-kwalitee.t`, which
reads the built `Developer-Dashboard-X.XX.tar.gz` through
`Module::CPANTS::Analyse` and fails unless every kwalitee indicator passes.
Use that tarball-focused check for CPANTS drift; the source tree itself is not
the right surface for this analyzer.
The JavaScript fast-check wrapper is a source-tree fuzz gate. It runs when
`node`, `npm`, `package.json`, and `package-lock.json` are all available, and
it skips in packaged install-test trees that do not ship those checkout-only
JavaScript manifests.
The contributor contract now lives here plus `AGENTS.override.md` and
`agents.md`, not in the top-level product manual in `README.md` or
`Developer::Dashboard.pm`. Those two files stay synced as user-facing product
documentation instead of repeating repo-process rules.
When editing `Developer::Dashboard.pm`, audit the whole shipped manual, not
just the paragraph you touched. In particular, the FAQ wording must describe
real product behavior rather than contributor-only framing, and the `SEE ALSO`
section must use stable local section links instead of brittle private-module
targets that can degrade into broken rendered links. The rest of the top-level
manual should also stay self-contained: prefer plain code references such as
`Developer::Dashboard::PathRegistry` over POD links to private modules, so the
main product guide does not depend on MetaCPAN cross-linking to remain usable.
The same boundary applies to repo-internal Markdown filenames: user-facing
manuals and shipped Perl POD must not send readers to `*.md` files by name.
If a product guide needs to refer to one of those internal documents, describe
it conceptually instead of exposing the repository filename.
Markdown files themselves are also checkout-only documentation and must not be
released in the CPAN tarball. Keep the `dist.ini` Markdown exclusion in place,

doc/testing.md  view on Meta::CPAN

- `localhost` helper login requirement
- helper login session creation and logout
- helper session remote-address binding and expiry validation paths
- forwarding of response headers such as `Location` and `Set-Cookie`
- root free-form editor behavior at `/`
- posted instruction handling through `/`, including default denial of unsaved transient execution unless `DEVELOPER_DASHBOARD_ALLOW_TRANSIENT_URLS` is enabled
- saved bookmark browser edits through `/app/<id>/edit`, including named-route saves and non-transient play links when transient URL execution stays disabled
- malformed bookmark icon bytes from older files are repaired into stable fallback glyphs on both `/app/<id>` and `/app/<id>/edit`, so browser verification should check for visible fallback icons instead of `�`
- nested saved bookmark ids such as `nav/foo.tt` through `/app/...`, `/app/.../edit`, and `/app/.../source`
- shared `nav/*.tt` bookmark rendering between top chrome and the main page body in sorted filename order
- raw `nav/*.tt` TT/HTML fragment rendering between top chrome and the main page body, plus direct `/app/nav/<name>.tt` and `/source` coverage for those raw fragment files
- Template Toolkit conditional rendering for shared nav fragments and saved pages using `env.current_page` and `env.runtime_context.current_page`
- `/apps -> /app/index` compatibility
- top chrome rendering on edit and saved render pages
- denial of browser `token=` and `atoken=` execution for transient page and action payloads, plus transient `/ajax?token=...`, when the transient URL opt-in env var is absent
- absence of accidental project-local `.developer-dashboard` creation when `dashboard restart` runs inside a git repo that has not opted into a local dashboard root
- saved bookmark `Ajax file => ...` handlers through `/ajax/<file>?type=...`, including `dashboards/ajax/...` storage, direct process-backed streamed ajax execution for both `stdout` and `stderr`, and blank-env verification under the default deny pol...
- file-backed saved Ajax Perl wrappers with autoflushed `STDOUT` and `STDERR`, including a timing check that long-running `print` plus `sleep` handlers emit early chunks instead of buffering until exit

## Blank Environment Integration

Run the host-built tarball integration flow with:

```bash
integration/blank-env/run-host-integration.sh
```

This integration path builds the distribution tarball on the host with
`dzil build`, runs the prebuilt `dd-int-test:latest` container with only that
tarball mounted into it, installs the tarball with `cpanm`, and then
exercises the installed `dashboard` command inside the clean Perl container.
The release gather rules also exclude local `cover_db` output so a covered
host run does not contaminate the tarball under test.
The release gather rules must also exclude local scratch and dependency trees
such as `node_modules/` and `test_by_michael/`. Those paths are source-tree
implementation details, not distributable runtime assets, so release metadata
must fail before build or release if they are gathered into the tarball.

The shipped runtime-manager lifecycle checks now also fall back to `/proc`
socket ownership scans when that prebuilt image does not include `ss`, and
they re-probe the managed port for late listener pids before restart, so the
integration flow verifies the same stop/restart behavior that a minimal Linux
runtime will see in practice.
Those checks also cover the Starman master-worker split, where the recorded
managed pid can be the master while the bound listener pid is a separate
worker process on the same managed port.
RuntimeManager tests also lock shutdown signal portability by proving the
dashboard lifecycle maps named dashboard intents such as TERM and KILL to
numeric POSIX signals before calling Perl `kill`, matching Alpine/iSH Perl
builds that reject named signal strings.

The integration flow also:

- creates a fake project with its own `./.developer-dashboard` runtime tree
- creates that fake-project runtime tree only after `cpanm` completes, so the tarball's own test phase still runs against a clean runtime
- verifies installed CLI and saved bookmarks from that fake project's local runtime plus config collectors from that same runtime root
- verifies `dashboard version` reports the installed runtime version
- seeds a user-provided fake-project `./.developer-dashboard/cli/update` command plus `update.d` hooks inside the container and verifies `dashboard update` uses the same executable command-hook path as every other top-level subcommand, including late...
- verifies the installed web app denies `/?token=...` browser execution by default while saved bookmark routes still render
- uses headless Chromium to validate the editor, the saved fake-project bookmark page, and the helper login page
- verifies that an installed long-running saved `/ajax/...` route starts streaming visible output within the expected first seconds instead of buffering until process exit
- should be interpreted together with the tracked source-tree integration assets in `doc/integration-test-plan.md`, `doc/windows-testing.md`, and `integration/browser/run-bookmark-browser-smoke.pl`; source-tree tests now fail if those release/support...

## Windows Verification

For Windows-targeted changes, keep the verification layered:

- run the fast forced-Windows unit coverage in `t/`
- run the real Strawberry Perl smoke on a Windows host with `integration/windows/run-strawberry-smoke.ps1`
- run the full-system QEMU guest smoke with `integration/windows/run-host-windows-smoke.sh` before making a release-grade Windows compatibility claim

The Strawberry smoke verifies `dashboard shell ps`, `dashboard ps1`, one
PowerShell-backed collector command, one saved Ajax PowerShell handler through
`Invoke-WebRequest`, and a browser DOM dump through Edge or Chrome when either
browser is present in the Windows environment.
In the Dockur-backed guest path, the launcher stages the Strawberry Perl MSI
from the Linux host and the Windows tarball install currently uses
`cpanm --notest` for third-party dependency setup before the real dashboard
runtime smoke runs.
The supported Windows runtime baseline is PowerShell plus Strawberry Perl.
Git Bash is optional. Scoop is optional. They remain setup helpers, not
runtime requirements for Developer Dashboard itself.



( run in 0.760 second using v1.01-cache-2.11-cpan-39bf76dae61 )