@minatojs/tests
Version:
Test Cases for Minato
511 lines (420 loc) • 18.6 kB
text/typescript
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