From 91f9bd944210afe4d6869cae3c6c20d8db0bf3c7 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 20 Feb 2025 11:04:41 -0600 Subject: [PATCH] Add mock LibreTranslate tests --- .../LibreTranslateTranslator.test.ts | 68 ++++++++++++++----- .../translators/LibreTranslateTranslator.ts | 25 +++++-- 2 files changed, 71 insertions(+), 22 deletions(-) diff --git a/packages/translators/LibreTranslateTranslator.test.ts b/packages/translators/LibreTranslateTranslator.test.ts index ca8c1d79..94da0ec0 100644 --- a/packages/translators/LibreTranslateTranslator.test.ts +++ b/packages/translators/LibreTranslateTranslator.test.ts @@ -1,21 +1,10 @@ -import { DittoConf } from '@ditto/conf'; import { detectLanguage } from '@ditto/lang'; import { assertEquals } from '@std/assert'; import { LibreTranslateTranslator } from './LibreTranslateTranslator.ts'; -const { - libretranslateBaseUrl: baseUrl, - libretranslateApiKey: apiKey, - translationProvider, -} = new DittoConf(Deno.env); - -const libretranslate = 'libretranslate'; - -Deno.test('LibreTranslate translation with source language omitted', { - ignore: !(translationProvider === libretranslate && apiKey), -}, async () => { - const translator = new LibreTranslateTranslator({ fetch: fetch, baseUrl, apiKey: apiKey! }); +Deno.test('LibreTranslate translation with source language omitted', async () => { + const translator = mockLibreTranslate(); const data = await translator.translate( [ @@ -33,10 +22,8 @@ Deno.test('LibreTranslate translation with source language omitted', { assertEquals(detectLanguage(data.results[2], 0), 'ca'); }); -Deno.test('LibreTranslate translation with source language set', { - ignore: !(translationProvider === libretranslate && apiKey), -}, async () => { - const translator = new LibreTranslateTranslator({ fetch: fetch, baseUrl, apiKey: apiKey! }); +Deno.test('LibreTranslate translation with source language set', async () => { + const translator = mockLibreTranslate(); const data = await translator.translate( [ @@ -53,3 +40,50 @@ Deno.test('LibreTranslate translation with source language set', { assertEquals(detectLanguage(data.results[1], 0), 'ca'); assertEquals(detectLanguage(data.results[2], 0), 'ca'); }); + +function mockLibreTranslate(): LibreTranslateTranslator { + return new LibreTranslateTranslator({ + apiKey: 'libretranslate', + fetch: async (input, init) => { + const req = new Request(input, init); + const body = await req.json(); + + switch (body.q) { + case 'Bom dia amigos': + return jsonResponse({ + detectedLanguage: { language: 'pt' }, + translatedText: 'Bon dia, amics.', + }); + case 'Meu nome é Patrick, um nome belo ou feio? A questão é mais profunda do que parece.': + return jsonResponse({ + detectedLanguage: { language: 'pt' }, + translatedText: 'Em dic Patrick, un nom molt o lleig? La pregunta és més profunda del que sembla.', + }); + case 'A respiração é mais importante do que comer e tomar agua.': + return jsonResponse({ + detectedLanguage: { language: 'pt' }, + translatedText: 'La respiració és més important que menjar i prendre aigua.', + }); + } + + return new Response(JSON.stringify({ error: 'Not found' }), { status: 404 }); + }, + }); +} + +interface LibreTranslateResponse { + translatedText: string; + detectedLanguage?: { + language: string; + }; +} + +function jsonResponse(json: LibreTranslateResponse): Response { + const body = JSON.stringify(json); + + return new Response(body, { + headers: { + 'Content-Type': 'application/json', + }, + }); +} diff --git a/packages/translators/LibreTranslateTranslator.ts b/packages/translators/LibreTranslateTranslator.ts index a8145223..cc978e90 100644 --- a/packages/translators/LibreTranslateTranslator.ts +++ b/packages/translators/LibreTranslateTranslator.ts @@ -71,12 +71,20 @@ export class LibreTranslateTranslator implements DittoTranslator { const response = await this.fetch(request); const json = await response.json(); - if (!response.ok) { - throw new Error(json['error']); - } - const data = LibreTranslateTranslator.schema().parse(json); - return data; + console.log(json); + + if (!response.ok) { + const result = LibreTranslateTranslator.errorSchema().safeParse(json); + + if (result.success) { + throw new Error(result.data.error); + } else { + throw new Error(`Unexpected LibreTranslate error: ${response.statusText} (${response.status})`); + } + } + + return LibreTranslateTranslator.schema().parse(json); } /** Libretranslate response schema. @@ -90,4 +98,11 @@ export class LibreTranslateTranslator implements DittoTranslator { }).optional(), }); } + + /** Libretranslate error response schema. */ + private static errorSchema() { + return z.object({ + error: z.string(), + }); + } }