summaly/test/index.ts
2023-02-12 14:37:37 +00:00

240 lines
6.8 KiB
TypeScript

/**
* Tests!
*/
'use strict';
/* dependencies below */
import fs from 'node:fs';
import process from 'node:process';
import fastify from 'fastify';
import { summaly } from '../src/index.js';
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import {expect, jest, test, describe, beforeEach, afterEach} from '@jest/globals';
import { Agent as httpAgent } from 'node:http';
import { Agent as httpsAgent } from 'node:https';
import { StatusError } from '../src/utils/status-error.js';
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
/* settings below */
Error.stackTraceLimit = Infinity;
// During the test the env variable is set to test
process.env.NODE_ENV = 'test';
process.env.SUMMALY_ALLOW_PRIVATE_IP = 'true';
const port = 3060;
const host = `http://localhost:${port}`;
// Display detail of unhandled promise rejection
process.on('unhandledRejection', console.dir);
let app: ReturnType<typeof fastify> | null = null;
let n = 0;
afterEach(async () => {
if (app) {
await app.close();
app = null;
}
});
/* tests below */
test('faviconがHTML上で指定されていないが、ルートに存在する場合、正しく設定される', async () => {
app = fastify();
app.get('/', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/no-favicon.html'));
});
app.get('/favicon.ico', (_, reply) => reply.status(200).send());
await app.listen({ port });
const summary = await summaly(host);
expect(summary.icon).toBe(`${host}/favicon.ico`);
});
test('faviconがHTML上で指定されていなくて、ルートにも存在しなかった場合 null になる', async () => {
app = fastify();
app.get('/', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/no-favicon.html'));
});
app.get('*', (_, reply) => reply.status(404).send());
await app.listen({ port });
const summary = await summaly(host);
expect(summary.icon).toBe(null);
});
test('titleがcleanupされる', async () => {
app = fastify();
app.get('/', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/dirty-title.html'));
});
await app.listen({ port });
const summary = await summaly(host);
expect(summary.title).toBe('Strawberry Pasta');
});
describe('Private IP blocking', () => {
beforeEach(() => {
process.env.SUMMALY_ALLOW_PRIVATE_IP = 'false';
app = fastify();
app.get('*', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/og-title.html'));
});
return app.listen({ port });
});
test('private ipなサーバーの情報を取得できない', async () => {
const summary = await summaly(host).catch((e: StatusError) => e);
if (summary instanceof StatusError) {
expect(summary.name).toBe('StatusError');
} else {
expect(summary).toBeInstanceOf(StatusError);
}
});
test('agentが指定されている場合はprivate ipを許可', async () => {
const summary = await summaly(host, {
agent: {
http: new httpAgent({ keepAlive: true }),
https: new httpsAgent({ keepAlive: true }),
}
});
expect(summary.title).toBe('Strawberry Pasta');
});
test('agentが空のオブジェクトの場合はprivate ipを許可しない', async () => {
const summary = await summaly(host, { agent: {} }).catch((e: StatusError) => e);
if (summary instanceof StatusError) {
expect(summary.name).toBe('StatusError');
} else {
expect(summary).toBeInstanceOf(StatusError);
}
});
afterEach(() => {
process.env.SUMMALY_ALLOW_PRIVATE_IP = 'true';
});
});
describe('OGP', () => {
test('title', async () => {
app = fastify();
app.get('*', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/og-title.html'));
});
await app.listen({ port });
const summary = await summaly(host);
expect(summary.title).toBe('Strawberry Pasta');
});
test('description', async () => {
app = fastify();
app.get('/', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/og-description.html'));
});
await app.listen({ port });
const summary = await summaly(host);
expect(summary.description).toBe('Strawberry Pasta');
});
test('site_name', async () => {
app = fastify();
app.get('/', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/og-site_name.html'));
});
await app.listen({ port });
const summary = await summaly(host);
expect(summary.sitename).toBe('Strawberry Pasta');
});
test('thumbnail', async () => {
app = fastify();
app.get('/', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/og-image.html'));
});
await app.listen({ port });
const summary = await summaly(host);
expect(summary.thumbnail).toBe('https://himasaku.net/himasaku.png');
});
});
describe('TwitterCard', () => {
test('title', async () => {
app = fastify();
app.get('/', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/twitter-title.html'));
});
await app.listen({ port });
const summary = await summaly(host);
expect(summary.title).toBe('Strawberry Pasta');
});
test('description', async () => {
app = fastify();
app.get('/', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/twitter-description.html'));
});
await app.listen({ port });
const summary = await summaly(host);
expect(summary.description).toBe('Strawberry Pasta');
});
test('thumbnail', async () => {
app = fastify();
app.get('/', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/twitter-image.html'));
});
await app.listen({ port });
const summary = await summaly(host);
expect(summary.thumbnail).toBe('https://himasaku.net/himasaku.png');
});
test('Player detection - PeerTube:video => video', async () => {
app = fastify();
app.get('/', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/player-peertube-video.html'));
});
await app.listen({ port });
const summary = await summaly(host);
expect(summary.player.url).toBe('https://example.com/embedurl');
});
test('Player detection - Pleroma:video => video', async () => {
app = fastify();
app.get('/', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/player-pleroma-video.html'));
});
await app.listen({ port });
const summary = await summaly(host);
expect(summary.player.url).toBe('https://example.com/embedurl');
});
test('Player detection - Pleroma:image => image', async () => {
app = fastify();
app.get('/', (request, reply) => {
return reply.send(fs.createReadStream(_dirname + '/htmls/player-pleroma-image.html'));
});
await app.listen({ port });
const summary = await summaly(host);
expect(summary.thumbnail).toBe('https://example.com/imageurl');
});
});