Files
kestrelos/test/unit/queryBuilder.spec.js
Madison Grubb b0e8dd7ad9
Some checks failed
ci/woodpecker/pr/pr Pipeline failed
make kestrel a tak server, so that it can send and receive pois as cots data
2026-02-17 10:42:53 -05:00

104 lines
3.6 KiB
JavaScript

import { describe, it, expect } from 'vitest'
import { buildUpdateQuery, getAllowedColumns } from '../../server/utils/queryBuilder.js'
describe('queryBuilder', () => {
describe('buildUpdateQuery', () => {
it('builds valid UPDATE query for devices', () => {
const { query, params } = buildUpdateQuery('devices', null, {
name: 'Test Device',
lat: 40.7128,
})
expect(query).toBe('UPDATE devices SET name = ?, lat = ? WHERE id = ?')
expect(params).toEqual(['Test Device', 40.7128])
})
it('builds valid UPDATE query for users', () => {
const { query, params } = buildUpdateQuery('users', null, {
role: 'admin',
identifier: 'testuser',
})
expect(query).toBe('UPDATE users SET role = ?, identifier = ? WHERE id = ?')
expect(params).toEqual(['admin', 'testuser'])
})
it('builds valid UPDATE query for pois', () => {
const { query, params } = buildUpdateQuery('pois', null, {
label: 'Test POI',
lat: 40.7128,
lng: -74.0060,
})
expect(query).toBe('UPDATE pois SET label = ?, lat = ?, lng = ? WHERE id = ?')
expect(params).toEqual(['Test POI', 40.7128, -74.0060])
})
it('returns empty query when no updates', () => {
const { query, params } = buildUpdateQuery('devices', null, {})
expect(query).toBe('')
expect(params).toEqual([])
})
it('throws error for unknown table', () => {
expect(() => {
buildUpdateQuery('unknown_table', null, { name: 'test' })
}).toThrow('Unknown table: unknown_table')
})
it('throws error for invalid column name', () => {
expect(() => {
buildUpdateQuery('devices', null, { invalid_column: 'test' })
}).toThrow('Invalid column: invalid_column for table: devices')
})
it('prevents SQL injection attempts in column names', () => {
expect(() => {
buildUpdateQuery('devices', null, { 'name\'; DROP TABLE devices; --': 'test' })
}).toThrow('Invalid column')
})
it('allows custom allowedColumns set', () => {
const customColumns = new Set(['name', 'custom_field'])
const { query, params } = buildUpdateQuery('devices', customColumns, {
name: 'Test',
custom_field: 'value',
})
expect(query).toBe('UPDATE devices SET name = ?, custom_field = ? WHERE id = ?')
expect(params).toEqual(['Test', 'value'])
})
it('rejects columns not in custom allowedColumns', () => {
const customColumns = new Set(['name'])
expect(() => {
buildUpdateQuery('devices', customColumns, { name: 'Test', lat: 40.7128 })
}).toThrow('Invalid column: lat')
})
})
describe('getAllowedColumns', () => {
it('returns allowed columns for devices', () => {
const columns = getAllowedColumns('devices')
expect(columns).toBeInstanceOf(Set)
expect(columns.has('name')).toBe(true)
expect(columns.has('lat')).toBe(true)
expect(columns.has('invalid')).toBe(false)
})
it('returns allowed columns for users', () => {
const columns = getAllowedColumns('users')
expect(columns.has('role')).toBe(true)
expect(columns.has('identifier')).toBe(true)
})
it('returns allowed columns for pois', () => {
const columns = getAllowedColumns('pois')
expect(columns.has('label')).toBe(true)
expect(columns.has('lat')).toBe(true)
})
it('returns empty set for unknown table', () => {
const columns = getAllowedColumns('unknown')
expect(columns).toBeInstanceOf(Set)
expect(columns.size).toBe(0)
})
})
})