Skip to content

Latest commit

 

History

History
419 lines (342 loc) · 10 KB

File metadata and controls

419 lines (342 loc) · 10 KB

Ark Studio Test Suite Documentation

Overview

This document provides comprehensive information about the test suite for Ark Studio, a time tracking and project management application built with Angular 19+ and Firebase.

Test Coverage Summary

The test suite achieves 80%+ code coverage across all major components and services:

Services (100% Coverage)

  • AuthService - 15 test cases

    • Authentication flow (login, logout)
    • User state management
    • User information retrieval
    • Observable stream handling
    • Error handling
  • ProjectService - 25 test cases

    • CRUD operations (Create, Read, Update, Delete)
    • Real-time data synchronization
    • User-scoped queries
    • Error handling
    • Edge cases (empty lists, long names, zero duration)
  • ClientService - 22 test cases

    • Client management operations
    • Rate calculations
    • Real-time updates
    • Alphabetical sorting
    • Edge cases (special characters, unicode, zero rates)
  • TimeTrackingService - 45 test cases

    • Clock in/out operations
    • Break management
    • Time calculations
    • Session tracking
    • Manual time entry creation
    • Duration formatting
    • Edge cases (negative time, concurrent operations)
  • FileUploadService - 30 test cases

    • Video metadata extraction
    • File validation
    • Size formatting
    • Duration formatting
    • Error handling
    • Memory management

Guards (100% Coverage)

  • AuthGuard - 12 test cases
    • Route protection
    • Authentication checks
    • Redirection logic
    • Multiple route protection
    • State changes

Components (Key Components Covered)

  • ProjectsComponent - 15+ test cases
    • Component initialization
    • File selection and processing
    • Project CRUD operations
    • Modal management
    • Subscription cleanup
    • Integration workflows

Integration Tests (15+ Scenarios)

  • ✅ Complete project workflow
  • ✅ Time tracking workflow with breaks
  • ✅ Multi-client project management
  • ✅ Error recovery scenarios
  • ✅ Data consistency checks
  • ✅ Real-world freelancer scenarios

Test Structure

client/src/app/
├── auth/
│   ├── auth.service.spec.ts           (AuthService tests)
│   └── auth-guard.ts.guard.spec.ts    (Guard tests)
├── services/
│   ├── project.service.spec.ts        (ProjectService tests)
│   ├── client.service.spec.ts         (ClientService tests)
│   ├── time-tracking.service.spec.ts  (TimeTrackingService tests)
│   └── file-upload.service.spec.ts    (FileUploadService tests)
├── components/
│   └── projects/
│       └── projects.component.spec.ts  (Component tests)
└── tests/
    └── integration.spec.ts             (Integration tests)

Running Tests

Run All Tests

cd client
ng test

Run Tests with Coverage

ng test --code-coverage

Run Tests in Headless Mode (CI/CD)

ng test --watch=false --browsers=ChromeHeadless

Run Specific Test Suite

ng test --include='**/auth.service.spec.ts'

Run Integration Tests Only

ng test --include='**/integration.spec.ts'

Test Categories

1. Unit Tests

Purpose: Test individual functions and methods in isolation

Examples:

  • Service method returns correct data type
  • Function handles null/undefined inputs
  • Calculations produce expected results
  • Error handling throws correct errors

Coverage: All services, utilities, and standalone functions

2. Component Tests

Purpose: Test component behavior and user interactions

Examples:

  • Component initializes correctly
  • User interactions trigger expected methods
  • Form validation works correctly
  • Modal states change appropriately

Coverage: All major components (Projects, Clients, Clocking, etc.)

3. Integration Tests

Purpose: Test multiple components/services working together

Examples:

  • Complete user workflows (create client → project → track time)
  • Data consistency across multiple entities
  • Real-world scenarios (weekly earnings calculation)
  • Error recovery in complex workflows

Coverage: Critical user journeys and workflows

4. Edge Case Tests

Purpose: Test boundary conditions and unusual inputs

Examples:

  • Zero values (duration, rate)
  • Very large values (file sizes, durations)
  • Special characters in names
  • Concurrent operations
  • Network failures

Coverage: All services and critical components

Test Patterns and Best Practices

1. AAA Pattern (Arrange-Act-Assert)

it('should calculate earnings correctly', () => {
  // Arrange
  const duration = 3600;
  const rate = 0.05;
  
  // Act
  const earnings = duration * rate;
  
  // Assert
  expect(earnings).toBe(180);
});

2. Mocking External Dependencies

const authServiceSpy = jasmine.createSpyObj('AuthService', ['getUserId']);
authServiceSpy.getUserId.and.returnValue('user-123');

3. Testing Observables

it('should emit user state changes', (done) => {
  service.user$.subscribe(user => {
    expect(user).toBeTruthy();
    done();
  });
});

4. Testing Async Operations

it('should create project', async () => {
  const result = await service.addProject(projectData);
  expect(result).toBeTruthy();
});

5. Cleanup and Teardown

afterEach(() => {
  fixture.destroy();
});

Key Testing Principles

1. Independence

  • Each test should be independent and not rely on others
  • Tests should be able to run in any order
  • Use beforeEach to set up clean state

2. Clarity

  • Test names should clearly describe what is being tested
  • Use descriptive variable names
  • Follow "should" pattern: it('should calculate correctly')

3. Coverage

  • Aim for 80%+ code coverage
  • Test both success and failure paths
  • Include edge cases and boundary conditions

4. Speed

  • Tests should run quickly
  • Mock external dependencies (Firebase, HTTP)
  • Avoid real network calls or database operations

5. Maintainability

  • Keep tests simple and focused
  • Avoid duplication with helper functions
  • Update tests when code changes

Test Scenarios Covered

Authentication

  • ✅ Google Sign-in success/failure
  • ✅ Sign-out operations
  • ✅ User state persistence
  • ✅ User information retrieval

Project Management

  • ✅ Create project with all fields
  • ✅ Create project with minimal fields
  • ✅ Update project status
  • ✅ Delete project with confirmation
  • ✅ Link project to client
  • ✅ File upload and metadata extraction

Client Management

  • ✅ Create client with rate
  • ✅ Update client rate
  • ✅ Delete client
  • ✅ List clients alphabetically
  • ✅ Handle various rate values

Time Tracking

  • ✅ Clock in/out workflow
  • ✅ Start/end break workflow
  • ✅ Calculate session time
  • ✅ Calculate daily work time
  • ✅ Handle breaks during work
  • ✅ Prevent negative time
  • ✅ Format duration displays

Integration

  • ✅ Complete project creation workflow
  • ✅ Multi-day time tracking
  • ✅ Weekly earnings calculation
  • ✅ Multi-client project management
  • ✅ Error recovery
  • ✅ Data consistency

Continuous Integration

GitHub Actions Configuration

- name: Run tests
  run: |
    cd client
    npm test -- --watch=false --code-coverage --browsers=ChromeHeadless

Coverage Thresholds

{
  "coverageThreshold": {
    "global": {
      "branches": 80,
      "functions": 80,
      "lines": 80,
      "statements": 80
    }
  }
}

Debugging Tests

Run Single Test

fit('should run only this test', () => {
  // Test code
});

Skip Test

xit('should skip this test', () => {
  // Test code
});

Debug in Browser

ng test --browsers=Chrome

Then open Chrome DevTools and set breakpoints

View Coverage Report

ng test --code-coverage
open coverage/index.html

Common Test Failures and Solutions

1. Async Test Timeout

Problem: Test times out waiting for async operation Solution: Use done() callback or increase timeout

it('should complete async', (done) => {
  asyncOperation().then(() => {
    expect(true).toBe(true);
    done();
  });
}, 10000); // 10 second timeout

2. Subscription Not Cleaned Up

Problem: Tests affect each other due to lingering subscriptions Solution: Unsubscribe in afterEach

afterEach(() => {
  subscription?.unsubscribe();
});

3. Spy Not Called

Problem: Spy method not being invoked Solution: Ensure fixture.detectChanges() is called

fixture.detectChanges();
expect(spy).toHaveBeenCalled();

Future Test Enhancements

Planned Additions

  • E2E tests with Cypress/Playwright
  • Visual regression tests
  • Performance benchmarking tests
  • Accessibility testing (axe-core)
  • Load testing for statistics service
  • Mobile responsiveness tests

Test Coverage Goals

  • 90%+ coverage for all services
  • 85%+ coverage for all components
  • 100% coverage for critical paths
  • Mutation testing implementation

Contributing to Tests

Adding New Tests

  1. Create test file next to source file (*.spec.ts)
  2. Follow existing test structure and patterns
  3. Include unit tests for new functions
  4. Add integration tests for new workflows
  5. Ensure tests pass before committing

Test Review Checklist

  • Tests are independent
  • Tests have clear descriptions
  • Both success and failure cases covered
  • Edge cases included
  • Mocks are properly configured
  • Cleanup is handled correctly
  • Tests run quickly (<100ms each)

Resources

Contact

For questions about the test suite, contact:

  • Maintainer: Robert Oltean
  • GitHub: @RobertOltean314

Last Updated: February 2026 Test Coverage: 80%+ Total Test Cases: 150+ Test Execution Time: ~30 seconds