TESTING.md

WebholeInk Testing Philosophy

WebholeInk is designed to be predictable, boring, and auditable.

Testing exists to protect invariants, not to chase coverage metrics or simulate user behavior that WebholeInk explicitly does not support.

If a test does not protect a long-term guarantee, it does not belong here.


What Testing Is For

Testing in WebholeInk exists to ensure:


What Testing Is NOT For

WebholeInk does not test:

Those concerns are outside the scope of this project.


Core Invariants (Must Never Break)

The following invariants define WebholeInk.
Any change that violates these must not be merged.


1. File-First Content

Invariant:
If the filesystem is correct, the site is correct.


2. Deterministic Routing

Invariant:
The same URL must always resolve the same content.


3. Explicit Metadata

Metadata must be:

Required metadata fields:

Invariant:
Metadata is never guessed.


4. Draft Handling

Invariant:
Draft content is invisible unless explicitly published.


5. Markdown Rendering

Invariant:
Rendered HTML is always clean and predictable.


6. Layout Integrity

Invariant:
Each request produces a single, valid HTML document.


7. Caching Correctness

Invariant:
Caches may optimize delivery, never correctness.


8. Feed Accuracy

Feeds must:

Supported feeds:

Invariant:
Feeds must never lie.


9. Sitemap Accuracy

Invariant:
The sitemap must match reality.


Recommended Test Types

WebholeInk favors simple, explicit tests.

Recommended approaches:

Manual Verification (Primary)

Example:

curl -I https://example.com/about
curl https://example.com/posts/example-post

Scripted Smoke Tests (Optional)

WebholeInk supports lightweight scripted checks to confirm that core behavior has not regressed. These tests are intentionally simple and require no testing framework.


Route Resolution Verify that pages and posts resolve correctly: `

 curl -s https://example.com/ | grep "<title>"
 curl -s https://example.com/about | grep "<h1>"
 curl -s https://example.com/posts/example-post | grep "<article>"

Expected:

• Pages return rendered HTML

• No raw Markdown appears

• HTTP status is 200

Draft Exclusion

Verify that draft posts are not visible:

curl -s https://example.com/posts | grep draft-post && echo "FAIL"

Expected:

• Draft posts do not appear in output

Metadata Presence

Verify required metadata:

curl -s https://example.com/about | grep "<meta name=\"description\"" curl -s
https://example.com/posts/example-post | grep "<title>"

Expected: • <title> always present

• <meta name="description"> present when defined

Cache Headers

Verify cache behavior:

curl -I https://example.com/about

Expected headers: • ETag

• Last-Modified

• Cache-Control

Revalidate cache:

curl -I -H 'If-None-Match: "etag-value"' https://example.com/about 

Expected:

• 304 Not Modified when unchanged

Feed Validation

Verify RSS feed:

curl -s https://example.com/feed.xml 

Verify JSON feed:

curl -s https://example.com/feed.json | jq . 

Expected:

• Valid XML / JSON

• Published posts only

• Correct URLs and dates

Sitemap Validation

Verify sitemap:

curl -s https://example.com/sitemap.xml 

Expected:

• Pages included

• Published posts included

• Drafts excluded

• Canonical URLs only

When to Run Smoke Tests

Run smoke tests when:

• Modifying routing

• Changing resolvers

• Adjusting metadata handling

• Altering caching behavior

• Preparing a release tag

Smoke tests should be quick, repeatable, and boring.