UNPKG

@minatojs/tests

Version:
511 lines (420 loc) 18.6 kB
import { $, Database } from 'minato' import { expect } from 'chai' interface Foo { id?: number text?: string value?: number bool?: boolean list?: number[] timestamp?: Date date?: Date time?: Date regex?: string } interface Tables { temp1: Foo } function QueryOperators(database: Database<Tables>) { database.extend('temp1', { id: 'unsigned', text: 'string', value: 'integer', bool: 'boolean', list: 'list', timestamp: 'timestamp', date: 'date', time: 'time', regex: 'string', }, { autoInc: true, }) } namespace QueryOperators { interface QueryOptions { nullableComparator?: boolean } export const comparison = function Comparison(database: Database<Tables>, options: QueryOptions = {}) { const { nullableComparator = true } = options before(async () => { await database.remove('temp1', {}) await database.create('temp1', { text: 'awesome foo', timestamp: new Date('2000-01-01'), date: new Date('2020-01-01'), time: new Date('2020-01-01 12:00:00'), }) await database.create('temp1', { text: 'awesome bar' }) await database.create('temp1', { text: 'awesome baz' }) }) it('basic support', async () => { await expect(database.get('temp1', { id: { $eq: 2 }, })).eventually.to.have.length(1).with.nested.property('0.text').equal('awesome bar') await expect(database.get('temp1', { id: { $ne: 3 }, })).eventually.to.have.length(2).with.nested.property('0.text').equal('awesome foo') await expect(database.get('temp1', { id: { $gt: 1 }, })).eventually.to.have.length(2).with.nested.property('1.text').equal('awesome baz') await expect(database.get('temp1', { id: { $gte: 3 }, })).eventually.to.have.length(1).with.nested.property('0.text').equal('awesome baz') await expect(database.get('temp1', { id: { $lt: 1 }, })).eventually.to.have.length(0) await expect(database.get('temp1', { id: { $lte: 2 }, })).eventually.to.have.length(2).with.nested.property('0.text').equal('awesome foo') }) it('timestamp comparisons', async () => { await expect(database.get('temp1', { timestamp: { $gt: new Date('1999-01-01') }, })).eventually.to.have.length(1).with.nested.property('0.text').equal('awesome foo') await expect(database.get('temp1', { timestamp: { $lte: new Date('1999-01-01') }, })).eventually.to.have.length(0) nullableComparator && await expect(database.get('temp1', row => $.gt(row.timestamp, new Date('1999-01-01')) )).eventually.to.have.length(1).with.nested.property('0.text').equal('awesome foo') }) it('date comparisons', async () => { await expect(database.get('temp1', { date: { $gt: new Date('1999-01-01') }, })).eventually.to.have.length(1).with.nested.property('0.text').equal('awesome foo') await expect(database.get('temp1', { date: { $lte: new Date('1999-01-01') }, })).eventually.to.have.length(0) }) it('time comparisons', async () => { await expect(database.get('temp1', { // date should not matter time: { $gt: new Date('1970-01-01 11:00:00') }, })).eventually.to.have.length(1).with.nested.property('0.text').equal('awesome foo') await expect(database.get('temp1', { time: { $lte: new Date('1970-01-01 11:00:00') }, })).eventually.to.have.length(0) }) it('shorthand syntax', async () => { await expect(database.get('temp1', { id: 2, })).eventually.to.have.length(1).with.nested.property('0.text').equal('awesome bar') await expect(database.get('temp1', { timestamp: new Date('2000-01-01'), })).eventually.to.have.length(1).with.nested.property('0.text').equal('awesome foo') }) } export const existence = function Existence(database: Database<Tables>) { before(async () => { await database.remove('temp1', {}) await database.create('temp1', { date: new Date('2010-01-01') }) await database.create('temp1', { date: new Date('2020-01-01') }) await database.create('temp1', {}) }) it('basic support', async () => { await expect(database.get('temp1', { date: { $exists: true }, })).eventually.to.have.length(2) await expect(database.get('temp1', { date: { $exists: false }, })).eventually.to.have.length(1) }) it('shorthand syntax', async () => { await expect(database.get('temp1', { date: null, })).eventually.to.have.length(1) }) } export const membership = function Membership(database: Database<Tables>) { before(async () => { await database.remove('temp1', {}) await database.create('temp1', { value: 3 }) await database.create('temp1', { value: 4 }) await database.create('temp1', { value: 7 }) }) it('edge cases', async () => { await expect(database.get('temp1', { value: { $in: [] }, })).eventually.to.have.length(0) await expect(database.get('temp1', { value: { $nin: [] }, })).eventually.to.have.length(3) }) it('basic support', async () => { await expect(database.get('temp1', { value: { $in: [3, 4, 5] }, })).eventually.to.have.length(2) await expect(database.get('temp1', (row) => { return $.in(row.value, [3, 4, 5]) })).eventually.to.have.length(2) await expect(database.get('temp1', { value: { $nin: [4, 5, 6] }, })).eventually.to.have.length(2) }) it('shorthand syntax', async () => { await expect(database.get('temp1', { value: [], })).eventually.to.have.length(0) await expect(database.get('temp1', { value: [3, 4, 5], })).eventually.to.have.length(2) }) } interface RegExpOptions { regexBy?: boolean regexFor?: boolean } export const regexp = function RegularExpression(database: Database<Tables>, options: RegExpOptions = {}) { const { regexBy = true, regexFor = true } = options before(async () => { await database.remove('temp1', {}) await database.create('temp1', { text: 'awesome foo', regex: 'foo' }) await database.create('temp1', { text: 'awesome bar', regex: 'bar' }) await database.create('temp1', { text: 'awesome foo bar', regex: 'baz' }) await database.create('temp1', { text: 'xxx', regex: 'bAz' }) }) regexFor && it('$regexFor', async () => { await expect(database.get('temp1', { regex: { $regexFor: 'foo bar' }, })).eventually.to.have.length(2) await expect(database.get('temp1', { regex: { $regexFor: 'baz' }, })).eventually.to.have.length(1) await expect(database.get('temp1', { regex: { $regexFor: 'bAr' }, })).eventually.to.have.length(0) await expect(database.get('temp1', { regex: { $regexFor: { input: 'foo bar' } }, })).eventually.to.have.length(2) await expect(database.get('temp1', { regex: { $regexFor: { input: 'bAr', flags: 'i' } }, })).eventually.to.have.length(1) }) regexBy && it('$regexBy', async () => { await expect(database.get('temp1', { text: { $regex: /^.*foo.*$/ }, })).eventually.to.have.length(2) await expect(database.get('temp1', { text: { $regex: /^.*bar$/ }, })).eventually.to.have.length(2) await expect(database.get('temp1', { text: { $regex: /^.*bAr$/ }, })).eventually.to.have.length(0) await expect(database.get('temp1', { text: { $regex: /^.*bAr$/i }, })).eventually.to.have.length(2) await expect(database.get('temp1', { text: { $regex: { source: '^.*foo.*$' } }, })).eventually.to.have.length(2) }) regexBy && it('shorthand syntax', async () => { await expect(database.get('temp1', { text: /^.*foo$/, })).eventually.to.have.length(1).with.nested.property('[0].text').equal('awesome foo') }) regexBy && regexFor && it('$.regex', async () => { await expect(database.get('temp1', row => $.regex('foo bar', row.regex))).eventually.to.have.length(2) await expect(database.get('temp1', row => $.regex('baz', row.regex))).eventually.to.have.length(1) await expect(database.get('temp1', row => $.regex(row.text, /^.*foo.*$/))).eventually.to.have.length(2) await expect(database.get('temp1', row => $.regex(row.text, /^.*bar.*$/))).eventually.to.have.length(2) await expect(database.get('temp1', row => $.regex(row.text, row.regex))).eventually.to.have.length(2) await expect(database.get('temp1', row => $.regex(row.text, /^.*bAr.*$/i))).eventually.to.have.length(2) await expect(database.get('temp1', row => $.regex(row.text, /^.*bAr.*$/))).eventually.to.have.length(0) await expect(database.get('temp1', row => $.regex(row.text, '^.*bAr.*$', 'i'))).eventually.to.have.length(2) }) } export const bitwise = function Bitwise(database: Database<Tables>) { before(async () => { await database.remove('temp1', {}) await database.create('temp1', { value: 3 }) await database.create('temp1', { value: 4 }) await database.create('temp1', { value: 7 }) }) it('basic support', async () => { await expect(database.get('temp1', { value: { $bitsAllSet: 3 }, })).eventually.to.have.shape([{ value: 3 }, { value: 7 }]) await expect(database.get('temp1', { value: { $bitsAllClear: 9 }, })).eventually.to.have.shape([{ value: 4 }]) await expect(database.get('temp1', { value: { $bitsAnySet: 4 }, })).eventually.to.have.shape([{ value: 4 }, { value: 7 }]) await expect(database.get('temp1', { value: { $bitsAnyClear: 6 }, })).eventually.to.have.shape([{ value: 3 }, { value: 4 }]) }) it('using expressions', async () => { await expect(database.get('temp1', row => $.eq($.and(row.value, 1, 1), 1), )).eventually.to.have.shape([{ value: 3 }, { value: 7 }]) await expect(database.get('temp1', row => $.eq($.or(row.value, 3, 3), 7), )).eventually.to.have.shape([{ value: 4 }, { value: 7 }]) await expect(database.get('temp1', row => $.eq($.and(row.value, $.not(4)), 3), )).eventually.to.have.shape([{ value: 3 }, { value: 7 }]) await expect(database.get('temp1', row => $.eq($.xor(0, row.value, 3), 7), )).eventually.to.have.shape([{ value: 4 }]) await expect(database.eval('temp1', _ => $.max($.not(2 ** 30)))).eventually.to.deep.equal(-(2 ** 30) - 1) await expect(database.eval('temp1', _ => $.max($.not(-(2 ** 30))))).eventually.to.deep.equal(2 ** 30 - 1) await expect(database.eval('temp1', _ => $.max($.or(-(2 ** 30), 1)))).eventually.to.deep.equal(-(2 ** 30) + 1) await expect(database.eval('temp1', _ => $.max($.xor(2, 3, 6)))).eventually.to.deep.equal(7) await expect(database.eval('temp1', _ => $.array($.xor(true, false)))).eventually.to.include.members([true]) await expect(database.eval('temp1', _ => $.array($.xor(true, false, true)))).eventually.to.include.members([false]) await expect(database.eval('temp1', _ => $.max($.not(BigInt(2 ** 40))))).eventually.to.deep.equal(BigInt(-(2 ** 40) - 1)) await expect(database.eval('temp1', _ => $.max($.and(9223372036854775701n, 9223372036854775702n)))).eventually.to.deep.equal(9223372036854775700n) await expect(database.eval('temp1', _ => $.max($.or(9223372036854775701n, 1n)))).eventually.to.deep.equal(9223372036854775701n) await expect(database.eval('temp1', _ => $.max($.xor(9223372036854775701n, 9223372036854775702n)))).eventually.to.deep.equal(3n) await expect(database.eval('temp1', _ => $.max($.not(9223372036854775701n)))).eventually.to.deep.equal(-9223372036854775702n) }) } interface ListOptions { size?: boolean element?: boolean elementQuery?: boolean } export const list = function List(database: Database<Tables>, options: ListOptions = {}) { const { size = true, element = true, elementQuery = element } = options before(async () => { await database.remove('temp1', {}) await database.create('temp1', { id: 1, list: [] }) await database.create('temp1', { id: 2, list: [23] }) await database.create('temp1', { id: 3, list: [233] }) await database.create('temp1', { id: 4, list: [233, 332] }) }) size && it('$size', async () => { await expect(database.get('temp1', { list: { $size: 1 }, })).eventually.to.have.length(2).with.shape([{ id: 2 }, { id: 3 }]) await expect(database.get('temp1', { list: { $size: 0 }, })).eventually.to.have.length(1).with.shape([{ id: 1 }]) }) size && it('$.length', async () => { await expect(database.select('temp1') .project({ x: row => $.length(row.list) }) .orderBy(row => row.x) .execute() ).eventually.to.deep.equal([ { x: 0 }, { x: 1 }, { x: 1 }, { x: 2 }, ]) }) element && it('$el shorthand', async () => { await expect(database.get('temp1', { list: { $el: 233 }, })).eventually.to.have.length(2).with.shape([{ id: 3 }, { id: 4 }]) }) elementQuery && it('$el with field temp1', async () => { await expect(database.get('temp1', { list: { $el: { $lt: 50 } }, })).eventually.to.have.shape([{ id: 2 }]) }) } export const evaluation = function Evaluation(database: Database<Tables>) { before(async () => { await database.remove('temp1', {}) await database.create('temp1', { id: 1, value: 8 }) await database.create('temp1', { id: 2, value: 7 }) await database.create('temp1', { id: 3, value: 9 }) }) it('arithmetic operators', async () => { await expect(database.get('temp1', (row) => { return $.eq(9, $.add(row.id, row.value)) })).eventually.to.have.length(2).with.shape([{ id: 1 }, { id: 2 }]) }) } namespace Logical { export const queryLevel = function LogicalQueryLevel(database: Database<Tables>) { before(async () => { await database.remove('temp1', {}) await database.create('temp1', { id: 1 }) await database.create('temp1', { id: 2 }) await database.create('temp1', { id: 3 }) }) it('edge cases', async () => { await expect(database.get('temp1', {})).eventually.to.have.length(3) await expect(database.get('temp1', { $and: [] })).eventually.to.have.length(3) await expect(database.get('temp1', { $or: [] })).eventually.to.have.length(0) await expect(database.get('temp1', { $not: {} })).eventually.to.have.length(0) await expect(database.get('temp1', { $not: { $and: [] } })).eventually.to.have.length(0) await expect(database.get('temp1', { $not: { $or: [] } })).eventually.to.have.length(3) }) it('$or', async () => { await expect(database.get('temp1', { $or: [{ id: 1 }, { id: { $ne: 2 } }], })).eventually.to.have.length(2).with.shape([{ id: 1 }, { id: 3 }]) await expect(database.get('temp1', { $or: [{ id: 1 }, { id: { $eq: 2 } }], })).eventually.to.have.length(2).with.shape([{ id: 1 }, { id: 2 }]) await expect(database.get('temp1', { $or: [{ id: { $ne: 1 } }, { id: { $ne: 2 } }], })).eventually.to.have.length(3).with.shape([{ id: 1 }, { id: 2 }, { id: 3 }]) }) it('$and', async () => { await expect(database.get('temp1', { $and: [{ id: 1 }, { id: { $ne: 2 } }], })).eventually.to.have.length(1).with.shape([{ id: 1 }]) await expect(database.get('temp1', { $and: [{ id: 1 }, { id: { $eq: 2 } }], })).eventually.to.have.length(0) await expect(database.get('temp1', { $and: [{ id: { $ne: 1 } }, { id: { $ne: 2 } }], })).eventually.to.have.length(1).with.shape([{ id: 3 }]) }) it('$not', async () => { await expect(database.get('temp1', { $not: { id: 1 }, })).eventually.to.have.length(2).with.shape([{ id: 2 }, { id: 3 }]) await expect(database.get('temp1', { $not: { id: { $ne: 1 } }, })).eventually.to.have.length(1).with.shape([{ id: 1 }]) }) } export const fieldLevel = function LogicalFieldLevel(database: Database<Tables>) { before(async () => { await database.remove('temp1', {}) await database.create('temp1', { id: 1 }) await database.create('temp1', { id: 2 }) await database.create('temp1', { id: 3 }) }) it('edge cases', async () => { await expect(database.get('temp1', { id: {} })).eventually.to.have.length(3) await expect(database.get('temp1', { id: { $and: [] } })).eventually.to.have.length(3) await expect(database.get('temp1', { id: { $or: [] } })).eventually.to.have.length(0) await expect(database.get('temp1', { id: { $not: {} } })).eventually.to.have.length(0) await expect(database.get('temp1', { id: { $not: { $and: [] } } })).eventually.to.have.length(0) await expect(database.get('temp1', { id: { $not: { $or: [] } } })).eventually.to.have.length(3) }) it('$or', async () => { await expect(database.get('temp1', { id: { $or: [1, { $gt: 2 }] }, })).eventually.to.have.length(2).with.shape([{ id: 1 }, { id: 3 }]) await expect(database.get('temp1', { id: { $or: [1, { $gt: 2 }], $ne: 3 }, })).eventually.to.have.length(1).with.shape([{ id: 1 }]) }) it('$and', async () => { await expect(database.get('temp1', { id: { $and: [[1, 2], { $lt: 2 }] }, })).eventually.to.have.length(1).with.shape([{ id: 1 }]) await expect(database.get('temp1', { id: { $and: [[1, 2], { $lt: 2 }], $eq: 2 }, })).eventually.to.have.length(0) }) it('$not', async () => { await expect(database.get('temp1', { id: { $not: 1 }, })).eventually.to.have.length(2).with.shape([{ id: 2 }, { id: 3 }]) await expect(database.get('temp1', { id: { $not: 1, $lt: 3 }, })).eventually.to.have.length(1).with.shape([{ id: 2 }]) }) } } export const logical = Logical } export default QueryOperators