Testing Strategy
Priority: Automated tests FIRST, manual testing as supplementary safety net.
Philosophy: Automated Tests Are Primary
Before writing ANY refactoring code:
Write comprehensive automated tests for current behaviour
Verify tests pass (establish baseline)
Make refactoring changes
Tests still pass (green to green refactoring)
(Optional) Run manual testing checklist for extra confidence
Why automated tests first?
Immediate feedback on every change
No manual clicking through scenarios
Runs in CI/CD on every commit
Documents expected behaviour
Prevents regressions permanently
Required Automated Test Coverage
Before Starting Any Phase
You MUST have automated tests covering:
Context Unit Tests
File: content/webapp/contexts/ItemViewerContextV2/ItemViewerContextV2.test.tsx
Test ALL derived values:
Test all edge cases:
New (from restricted-images merge):
Component Integration Tests
Files: Component .refactored.test.tsx files
Test that components actually consume context values:
ViewerTopBar.refactored.test.tsxUses
currentCanvasfrom context (not calculating)Uses navigation booleans for button states
Uses
isCurrentCanvasRestrictedfor restriction badgeUses
hasDownloadOptionsfor download button
ZoomedImage.refactored.test.tsxUses
currentCanvasfrom contextUses
mainImageServicefrom contextHandles empty
mainImageServicecorrectly
Download Options Hook Tests (Phase 2)
File: content/webapp/hooks/useDownloadOptions.test.ts
Test download option calculations:
Returns empty array when no canvas or manifest
Includes IIIF image download options
Includes canvas image downloads from services
Includes canvas rendering downloads (PDFs)
Includes manifest-level downloads
Includes video/audio downloads
Handles ChoiceBody items correctly
Deduplicates downloads with same id (from
restricted-imagesmerge)Memoises results correctly
Updates when dependencies change
Test edge cases:
Multiple downloads with different URLs (all included)
Multiple downloads with same URL (only one included after dedup)
ChoiceBody in
renderingarrayChoiceBody in
supplementingarrayEmpty download arrays
Restricted downloads for staff vs non-staff users
Mock Utilities
File: content/webapp/contexts/ItemViewerContextV2/test-utils.ts
mockDefaultContextwith proper TypeScript typesHelper functions for creating test manifests
Helper functions for creating test canvases
All mocks properly typed (no
any)
Test Examples
See refactoring-iiif-viewer-context-testing.md for complete TypeScript test examples.
Quick example:
Manual Testing Checklist
Use this AFTER automated tests pass as an extra safety net.
For Each Phase: Core Functionality
Navigate between canvases
Thumbnails navigation works
Next/Previous buttons work
URL updates with canvas number
Page title updates
UI controls
Sidebar toggle (desktop)
Sidebar toggle (mobile)
Grid view toggle (multi-canvas works only)
Zoom in/out controls
Fullscreen mode
Visual appearance
Layout looks correct
Images load correctly
No console errors
No React warnings
Different Work Types
Test with these specific work types:
Multi-canvas image work (
/works/[id]/images)Canvas count shows correctly
Grid view available
Navigation between canvases works
Download options appear
Single canvas work
No grid view toggle (should be hidden)
Navigation buttons hidden/disabled
Layout optimised for single canvas
Archive items (
/works/[id]/items)Archive tree navigation works
Correct canvas loads from tree selection
Breadcrumb navigation works
Restricted access works
Restriction badge appears
Auth flow works correctly
Restricted content shows after auth
Download disabled for restricted canvas
Works with video/audio
Video player appears in viewer
Audio player appears in viewer
Download options include video/audio
Works with downloadable PDFs
PDF renders in viewer
PDF download option appears
PDF downloads correctly
User Scenarios Matrix
The table below lists key combinations of work types, authentication states, and access restrictions. Test coverage should span these scenarios to ensure the viewer handles all cases correctly.
Authentication States:
Logged out - no authentication
Logged in (regular user) - standard library member
Logged in (restricted access) - user with restricted content access (same UI, different access level)
Access Types:
✓ Open access - no restrictions
🔒 Restricted - requires authentication with restricted access role
⚠️ Content advisory - requires clicking through warning modal (any auth state)
Multi-canvas images
✓ Open
✓ Open
✓ Open
a55dcp3h
Grid view, navigation
Single canvas image
✓ Open
✓ Open
✓ Open
b5kqccbb
No grid/nav controls
Archive items
✓ Open
✓ Open
✓ Open
a222zvge
Tree navigation
Video/audio
✓ Open
✓ Open
✓ Open
a9w3qy3j
In-viewer playback
✓ Open
✓ Open
✓ Open
ndx5vuhy
In-viewer rendering
Mixed content (born digital)
✓ Open
✓ Open
✓ Open
dn9jwck6
Multiple media types
Content advisory
⚠️ Modal
⚠️ Modal
⚠️ Modal
pnud3fzb
Warning modal required
Restricted whole item
🔒 Blocked
🔒 Blocked
✓ Access granted
rp9jnamu
Auth + role required
Restricted audio
🔒 Blocked
🔒 Blocked
✓ Access granted
esd6gs3s
Auth + role required
Restricted video
🔒 Blocked
🔒 Blocked
✓ Access granted
zsgh5y3z
Auth + role required
Restricted born digital
🔒 Blocked
🔒 Blocked
✓ Access granted
my6bzerr
Auth + role required
Note: The "logged in (restricted)" authentication state only affects access (whether content is granted), not which component renders — the viewer always renders regardless of auth state.
Specific Test Works
The following works provide comprehensive coverage for all scenarios from the matrix above.
Unrestricted Works (Open Access)
Multi-Canvas Image Work
Type: Multi-canvas images (unrestricted)
What to test: Grid view, canvas navigation, thumbnails, all accessible to everyone
Test with: Logged out | Logged in (regular) | Logged in (restricted)
Single Canvas Image Work
Type: Single canvas image (unrestricted)
What to test: No grid/nav controls, single image display, all accessible to everyone
Test with: Logged out | Logged in (regular) | Logged in (restricted)
Archive Items
Type: Archive with tree navigation (unrestricted)
What to test: Archive tree, breadcrumbs, canvas selection from tree, all accessible to everyone
Test with: Logged out | Logged in (regular) | Logged in (restricted)
PDF Work
Type: PDF document (unrestricted)
What to test: PDF rendering in viewer, download options, all accessible to everyone
Test with: Logged out | Logged in (regular) | Logged in (restricted)
Mixed Media (Born Digital)
Type: Mixed content with multiple media types (unrestricted)
What to test: Multiple media types in same viewer, navigation between media, all accessible to everyone
Test with: Logged out | Logged in (regular) | Logged in (restricted)
Regular Video (Unrestricted)
Type: Open access video
What to test: Video player accessible to all users
Test with: Logged out | Logged in (regular) | Logged in (restricted)
Restricted/Special Access Works
Content Advisory (Clickthrough Warning Modal)
Type: Restricted/Clickthrough Mix
What to test: Modal warning appears for all users before accessing items
Test with: Logged out | Logged in (regular) | Logged in (restricted)
Restricted Whole Item
Type: Fully restricted content
What to test: Blocked for logged out + regular users; accessible for restricted role
Test with: Logged out | Logged in (regular) | Logged in (restricted)
Restricted Audio
Type: Restricted audio content
What to test: Audio player only appears for restricted role users
Test with: Logged out | Logged in (regular) | Logged in (restricted)
Restricted Video
Type: Restricted video content
What to test: Video player only appears for restricted role users
Test with: Logged out | Logged in (regular) | Logged in (restricted)
Restricted Born Digital
Type: Restricted born digital/mixed content
What to test: Mixed media (PDF/video/audio) only accessible for restricted role
Test with: Logged out | Logged in (regular) | Logged in (restricted)
Edge Cases
Works with no manifest
Error message displays gracefully
No JavaScript errors
Works with JavaScript disabled (progressive enhancement)
NoScriptImage component renders on server
Image is visible without JavaScript enabled
OCR text is accessible (check view source)
Page doesn't appear broken
Works with empty canvases
Handles gracefully
No infinite loops or crashes
Missing image services
Falls back to alternative rendering
No broken images
Invalid canvas numbers
/works/[id]/items?canvas=999redirects or shows errorNo crashes
Canvas without imageServiceId
Still renders (uses alternative)
Zoom controls hidden
No console errors
Normalisation-Specific Tests
These are critical when normalising variant implementations:
Test currentCanvas Normalisation
currentCanvas NormalisationDifferent components previously calculated currentCanvas differently. Verify they all work:
ViewerTopBar
canvases?.[index]
Download options appear, canvas title shows
ZoomedImage
transformedManifest?.canvases[index]
Zoom shows correct canvas image
MainViewer
May calculate independently
Canvas scrolling works, canvas displays correctly
Thumbnails
Used queryParamToArrayIndex directly
Correct thumbnail highlighted
Key question: Verify the || '' fallback only exists where genuinely needed.
IIIFViewer
No || '' fallback
iiifImageTemplate handles undefined correctly
ZoomedImage
Had || '' fallback
Verify convertRequestUriToInfoUri still works
Test both:
Canvas WITH
imageServiceId- zoom should workCanvas WITHOUT
imageServiceId- should fall back gracefully, no errors
Critical: Test on all supported browsers BEFORE releasing.
Chrome/Edge (latest)
All core functionality
Zoom controls
Fullscreen
Downloads
Firefox (latest)
All core functionality
Check for Firefox-specific quirks
Safari (latest macOS)
All core functionality
Image rendering
Fullscreen API differences
Mobile Safari (iOS)
Sidebar toggle works
Touch navigation
Pinch to zoom
Fullscreen on mobile
Mobile Chrome (Android)
Sidebar toggle works
Touch navigation
Downloads work
Performance Testing
Large manifests (100+ canvases)
Page loads within 3 seconds
No lag when navigating
Thumbnails load smoothly
React DevTools Profiler
Check for unnecessary re-renders
Verify memoization works
Compare before/after performance
Comparison Testing (Legacy vs Refactored)
Most important test: Side-by-side comparison.
For each work type listed above:
Test with
iiifViewerRefactoredflag OFF (legacy)Note behaviour, take screenshots
Test with
iiifViewerRefactoredflag ON (refactored)Verify IDENTICAL behaviour and appearance
Document any differences (should be zero)
Test Work IDs
See the User Scenarios Matrix and Specific Test Works sections above for a comprehensive list of test works covering the scenarios listed in this document.
All test scenarios now have example work IDs:
✅ Multi-canvas images:
a55dcp3h✅ Single canvas:
b5kqccbb✅ Archive items:
a222zvge✅ PDF:
ndx5vuhy✅ Mixed media (born digital):
dn9jwck6✅ Video/audio:
a9w3qy3j✅ Content advisory:
pnud3fzb✅ Restricted works:
rp9jnamu,esd6gs3s,zsgh5y3z,my6bzerr
When Manual Testing Finds Issues
If manual testing reveals a bug that automated tests didn't catch:
Write an automated test for the bug FIRST
Verify the test fails (reproduces the bug)
Fix the bug
Verify the test passes
Add test to permanent test suite
This prevents the bug from reoccurring and improves test coverage.
Success Criteria
Before marking a phase complete:
Required:
All automated tests pass with flag OFF (legacy)
All automated tests pass with flag ON (refactored)
TypeScript compiles with no errors
No console warnings or errors
Test coverage >80% for new code
Highly Recommended:
Manual testing checklist completed
Tested on all browsers
Comparison testing shows identical behaviour
Performance profiling shows no regressions
See also:
refactoring-iiif-viewer-context-testing.md - Complete TypeScript test examples
04-test-first-approach.md - Why we test first
13-migration-checklist.md - Per-phase checklists
Next: Risks & Success Metrics
Last updated