import { readId } from '../../src/utils'; describe('readId', () => { it('reads a positive integer', () => { expect(readId('7')).toBe(7); expect(readId('999999')).toBe(999999); }); // Each of these used to be sent to Postgres as text, raising 22P02 for an // integer column and surfacing to the caller as a 500 (#207). it.each(['abc', '', ' ', '1.5', '-1', '0', 'NaN', '1e5abc'])( 'refuses %p', (value) => { expect(readId(value)).toBeNull(); } ); // These are the dangerous ones, because they were never a 500 and so never // announced themselves (#307). Number reads each as a positive integer, so // every check this function used to make passed and the route fetched a real // row for a URL nobody wrote: /items/5.0 answered with item 5. it.each(['5.0', '1e2', '0x10', '+5', '1_0'])( 'refuses %p, which parses to a positive integer but is not an id', (value) => { expect(readId(value)).toBeNull(); } ); // The column is a 32-bit serial. Above that Postgres raises 22003 rather than // returning nothing, which is the same wrong answer to the caller as the // 22P02 this function was written to prevent. it('refuses an id past the top of a 32-bit serial', () => { expect(readId('2147483647')).toBe(2147483647); expect(readId('2147483648')).toBeNull(); expect(readId('99999999999999999999')).toBeNull(); }); // Surrounding whitespace is a URL artefact rather than a different id. it('reads an id with surrounding whitespace', () => { expect(readId(' 7 ')).toBe(7); }); it('refuses a missing param', () => { expect(readId(undefined)).toBeNull(); }); });