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

  1. 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
  2. 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
  3. Error Handling (5 tests)
    • API errors (Error instances)
    • Non-Error exceptions
    • Unknown errors (null/undefined)
    • Network errors
    • Timeout errors
  4. Event Validation (2 tests)
    • Required field validation
    • Field preservation in result
  5. Video URL Handling (4 tests)
    • URL presence for completed status
    • URL absence for pending/processing/failed status
  6. Different Video ID and Course ID Combinations (2 tests)
    • Long video IDs
    • UUID-formatted IDs
  7. Timeout Behavior (2 tests)
    • Timeout at exactly 20 polls
    • No timeout at 19 polls
  8. Edge Cases (4 tests)
    • Empty error messages
    • Null video URLs
    • Zero poll count
    • Negative poll count
  9. 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

  1. 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
  2. Error Handling - Missing Required Fields (3 tests)
    • Missing courseId
    • Missing videoStatus
    • Empty videoUrl with failed status (allowed)
  3. Error Handling - Course Not Found (2 tests)
    • Non-existent course error
    • No videoUrl in error response
  4. Error Handling - Database Errors (5 tests)
    • Database connection errors
    • SQL syntax errors
    • Unknown database errors
    • Non-Error exceptions
    • Null exceptions
  5. SQL Query Validation (2 tests)
    • Correct column updates
    • Correct return columns
  6. Different Video URL Formats (4 tests)
    • Standard HTTPS URLs
    • CDN URLs
    • URLs with query parameters
    • Very long URLs
  7. Different Course ID Formats (2 tests)
    • UUID-formatted course IDs
    • Short course IDs
  8. Video Status Values (2 tests)
    • COMPLETED status
    • FAILED status
  9. Result Structure Validation (3 tests)
    • Success result structure
    • Failure result structure
    • No error field on success
  10. 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 - Mock getVideoStatus function
  • @aws-lambda-powertools/logger - Mock logger

update-course-video.test.ts

  • ../../../../../shared/utils/database - Mock query function
  • @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

  1. Follow the existing test structure
  2. Use descriptive test names
  3. Group related tests in describe blocks
  4. Clear mock setup in beforeEach
  5. 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

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


Back to top

Momentum LMS © 2025. Distributed under the MIT license.