BlockKey Reconciliation
Spec file: blockkey-reconciliation.spec.ts
Tests: 14 (across 8 sprint groups)
Section: API + Settings → UpDoc → Tailored Tour Pdf workflow
These tests cover the BlockKey reconciliation feature — ensuring that block mappings in map.json survive blueprint regeneration and that orphaned mappings are detected and surfaced in the UI. Tests are organised by the sprint in which they were implemented.
Sprint 1: contentTypeKey Model Support
Section titled “Sprint 1: contentTypeKey Model Support”2 tests — Verifies that contentTypeKey can be stored in and retrieved from map.json.
flowchart TD
A1["Read map.json +\ndestination.json via API"]
A1 --> B1["Save map with\ncontentTypeKey added"]
B1 --> C1["Read back → assert\ncontentTypeKey persisted"]
C1 --> D1["Cleanup: restore original"]
A1b["Read map.json via API"]
A1b --> B1b["Assert mappings load\nwithout contentTypeKey\n(backwards compat)"]
Round-Trip Test
Section titled “Round-Trip Test”- Read current
map.jsonanddestination.jsonvia API - Find a mapping with a
blockKey, addcontentTypeKeyfrom destination - Save via
PUT /workflows/{name}/map - Read back and assert
contentTypeKeypersisted - Cleanup: restore original
map.json
Backwards Compatibility
Section titled “Backwards Compatibility”- Read existing
map.json(pre-contentTypeKey era) - Assert mappings load correctly even when
contentTypeKeyis absent
Sprint 2: Destination Blocks Have contentTypeKey
Section titled “Sprint 2: Destination Blocks Have contentTypeKey”3 tests — Verifies that destination.json provides contentTypeKey on every block.
flowchart TD
A2["Read destination.json"] --> B2["Assert every block has\ncontentTypeKey (GUID format)"]
A2b["Collect all contentTypeKeys"] --> B2b["Assert unique\n(no duplicates)"]
A2c["Read each block"] --> B2c["Assert blockKey ≠\ncontentTypeKey"]
| Test | Asserts |
|---|---|
| Non-empty contentTypeKey | Every block in blockGrids and blockLists has a GUID-format contentTypeKey |
| Unique contentTypeKeys | No two blocks share the same contentTypeKey |
| blockKey ≠ contentTypeKey | Instance key and type key are different values |
Sprint 3: Bridge Resilience
Section titled “Sprint 3: Bridge Resilience”2 tests — Verifies that the Create from Source bridge code uses contentTypeKey to match blocks.
flowchart TD
A3["Read map.json → assert\ncontentTypeKey present,\nblockKeys not all-zero"]
A3b["Full Create from Source\nflow (Tailored Tour, test-01)"]
A3b --> B3b["Capture document ID"]
B3b --> C3b["GET document via API"]
C3b --> D3b["Assert blocks have\nPDF-sourced titles"]
D3b --> E3b["Cleanup: trash document"]
Precondition Check
Section titled “Precondition Check”- Read
map.json→ assert all block mappings havecontentTypeKeyand reconciled (non-zero)blockKey
Full Creation Flow
Section titled “Full Creation Flow”- Navigate to Tailored Tours collection
- Create from Source → select Tailored Tour blueprint →
updoc-test-01.pdf - Wait for extraction, click Create, capture document ID from URL
GET /document/{id}via API- Assert block grid blocks have PDF-sourced titles (not blueprint defaults like “Features”)
- Assert Accommodation block is populated
- Cleanup: move document to recycle bin
Sprint 4: Auto-Reconcile on Regenerate
Section titled “Sprint 4: Auto-Reconcile on Regenerate”2 tests — Verifies that POST /workflows/{name}/regenerate-destination reconciles blockKeys.
flowchart TD
A4["POST regenerate-destination"]
A4 --> B4["Assert reconciliation\nsummary returned"]
B4 --> C4["Assert all blockKeys\nexist in new destination"]
C4 --> D4["Assert contentTypeKey\nbackfilled"]
A4b["Regenerate twice"]
A4b --> B4b["Assert second call\nreports zero orphaned"]
Reconciliation Test
Section titled “Reconciliation Test”- Read current config
POST regenerate-destination- Assert response contains
reconciliationobject withupdated,orphaned,details - Read
map.jsonafter reconciliation - Build set of valid blockKeys from new
destination.json - Assert all blockKeys in
map.jsonexist in new destination - Assert
contentTypeKeyis present on all block mappings (backfilled)
Idempotent Test
Section titled “Idempotent Test”- Call
regenerate-destinationtwice - Assert second call reports
orphaned = 0
Sprint 5: Validation Warnings
Section titled “Sprint 5: Validation Warnings”3 tests — Verifies that orphaned blockKeys produce validation warnings in the API response.
flowchart TD
A5["Corrupt blockKey →\nGET workflow"]
A5 --> B5["Assert validationWarnings\ncontains orphaned warning"]
A5b["Regenerate → GET workflow"]
A5b --> B5b["Assert no\norphan warnings"]
A5c["Corrupt blockKey"]
A5c --> B5c["Assert warning includes\ntarget field name"]
Orphaned Warning
Section titled “Orphaned Warning”- Read
map.json, save original - Corrupt a blockKey to
deadbeef-dead-beef-dead-beefdeadbeef - Save corrupted map
GET /workflows/{name}→ assertvalidationWarningsarray contains warning mentioning the bogus key and the word “orphaned”- Cleanup: restore original
No Warnings When Healthy
Section titled “No Warnings When Healthy”- Regenerate destination, then GET workflow
- Assert no orphan warnings in
validationWarnings
Warning Includes Target Name
Section titled “Warning Includes Target Name”- Corrupt a blockKey, note the
targetfield name - GET workflow → assert warning includes both the bogus key and the target name
- Cleanup: restore
Sprint 6: Backfill Migration
Section titled “Sprint 6: Backfill Migration”3 tests — Verifies the POST /workflows/{name}/backfill-content-type-keys endpoint.
flowchart TD
A6["Strip contentTypeKey →\nPOST backfill"]
A6 --> B6["Assert backfilled > 0"]
A6b["Backfill when\nalready present"]
A6b --> B6b["Assert backfilled = 0"]
A6c["Strip → backfill →\nverify each key"]
A6c --> B6c["Assert matches\ndestination.json lookup"]
Backfill Adds Missing Keys
Section titled “Backfill Adds Missing Keys”- Regenerate destination (ensure blockKeys are valid)
- Strip
contentTypeKeyfrom all block mappings inmap.json - Save stripped map, verify keys are gone
POST backfill-content-type-keys- Assert
backfilled > 0 - Read map back — all block mappings have
contentTypeKeyin GUID format - Cleanup: restore original
Already Present
Section titled “Already Present”- Regenerate + backfill when keys already exist
- Assert
backfilled = 0
Correct Matching
Section titled “Correct Matching”- Build a
blockKey → contentTypeKeylookup fromdestination.json - Strip contentTypeKey from map, backfill
- Verify each backfilled
contentTypeKeymatches the destination lookup - Cleanup: restore
Sprint 7: Orphaned Tag on Map Tab
Section titled “Sprint 7: Orphaned Tag on Map Tab”2 tests — Verifies the UI surfaces orphaned mappings on the Map tab.
flowchart TD
A7["Corrupt blockKey → save"]
A7 --> B7["Navigate to\nworkflow Map tab"]
B7 --> C7["Assert 'Orphaned'\ntag visible"]
C7 --> D7["Cleanup: restore"]
A7b["Regenerate destination"]
A7b --> B7b["Navigate to Map tab"]
B7b --> C7b["Assert zero\n'Orphaned' tags"]
Orphaned Tag Visible
Section titled “Orphaned Tag Visible”- Corrupt a blockKey → save
map.json - Navigate to
settings/workspace/updoc-workflow/edit/tailoredTourPdf - Click “Map” tab
- Assert
uui-tagwith text “Orphaned” is visible - Cleanup: restore
No Orphaned Tags When Healthy
Section titled “No Orphaned Tags When Healthy”- Regenerate destination
- Navigate to Map tab
- Assert zero “Orphaned” tags
Sprint 8: Orphaned Badges on Source Tab
Section titled “Sprint 8: Orphaned Badges on Source Tab”2 tests — Verifies warning-colour badges on the Source tab for orphaned mappings.
flowchart TD
A8["Corrupt blockKey → save"]
A8 --> B8["Navigate to\nworkflow Source tab"]
B8 --> C8["Assert warning-colour\nbadge visible"]
C8 --> D8["Assert healthy positive\nbadges also exist"]
D8 --> E8["Cleanup: restore"]
A8b["Regenerate destination"]
A8b --> B8b["Navigate to Source tab"]
B8b --> C8b["Assert zero\nwarning badges"]
Warning Badge Visible
Section titled “Warning Badge Visible”- Corrupt a blockKey → save
map.json - Navigate to workflow Source tab
- Assert
uui-tag[color="warning"].mapped-tagis visible - Assert
uui-tag[color="positive"].mapped-tagalso exists (healthy mappings) - Cleanup: restore
No Warning Badges When Healthy
Section titled “No Warning Badges When Healthy”- Regenerate destination
- Navigate to Source tab
- Assert zero
uui-tag[color="warning"]badges
Cleanup Pattern
Section titled “Cleanup Pattern”Most tests in this spec follow the same cleanup pattern:
- Save original state —
JSON.parse(JSON.stringify(config.map))at the start - Corrupt/modify — change blockKeys or strip contentTypeKey
- Test — assert expected behaviour
- Restore —
PUT /workflows/{name}/mapwith the original map in afinallyblock
Sprint 3’s creation test uses trashDocument() to move the created document to the recycle bin, with PROTECTED_IDS safeguards.