als-mongo-list
Version:
A flexible, lightweight MongoDB query utility for Node.js applications. Simplifies database operations with intuitive filtering, pagination, sorting, and field selection. Ideal for REST API endpoints, providing a primary List class that abstracts complex
243 lines (213 loc) • 9.48 kB
JavaScript
const Filter = require('../lib/filter/filter'); // Обновите путь к файлу Filter
const assert = require('node:assert');
const { describe, it } = require('node:test');
const { Types: { ObjectId } } = require('mongoose');
describe('Filter', () => {
const tree = {
name: { type: String },
age: { type: Number, min: 18, max: 99 },
isActive: { type: Boolean },
userId: { type: ObjectId },
createdAt: { type: Date },
status: { type: String, enum: ['active', 'inactive', 'pending'] }
};
const searchKeys = ['name', 'age', 'isActive', 'userId', 'createdAt', 'status'];
const filter = new Filter({ tree, searchKeys });
describe('getSearch', () => {
it('should create regex filter for String fields', () => {
const query = { name: 'John' };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, { name: { $regex: 'John', $options: 'i' } });
});
it('should create range filters for Number fields', () => {
const query = { age_gte: '18', age_lte: '30' };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, { age: { $gte: 18, $lte: 30 } });
});
it('should create boolean filter for Boolean fields', () => {
const query = { isActive: 'true' };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, { isActive: true });
});
it('should create range filters for Date fields', () => {
const dateFrom = '2022-01-01';
const dateTo = '2022-12-31';
const query = { createdAt_gte: dateFrom, createdAt_lte: dateTo };
const search = filter.getSearch(query);
const expected = { createdAt: { $gte: new Date(dateFrom), $lte: new Date(dateTo) } }
// console.log({search,expected})
assert.deepStrictEqual(search, expected);
});
it('should ignore invalid ObjectId values', () => {
const query = { userId: 'invalidObjectId' };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, {});
});
it('should create ObjectId filter for ObjectId fields', () => {
const validId = new ObjectId().toString();
const query = { userId: validId };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, { userId: new ObjectId(validId) });
});
});
describe('validators and inputs initialization', () => {
it('should initialize validators for each searchKey', () => {
assert.strictEqual(typeof filter.validators.name, 'function');
assert.strictEqual(typeof filter.validators.age_gte, 'function');
assert.strictEqual(typeof filter.validators.age_lte, 'function');
assert.strictEqual(typeof filter.validators.isActive, 'function');
assert.strictEqual(typeof filter.validators.userId, 'function');
assert.strictEqual(typeof filter.validators.createdAt_gte, 'function');
assert.strictEqual(typeof filter.validators.createdAt_lte, 'function');
assert.strictEqual(typeof filter.validators.status, 'function');
});
it('should initialize inputs correctly based on field types', () => {
const { name, age_gte, age_lte, isActive, userId, status } = filter.inputs;
assert.deepStrictEqual(name, { tag: 'input', type: 'search', name: 'name' });
assert.deepStrictEqual(age_gte, { tag: 'input', type: 'number', name: 'age_gte', min: 18, max: 99, step: undefined });
assert.deepStrictEqual(age_lte, { tag: 'input', type: 'number', name: 'age_lte', min: 18, max: 99, step: undefined });
assert.deepStrictEqual(userId, { tag: 'input', type: 'text', name: 'userId' });
assert.deepStrictEqual(isActive, {
tag: 'select',
name: 'isActive',
options: [
{ value: '', text: 'all' },
{ value: 'true', text: 'true' },
{ value: 'false', text: 'false' }
]
});
assert.deepStrictEqual(status, {
tag: 'select',
name: 'status',
options: [
{ value: 'active', text: 'active' },
{ value: 'inactive', text: 'inactive' },
{ value: 'pending', text: 'pending' }
]
});
});
});
describe('Additional tests', () => {
const treeWithEnums = {
status: { type: String, enum: ['active', 'inactive'], default: 'inactive' },
category: { type: String }
};
it('should set input attributes for enums and other fields', () => {
const customFilter = new Filter({ tree: treeWithEnums, searchKeys: ['status', 'category'] });
assert.deepStrictEqual(customFilter.inputs.status, {
tag: 'select',
name: 'status',
options: [
{ value: 'active', text: 'active' },
{ value: 'inactive', text: 'inactive' }
]
});
assert.deepStrictEqual(customFilter.inputs.category, { tag: 'input', type: 'search', name: 'category' });
});
});
describe('Additional and edge case tests', () => {
it('should handle empty query gracefully', () => {
const query = {};
const search = filter.getSearch(query);
assert.deepStrictEqual(search, {});
});
it('should create range filters for Number fields with boundary values', () => {
const query = { age_gte: '18', age_lte: '99' };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, { age: { $gte: 18, $lte: 99 } });
});
it('should ignore invalid range for Number fields', () => {
const query = { age_gte: 'abc', age_lte: 'xyz' };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, {});
});
it('should create boolean filter for Boolean fields with "false"', () => {
const query = { isActive: 'false' };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, { isActive: false });
});
it('should handle non-boolean values for Boolean fields', () => {
const query = { isActive: 'yes' };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, { isActive: true });
});
it('should ignore invalid Date values', () => {
const query = { createdAt_gte: 'invalid-date', createdAt_lte: 'another-invalid-date' };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, {});
});
it('should handle multiple filters in a single query', () => {
const query = {
name: 'John',
age_gte: '25',
createdAt_gte: '2022-01-01',
isActive: 'true'
};
const search = filter.getSearch(query);
const expected = {
name: { $regex: 'John', $options: 'i' },
age: { $gte: 25 },
createdAt: { $gte: new Date(Date.UTC(2022, 0, 1)) },
isActive: true
};
assert.deepStrictEqual(search, expected);
});
it('should ignore unsupported keys in the query', () => {
const query = { unsupportedKey: 'value' };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, {});
});
it('should handle empty strings as query values gracefully', () => {
const query = { name: '' };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, {});
});
it('should handle null or undefined values in the query', () => {
const query = { name: null, age_gte: undefined };
const search = filter.getSearch(query);
assert.deepStrictEqual(search, {});
});
});
});
describe('Filter date inputs', () => {
it('should have select input with default date options', () => {
const tree = {
createdAt: { type: Date }
};
const searchKeys = ['createdAt'];
const filter = new Filter({ tree, searchKeys });
assert.deepStrictEqual(filter.inputs, {
createdAt_gte: {
tag: 'input',
type: 'date',
name: 'createdAt_gte',
key: 'createdAt'
},
createdAt_lte: {
tag: 'input',
type: 'date',
name: 'createdAt_lte',
key: 'createdAt'
}
})
});
});
describe('Filter few strings', () => {
const tree = {
title: { type: String },
description: { type: String },
keywords: [{ type: String }],
};
const searchKeys = ['title', 'description', 'keywords'];
const filter = new Filter({ tree, searchKeys });
it('basic search', () => {
const search = filter.getSearch({ search: 'John', title: 'true', description: 'true', keywords: 'true' })
assert.deepStrictEqual(search, {
$or: [
{title: {$regex: "John",$options: "i"}},
{description: {$regex: "John",$options: "i"}},
{keywords: {$regex: "John",$options: "i"}}
]
})
})
});