Files
2026-07-13 13:23:39 +08:00

115 lines
4.2 KiB
TypeScript

import nock from 'nock';
import { beforeEach, describe, expect, it } from 'vitest';
import { RobotsTxtFile } from '../src/internals/robots';
describe('RobotsTxtFile', () => {
beforeEach(() => {
nock.disableNetConnect();
nock('http://not-exists.com')
.persist()
.get('/robots.txt')
.delay(500)
.reply(
200,
[
'User-agent: *',
'Disallow: *deny_all/',
'crawl-delay: 10',
'User-agent: Googlebot',
'Disallow: *deny_googlebot/',
'crawl-delay: 1',
'user-agent: Mozilla',
'crawl-delay: 2',
'sitemap: http://not-exists.com/sitemap_1.xml',
'sitemap: http://not-exists.com/sitemap_2.xml',
].join('\n'),
)
.get('*')
.reply(404);
});
afterEach(() => {
nock.cleanAll();
nock.enableNetConnect();
});
it('generates the correct robots.txt URL', async () => {
const robots = await RobotsTxtFile.find('http://not-exists.com/nested/index.html');
expect(robots.getSitemaps()).not.toHaveLength(0);
});
it('parses allow/deny directives from robots.txt', async () => {
const robots = await RobotsTxtFile.find('http://not-exists.com/robots.txt');
console.log(robots.isAllowed('https://crawlee.dev'));
expect(robots.isAllowed('http://not-exists.com/something/page.html')).toBe(true);
expect(robots.isAllowed('http://not-exists.com/deny_googlebot/page.html')).toBe(true);
expect(robots.isAllowed('http://not-exists.com/deny_all/page.html')).toBe(false);
});
it('extracts sitemap urls', async () => {
const robots = await RobotsTxtFile.find('http://not-exists.com/robots.txt');
expect(robots.getSitemaps()).toEqual([
'http://not-exists.com/sitemap_1.xml',
'http://not-exists.com/sitemap_2.xml',
]);
});
it('respects user-set timeout', async () => {
const start = +Date.now();
const robots = RobotsTxtFile.find('http://not-exists.com/robots.txt', undefined, { timeoutMillis: 200 });
await expect(robots).rejects.toThrow(/timeout/i);
const end = +Date.now();
expect(end - start).toBeGreaterThanOrEqual(200);
expect(end - start).toBeLessThanOrEqual(500);
});
it('respects AbortSignal parameter', async () => {
const controller = new AbortController();
setTimeout(() => controller.abort(), 200);
const start = +Date.now();
const robots = RobotsTxtFile.find('http://not-exists.com/robots.txt', undefined, { signal: controller.signal });
await expect(robots).rejects.toThrow(/aborted/i);
const end = +Date.now();
expect(end - start).toBeGreaterThanOrEqual(200);
expect(end - start).toBeLessThanOrEqual(500);
});
it('respects AbortSignal parameter and timeout together', async () => {
const controller = new AbortController();
const start = +Date.now();
const robots = RobotsTxtFile.find('http://not-exists.com/robots.txt', undefined, {
signal: controller.signal,
timeoutMillis: 200,
});
await expect(robots).rejects.toThrow(/timeout/i);
const end = +Date.now();
expect(end - start).toBeGreaterThanOrEqual(200);
expect(end - start).toBeLessThanOrEqual(500);
});
it('parses allow/deny directives from explicitly provided robots.txt contents', async () => {
const contents = `User-agent: *',
Disallow: *deny_all/
crawl-delay: 10
User-agent: Googlebot
Disallow: *deny_googlebot/`;
const robots = RobotsTxtFile.from('http://not-exists.com/robots.txt', contents);
expect(robots.isAllowed('http://not-exists.com/something/page.html')).toBe(true);
expect(robots.isAllowed('http://not-exists.com/deny_googlebot/page.html')).toBe(true);
expect(robots.isAllowed('http://not-exists.com/deny_googlebot/page.html', 'Googlebot')).toBe(false);
expect(robots.isAllowed('http://not-exists.com/deny_all/page.html')).toBe(true);
});
});