Files
sporel-lib-management.dep-f…/README.md
Axel Meyer 9072f5eec6 lib-management.dep-fetcher-test v0.1.0: TAP suite + fixtures
27-assertion TAP-style suite for lib-management.dep-fetcher v0.1.0:

  - 4 internal-helper tests (id_to_path, gitea_slug_for incl. .git
    exception)
  - 6 JSON decoder tests (objects/arrays/nesting)
  - 3 conflict-detection tests (synthetic two-parent fixture)
  - 3 closure-walk tests (clean fixture, check_only mode)
  - 3 case-B (clean) tests
  - 4 case-C (dirty) tests
  - 4 case-D (wrong-tag → silent checkout, post-state verification)

Cases A (missing+clone) and E (broken describe) need network or
contrived corruption; out of scope for slice 5 per architecture spec.

Fixture matrix:
  conflict_a/  — static, no .git needed
  clean_b/     — .git at v0.1.0 (clean)
  dirty_c/     — .git at v0.1.0-1-g…-dirty
  wrong_tag_d/ — .git with tags v0.1.0 + v0.2.0, HEAD at v0.1.0

fixtures/_setup.sh reconstructs the .git states (idempotent — restores
manifest.lib content after the case-D silent-checkout side-effect).
Required pre-step before each test session; the test-runner blocks
with a clear error if fixtures/_setup.stamp is missing.

.gitignore covers the .git subdirs and the stamp file — they are
local-machine state, rebuilt by _setup.sh from the source-tracked
manifest.lib seed files.
2026-05-31 01:47:34 +02:00

2.8 KiB

lib-management.dep-fetcher-test

TAP-style assertion suite for lib-management.dep-fetcher (slice 5 of the dep-fetcher implementation plan).

Coverage

Case Spec What it verifies
Internal _id_to_path, _gitea_slug_for (incl. .git-suffix exception), _json_decode
Conflict §5 conflict-detection Two parents pin same lib to different versions → ok=false, one conflict entry
Walk §5 closure walk Manifest tree resolves transitively; deduplication; closure non-empty
B §5 case B (clean) describe == v<X.Y.Z> → no warning, no error
C §5 case C (dirty) describe matches v<X.Y.Z>-N-g…[-dirty] → one kind="dirty" warning
D §5 case D (wrong-tag) describe != v<X.Y.Z> → silent checkout; post-state is case B

Cases A (missing → clone) and E (broken describe) require live network or contrived corruption; they are out of scope for slice 5 (public-network only; private repos = paid content in later slice).

Running

# 1. Stage source to install (see install-reference-workflow.md)
bash ~/Projects/Sporel/install-reference.sh --no-verify

# 2. Reconstruct .git fixtures (case B / C / D)
bash /c/Games/Sporel/libs/lib-management/dep-fetcher-test/fixtures/_setup.sh

# 3. Run the test-runner module headless
cd /c/Games/Sporel
SPOREL_CI=1 ./bin/Sporel.exe --module=dep-fetcher-test-runner
# expected: 27/27 assertions pass; exit 0

The runner lives at sporel-modules/dep-fetcher-test-runner/. It is a kind=test-module that re-exports the assertions from this lib so they participate in test-all-modules.sh aggregation (and therefore milestone-check).

Fixture layout

fixtures/
├── _setup.sh          # rebuild .git state for cases B/C/D
├── _setup.stamp       # touched by _setup.sh; presence-check in init.lua
│
├── conflict_a/        # static (no .git needed): two parents pin
│   ├── manifest.module      lib-core.maps to different versions
│   └── install/libs/lib-x/consumer/manifest.lib
│
├── clean_b/           # _setup.sh creates .git at v0.1.0
├── dirty_c/           # _setup.sh creates .git at v0.1.0-1-g…-dirty
└── wrong_tag_d/       # _setup.sh creates .git with tags v0.1.0 + v0.2.0,
                       # HEAD at v0.1.0 (module pins v0.2.0)

_setup.sh is idempotent — re-runs after the case-D silent-checkout side-effect restore the wrong-tag fixture to its initial v0.1.0 HEAD. The script sets per-repo user.name / user.email so it does not touch the user's global git config.

Why a separate runner module?

Test libs (role: "test") cannot be consumed by production modules (kind: "module"). The runner is therefore kind: "test-module", which can depend on test libs (per engine_lib_resolver role-check).