jevstrudel.git / tools / events / events.test.mjs
1import { describe, expect, it } from 'vitest';
2import { dataPoint } from '../../worker/src/events.ts';
3import { dataset, decodeRows, eventQuery } from './events.mjs';
4
5describe('eventQuery: an event read back by its schema names', () => {
6  it('selects its columns as named, filtered to the event and the window', () => {
7    const sql = eventQuery('jev.relay', { since: '7d', limit: 500 });
8    expect(sql).toContain('blob1 AS outcome, blob2 AS colo');
9    expect(sql).toContain('double2 AS status, double3 AS upstreamMs');
10    expect(sql).toContain(`FROM ${dataset()}`);
11    expect(sql).toContain("WHERE index1 = 'jev.relay' AND timestamp > NOW() - INTERVAL '7' DAY");
12    expect(sql).toMatch(/LIMIT 500\nFORMAT JSON$/);
13  });
14
15  it('refuses what is not in the schema or not a window', () => {
16    expect(() => eventQuery("x' OR 1=1 --")).toThrow(/no event/);
17    expect(() => eventQuery('jev.relay', { since: "1d' OR 1" })).toThrow(/--since/);
18    expect(() => eventQuery('jev.relay', { limit: 0 })).toThrow(/--limit/);
19  });
20});
21
22describe('decodeRows: the known-mask undone', () => {
23  it('gives back what the Worker wrote, unknown doubles as null', () => {
24    const point = dataPoint('jev.relay', {
25      blobs: { outcome: 'refused', colo: 'DFW' },
26      doubles: { status: 429, upstreamMs: null, requestBytes: null, sectionInS: 1.5, attempt: 0 },
27    });
28    // a row as the SQL API returns it for eventQuery's columns
29    const row = {
30      timestamp: '2026-09-25 12:00:00',
31      weight: '1',
32      _known: point.doubles[0],
33      outcome: point.blobs[0],
34      colo: point.blobs[1],
35      status: point.doubles[1],
36      upstreamMs: point.doubles[2],
37      requestBytes: point.doubles[3],
38      sectionInS: point.doubles[4],
39      attempt: point.doubles[5],
40    };
41    expect(decodeRows('jev.relay', [row])).toEqual([
42      {
43        timestamp: '2026-09-25 12:00:00',
44        weight: 1,
45        outcome: 'refused',
46        colo: 'DFW',
47        status: 429,
48        upstreamMs: null,
49        requestBytes: null,
50        sectionInS: 1.5,
51        attempt: 0,
52      },
53    ]);
54  });
55});