webstreamr/src/utils/Fetcher.test.ts
2025-05-29 18:32:06 +00:00

92 lines
3.3 KiB
TypeScript

import winston from 'winston';
import axios, { AxiosError } from 'axios';
import AxiosMockAdapter from 'axios-mock-adapter';
import { Fetcher } from './Fetcher';
import { Context } from '../types';
import { CloudflareChallengeError, NotFoundError } from '../error';
const axiosMock = new AxiosMockAdapter(axios);
const fetcher = new Fetcher(axios, winston.createLogger({ transports: [new winston.transports.Console({ level: 'nope' })] }));
describe('fetch', () => {
const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { de: 'on' } };
test('text passes successful response through setting headers', async () => {
axiosMock.onGet().reply(200, 'some text');
const axiosSpy = jest.spyOn(axios, 'get');
const responseText1 = await fetcher.text(ctx, new URL('https://some-url.test/'));
const responseText2 = await fetcher.text(ctx, new URL('https://some-url.test/'), { headers: { 'User-Agent': 'jest' } });
expect(responseText1).toBe('some text');
expect(responseText2).toStrictEqual(responseText1);
expect(axiosSpy).toHaveBeenCalledWith(
'https://some-url.test/',
{
headers: {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en',
'Forwarded': 'for=127.0.0.1',
'Origin': 'https://some-url.test',
'Priority': 'u=0',
'Referer': 'https://some-url.test',
'User-Agent': expect.not.stringMatching(/jest/),
'X-Forwarded-For': '127.0.0.1',
'X-Forwarded-Proto': 'https',
'X-Real-IP': '127.0.0.1',
},
responseType: 'text',
timeout: 5000,
},
);
});
test('textPost ', async () => {
axiosMock.onPost().reply(200, 'some text');
expect(await fetcher.textPost(ctx, new URL('https://some-url.test/'), { foo: 'bar' })).toBe('some text');
});
test('head', async () => {
axiosMock.onHead().reply(200, undefined, { 'X-Fake-Response': 'foo' });
expect(await fetcher.head(ctx, new URL('https://some-url.test/'))).toMatchObject({ 'X-Fake-Response': 'foo' });
});
test('uses context referer', async () => {
axiosMock.onGet().reply(200, 'some text');
const axiosSpy = jest.spyOn(axios, 'get');
await fetcher.text({ ...ctx, referer: new URL('https://example.com/foo/bar') }, new URL('https://some-url.test/'));
expect(axiosSpy).toHaveBeenCalledWith(
'https://some-url.test/',
expect.objectContaining({
headers: expect.objectContaining({
Origin: 'https://example.com',
Referer: 'https://example.com/foo/bar',
}),
}),
);
});
test('converts 404 to custom NotFoundError', async () => {
axiosMock.onGet().reply(404);
await expect(fetcher.text(ctx, new URL('https://some-url.test/'))).rejects.toBeInstanceOf(NotFoundError);
});
test('converts Cloudflare challenge block to custom CloudflareChallengeError', async () => {
axiosMock.onGet().reply(403, undefined, { 'cf-mitigated': 'challenge' });
await expect(fetcher.text(ctx, new URL('https://some-url.test/'))).rejects.toBeInstanceOf(CloudflareChallengeError);
});
test('passes through other errors', async () => {
axiosMock.onGet().networkError();
await expect(fetcher.text(ctx, new URL('https://some-url.test/'))).rejects.toBeInstanceOf(AxiosError);
});
});