UNPKG

illyria-scraper

Version:

Google Translate scraper for Illyria Translate

213 lines 9.14 kB
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import request, { Endpoint } from '../utils/request.js'; import axios from 'axios'; // Mock axios to avoid real network requests vi.mock('axios', () => ({ default: { get: vi.fn(), post: vi.fn() } })); describe('request utilities integration', () => { beforeEach(() => { vi.resetAllMocks(); }); afterEach(() => { vi.clearAllMocks(); }); describe('INFO endpoint', () => { it('should make proper POST requests to the info endpoint', async () => { const mockBody = 'f.req=mockData'; const mockResponse = { data: '\n\n\n[[[["wrb.fr","MkEWBc","mock data",null,null,null,"generic"]],["di",123],["af.httprm",123,"abcde",123]]]' }; axios.post.mockResolvedValue(mockResponse); const response = await request(Endpoint.INFO).with({ body: mockBody }) .promise; expect(axios.post).toHaveBeenCalledWith(expect.stringContaining('https://translate.google.com/_/TranslateWebserverUi/data/batchexecute?rpcids=MkEWBc'), mockBody, expect.objectContaining({ headers: expect.objectContaining({ 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': expect.any(String) }) })); expect(response).toEqual(mockResponse); }); it('should process INFO endpoint data correctly', async () => { const mockResponse = { data: '\n\n\n[[[["wrb.fr","MkEWBc","[[\\"test\\",\\"en\\",\\"fr\\",true],null]",null,null,null,"generic"]],["di",123],["af.httprm",123,"abcde",123]]]' }; axios.post.mockResolvedValue(mockResponse); const result = await request(Endpoint.INFO) .with({ body: 'f.req=mockData' }) .doing(({ data }) => { return { processedData: data ? 'processed' : 'empty' }; }); expect(result).toEqual({ processedData: 'processed' }); }); }); describe('TEXT endpoint', () => { it('should make proper GET requests to the text endpoint', async () => { const mockResponse = { data: '<div class="result-container">Translated text</div>' }; axios.get.mockResolvedValue(mockResponse); const response = await request(Endpoint.TEXT).with({ source: 'en', target: 'fr', query: 'test' }).promise; expect(axios.get).toHaveBeenCalledWith('https://translate.google.com/m?sl=en&tl=fr&q=test', expect.objectContaining({ headers: expect.objectContaining({ 'User-Agent': expect.any(String) }) })); expect(response).toEqual(mockResponse); }); it('should process TEXT endpoint data correctly', async () => { const mockResponse = { data: '<div class="result-container">Translated text</div>' }; axios.get.mockResolvedValue(mockResponse); const result = await request(Endpoint.TEXT) .with({ source: 'en', target: 'fr', query: 'test' }) .doing(({ data }) => { return data ? 'processed' : 'empty'; }); expect(result).toBe('processed'); }); }); describe('AUDIO endpoint', () => { it('should make proper GET requests to the audio endpoint', async () => { const mockResponse = { data: new ArrayBuffer(8) }; axios.get.mockResolvedValue(mockResponse); const response = await request(Endpoint.AUDIO).with({ lang: 'fr', text: 'bonjour', textLength: 7, speed: 1 }).promise; expect(axios.get).toHaveBeenCalledWith('https://translate.google.com/translate_tts?tl=fr&q=bonjour&textlen=7&speed=1&client=tw-ob', expect.objectContaining({ responseType: 'arraybuffer', timeout: 60000, headers: expect.objectContaining({ 'User-Agent': expect.any(String) }) })); expect(response).toEqual(mockResponse); }); it('should process AUDIO endpoint data correctly', async () => { const mockArrayBuffer = new ArrayBuffer(8); const mockUint8Array = new Uint8Array(mockArrayBuffer); mockUint8Array.set([1, 2, 3, 4, 5, 6, 7, 8]); const mockResponse = { data: mockArrayBuffer }; axios.get.mockResolvedValue(mockResponse); const result = await request(Endpoint.AUDIO) .with({ lang: 'fr', text: 'bonjour', textLength: 7, speed: 1 }) .doing(({ data }) => { return data ? 'has data' : 'no data'; }); expect(result).toBe('has data'); }); }); describe('error handling and retries', () => { it('should handle network errors and retry', async () => { // Mock a network error for the first call, then succeed const networkError = new Error('Network Error'); networkError.request = {} // Make it look like a network error ; axios.get .mockRejectedValueOnce(networkError) .mockResolvedValueOnce({ data: '<div class="result-container">Retry worked</div>' }); const consoleSpy = vi .spyOn(console, 'error') .mockImplementation(() => { }); const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { }); const result = await request(Endpoint.TEXT) .with({ source: 'en', target: 'fr', query: 'test' }) .doing(({ data }) => { return data ? 'success' : 'failure'; }); expect(axios.get).toHaveBeenCalledTimes(2); expect(consoleSpy).toHaveBeenCalled(); expect(warnSpy).toHaveBeenCalled(); expect(result).toBe('success'); consoleSpy.mockRestore(); warnSpy.mockRestore(); }); it('should handle empty results and retry', async () => { // First response is empty, second has data ; axios.get .mockResolvedValueOnce({ data: '' }) .mockResolvedValueOnce({ data: '<div class="result-container">Data on retry</div>' }); const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { }); const result = await request(Endpoint.TEXT) .with({ source: 'en', target: 'fr', query: 'test' }) .doing(({ data }) => data || null); expect(axios.get).toHaveBeenCalledTimes(2); expect(result).toBe('<div class="result-container">Data on retry</div>'); warnSpy.mockRestore(); }); it('should give up after max retries', async () => { // All requests fail with 500 error const serverError = new Error('Server Error'); serverError.response = { status: 500, data: 'Server Error' }; axios.get.mockRejectedValue(serverError); const consoleSpy = vi .spyOn(console, 'error') .mockImplementation(() => { }); const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { }); const result = await request(Endpoint.TEXT) .with({ source: 'en', target: 'fr', query: 'test' }) .doing(({ data }) => { return data ? 'success' : 'failure'; }); // Initial + 3 retries = 4 calls expect(axios.get).toHaveBeenCalledTimes(4); expect(consoleSpy).toHaveBeenCalledTimes(4); expect(warnSpy).toHaveBeenCalledTimes(3); expect(result).toBeNull(); consoleSpy.mockRestore(); warnSpy.mockRestore(); }); }); it('should throw error for invalid endpoint', async () => { // Use a try/catch approach instead of expect().rejects.toThrow() // because the error is thrown synchronously during the .with() call try { // @ts-ignore - Testing invalid endpoint await request('invalid').with({}).promise; expect.fail('Expected error to be thrown'); } catch (error) { expect(error).toBeInstanceOf(Error); expect(error.message).toBe('Invalid endpoint: invalid'); } }); }); //# sourceMappingURL=request.integration.test.js.map