File size: 4,785 Bytes
bf48b89 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | import { describe, expect, it, vi } from 'vitest';
import { config } from '@/config';
import template from '@/middleware/template';
const createCtx = (query: Record<string, string | undefined>, data: any, extra: Record<string, unknown> = {}) => {
const store = new Map<string, unknown>([['data', data], ...Object.entries(extra)]);
return {
req: {
query: (key: string) => query[key],
url: 'http://localhost/rss',
},
get: (key: string) => store.get(key),
set: (key: string, value: unknown) => store.set(key, value),
json: vi.fn((payload) => payload),
html: vi.fn((payload) => payload),
render: vi.fn((payload) => payload),
body: vi.fn((payload) => payload),
redirect: vi.fn((url: string, status: number) => ({ url, status })),
header: vi.fn(),
res: { headers: new Headers() },
};
};
describe('template middleware', () => {
it('returns debug json when requested', async () => {
const originalDebug = config.debugInfo;
config.debugInfo = true;
const ctx = createCtx({ format: 'debug.json' }, { item: [] }, { json: { ok: true } });
const result = await template(ctx as any, async () => {});
expect(result).toEqual({ ok: true });
expect(ctx.json).toHaveBeenCalled();
config.debugInfo = originalDebug;
});
it('returns api data without rendering', async () => {
const ctx = createCtx({}, null, { apiData: { ok: true } });
const result = await template(ctx as any, async () => {});
expect(result).toEqual({ ok: true });
expect(ctx.json).toHaveBeenCalledWith({ ok: true });
});
it('renders debug html snippet when requested', async () => {
const originalDebug = config.debugInfo;
config.debugInfo = true;
const ctx = createCtx({ format: '0.debug.html' }, { item: [{ description: 'Hello' }] });
const result = await template(ctx as any, async () => {});
expect(result).toBe('Hello');
expect(ctx.html).toHaveBeenCalled();
config.debugInfo = originalDebug;
});
it('trims long titles and normalizes authors', async () => {
const originalLimit = config.titleLengthLimit;
config.titleLengthLimit = 3;
const data = {
title: 'Feed',
item: [
{
title: 'ABCDE',
author: [{ name: ' Alice ' }, { name: 'Bob ' }],
itunes_duration: '65',
},
],
};
const ctx = createCtx({ format: 'rss' }, data);
await template(ctx as any, async () => {});
expect(data.item[0].title).toBe('ABC...');
expect(data.item[0].author).toBe('Alice, Bob');
expect(data.item[0].itunes_duration).toBe('0:01:05');
config.titleLengthLimit = originalLimit;
});
it('clears invalid dates for non-rss formats', async () => {
const data = {
title: 'Test',
item: [
{
title: 'Item',
pubDate: 'invalid-date',
updated: 'invalid-updated',
},
],
};
const ctx = createCtx({ format: 'json' }, data);
await template(ctx as any, async () => {});
expect(data.item[0].pubDate).toBe('');
expect(data.item[0].updated).toBe('');
});
it('returns redirect response when redirect is set', async () => {
const ctx = createCtx({}, { item: [] }, { redirect: 'https://example.com' });
const result = await template(ctx as any, async () => {});
expect(result).toEqual({ url: 'https://example.com', status: 301 });
expect(ctx.redirect).toHaveBeenCalledWith('https://example.com', 301);
});
it('renders rss3 output', async () => {
const data = {
title: 'Test',
item: [
{
title: 'Item',
link: 'https://example.com/item',
},
],
};
const ctx = createCtx({ format: 'rss3' }, data);
const result = await template(ctx as any, async () => {});
expect(ctx.json).toHaveBeenCalled();
expect(result).toHaveProperty('data');
});
it('renders atom output', async () => {
const data = {
title: 'Test',
item: [
{
title: 'Item',
link: 'https://example.com/item',
},
],
};
const ctx = createCtx({ format: 'atom' }, data);
await template(ctx as any, async () => {});
expect(ctx.render).toHaveBeenCalled();
});
});
|