
A WordPress sandbox test passes only when the temporary site works, expires and leaves no residue. Opening the demo homepage proves almost nothing about token replay, reset integrity, delayed cron, partial deletion or orphaned users. Test the complete state transition from launch request to independently verified absence.
Write the allowed states and transitions: requested, provisioning, active, extending, resetting, expired, deleting, deleted and failed. For every transition, specify the trigger, database record, visible result, side effects, timeout, retry policy and rollback. Impossible transitions—such as extending a deleted session—must fail safely.
| Stage | Primary assertion | Independent evidence |
|---|---|---|
| Create | One isolated site/account exists | Site list, session registry, unique IDs |
| Login | Token works once for intended account | Replay fails; cookie belongs to sandbox |
| Use | Required plugin workflow succeeds | Denied-action matrix still fails |
| Extend | Expiry changes within policy | Old deadline replaced atomically |
| Reset | Known seed baseline returns | Mutation set disappears; identity rules hold |
| Expire | Access stops at server boundary | Existing and new requests are denied |
| Delete | Owned resources are removed | Site, user, tables and files absent |
| Reconcile | No orphan remains | Two-way inventory comparison is clean |
Seed a small fixture with posts, media, plugin settings and one background job. Mark every generated resource with the test run/session ID. Avoid real customer data and external credentials. The marker lets the test prove isolation and find residue without relying on a human-readable subdomain.
Inject failure after site creation, after user creation, during plugin activation and during seed import. Each failure should either roll back immediately or create a visible cleanup obligation with a retry. Retrying the same request must not create duplicate sites. Test simultaneous identical launch requests to expose race conditions.
Consume the launch token once and replay it from a second clean browser; replay must fail. Verify token expiry, account binding and revocation after reset. Exercise required actions, then attempt direct Network Admin access, user promotion, plugin installation, REST/AJAX mutations, email and external HTTP. A hidden menu is not proof of denial.
“Reset” can mean restoring content, recreating the subsite or launching a replacement. Define which identity, URL and expiry survive. Mutate every seeded resource type, upload an extra file, schedule a job and change plugin settings. After reset, compare with a canonical manifest. Also confirm that caches and browser sessions cannot expose the previous state.
Use short test lifetimes or an injectable clock in non-production environments. Assert behavior immediately before and after the deadline. Extending a session must update the authoritative deadline once; two concurrent extensions must follow a documented rule. The countdown display may drift, but the server must reject actions after expiry.
Run the named cleanup event and poll with a bounded timeout. Confirm the site is absent from the Multisite site list, its tables and site meta are removed, its upload prefix is gone, and its dedicated user has no remaining membership or record. Check session and token tables, object cache and queued jobs. Treat “already absent” as a safe retry result.
Each test needs an alert, a recoverable state and a reconciliation result. This is where most “happy path” demo checks fail.
Run the full suite when WordPress core, the sandbox manager, the demonstrated plugin, its dependencies, PHP or hosting configuration changes. Block release on isolation, token replay, authorization, reset mismatch, cleanup residue or missing monitoring. Store run ID, versions, timings and evidence—not visitor data.
A low-frequency synthetic launch can reveal DNS, TLS, scheduler and storage failures that staging cannot reproduce. Give the canary an unmistakable marker, never real credentials, and a strict resource quota. It should launch, log in, perform one harmless plugin action, expire and confirm deletion. Alert only after bounded retries and ensure the canary itself cannot build a backlog.
For each state transition, capture a correlation ID, timestamps, site/user IDs, software versions, attempt count and sanitized error category. Do not log launch tokens, cookies or visitor content. Retain enough history to distinguish a slow cleanup from a missing one and to compare failure rate before and after a release. A screenshot of the final page cannot provide that evidence.
Before changing lifecycle code, back up the network database and relevant storage and verify restore in staging. If a release fails the gate, stop new launches, roll back the plugin/configuration, revoke temporary access and run reconciliation in report-only mode. Repair confirmed orphans in small batches, then re-enable launching only after a complete canary finishes cleanly.
Define what must always be true: one sandbox has one identity and generation; visitors cannot access siblings; expired sessions cannot mutate state; reset removes prior changes; cleanup is idempotent; and verified deletion leaves no in-scope residue. Tests should assert these properties, not only button text.
Keep invariants versioned with the demonstrated product and infrastructure.
Create known posts, users, options, files, custom-table rows, queues and mock external records tagged to the sandbox. Include one item in every storage layer. Hash or otherwise identify fixtures so reset and cleanup can be reconciled exactly.
Use synthetic data and never clone production customers into a public demo.
Inject failure after site creation, role setup, dependency activation, content import, routing and token creation. Each retry must resume or compensate without producing duplicate sites or reusable credentials. Visitors should never enter an environment falsely marked ready.
Record state, owner and error for operator recovery.
Request the assigned host or path externally, validate certificate coverage, redirects, cookie scope and canonical URL. Wildcard DNS can remove propagation delay but still needs routing and certificate renewal tests. Path-based environments require strict site and cache keys.
A database row alone is not a successful provision.
Send two simultaneous redemption requests and assert only one succeeds. Replay from another browser, after expiry and after reset. Confirm logs, analytics and referrers never contain the raw token, and the final browser URL is clean.
Check session rotation and intended role after automatic login.
Enumerate admin, REST, AJAX, upload and plugin-specific actions. Call them anonymously, as the temporary user, as a sibling sandbox and after expiry. Change resource and blog identifiers. Expected denial must occur server-side even if the UI hides the action.
Keep administrator-only test credentials outside the demo and automated artifacts.
Attempt email through core and plugin-specific providers, and HTTP toward allowed mock, blocked public, loopback, private and link-local destinations. Follow redirects in tests to expose server-side request forgery gaps. Confirm blocks are logged safely and do not silence platform alerts.
Use mocks so no real messages, charges or external mutations occur.
Install or activate only declared dependencies, perform the main demo tasks, upload bounded media, save settings and view results. Assert the user can complete the promised experience without excessive capability. Record errors, latency and resource use.
A secure sandbox that cannot demonstrate the product fails its contract.
Create changes in every layer, start a background job, open two sessions and trigger reset. Assert starter fixtures return, visitor data disappears, stale sessions/jobs cannot write, caches are isolated and the generation identifier changes.
Repeat reset to prove idempotency and interruption recovery.
Inject or abstract the authoritative clock where the system supports it; otherwise set short safe test lifetimes in an isolated environment. Test warning boundary, expiry, request crossing expiry, scheduler delay and clock/timezone edge. Do not wait for production-length windows in every release run.
Confirm browser countdown is presentation only and server authorization owns the decision.
After expiry, reconcile site tables, users/memberships, posts/meta, files, object versions, caches, queues, routes and mock external records. “Delete returned success” is insufficient. Preserve a tombstone and resource counts.
Run cleanup twice; the second pass should be safe and report nothing remaining.
Pause WP-Cron or the system scheduler, allow sandboxes to expire and confirm access is still revoked. Resume and measure backlog drain. Invoke two cleanup workers concurrently and verify atomic ownership.
Alert on oldest overdue item and cleanup capacity, not just scheduled-event presence.
Simulate a deadlock, unavailable table, read-only directory, full temporary storage and missing file. The lifecycle should move to retry or quarantine with a clear reason, retain its manifest and avoid deleting identity too early.
Repair the dependency and prove restart from the checkpoint.
Return throttling, timeout, permission denial and partial deletion. Retry only transient classes with capped backoff. Quarantine permanent configuration errors. Verify no shared prefix is deleted and billed versions are reported honestly.
Use local mocks or isolated test buckets, not production objects.
Launch concurrently until the configured safe limit. Confirm excess requests queue or reject before provisioning, cleanup and administrators retain reserved resources, and retry messaging is accurate. Mix active sessions, resets and expiry rather than testing launch alone.
Stop at defined database, memory, queue and storage thresholds.
Give a synthetic user membership in two test subsites and expire one. Assert only intended membership/content is removed and the network user remains when policy requires. Test site deletion, user deletion and reassignment separately.
Never run identity lifecycle tests against real network users.
Each transition should emit sandbox ID, generation, prior/new state, duration, safe error class and owner without tokens or personal content. Correlate provisioning, access, reset and cleanup. Force notification failure and confirm it is visible.
Dashboards must distinguish active, expired, cleaning, quarantined and verified-deleted.
| Suite | Release condition |
|---|---|
| Provision | Transactional and external route ready |
| Access | Single-use token and tenant authorization pass |
| Containment | Email, HTTP, file and cache boundaries pass |
| Reset | All fixtures restored and stale work rejected |
| Expiry | Access denied independent of cleanup |
| Cleanup | All layers reconcile and rerun safely |
At a safe frequency, launch a synthetic sandbox, verify login and a harmless product action, expire it and confirm cleanup within objective. Use dedicated identifiers and exclude canaries from marketing analytics. Do not grant wider rights than public visitors.
Alert only on failure or meaningful regression and prevent overlapping canaries.
Store state timelines, counts, safe errors and screenshots of synthetic data. Redact tokens, cookies, paths and credentials. Define retention and access. A failure artifact should support debugging without becoming a way into the environment.
Delete temporary exports and test media after verification.
Roll back the plugin/configuration while active test sandboxes exist, then verify their access, expiry and cleanup remain defined. Restore a cleanup manifest from backup and finish deletion. Test manual quarantine release with approval and audit.
A release is not safe if rollback strands environments that the new version created.
A visitor starts an import and resets immediately. Starter content returns, but the old job later writes products into the new session. Page-only assertions passed while generation isolation failed.
The system tags jobs with sandbox generation and rechecks current state before commit. The lifecycle test now holds the worker until after reset and proves the stale write is rejected.
A low-traffic demo has no request to trigger WP-Cron. The countdown ends, but an open browser can keep saving because authorization checks only whether the site was deleted. The test pauses the scheduler and exposes the gap.
Expiry becomes a server-side access boundary; cleanup remains asynchronous and resumes later.
All lifecycle invariants pass under normal, duplicate and interrupted execution; direct endpoints enforce tenant and expiry boundaries; reset rejects stale generations; cleanup reconciles every layer and reruns safely; capacity admission preserves recovery; rollback handles existing sandboxes; and a production canary detects regression without exposing data or credentials.
After expiry and reset, use the back button, restore a suspended tab and request cached pages. Sensitive admin content must not reappear as usable state, and actions must be denied server-side. Set appropriate private cache headers for authenticated responses.
Test service workers and application caches where present.
Trigger reset near the expiry boundary and send duplicate requests. One state transition must own the result; no replacement generation should inherit a cleanup intended for the old one. Stable generation IDs make the expected behavior assertable.
Repeat with a running background job and file upload.
Provision with the previous and candidate plugin versions, exercise the same journey and clean both. Compare capabilities, endpoints, tables, files and outbound calls. A dependency update can expand the lifecycle surface without changing Sandbox Manager.
Block release until the inventory and containment tests are updated.
Capture database, files, object versions, caches and jobs before provision, after use and after verified cleanup. Explain delayed physical reclamation. The test should fail when a tagged fixture remains, even if the public site disappeared.
Use the accounting result in capacity regression.
Extend, expire, reset, quarantine, retry and delete through approved tools. Verify capability, nonce, audit log and idempotency. Attempt each as a temporary user and confirm denial.
Operator convenience must not bypass state invariants or conceal partial cleanup.
A canary should use synthetic identity, bounded resources and mocked side effects. Deduplicate alerts until state changes and archive successful detailed logs according to retention. Failed canary cleanup must enter the same visible recovery path as real sandboxes.
Periodically prove the canary itself cannot overlap or exhaust capacity.
Record versions, environment, fixture manifest, suites passed, injected failures, capacity mix, known exclusions, reviewer and rollback. Link detailed protected logs without copying secrets into the release note.
This artifact lets operators distinguish a newly introduced failure from an infrastructure change and repeat the exact gate.
Launch, countdown, warning, reset, expiry and error states must work by keyboard and assistive technology. Focus should move predictably after automatic login or reset, and time limits need accessible notice and extension behavior where offered.
Do not rely on color, animation or a disappearing countdown as the only lifecycle signal.
Exercise supported browsers, mobile layout, private browsing and cookie restrictions. Automatic login and routing can behave differently under tracking prevention. Record the supported matrix and fail with useful guidance rather than looping redirects.
Security boundaries remain server-side regardless of browser behavior.
Each failed transition should tell the visitor what can be done without exposing paths, queries, site IDs or stack traces. Operators need a correlation identifier and safe error class. Test unauthorized, expired, capacity-full and dependency-failure responses.
Ensure errors themselves are not cached across visitors.
Close the browser mid-upload, start several jobs, abandon an import and leave a transaction incomplete. Expiry and cleanup must still revoke access, cancel or reject stale work and reconcile partial files.
Use bounded synthetic payloads so tests do not become denial-of-service events.
Disable one telemetry destination or fill a test log quota. The platform should preserve lifecycle safety and surface monitoring degradation through a separate route. Do not let logging failure roll back successful authorization revocation.
Keep local bounded evidence until the external system recovers.
Review fixtures and routes after every demonstrated-plugin or infrastructure change. Remove obsolete assertions and add new storage, endpoint or dependency layers. Flaky tests should be investigated rather than retried until green.
Assign suite ownership and keep runtime short enough for every release, with deeper failure drills on a scheduled cadence.
Close each release with one clean provision-to-deletion run through the actual scheduler and routing path. This final integration check complements isolated tests and proves that the supported environment can create, use, expire and fully reconcile a synthetic sandbox without manual intervention.
Retain the final canary’s state timeline, safe resource counts and installed versions as the release baseline. Do not retain its token, cookie or synthetic upload longer than necessary. On the next release, compare transition duration and residual checks with this baseline and investigate drift before widening concurrency or publishing new product promises.
Add one test in which the canary runner crashes after each major transition. The next invocation should discover authoritative state, acquire ownership safely and continue or compensate without duplicating the sandbox. This proves persistence rather than success inside one uninterrupted process.
Review failed assertions by invariant and resource layer. A flaky timing retry must not conceal a cross-tenant read, post-expiry write or leftover object. Security and cleanup invariants remain release blockers until the cause is understood and the regression reliably passes.
WPStack Sandbox Manager 0.3.2 is described as providing per-visitor Multisite demos, one-time automatic login, controlled extensions, immediate expiry/new-test controls, timed cleanup, launch limits, outbound email/HTTP blocking and recent-session visibility. Those behaviors map directly to the lifecycle test matrix.
Do not substitute claims for verification. It is self-hosted and requires Multisite, so scheduler behavior, storage, DNS, SSL and infrastructure failures are environment-specific. Test the installed version with the actual product and dependencies.
No. It misses replay, authorization, reset, expiry, deletion and reconciliation failures that can create security or capacity problems.
Run the named event through WP-CLI in staging, record its output, and independently verify resource absence.
Use supported APIs for behavior, plus read-only inventory checks where needed to prove no tables or records remain.
The session should remain visibly incomplete, retry idempotently, and be found by reconciliation—not be marked successfully deleted.
At every relevant release or infrastructure change, with a smaller scheduled canary if the public demo is business-critical.

Aditya Bhimrajka is a technology entrepreneur, product strategist, and software solutions expert with over a decade of experience building scalable web and mobile applications. His expertise spans SaaS, AI, cloud technologies, custom software development, and digital transformation. Passionate about solving real-world business challenges through technology, Aditya shares practical insights on WordPress, plugins, software development, startup growth, product strategy, and emerging technologies. At WPStack, he writes actionable, experience-driven content that helps developers, businesses, and website owners build secure, high-performing, and future-ready WordPress solutions.