@lobehub/chat
Version:
Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.
136 lines (111 loc) • 4.74 kB
text/typescript
import { describe, expect, it, vi } from 'vitest';
import { browserless } from '../browserless';
describe('browserless', () => {
it('should throw BrowserlessInitError when env vars not set', async () => {
const originalEnv = { ...process.env };
process.env = { ...originalEnv };
delete process.env.BROWSERLESS_URL;
delete process.env.BROWSERLESS_TOKEN;
await expect(browserless('https://example.com', { filterOptions: {} })).rejects.toThrow(
'`BROWSERLESS_URL` or `BROWSERLESS_TOKEN` are required',
);
process.env = originalEnv;
});
it('should return undefined on fetch error', async () => {
process.env.BROWSERLESS_TOKEN = 'test-token';
global.fetch = vi.fn().mockRejectedValue(new Error('Fetch error'));
const result = await browserless('https://example.com', { filterOptions: {} });
expect(result).toBeUndefined();
});
it('should return undefined when content is empty', async () => {
process.env.BROWSERLESS_TOKEN = 'test-token';
global.fetch = vi.fn().mockResolvedValue({
text: vi.fn().mockResolvedValue('<html></html>'),
} as any);
const result = await browserless('https://example.com', { filterOptions: {} });
expect(result).toBeUndefined();
});
it('should return undefined when title is "Just a moment..."', async () => {
process.env.BROWSERLESS_TOKEN = 'test-token';
global.fetch = vi.fn().mockResolvedValue({
text: vi.fn().mockResolvedValue('<html><title>Just a moment...</title></html>'),
} as any);
const result = await browserless('https://example.com', { filterOptions: {} });
expect(result).toBeUndefined();
});
it('should return crawl result on successful fetch', async () => {
process.env.BROWSERLESS_TOKEN = 'test-token';
global.fetch = vi.fn().mockResolvedValue({
text: vi.fn().mockResolvedValue(`
<html>
<head>
<title>Test Title</title>
<meta name="description" content="Test Description">
</head>
<body>
<h1>Test Content</h1>
</body>
</html>
`),
} as any);
const result = await browserless('https://example.com', { filterOptions: {} });
expect(result).toEqual({
content: expect.any(String),
contentType: 'text',
description: expect.any(String),
length: expect.any(Number),
siteName: undefined,
title: 'Test Title',
url: 'https://example.com',
});
});
it('should include rejectRequestPattern in request payload', async () => {
process.env.BROWSERLESS_TOKEN = 'test-token';
const fetchMock = vi.fn().mockResolvedValue({
text: vi.fn().mockResolvedValue('<html><title>Test</title></html>'),
});
global.fetch = fetchMock;
await browserless('https://example.com', { filterOptions: {} });
const requestPayload = JSON.parse(fetchMock.mock.calls[0][1].body);
expect(requestPayload.rejectRequestPattern).toEqual([
'.*\\.(?!(html|css|js|json|xml|webmanifest|txt|md)(\\?|#|$))[\\w-]+(?:[\\?#].*)?$',
]);
});
it('should allow requests to permitted file types', async () => {
const allowedExtensions = ['html', 'css', 'js', 'json', 'xml', 'webmanifest', 'txt', 'md'];
const pattern = new RegExp(
'.*\\.(?!(html|css|js|json|xml|webmanifest|txt|md)(\\?|#|$))[\\w-]+(?:[\\?#].*)?$',
);
allowedExtensions.forEach((ext) => {
expect(`file.${ext}`).not.toMatch(pattern);
expect(`file.${ext}?param=value`).not.toMatch(pattern);
expect(`file.${ext}#hash`).not.toMatch(pattern);
});
});
it('should reject requests to non-permitted file types', async () => {
const rejectedExtensions = ['jpg', 'png', 'gif', 'pdf', 'doc', 'mp4', 'wav'];
const pattern = new RegExp(
'.*\\.(?!(html|css|js|json|xml|webmanifest|txt|md)(\\?|#|$))[\\w-]+(?:[\\?#].*)?$',
);
rejectedExtensions.forEach((ext) => {
expect(`file.${ext}`).toMatch(pattern);
expect(`file.${ext}?param=value`).toMatch(pattern);
expect(`file.${ext}#hash`).toMatch(pattern);
});
});
it('should use correct URL when BROWSERLESS_URL is provided', async () => {
const customUrl = 'https://custom.browserless.io';
const originalEnv = { ...process.env };
process.env.BROWSERLESS_TOKEN = 'test-token';
process.env.BROWSERLESS_URL = customUrl;
global.fetch = vi.fn().mockImplementation((url) => {
expect(url).toContain(customUrl);
return Promise.resolve({
text: () => Promise.resolve('<html><title>Test</title></html>'),
});
});
await browserless('https://example.com', { filterOptions: {} });
expect(global.fetch).toHaveBeenCalled();
process.env = originalEnv;
});
});