104 lines
3.6 KiB
JavaScript
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)
|
|
})
|
|
})
|
|
})
|