Add template animation editor
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
|
||||
const {
|
||||
buildSearchFilter,
|
||||
buildSortOrderClause,
|
||||
fetchPagedRows,
|
||||
findTopLevelOrderByIndex,
|
||||
normalizePageNumber,
|
||||
normalizeSortDirection,
|
||||
parseJsonSafe,
|
||||
readFormArray
|
||||
} = require('../src/data/utils');
|
||||
|
||||
test('parseJsonSafe returns null for invalid JSON and preserves objects', () => {
|
||||
assert.equal(parseJsonSafe(''), null);
|
||||
assert.equal(parseJsonSafe('not-json'), null);
|
||||
assert.deepEqual(parseJsonSafe('{"value":true}'), { value: true });
|
||||
const value = { nested: ['a'] };
|
||||
assert.equal(parseJsonSafe(value), value);
|
||||
});
|
||||
|
||||
test('readFormArray always returns an array shape', () => {
|
||||
assert.deepEqual(readFormArray({}, 'roles'), []);
|
||||
assert.deepEqual(readFormArray({ roles: 'admin' }, 'roles'), ['admin']);
|
||||
assert.deepEqual(readFormArray({ roles: ['admin', 'editor'] }, 'roles'), ['admin', 'editor']);
|
||||
});
|
||||
|
||||
test('normalize helpers clamp pagination and sort direction', () => {
|
||||
assert.equal(normalizePageNumber('0'), 1);
|
||||
assert.equal(normalizePageNumber('3.9'), 3);
|
||||
assert.equal(normalizePageNumber('abc'), 1);
|
||||
assert.equal(normalizeSortDirection('DESC'), 'desc');
|
||||
assert.equal(normalizeSortDirection('anything else'), 'asc');
|
||||
});
|
||||
|
||||
test('buildSortOrderClause applies multiple columns and ignores unknown keys', () => {
|
||||
assert.deepEqual(buildSortOrderClause({ name: 'title' }, 'name', 'desc'), {
|
||||
clause: ' ORDER BY title DESC',
|
||||
sortKey: 'name',
|
||||
sortDirection: 'desc'
|
||||
});
|
||||
assert.deepEqual(buildSortOrderClause({ name: ['title', 'id'] }, 'name', 'asc'), {
|
||||
clause: ' ORDER BY title ASC, id ASC',
|
||||
sortKey: 'name',
|
||||
sortDirection: 'asc'
|
||||
});
|
||||
assert.deepEqual(buildSortOrderClause({ name: 'title' }, 'missing', 'desc'), {
|
||||
clause: '',
|
||||
sortKey: 'missing',
|
||||
sortDirection: 'desc'
|
||||
});
|
||||
});
|
||||
|
||||
test('buildSearchFilter generates escaped LIKE clauses', () => {
|
||||
assert.deepEqual(buildSearchFilter(['name', 'description'], '100%_ready'), {
|
||||
clause: " WHERE (LOWER(COALESCE(CAST(name AS CHAR), '')) LIKE ? ESCAPE '\\\\' OR LOWER(COALESCE(CAST(description AS CHAR), '')) LIKE ? ESCAPE '\\\\')",
|
||||
params: ['%100\\%\\_ready%', '%100\\%\\_ready%']
|
||||
});
|
||||
assert.deepEqual(buildSearchFilter([], 'anything'), { clause: '', params: [] });
|
||||
});
|
||||
|
||||
test('findTopLevelOrderByIndex skips nested subqueries', () => {
|
||||
const sql = 'SELECT * FROM (SELECT * FROM items ORDER BY created_at DESC) AS nested ORDER BY id ASC';
|
||||
assert.equal(findTopLevelOrderByIndex(sql), sql.lastIndexOf('ORDER BY id ASC'));
|
||||
});
|
||||
|
||||
test('fetchPagedRows combines search, ordering, and pagination parameters', async () => {
|
||||
const queries = [];
|
||||
const pool = {
|
||||
async query(sql, params) {
|
||||
queries.push({ sql, params });
|
||||
if (sql.startsWith('SELECT COUNT(*)')) {
|
||||
return [[{ count: 3 }]];
|
||||
}
|
||||
return [[{ id: 1 }]];
|
||||
}
|
||||
};
|
||||
|
||||
const result = await fetchPagedRows(pool, {
|
||||
selectSql: 'SELECT id, name FROM items WHERE active = 1 ORDER BY name ASC',
|
||||
countSql: 'SELECT COUNT(*) AS count FROM items WHERE active = 1',
|
||||
params: ['active'],
|
||||
searchColumns: ['name'],
|
||||
searchTerm: 'alpha',
|
||||
sortColumns: { name: 'name' },
|
||||
sortKey: 'name',
|
||||
sortDirection: 'desc',
|
||||
pageSize: 2,
|
||||
page: 2
|
||||
});
|
||||
|
||||
assert.deepEqual(result, {
|
||||
rows: [{ id: 1 }],
|
||||
totalItems: 3,
|
||||
totalPages: 2,
|
||||
currentPage: 2,
|
||||
pageSize: 2
|
||||
});
|
||||
assert.equal(queries.length, 2);
|
||||
assert.equal(queries[0].sql, "SELECT COUNT(*) AS count FROM (SELECT id, name FROM items WHERE active = 1 AND (LOWER(COALESCE(CAST(name AS CHAR), '')) LIKE ? ESCAPE '\\\\')) AS filtered_rows");
|
||||
assert.deepEqual(queries[0].params, ['active', '%alpha%']);
|
||||
assert.equal(queries[1].sql, "SELECT id, name FROM items WHERE active = 1 AND (LOWER(COALESCE(CAST(name AS CHAR), '')) LIKE ? ESCAPE '\\\\') ORDER BY name DESC LIMIT ? OFFSET ?");
|
||||
assert.deepEqual(queries[1].params, ['active', '%alpha%', 2, 2]);
|
||||
});
|
||||
Reference in New Issue
Block a user