Files
Hoan Luu HuuandClaude Opus 5 baf80cb84c fix: speechmatics credential test ignored the configured region (#563)
The speechmatics branch of the /test route destructured only api_key out of the
decrypted credential, so testSpeechmaticsStt() passed realtimeUrl: undefined to
the sdk. ConnectionConfigFull only applies an override when the value is truthy,
so every credential was silently tested against wss://eu2.rt.speechmatics.com/v2
no matter which region was stored - a neu or wus key was judged by whatever eu2
happened to answer.

- pass speechmatics_stt_uri through from the route
- normalize it before handing it to the sdk. The field holds a bare hostname,
  which the sdk cannot use as-is: it appends the language, yielding
  "eu2.rt.speechmatics.com/en" and ERR_INVALID_URL. At call time the same value
  goes to mod_speechmatics_transcribe as SPEECHMATICS_HOST, which always
  connects over wss on port 443 with a path of /v2, so build exactly that url.
  Anything else - a full ws url, a port - now fails the test with an actionable
  message rather than passing against an endpoint only the test can reach, and a
  credential that has lost the field fails too: the feature server omits
  SPEECHMATICS_HOST when it is unset and the module refuses the session, so
  defaulting to a hosted region here would show a green check on a dead
  credential.
- record the speechmatics STT result with sttTestResult(), not ttsTestResult(),
  which is what every other STT vendor in this file does; the tts column was
  being stamped for an STT-only vendor

Adds coverage for the url building to the main test suite - it is the part of
this that can be exercised without an api key.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-14 11:06:28 -04:00

36 lines
1.5 KiB
JavaScript

const test = require('tape');
const {speechmaticsRealtimeUrl} = require('../lib/utils/speech-utils');
/* the runtime hands speechmatics_stt_uri to mod_speechmatics_transcribe as a bare hostname and
always dials wss on 443 with a path of /v2, so anything else must fail the credential test
rather than pass against a url only the test can reach
*/
test('speechmatics-url', (t) => {
t.equal(speechmaticsRealtimeUrl('eu2.rt.speechmatics.com'),
'wss://eu2.rt.speechmatics.com/v2', 'builds the url the runtime dials');
t.equal(speechmaticsRealtimeUrl('wus.rt.speechmatics.com'),
'wss://wus.rt.speechmatics.com/v2', 'honors the configured region');
t.equal(speechmaticsRealtimeUrl('sm-container.internal'),
'wss://sm-container.internal/v2', 'accepts an on-prem hostname');
t.equal(speechmaticsRealtimeUrl(' neu.rt.speechmatics.com '),
'wss://neu.rt.speechmatics.com/v2', 'trims surrounding whitespace');
for (const uri of [undefined, null, '', ' ']) {
t.throws(() => speechmaticsRealtimeUrl(uri), /is not set on this speech credential/,
`rejects a credential with no host: ${JSON.stringify(uri)}`);
}
for (const uri of [
'wss://eu2.rt.speechmatics.com/v2',
'https://eu2.rt.speechmatics.com',
'sm-container.internal:9000',
'eu2.rt.speechmatics.com/v2',
'my host'
]) {
t.throws(() => speechmaticsRealtimeUrl(uri), /expected a bare hostname/,
`rejects a shape the runtime cannot dial: ${uri}`);
}
t.end();
});