CI / Generate TypeScript types (push) Successful in 12s
CI / Server unit tests (push) Successful in 25s
CI / Build server (push) Successful in 30s
CI / Build client (push) Successful in 39s
CI / Playwright E2E tests (push) Successful in 3m55s
CI / Build and push Docker image (push) Successful in 49s
CI / Notify (push) Successful in 2s
126 lines
5.9 KiB
TypeScript
126 lines
5.9 KiB
TypeScript
import express from 'express';
|
|
import request from 'supertest';
|
|
import bodyParser from 'body-parser';
|
|
import { generateToken } from '../auth';
|
|
import { resetMemoryStorage } from '../storage/memory';
|
|
import getStorage from '../storage';
|
|
import groupRouter from '../routes/groupRoutes';
|
|
import { DEFAULT_GROUP_LIMITS, getGroupLimits, resetGroupLimits } from '../limits';
|
|
|
|
const MAX_NOTE_LENGTH = DEFAULT_GROUP_LIMITS.maxNoteLength;
|
|
const MAX_SURCHARGE_TEXT_LENGTH = DEFAULT_GROUP_LIMITS.maxSurchargeTextLength;
|
|
/** Maximum částky v haléřích */
|
|
const MAX_AMOUNT = DEFAULT_GROUP_LIMITS.maxAmountKc * 100;
|
|
|
|
jest.mock('../websocket', () => ({ getWebsocket: () => ({ emit: jest.fn() }) }));
|
|
|
|
const CREATOR = 'kreator';
|
|
const TOKEN = `Bearer ${generateToken(CREATOR)}`;
|
|
|
|
function buildApp() {
|
|
const app = express();
|
|
app.use(bodyParser.json());
|
|
app.use('/api/groups', groupRouter);
|
|
app.use((err: any, _req: any, res: any, _next: any) => {
|
|
res.status(500).json({ error: err.message });
|
|
});
|
|
return app;
|
|
}
|
|
|
|
/** Založí skupinu a vrátí její ID. */
|
|
async function createTestGroup(app: express.Express): Promise<string> {
|
|
const res = await request(app).post('/api/groups/create').set('Authorization', TOKEN).send({ name: 'Bistro' });
|
|
expect(res.status).toBe(200);
|
|
return res.body.groups[0].id;
|
|
}
|
|
|
|
beforeEach(async () => {
|
|
resetMemoryStorage();
|
|
resetGroupLimits();
|
|
await getStorage().setData('stores', [{ name: 'Bistro' }]);
|
|
});
|
|
|
|
describe('limity vstupů skupinových objednávek', () => {
|
|
test('poznámka a popis příplatku mají maximální délku', async () => {
|
|
const app = buildApp();
|
|
const id = await createTestGroup(app);
|
|
const post = (body: object) => request(app).post('/api/groups/updateMember').set('Authorization', TOKEN).send({ id, login: CREATOR, ...body });
|
|
|
|
expect((await post({ note: 'x'.repeat(MAX_NOTE_LENGTH) })).status).toBe(200);
|
|
const tooLong = await post({ note: 'x'.repeat(MAX_NOTE_LENGTH + 1) });
|
|
expect(tooLong.status).toBe(400);
|
|
expect(tooLong.body.error).toContain(`${MAX_NOTE_LENGTH} znaků`);
|
|
expect((await post({ surchargeText: 'x'.repeat(MAX_SURCHARGE_TEXT_LENGTH + 1) })).status).toBe(400);
|
|
});
|
|
|
|
test('částka a příplatek mají maximální výši', async () => {
|
|
const app = buildApp();
|
|
const id = await createTestGroup(app);
|
|
const post = (body: object) => request(app).post('/api/groups/updateMember').set('Authorization', TOKEN).send({ id, login: CREATOR, ...body });
|
|
|
|
expect((await post({ amount: MAX_AMOUNT })).status).toBe(200);
|
|
const tooMuch = await post({ amount: MAX_AMOUNT + 1 });
|
|
expect(tooMuch.status).toBe(400);
|
|
expect(tooMuch.body.error).toContain('10000 Kč');
|
|
expect((await post({ surchargeAmount: MAX_AMOUNT + 1 })).status).toBe(400);
|
|
expect((await post({ amount: -1 })).status).toBe(400);
|
|
});
|
|
|
|
test('poplatky mají maximum a procentní sleva nesmí přesáhnout 100 %', async () => {
|
|
const app = buildApp();
|
|
const id = await createTestGroup(app);
|
|
const post = (body: object) => request(app).post('/api/groups/updateFees').set('Authorization', TOKEN).send({ id, ...body });
|
|
|
|
expect((await post({ shipping: MAX_AMOUNT + 1 })).status).toBe(400);
|
|
expect((await post({ discountType: 'percent', discountValue: 101 })).status).toBe(400);
|
|
expect((await post({ discountType: 'percent', discountValue: 100 })).status).toBe(200);
|
|
// Jen hodnota při již nastavené procentní slevě — pojistka v groups.ts
|
|
const onlyValue = await post({ discountValue: 150 });
|
|
expect(onlyValue.status).toBe(500);
|
|
expect(onlyValue.body.error).toContain('100 %');
|
|
expect((await post({ discountType: 'fixed', discountValue: MAX_AMOUNT + 1 })).status).toBe(400);
|
|
});
|
|
|
|
test('název skupiny a odkaz na sledování mají maximální délku', async () => {
|
|
const app = buildApp();
|
|
expect((await request(app).post('/api/groups/create').set('Authorization', TOKEN).send({ name: 'x'.repeat(101) })).status).toBe(400);
|
|
const id = await createTestGroup(app);
|
|
const res = await request(app).post('/api/groups/setTracking').set('Authorization', TOKEN).send({ id, shareUrl: 'https://x.cz/' + 'a'.repeat(600) });
|
|
expect(res.status).toBe(400);
|
|
});
|
|
});
|
|
|
|
describe('limity z proměnných prostředí', () => {
|
|
const ENV_KEYS = ['GROUP_MAX_NOTE_LENGTH', 'GROUP_MAX_AMOUNT_KC', 'GROUP_MAX_ITEMS'];
|
|
afterEach(() => {
|
|
ENV_KEYS.forEach(k => delete process.env[k]);
|
|
resetGroupLimits();
|
|
});
|
|
|
|
test('env přepíše výchozí hodnoty a limity se uplatní v API', async () => {
|
|
process.env.GROUP_MAX_NOTE_LENGTH = '20';
|
|
process.env.GROUP_MAX_AMOUNT_KC = '500';
|
|
process.env.GROUP_MAX_ITEMS = '5';
|
|
resetGroupLimits();
|
|
expect(getGroupLimits()).toEqual({ ...DEFAULT_GROUP_LIMITS, maxNoteLength: 20, maxAmountKc: 500, maxItems: 5 });
|
|
|
|
const app = buildApp();
|
|
const id = await createTestGroup(app);
|
|
const post = (body: object) => request(app).post('/api/groups/updateMember').set('Authorization', TOKEN).send({ id, login: CREATOR, ...body });
|
|
expect((await post({ note: 'x'.repeat(21) })).body.error).toContain('20 znaků');
|
|
expect((await post({ amount: 50001 })).body.error).toContain('500 Kč');
|
|
expect((await post({ amount: 50000 })).status).toBe(200);
|
|
});
|
|
|
|
test('neplatná hodnota v env se ignoruje (zůstane výchozí)', () => {
|
|
const warn = jest.spyOn(console, 'warn').mockImplementation(() => { });
|
|
process.env.GROUP_MAX_NOTE_LENGTH = 'hodně';
|
|
process.env.GROUP_MAX_AMOUNT_KC = '-5';
|
|
process.env.GROUP_MAX_ITEMS = '999999';
|
|
resetGroupLimits();
|
|
expect(getGroupLimits()).toEqual(DEFAULT_GROUP_LIMITS);
|
|
expect(warn).toHaveBeenCalledTimes(3);
|
|
warn.mockRestore();
|
|
});
|
|
});
|