Skip to main content
This guide covers how to test your SofIA SDK integration, from verifying basic setup to automating tests in CI/CD pipelines.

Testing strategy overview

LevelWhat to testTools
Manual verificationComponent renders, props are accepted, debug logs appearBrowser DevTools
Unit testsCallback functions, data transformations, template validationVitest, Jest
Integration testsComponent mounting, prop passing, event handlingTesting Library, Cypress
E2E testsFull workflow from transcription to reportPlaywright, Cypress

Manual verification checklist

Before writing automated tests, verify the basics with debug="true":
1

Component renders

Open your page and confirm the SofIA widget appears. Check the console for [Sofia SDK] Configuration Error — if absent, props are valid.
2

Template loads

Look for [Sofia SDK] Settings - Template loaded: {n} fields in the console. If n matches your expected field count, the template parsed correctly.
3

Generate button appears

If both template and templateid are set, the generate button should be visible. If missing, check template validation logs.
4

handleReport fires

Click Generate after a conversation and verify your handleReport callback receives data. Log the output with JSON.stringify(report, null, 2).

Unit testing callbacks

Test your callback functions independently from the SDK. These tests verify that your application correctly processes the data SofIA delivers.

Testing handleReport

import { describe, it, expect, vi } from 'vitest';

// Your application's report handler
function processReport(report) {
  if (!report || Object.keys(report).length === 0) {
    throw new Error('Empty report received');
  }

  return {
    diagnosis: report.primary_diagnosis || null,
    symptoms: report.symptoms || [],
    timestamp: new Date().toISOString(),
  };
}

describe('processReport', () => {
  it('should extract diagnosis from report', () => {
    const mockReport = {
      primary_diagnosis: 'Type 2 Diabetes Mellitus',
      symptoms: ['polyuria', 'polydipsia', 'fatigue'],
    };

    const result = processReport(mockReport);

    expect(result.diagnosis).toBe('Type 2 Diabetes Mellitus');
    expect(result.symptoms).toHaveLength(3);
    expect(result.timestamp).toBeDefined();
  });

  it('should handle missing optional fields', () => {
    const mockReport = {
      primary_diagnosis: 'Hypertension',
    };

    const result = processReport(mockReport);

    expect(result.diagnosis).toBe('Hypertension');
    expect(result.symptoms).toEqual([]);
  });

  it('should throw on empty report', () => {
    expect(() => processReport({})).toThrow('Empty report received');
  });
});

Testing template validation

import { describe, it, expect } from 'vitest';

function isValidTemplate(template) {
  try {
    const schema = typeof template === 'string' ? JSON.parse(template) : template;
    return (
      schema.$schema === 'http://json-schema.org/draft-07/schema#' &&
      schema.type === 'object' &&
      schema.properties &&
      Object.keys(schema.properties).length > 0
    );
  } catch {
    return false;
  }
}

describe('isValidTemplate', () => {
  it('should accept valid JSON Schema Draft-07', () => {
    const template = JSON.stringify({
      $schema: 'http://json-schema.org/draft-07/schema#',
      title: 'test',
      type: 'object',
      properties: {
        diagnosis: { type: 'string' },
      },
    });

    expect(isValidTemplate(template)).toBe(true);
  });

  it('should reject schema without properties', () => {
    const template = JSON.stringify({
      $schema: 'http://json-schema.org/draft-07/schema#',
      type: 'object',
      properties: {},
    });

    expect(isValidTemplate(template)).toBe(false);
  });

  it('should reject invalid JSON', () => {
    expect(isValidTemplate('{invalid')).toBe(false);
  });
});

Integration testing

Testing component mounting (Vanilla JS)

import { describe, it, expect, beforeEach, afterEach } from 'vitest';

describe('SofIA SDK mounting', () => {
  let container;

  beforeEach(() => {
    container = document.createElement('div');
    document.body.appendChild(container);
  });

  afterEach(() => {
    container.remove();
  });

  it('should mount with required props', async () => {
    container.innerHTML = `
      <sofia-sdk
        baseurl="https://api.test.com"
        wssurl="wss://ws.test.com"
        apikey="test-key"
        userid="doctor-1"
        patientid="patient-1"
      ></sofia-sdk>
    `;

    const sofia = container.querySelector('sofia-sdk');
    expect(sofia).not.toBeNull();
  });

  it('should accept handleReport callback', async () => {
    container.innerHTML = '<sofia-sdk></sofia-sdk>';
    const sofia = container.querySelector('sofia-sdk');

    const handleReport = vi.fn();
    sofia.handleReport = handleReport;

    expect(sofia.handleReport).toBe(handleReport);
  });
});

Testing with React

import { render, screen } from '@testing-library/react';
import { useRef, useEffect } from 'react';
import { describe, it, expect, vi } from 'vitest';

function SofiaWrapper({ onReport, template, templateId }) {
  const ref = useRef(null);

  useEffect(() => {
    if (ref.current) {
      ref.current.handleReport = onReport;
    }
  }, [onReport]);

  return (
    <sofia-sdk
      ref={ref}
      baseurl="https://api.test.com"
      wssurl="wss://ws.test.com"
      apikey="test-key"
      userid="doctor-1"
      patientid="patient-1"
      template={template}
      templateid={templateId}
    />
  );
}

describe('SofiaWrapper', () => {
  it('should render without crashing', () => {
    const handleReport = vi.fn();
    render(<SofiaWrapper onReport={handleReport} />);

    // Component renders without throwing
    expect(document.querySelector('sofia-sdk')).not.toBeNull();
  });

  it('should assign handleReport callback', () => {
    const handleReport = vi.fn();
    render(<SofiaWrapper onReport={handleReport} />);

    const sofia = document.querySelector('sofia-sdk');
    expect(sofia.handleReport).toBe(handleReport);
  });
});

Testing with Angular

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { SofiaComponent } from './sofia.component';

describe('SofiaComponent', () => {
  let component: SofiaComponent;
  let fixture: ComponentFixture<SofiaComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [SofiaComponent],
      schemas: [CUSTOM_ELEMENTS_SCHEMA], // Required for web components
    }).compileComponents();

    fixture = TestBed.createComponent(SofiaComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should have sofia-sdk element in template', () => {
    const compiled = fixture.nativeElement;
    expect(compiled.querySelector('sofia-sdk')).not.toBeNull();
  });
});

Mocking the SDK for CI/CD

In CI environments where the SDK cannot connect to real servers, mock the web component to test your integration logic:
// test/mocks/sofia-sdk-mock.js

class MockSofiaSDK extends HTMLElement {
  constructor() {
    super();
    this._handleReport = null;
  }

  set handleReport(fn) {
    this._handleReport = fn;
  }

  get handleReport() {
    return this._handleReport;
  }

  // Simulate report generation for testing
  simulateReport(report) {
    if (this._handleReport) {
      this._handleReport(report);
    }
    this.dispatchEvent(new CustomEvent('handle-report', {
      detail: report,
      bubbles: true,
      composed: true,
    }));
  }
}

// Register mock before tests
if (!customElements.get('sofia-sdk')) {
  customElements.define('sofia-sdk', MockSofiaSDK);
}
Using the mock in tests:
import './mocks/sofia-sdk-mock.js';
import { describe, it, expect, vi } from 'vitest';

describe('Report processing with mock SDK', () => {
  it('should process simulated report', () => {
    const container = document.createElement('div');
    container.innerHTML = '<sofia-sdk></sofia-sdk>';
    document.body.appendChild(container);

    const sofia = container.querySelector('sofia-sdk');
    const handleReport = vi.fn();
    sofia.handleReport = handleReport;

    // Simulate the SDK generating a report
    sofia.simulateReport({
      primary_diagnosis: 'Acute bronchitis',
      symptoms: ['cough', 'fever'],
    });

    expect(handleReport).toHaveBeenCalledWith({
      primary_diagnosis: 'Acute bronchitis',
      symptoms: ['cough', 'fever'],
    });

    container.remove();
  });
});

Testing custom events

The SDK emits custom DOM events that can be tested directly:
import { describe, it, expect, vi } from 'vitest';

describe('SDK custom events', () => {
  it('should listen for handle-report event', () => {
    const container = document.createElement('div');
    container.innerHTML = '<sofia-sdk></sofia-sdk>';
    document.body.appendChild(container);

    const sofia = container.querySelector('sofia-sdk');
    const listener = vi.fn();

    sofia.addEventListener('handle-report', (e) => {
      listener(e.detail);
    });

    // Simulate the event
    sofia.dispatchEvent(new CustomEvent('handle-report', {
      detail: { diagnosis: 'Test' },
      bubbles: true,
      composed: true,
    }));

    expect(listener).toHaveBeenCalledWith({ diagnosis: 'Test' });

    container.remove();
  });
});

Test environment configuration

Vitest configuration

// vitest.config.js
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    environment: 'jsdom', // Required for DOM APIs
    globals: true,
    setupFiles: ['./test/setup.js'],
  },
});

Setup file

// test/setup.js

// Register mock SDK before all tests
import './mocks/sofia-sdk-mock.js';

// Suppress console warnings from SDK in test output
const originalWarn = console.warn;
console.warn = (...args) => {
  if (args[0]?.includes?.('[Sofia SDK]')) return;
  originalWarn(...args);
};
Focus your automated tests on your integration code (callbacks, data transformations, UI updates), not on the SDK internals. The SDK is tested internally with 160+ test cases. Your tests should verify that your application correctly processes the data SofIA delivers.

Next steps

  1. Troubleshooting — solutions for common issues
  2. Error Reference — complete catalog of SDK error messages
  3. Migration Guide — upgrade from v0.x to v1.0