Sanjeev Satheesh
Sanjeev Satheesh

Reputation: 424

Unittesting the SpeechRecognition API

The webkitSpeechRecognition api is very much a blackbox to unit test

It looks like I have to speak into the browser if I want to test the api. Is anyone aware of alternate ways of testing a workflow which uses this api?

Upvotes: 0

Views: 1373

Answers (1)

Tal Ater
Tal Ater

Reputation: 1189

Try Corti which replaces the browser's SpeechRecognition (or webkitSpeechRecognition) with a mock object.

This mock of the Speech Recognition API replicates the native functionality and adds some other helpful methods to make automated testing easier (e.g. a say() method to programmatically emulate speech input).

You can install it with:

npm install corti

Once installed, you can use it in tests written in any testing framework, in Node.js, or in the browser.

Sample ESM code using Vitest:

import { SpeechRecognition } from 'corti';
import { describe, it, expect, beforeEach, beforeAll, afterAll, vi } from 'vitest';

beforeAll(() => {
  vi.stubGlobal('SpeechRecognition', SpeechRecognition);
});

afterAll(() => {
  vi.unstubAllGlobals();
});

describe('Mirror mirror on the wall', () => {
  let recognition;
  let spyFn;

  beforeEach(() => {
    recognition = new globalThis.SpeechRecognition();
    spyFn = vi.fn();
    recognition.maxAlternatives = 5;
    recognition.onresult = spyFn;
    recognition.start();
  });

  it('should call callback when called with a single sentence', () => {
    recognition.say('Hello world');
    expect(spyFn).toHaveBeenCalled();
    const event = spyFn.mock.calls[0][0];
    expect(event.results[0][0].transcript).toBe('Hello world');
  });

  it('should call callback when called with multiple sentences', () => {
    recognition.say(['Hello world', 'How are you?']);
    expect(spyFn).toHaveBeenCalled();
    const event = spyFn.mock.calls[0][0];
    expect(event.results[0][0].transcript).toBe('Hello world');
    expect(event.results[0][1].transcript).toBe('How are you?');
  });
});

Sample CJS code using Jest:

const { SpeechRecognition } = require('corti');

beforeAll(() => {
  global.SpeechRecognition = SpeechRecognition;
});

test('SpeechRecognition', () => {
  const speech = new globalThis.SpeechRecognition();
  const spyFn = jest.fn();
  speech.onresult = spyFn;
  speech.continuous = true;
  speech.start();
  speech.say('Hello world');
  speech.say('Hello world');
  expect(spyFn.mock.calls.length).toBe(2);
});

Upvotes: 1

Related Questions