9.1 KiB
9.1 KiB
Test Infrastructure & Strategy — diablo2-web Module Split (TEST_INFRA.md)
1. Test Philosophy
- Requirement-Driven & Opaque-Box Verification: Every test case in
tests/e2e-module-split/is derived directly fromORIGINAL_REQUEST.md(R1–R4and Acceptance Criteria),PROJECT.md(F1–F10and Interface Contracts 1–4), andAGENTS.md(Diablo II v1.13c Ground Truth Parity Rules). - 1.13c Ground Truth & Anti-Silent Failure Enforcement:
- Universal DT1 libraries (
data\global\tiles\Act1\Outdoors\Blank.dt1,data\global\tiles\Act1\Barracks\InvisWal.dt1withstyle=49 sequence=7collision floor,data\global\tiles\Act1\Barracks\Warp.dt1) must be unconditionally loaded perD2Common.dllDRLGROOM_LoadDt1Files(0x6fdb8400). - Sparse/void cells must be blocked (
blocked === 1) and masked withCOLLIDE_MASK_INVALID(COLLIDE_BLANK | COLLIDE_WALL), andfindIsoSpawnmust never spawn in void or default blindly to geometric center(width/2, height/2). - Tile variant selection (
pickVariant) must use high-entropy SplitMix64 2D spatial coordinate hashing without 45-degree diagonal striping. - All 66
SuperUniquesmust preserve exact 1.13cClassand minion identifiers (scarab2,zombie5,fetishshaman4,nihlathakboss,minion1..minion11-> token'XX', etc.). - Missing required parameters (e.g.,
D2DataRegistry/getSharedDataRegistrycalled without anArchiveSource) must fail fast by throwing an explicitError.
- Universal DT1 libraries (
- Dynamic Import & AST/Filesystem Inspection: All module imports inside
tests/e2e-module-split/*.test.tsuse runtime dynamicawait import(...),node:fsinspection, and source/AST boundary scanning insideit(...)blocks so the test files remain 100% valid TypeScript at all times and execute against the post-split architecture (src/common/,src/netproto/,src/server/,src/client/,src/baker/,tools/,play.html).
2. Feature Inventory (F1–F10)
| Feature ID | Feature Name | Target Module / Path | Core Requirements & Contracts | Tier 1 | Tier 2 | Tier 3 | Tier 4 |
|---|---|---|---|---|---|---|---|
| F1 | src/common/ Pure Module & Data Registry Decoupling |
src/common/{mpq,formats,data,drlg,world,items,skills,units,i18n,rng,pack-contract}, tsconfig.common.json |
Pure ES2022 (types: [], zero DOM, zero node:*), D2DataRegistry & getSharedDataRegistry require injected ArchiveSource (no /usr/local/google/home/taodao/d2-data), D2Rng, SplitMix64 pickVariant, pure lookupTbl. |
6 | 6 | ✓ | ✓ |
| F2 | Shared Pack Contract (src/common/pack-contract/) |
src/common/pack-contract/index.ts |
Exports PackedDrlgBundleManifest, PackedTileCatalogIndex, PackIndex, PackSceneJson, EntityMeta, ClipMeta, validateUniversalDt1Libraries, validatePackManifest. |
5 | 5 | ✓ | ✓ |
| F3 | Elimination of All 23 Server-to-Client Reverse Dependencies | src/common/{items,units,skills,i18n,world}, src/server/** |
Extract inventory-model, belt-model, item-bridge, CharacterAttributes, resolvePlayerCharToken, HotkeySkillEntry, getSkillName, subTileToScene; zero imports from src/server/** into src/client/**. |
5 | 5 | ✓ | ✓ |
| F4 | src/baker/ Offline Baker Module & Unified CLI |
src/baker/{cli.ts,io,packers,extract,audit}, tsconfig.baker.json |
Node-only offline baker (types: ["node"], zero DOM, zero client/server imports), unified src/baker/cli.ts (npm run bake -- <target> & --verify). |
5 | 5 | ✓ | ✓ |
| F5 | tools/ CLI Consolidation & Legacy Relay Deletion |
tools/*.ts, package.json |
Migrate 93 CLI/bot/replay/verify tools to tools/; delete scripts/net-relay.ts, scripts/net-server.ts, and scripts/ directory; update package.json scripts. |
5 | 5 | ✓ | ✓ |
| F6 | src/server/ Authoritative Simulation & LocalLoopbackAdapter |
src/server/{engine,ai,skills,items,world,save,scene,adapter}, tsconfig.server.json |
Zero DOM globals, zero Math.random/Date.now/performance.now, zero node:* in skills/registry.ts; LocalLoopbackAdapter implements GameServerAdapter. |
6 | 6 | ✓ | ✓ |
| F7 | src/client/ Pure Browser Module & MapService Decoupling |
src/client/{main.ts,render,ui,frontend,scene,audio,sim,i18n,map,session,world}, tsconfig.client.json |
Pure browser (types: [], zero node:*, zero server/baker imports); MapService.fromLoader / fromPackedUrls without node:fs/node:path. |
5 | 5 | ✓ | ✓ |
| F8 | Single HTML Entry (play.html) & Legacy Entry Removal |
play.html, vite.config.ts |
play.html is sole .html in root and vite.config.ts (with D2Exocet/D2Formal436 @font-face); index.html, acts*.html, bnet.html, act-scene.ts, net-scene.ts, src/net/* deleted. |
5 | 5 | ✓ | ✓ |
| F9 | Compiler-Level Isolation & Boundary Gate (tests/arch/boundaries.test.ts) |
tsconfig.*.json, tests/arch/boundaries.test.ts |
All 5 tsconfig.<module>.json files wired into npm run typecheck; src/ contains only {common,netproto,server,client,baker}; tests/arch/boundaries.test.ts passes with 0 whitelist exceptions. |
5 | 5 | ✓ | ✓ |
| F10 | Full 1.13c Parity, Baker, Replay & DRLG Invariants | src/common/drlg/, src/common/world/, src/common/units/, tools/netproto-replay.ts |
Universal DT1s (Blank.dt1, InvisWal.dt1, Warp.dt1), void blocking (COLLIDE_MASK_INVALID), non-void findIsoSpawn, SplitMix64 pickVariant, SuperUnique minion closure, .d2cap replay parity. |
5 | 5 | ✓ | ✓ |
3. Test Architecture
tests/e2e-module-split/
├── tier1-feature-coverage.test.ts # >= 50 tests (>= 5 per feature F1–F10): happy-path module layout, exports, & contracts
├── tier2-boundary-corner.test.ts # >= 50 tests (>= 5 per feature F1–F10): fail-fast, negative, boundary & isolation invariants
├── tier3-cross-feature.test.ts # >= 15 tests: pairwise cross-module & cross-feature integration contracts
└── tier4-real-world-scenarios.test.ts # >= 6 tests: realistic end-to-end gameplay, DRLG, item/socket, .d2cap replay, & repo audit scenarios
- Test Runner Command:
npx vitest run tests/e2e-module-split/
4. Real-World Application Scenarios (Tier 4)
- Scenario 1 — End-to-End Single-Player Game Loop (
LocalLoopbackAdapter→OnlineSession→ClientWorld):- Connect
LocalLoopbackAdaptertoOnlineSessionandClientWorld, verify initial handshake (LoadAct,UnitAssign,MapSeed), dispatch movement (RunToLocation/WalkToLocation) and skill cast (CastLeftSkillAtLocation/CastRightSkillAtLocation), step server ticks, verify authoritativeClientWorldstate updates, and cleanly disconnect.
- Connect
- Scenario 2 — End-to-End DRLG Level Generation, Void Collision &
findIsoSpawnAcross Act 1–5:- Verify universal DT1 inclusion (
Blank.dt1,InvisWal.dt1style=49 seq=7,Warp.dt1), void cell collision masking (COLLIDE_MASK_INVALID = COLLIDE_BLANK | COLLIDE_WALL), largest walkable floor region spawn resolution (findIsoSpawn), and SplitMix64pickVariantspatial decorrelation across Act 1–5 levels.
- Verify universal DT1 inclusion (
- Scenario 3 — End-to-End Item, Inventory, Belt & Socket Pipeline (
src/common/items/↔src/server/items/):- Generate and bridge items via
itemToUiInventoryItem, place items intoInventoryGrid(findFreeGridSlot), manage belt potions (BeltHud/BeltModel/itemToBeltPotion/ column gravity shift), and socket gems/runes into host items (socketItemIntoHost,checkRunewordMatch).
- Generate and bridge items via
- Scenario 4 — End-to-End
.d2capBinary Packet Capture Replay intoClientWorld:- Replay all 4 real
.d2capcapture fixtures (01-bncs-mcp-lobby.d2cap,02-d2gs-town-walk-chat.d2cap,03-d2gs-items-npc-skills.d2cap,04-d2gs-idle-60s.d2cap) viareplayD2CapText(..., { strict: true })and verifyunknownPackets === 0,opaquePackets === 0,protocolErrors === 0, and populatedClientWorldstate.
- Replay all 4 real
- Scenario 5 — End-to-End Offline Asset Pack Manifest & Entity/Tile Pack Integrity:
- Load and validate
public/act-packs/tiles/{index.json, drlg-bundle.json, drlg-bundle.bin}againstsrc/common/pack-contract/validators (validateUniversalDt1Libraries,validatePackManifest), and initializeMapService.fromLoaderwith an injected loader to generate an Act 1 level view withoutnode:fsinsrc/client/.
- Load and validate
- Scenario 6 — End-to-End Repository Architectural & Module Boundary Audit:
- Programmatically scan every
.tsfile insrc/**,tools/**, root*.html,vite.config.ts,package.json, andtsconfig*.jsonto verify all R1–R4 architectural invariants with zero exceptions.
- Programmatically scan every
5. Coverage Thresholds
| Tier | File | Minimum Required Tests | Target Tests |
|---|---|---|---|
| Tier 1 | tests/e2e-module-split/tier1-feature-coverage.test.ts |
50 (>= 5 per F1–F10) |
52 |
| Tier 2 | tests/e2e-module-split/tier2-boundary-corner.test.ts |
50 (>= 5 per F1–F10) |
52 |
| Tier 3 | tests/e2e-module-split/tier3-cross-feature.test.ts |
15 | 16 |
| Tier 4 | tests/e2e-module-split/tier4-real-world-scenarios.test.ts |
6 | 6 |
| Total | tests/e2e-module-split/ |
121 | 126 |