Files
badgedex/test/tag.api.test.js
T
2026-07-17 14:08:00 +02:00

184 lines
6.3 KiB
JavaScript

const request = require('supertest');
const express = require('express');
const helmet = require('helmet');
const tagRouter = require('../src/api/tag');
const app = express();
app.use(helmet({ crossOriginResourcePolicy: false }));
app.use(tagRouter);
describe('GET /tag', () => {
// --- Basic happy-path ---
it('should return SVG with default params', async () => {
const res = await request(app).get('/tag');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(res.headers['content-type']).toMatch(/image\/svg\+xml/);
expect(body).toContain('<svg');
expect(body).toContain('<rect');
expect(body).toContain('badgedex');
expect(body).toContain('BADGEDEX');
});
it('should use custom tag and label', async () => {
const res = await request(app).get('/tag?tag=test&label=Teszt');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('test');
expect(body).toContain('TESZT');
});
// --- Backgrounds ---
it('should set tag background to transparent', async () => {
const res = await request(app).get('/tag?bgtag=none');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('fill="none"');
});
it('should set label background to transparent', async () => {
const res = await request(app).get('/tag?bglabel=none');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('fill="none"');
});
it('should apply custom bgtag and bglabel colours', async () => {
const res = await request(app).get('/tag?bgtag=green&bglabel=orange');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('fill="green"');
expect(body).toContain('fill="orange"');
});
// --- Styles ---
it('should use rect style', async () => {
const res = await request(app).get('/tag?style=rect');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('shape-rendering="crispEdges"');
});
it('should use flat style with dynamic dimensions', async () => {
const res = await request(app).get('/tag?style=flat');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('<linearGradient');
expect(body).toContain('<clipPath');
expect(body).toContain('rx="3"');
});
it('should fall back to rect for invalid style', async () => {
const res = await request(app).get('/tag?style=invalid');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('shape-rendering="crispEdges"');
});
// --- fontweight ---
it('should handle custom fontweight bold', async () => {
const res = await request(app).get('/tag?fontweight=bold');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('font-weight="bold"');
});
it('should handle fontweight lighter', async () => {
const res = await request(app).get('/tag?fontweight=lighter');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('font-weight="lighter"');
});
// --- color ---
it('should handle custom color', async () => {
const res = await request(app).get('/tag?color=%23ff0000');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('fill="#ff0000"');
});
it('should reject invalid color and fall back to default', async () => {
const res = await request(app).get('/tag?color=bad-color-value');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('fill="#000000"');
});
// --- size ---
it('should handle custom size', async () => {
const res = await request(app).get('/tag?size=48');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('height="48"');
});
it('should handle minimum size (8)', async () => {
const res = await request(app).get('/tag?size=8');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('<svg');
});
it('should fall back to default size for NaN', async () => {
const res = await request(app).get('/tag?size=abc');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('height="24"');
});
it('should fall back to default size for negative value', async () => {
const res = await request(app).get('/tag?size=-10');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('height="24"');
});
it('should fall back to default size for value above max', async () => {
const res = await request(app).get('/tag?size=500');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('height="24"');
});
// --- XSS / injection ---
it('should escape XSS in tag', async () => {
const res = await request(app).get('/tag?tag=<img%20src=x%20onerror=alert(1)>');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).not.toContain('<img');
expect(body).toContain('&lt;img');
});
it('should escape XSS in label', async () => {
const res = await request(app).get('/tag?label=<script>alert(1)</script>');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).not.toContain('<script>');
expect(body).toContain('&lt;script&gt;');
});
// --- SVG structure ---
it('should include aria-label and title', async () => {
const res = await request(app).get('/tag?tag=status&label=OK');
const body = Buffer.from(res.body).toString();
expect(res.statusCode).toBe(200);
expect(body).toContain('aria-label="status: OK"');
expect(body).toContain('<title>status: OK</title>');
});
it('should include xmlns', async () => {
const res = await request(app).get('/tag');
const body = Buffer.from(res.body).toString();
expect(body).toContain('xmlns="http://www.w3.org/2000/svg"');
});
});