This guide covers how to test your SofIA SDK integration, from verifying basic setup to automating tests in CI/CD pipelines.
Testing strategy overview
| Level | What to test | Tools |
|---|
| Manual verification | Component renders, props are accepted, debug logs appear | Browser DevTools |
| Unit tests | Callback functions, data transformations, template validation | Vitest, Jest |
| Integration tests | Component mounting, prop passing, event handling | Testing Library, Cypress |
| E2E tests | Full workflow from transcription to report | Playwright, Cypress |
Manual verification checklist
Before writing automated tests, verify the basics with debug="true":
Component renders
Open your page and confirm the SofIA widget appears. Check the console for [Sofia SDK] Configuration Error — if absent, props are valid.
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.
Generate button appears
If both template and templateid are set, the generate button should be visible. If missing, check template validation logs.
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
- Troubleshooting — solutions for common issues
- Error Reference — complete catalog of SDK error messages
- Migration Guide — upgrade from v0.x to v1.0