Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion vendor/wheels/tests/runner.cfm
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,28 @@
}
}

// Resolve the TestBox scope from url.directory with a conservative allowlist.
// Permitted roots (plus any dotted sub-path of them):
// wheels.tests.* — core framework specs
// vendor.<package>.tests.* — first-party / installed package specs
// The /wheels/core/tests endpoint is unauthenticated and only safe in dev;
// the allowlist is defense-in-depth so stray input can't drive arbitrary
// CFC compilation through whatever mappings happen to be registered.
local.testDirectory = "wheels.tests.specs";
if (StructKeyExists(url, "directory") && Len(Trim(url.directory))) {
local.requestedDirectory = Trim(url.directory);
if (ReFindNoCase(
"^(wheels\.tests|vendor\.[a-z0-9][a-z0-9\-]*\.tests)(\.[a-zA-Z0-9_]+)*$",
local.requestedDirectory
)) {
local.testDirectory = local.requestedDirectory;
}
}

try {
// Try to create TestBox instance with coverage disabled
testBox = new wheels.wheelstest.system.TestBox(
directory="wheels.tests.specs",
directory=local.testDirectory,
options={ coverage = { enabled = false } }
);
} catch (any e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,13 @@ component extends="wheels.WheelsTest" output="false" {
}
```

<Aside type="caution">
The core test runner's `directory=` URL parameter (sometimes referenced as a way to scope a run to `vendor.mypackage.tests`) is documented but not currently honoured — [`wheels#2280`](https://github.com/wheels-dev/wheels/issues/2280) tracks the fix. Until that lands, run your package's specs in the package repo's own CI (most first-party packages do this) rather than through the app's HTTP test endpoint.
</Aside>
Scope a run to a single package with the `directory=` URL param on the core test runner:

```bash
curl "http://localhost:60007/wheels/core/tests?db=sqlite&format=json&directory=vendor.mypackage.tests"
```

The runner accepts two allowlisted roots: `wheels.tests.*` (the framework core) and `vendor.<package>.tests.*` (any installed package). Any other value is silently ignored and the full core suite runs instead — the endpoint is unauthenticated and the allowlist prevents it from driving arbitrary CFC compilation.

Package authors typically keep a matching set of specs in their repo and rely on the registry's `validate.yml` plus the package's own CI to catch regressions before tagging a release.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ curl "http://localhost:60007/wheels/core/tests?db=sqlite&format=json&directory=w

# Skip populate when iterating on one spec and the schema is already in place
curl "http://localhost:60007/wheels/core/tests?db=sqlite&format=json&populate=false&directory=wheels.tests.specs.model.postSpec"

# Scope to a single installed package's tests (e.g. wheels-sentry, wheels-i18n)
curl "http://localhost:60007/wheels/core/tests?db=sqlite&format=json&directory=vendor.wheels-sentry.tests"
```

The `populate=false` query param is the trick that makes tight inner loops possible. Populate drops and recreates every test table — a second or two on SQLite but much slower on networked databases. Once the schema is in place for the run, skipping populate shaves the wait down to just your specs executing.
Expand All @@ -114,6 +117,7 @@ The runner accepts filters at every layer. Pick whichever matches your workflow.
| By directory (script) | `bash tools/test-local.sh model` |
| By directory (URL) | `&directory=wheels.tests.specs.model` |
| By single spec file (URL) | `&directory=wheels.tests.specs.model.postSpec` |
| By installed package (URL) | `&directory=vendor.wheels-sentry.tests` |
| Skip in source | `xdescribe("...", ...)` / `xit("...", ...)` — built into WheelsTest |
| Skip the whole populate | `&populate=false` on the URL (schema must already exist) |

Expand Down
Loading