184 lines
6.3 KiB
JavaScript
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('<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('<script>');
|
|
});
|
|
|
|
// --- 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"');
|
|
});
|
|
}); |