Video Generation Handler Tests
Overview
Comprehensive unit tests for the video generation polling and course update handlers in the AI generation workflow.
Date: 2025-12-05 Test Framework: Jest with TypeScript Coverage: 100% (Statements, Branches, Functions, Lines)
Test Files Created
1. /backend/functions/ai-generation/src/__tests__/handlers/poll-video-status.test.ts
Unit tests for the poll-video-status.ts handler, which polls the HeyGen API to check video generation status.
Total Tests: 30 Status: ✅ All Passing Coverage: 100%
Test Categories
- Happy Path - Video Status Transitions (4 tests)
- Pending status handling
- Processing status with poll count increment
- Completed status with video URL
- Failed status with error message
- Poll Count Management (5 tests)
- Default pollCount initialization
- Poll count increment behavior
- Maximum poll count timeout (20 polls = 10 minutes)
- Poll count boundary conditions
- Edge case: polling one below max
- Error Handling (5 tests)
- API errors (Error instances)
- Non-Error exceptions
- Unknown errors (null/undefined)
- Network errors
- Timeout errors
- Event Validation (2 tests)
- Required field validation
- Field preservation in result
- Video URL Handling (4 tests)
- URL presence for completed status
- URL absence for pending/processing/failed status
- Different Video ID and Course ID Combinations (2 tests)
- Long video IDs
- UUID-formatted IDs
- Timeout Behavior (2 tests)
- Timeout at exactly 20 polls
- No timeout at 19 polls
- Edge Cases (4 tests)
- Empty error messages
- Null video URLs
- Zero poll count
- Negative poll count
- Successful Video Generation Scenarios (2 tests)
- Immediate completion (poll count 0)
- Completion after multiple polls
Key Testing Patterns
// Mock HeyGen API response
mockGetVideoStatus.mockResolvedValue({
status: 'completed',
video_url: 'https://heygen.com/videos/video-123.mp4',
});
// Test event structure
const event: PollVideoStatusEvent = {
videoId: 'video-123',
courseId: 'course-456',
pollCount: 5,
};
// Verify result
expect(result).toEqual({
videoId: 'video-123',
courseId: 'course-456',
status: 'completed',
videoUrl: 'https://heygen.com/videos/video-123.mp4',
pollCount: 6,
});
2. /backend/functions/ai-generation/src/__tests__/handlers/update-course-video.test.ts
Unit tests for the update-course-video.ts handler, which updates course records with completed video URLs.
Total Tests: 31 Status: ✅ All Passing Coverage: 100%
Test Categories
- Happy Path - Successful Updates (5 tests)
- Update with completed video URL
- Update with failed status
- Null video URL handling
- Timestamp update verification
- Return of updated course data
- Error Handling - Missing Required Fields (3 tests)
- Missing courseId
- Missing videoStatus
- Empty videoUrl with failed status (allowed)
- Error Handling - Course Not Found (2 tests)
- Non-existent course error
- No videoUrl in error response
- Error Handling - Database Errors (5 tests)
- Database connection errors
- SQL syntax errors
- Unknown database errors
- Non-Error exceptions
- Null exceptions
- SQL Query Validation (2 tests)
- Correct column updates
- Correct return columns
- Different Video URL Formats (4 tests)
- Standard HTTPS URLs
- CDN URLs
- URLs with query parameters
- Very long URLs
- Different Course ID Formats (2 tests)
- UUID-formatted course IDs
- Short course IDs
- Video Status Values (2 tests)
- COMPLETED status
- FAILED status
- Result Structure Validation (3 tests)
- Success result structure
- Failure result structure
- No error field on success
- Edge Cases (3 tests)
- Empty string to null conversion
- Undefined to null conversion
- Event field preservation in errors
Key Testing Patterns
// Mock database query response
mockQuery.mockResolvedValue({
rows: [
{
id: 'course-123',
intro_video_url: 'https://heygen.com/videos/video-456.mp4',
intro_video_status: 'COMPLETED',
},
],
command: 'UPDATE',
rowCount: 1,
oid: 0,
fields: [],
});
// Test event structure
const event: UpdateCourseVideoEvent = {
courseId: 'course-123',
videoUrl: 'https://heygen.com/videos/video-456.mp4',
videoStatus: 'COMPLETED',
};
// Verify SQL query
expect(mockQuery).toHaveBeenCalledWith(
expect.stringContaining('UPDATE courses'),
['https://heygen.com/videos/video-456.mp4', 'COMPLETED', 'course-123']
);
// Verify result
expect(result).toEqual({
success: true,
courseId: 'course-123',
videoUrl: 'https://heygen.com/videos/video-456.mp4',
videoStatus: 'COMPLETED',
});
Test Coverage Summary
Both handlers achieve 100% code coverage across all metrics:
| Handler | Statements | Branches | Functions | Lines |
|---|---|---|---|---|
| poll-video-status.ts | 100% | 100% | 100% | 100% |
| update-course-video.ts | 100% | 100% | 100% | 100% |
Coverage Report Output
------------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
poll-video-status.ts | 100 | 100 | 100 | 100 |
update-course-video.ts | 100 | 100 | 100 | 100 |
------------------------|---------|----------|---------|---------|-------------------
Dependencies Mocked
Both test files properly mock all external dependencies:
poll-video-status.test.ts
../../services/heygen-client- MockgetVideoStatusfunction@aws-lambda-powertools/logger- Mock logger
update-course-video.test.ts
../../../../../shared/utils/database- Mockqueryfunction@aws-lambda-powertools/logger- Mock logger
Testing Approach
1. Comprehensive Edge Case Coverage
- Boundary conditions (max poll count, empty values)
- Error scenarios (API failures, database errors)
- Different data formats (UUID, long IDs, various URL formats)
- Null/undefined handling
2. Proper Mocking Strategy
- External dependencies isolated
- Consistent mock setup in
beforeEach - Clear mock expectations
- No actual API or database calls
3. Clear Test Organization
- Descriptive test suite names
- Logical grouping of related tests
- Consistent test structure (Arrange-Act-Assert)
- Meaningful test descriptions
4. Error Path Testing
- All error conditions covered
- Both Error and non-Error exceptions
- Graceful degradation
- Proper error message propagation
Running the Tests
Run Individual Test Files
cd backend/functions/ai-generation
# Poll video status tests
npx jest src/__tests__/handlers/poll-video-status.test.ts
# Update course video tests
npx jest src/__tests__/handlers/update-course-video.test.ts
Run Both Tests Together
npx jest src/__tests__/handlers/poll-video-status.test.ts src/__tests__/handlers/update-course-video.test.ts
Run with Coverage
npx jest src/__tests__/handlers/poll-video-status.test.ts src/__tests__/handlers/update-course-video.test.ts \
--coverage \
--collectCoverageFrom='src/handlers/poll-video-status.ts' \
--collectCoverageFrom='src/handlers/update-course-video.ts'
Run with Verbose Output
npx jest src/__tests__/handlers/poll-video-status.test.ts --verbose
npx jest src/__tests__/handlers/update-course-video.test.ts --verbose
Test Results
poll-video-status.test.ts
PASS src/__tests__/handlers/poll-video-status.test.ts
Poll Video Status Handler
Happy Path - Video Status Transitions
✓ should return pending status when video is still processing
✓ should return processing status with incremented poll count
✓ should return completed status with video URL
✓ should return failed status with error message from HeyGen
Poll Count Management
✓ should default pollCount to 0 when not provided
✓ should increment pollCount on each invocation
✓ should return timeout error when max poll count is reached
✓ should return timeout error when poll count exceeds max
✓ should still poll when pollCount is one below max
Error Handling
✓ should handle API errors gracefully
✓ should handle non-Error exceptions
✓ should handle unknown errors
✓ should handle network errors
✓ should handle timeout errors
Event Validation
✓ should handle event with all required fields
✓ should preserve videoId and courseId in result
Video URL Handling
✓ should return videoUrl when status is completed
✓ should not include videoUrl when status is pending
✓ should not include videoUrl when status is processing
✓ should not include videoUrl when status is failed
Different Video ID and Course ID Combinations
✓ should handle long video IDs
✓ should handle UUID-formatted IDs
Timeout Behavior
✓ should timeout after 20 polls (10 minutes)
✓ should not timeout at exactly 19 polls
Edge Cases
✓ should handle empty error from HeyGen
✓ should handle status with video_url as null
✓ should handle pollCount of 0
✓ should handle negative pollCount (edge case)
Successful Video Generation Scenarios
✓ should handle immediate completion (poll count 0)
✓ should handle completion after multiple polls
Test Suites: 1 passed, 1 total
Tests: 30 passed, 30 total
update-course-video.test.ts
PASS src/__tests__/handlers/update-course-video.test.ts
Update Course Video Handler
Happy Path - Successful Updates
✓ should update course with completed video URL
✓ should update course with failed status
✓ should set videoUrl to null when not provided
✓ should update timestamp to current time
✓ should return updated course data from database
Error Handling - Missing Required Fields
✓ should return error when courseId is missing
✓ should return error when videoStatus is missing
✓ should allow empty videoUrl with failed status
Error Handling - Course Not Found
✓ should return error when course does not exist
✓ should not return videoUrl when course not found
Error Handling - Database Errors
✓ should handle database connection errors
✓ should handle database query syntax errors
✓ should handle unknown database errors
✓ should handle non-Error exceptions
✓ should handle null exceptions
SQL Query Validation
✓ should update correct columns in database
✓ should return specified columns from database
Different Video URL Formats
✓ should handle standard HTTPS URLs
✓ should handle CDN URLs
✓ should handle URLs with query parameters
✓ should handle very long URLs
Different Course ID Formats
✓ should handle UUID-formatted course IDs
✓ should handle short course IDs
Video Status Values
✓ should handle COMPLETED status
✓ should handle FAILED status
Result Structure Validation
✓ should return all required fields on success
✓ should return all required fields on failure
✓ should not include error field on success
Edge Cases
✓ should handle empty string as videoUrl (converts to null)
✓ should handle undefined videoUrl (converts to null)
✓ should preserve original event courseId and videoStatus in error result
Test Suites: 1 passed, 1 total
Tests: 31 passed, 31 total
Combined Test Run
Test Suites: 2 passed, 2 total
Tests: 61 passed, 61 total
Snapshots: 0 total
Time: 0.859 s
Integration with CI/CD
These tests are automatically run as part of the project’s test suite:
# Full test suite
npm test
# Unit tests only
npm run test:unit
Test Maintenance
Adding New Test Cases
- Follow the existing test structure
- Use descriptive test names
- Group related tests in
describeblocks - Clear mock setup in
beforeEach - Verify coverage remains at 100%
Common Mock Patterns
HeyGen API Mock
mockGetVideoStatus.mockResolvedValue({
status: 'completed',
video_url: 'https://heygen.com/video.mp4',
});
Database Query Mock
mockQuery.mockResolvedValue({
rows: [{ id: 'course-123', intro_video_url: 'url', intro_video_status: 'COMPLETED' }],
command: 'UPDATE',
rowCount: 1,
oid: 0,
fields: [],
});
Error Mock
mockGetVideoStatus.mockRejectedValue(new Error('API unavailable'));
Quality Metrics
- ✅ 100% Code Coverage: All statements, branches, functions, and lines covered
- ✅ 61 Test Cases: Comprehensive test coverage
- ✅ All Tests Passing: No failures or skipped tests
- ✅ Fast Execution: All tests complete in < 1 second
- ✅ Proper Mocking: No external dependencies called
- ✅ TypeScript Compliance: Full type safety
- ✅ Clear Documentation: Well-documented test cases
- ✅ Edge Case Coverage: Boundary conditions and error paths tested
Related Files
Handlers Under Test
/backend/functions/ai-generation/src/handlers/poll-video-status.ts/backend/functions/ai-generation/src/handlers/update-course-video.ts
Dependencies
/backend/functions/ai-generation/src/services/heygen-client.ts/backend/shared/utils/database.ts
Step Functions Integration
These handlers are used in the video generation workflow:
- Poll video status: Polling step in Step Functions state machine
- Update course video: Final update step after video completion
Conclusion
These comprehensive unit tests ensure the reliability and correctness of the video generation polling and course update handlers. The 100% code coverage, extensive edge case testing, and proper mocking strategy provide confidence that these handlers will perform correctly in production.
The tests follow industry best practices:
- Clear, descriptive test names
- Proper test organization
- Comprehensive coverage
- Fast execution
- Maintainable structure
- Type-safe implementation
Last Updated: 2025-12-05 Maintained By: Momentum Development Team