@@ -2,137 +2,78 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
22import { translateWordWithGoogle } from './translate' ;
33import type { TranslationResult } from '@/lib/domain/translation' ;
44
5- // Mock the global fetch function
65global . fetch = vi . fn ( ) ;
76
8- const mockFetch = ( status : number , body : unknown ) => {
9- vi . mocked ( fetch ) . mockResolvedValue ( {
10- ok : status >= 200 && status < 300 ,
11- status,
12- json : async ( ) => body ,
13- } as Response ) ;
14- } ;
15-
16- const mockFetchError = ( error : Error ) => {
17- vi . mocked ( fetch ) . mockRejectedValue ( error ) ;
18- } ;
19-
207describe ( 'translateWordWithGoogle' , ( ) => {
218 const originalEnv = process . env ;
229
2310 beforeEach ( ( ) => {
24- vi . resetModules ( ) ; // Reset modules to clear cache if needed
25- process . env = { ...originalEnv } ; // Clone env
26- vi . clearAllMocks ( ) ; // Clear mocks between tests
27- process . env [ 'GOOGLE_TRANSLATE_API_KEY' ] = 'test-api-key' ; // Set default test key
11+ vi . resetModules ( ) ;
12+ process . env = { ...originalEnv } ;
13+ vi . clearAllMocks ( ) ;
14+ process . env [ 'GOOGLE_TRANSLATE_API_KEY' ] = 'test-api-key' ;
2815 } ) ;
2916
3017 afterEach ( ( ) => {
31- process . env = originalEnv ; // Restore original env
18+ process . env = originalEnv ;
3219 } ) ;
3320
34- it ( 'should return null if word is missing' , async ( ) => {
35- const result = await translateWordWithGoogle ( '' , 'es' , 'en' ) ;
36- expect ( result ) . toBeNull ( ) ;
21+ it ( 'returns null if word is missing' , async ( ) => {
22+ expect ( await translateWordWithGoogle ( '' , 'es' , 'en' ) ) . toBeNull ( ) ;
3723 expect ( fetch ) . not . toHaveBeenCalled ( ) ;
3824 } ) ;
3925
40- it ( 'should return null if targetLang is missing' , async ( ) => {
41- const result = await translateWordWithGoogle ( 'hello' , '' , 'en' ) ;
42- expect ( result ) . toBeNull ( ) ;
26+ it ( 'returns null if targetLang is missing' , async ( ) => {
27+ expect ( await translateWordWithGoogle ( 'hello' , '' , 'en' ) ) . toBeNull ( ) ;
4328 expect ( fetch ) . not . toHaveBeenCalled ( ) ;
4429 } ) ;
4530
46- it ( 'should return null if sourceLang is missing' , async ( ) => {
47- // Note: sourceLang is optional in the call, but required logic inside
48- const result = await translateWordWithGoogle ( 'hello' , 'es' , '' ) ;
49- expect ( result ) . toBeNull ( ) ;
31+ it ( 'returns null if sourceLang is missing' , async ( ) => {
32+ expect ( await translateWordWithGoogle ( 'hello' , 'es' , '' ) ) . toBeNull ( ) ;
5033 expect ( fetch ) . not . toHaveBeenCalled ( ) ;
5134 } ) ;
5235
53- it ( 'should return null if GOOGLE_TRANSLATE_API_KEY is not configured' , async ( ) => {
36+ it ( 'returns null if GOOGLE_TRANSLATE_API_KEY is not configured' , async ( ) => {
5437 delete process . env [ 'GOOGLE_TRANSLATE_API_KEY' ] ;
55- const result = await translateWordWithGoogle ( 'hello' , 'es' , 'en' ) ;
56- expect ( result ) . toBeNull ( ) ;
38+ expect ( await translateWordWithGoogle ( 'hello' , 'es' , 'en' ) ) . toBeNull ( ) ;
5739 expect ( fetch ) . not . toHaveBeenCalled ( ) ;
5840 } ) ;
5941
60- it ( 'should return translation result on successful API call' , async ( ) => {
61- const mockResponse = {
62- data : {
63- translations : [ { translatedText : 'hola' } ] ,
64- } ,
65- } ;
66- mockFetch ( 200 , mockResponse ) ;
67-
68- const expectedResult : TranslationResult = {
69- translation : 'hola' ,
70- romanization : '' ,
71- } ;
42+ it ( 'returns translation result on success' , async ( ) => {
43+ vi . mocked ( fetch ) . mockResolvedValue ( {
44+ ok : true ,
45+ status : 200 ,
46+ json : async ( ) => ( { data : { translations : [ { translatedText : 'hola' } ] } } ) ,
47+ } as Response ) ;
48+ const expected : TranslationResult = { translation : 'hola' , romanization : '' } ;
7249 const result = await translateWordWithGoogle ( 'hello' , 'es' , 'en' ) ;
73-
74- expect ( fetch ) . toHaveBeenCalledTimes ( 1 ) ;
75- expect ( fetch ) . toHaveBeenCalledWith (
76- expect . stringContaining (
77- 'https://translation.googleapis.com/language/translate/v2?key=test-api-key'
78- ) ,
79- expect . objectContaining ( {
80- method : 'POST' ,
81- headers : { 'Content-Type' : 'application/json' } ,
82- body : JSON . stringify ( { q : 'hello' , target : 'es' , format : 'text' , source : 'en' } ) ,
83- } )
84- ) ;
85- expect ( result ) . toEqual ( expectedResult ) ;
86- } ) ;
87-
88- it ( 'should handle API response with error object' , async ( ) => {
89- const mockErrorResponse = {
90- error : {
91- code : 400 ,
92- message : 'Invalid target language' ,
93- errors : [ { message : 'Invalid Value' , domain : 'global' , reason : 'invalid' } ] ,
94- } ,
95- } ;
96- mockFetch ( 400 , mockErrorResponse ) ;
97-
98- const result = await translateWordWithGoogle ( 'hello' , 'xx' , 'en' ) ;
99- expect ( result ) . toBeNull ( ) ;
10050 expect ( fetch ) . toHaveBeenCalledTimes ( 1 ) ;
51+ expect ( result ) . toEqual ( expected ) ;
10152 } ) ;
10253
103- it ( 'should handle API response with non-ok status but no error object' , async ( ) => {
104- mockFetch ( 500 , { message : 'Internal Server Error' } ) ; // Simulate server error with generic message
105-
106- const result = await translateWordWithGoogle ( 'hello' , 'es' , 'en' ) ;
107- expect ( result ) . toBeNull ( ) ;
54+ it ( 'returns null if API error object' , async ( ) => {
55+ vi . mocked ( fetch ) . mockResolvedValue ( {
56+ ok : false ,
57+ status : 400 ,
58+ json : async ( ) => ( { error : { code : 400 } } ) ,
59+ } as Response ) ;
60+ expect ( await translateWordWithGoogle ( 'hello' , 'xx' , 'en' ) ) . toBeNull ( ) ;
10861 expect ( fetch ) . toHaveBeenCalledTimes ( 1 ) ;
10962 } ) ;
11063
111- it ( 'should return null if API response has no translations' , async ( ) => {
112- const mockResponse = {
113- data : {
114- translations : [ ] , // Empty translations array
115- } ,
116- } ;
117- mockFetch ( 200 , mockResponse ) ;
118-
119- const result = await translateWordWithGoogle ( 'hello' , 'es' , 'en' ) ;
120- expect ( result ) . toBeNull ( ) ;
64+ it ( 'returns null if API response has no translations' , async ( ) => {
65+ vi . mocked ( fetch ) . mockResolvedValue ( {
66+ ok : true ,
67+ status : 200 ,
68+ json : async ( ) => ( { data : { translations : [ ] } } ) ,
69+ } as Response ) ;
70+ expect ( await translateWordWithGoogle ( 'hello' , 'es' , 'en' ) ) . toBeNull ( ) ;
12171 expect ( fetch ) . toHaveBeenCalledTimes ( 1 ) ;
12272 } ) ;
12373
124- it ( 'should return null if fetch throws an error' , async ( ) => {
125- mockFetchError ( new Error ( 'Network failure' ) ) ;
126-
127- const result = await translateWordWithGoogle ( 'hello' , 'es' , 'en' ) ;
128- expect ( result ) . toBeNull ( ) ;
74+ it ( 'returns null if fetch throws' , async ( ) => {
75+ vi . mocked ( fetch ) . mockRejectedValue ( new Error ( 'fail' ) ) ;
76+ expect ( await translateWordWithGoogle ( 'hello' , 'es' , 'en' ) ) . toBeNull ( ) ;
12977 expect ( fetch ) . toHaveBeenCalledTimes ( 1 ) ;
13078 } ) ;
131-
132- it ( 'should call API without source language if provided as empty string initially (but fails validation)' , async ( ) => {
133- // This test primarily checks the internal logic flow before validation catches it
134- const result = await translateWordWithGoogle ( 'hello' , 'es' , '' ) ;
135- expect ( result ) . toBeNull ( ) ; // Fails validation before API call
136- expect ( fetch ) . not . toHaveBeenCalled ( ) ;
137- } ) ;
13879} ) ;
0 commit comments