Fuse/test/logical-search.test.js
2020-06-23 18:47:29 -07:00

243 lines
5.4 KiB
JavaScript

const Fuse = require('../dist/fuse')
const Books = require('./fixtures/books.json')
const idx = (result) => result.map((obj) => obj.refIndex)
describe('Logical parser', () => {
const options = {
useExtendedSearch: true,
includeMatches: true,
includeScore: true,
keys: ['title', 'author.firstName', 'author.lastName']
}
test('Tree structure', () => {
const query = {
$and: [
{ title: 'old war' },
{
$or: [{ title: '!arts' }, { title: '^lock' }]
}
]
}
let root = Fuse.parseQuery(query, options, { auto: false })
expect(root).toMatchSnapshot()
})
test('Implicit operations', () => {
const query = {
$and: [
{ title: 'old war' },
{
$or: [{ title: '!arts', tags: 'kiro' }, { title: '^lock' }]
}
]
}
let root = Fuse.parseQuery(query, options, { auto: false })
expect(root).toMatchSnapshot()
})
})
describe('Searching using logical search', () => {
const options = {
useExtendedSearch: true,
includeMatches: true,
includeScore: true,
keys: ['title', 'author.firstName', 'author.lastName']
}
const fuse = new Fuse(Books, options)
test('Search: implicit AND', () => {
let result = fuse.search({ title: 'old man' })
expect(result.length).toBe(1)
expect(result[0].refIndex).toBe(0)
expect(result[0].matches[0].indices).toMatchObject([
[0, 2],
[4, 6]
])
})
test('Search: AND with single item', () => {
let result = fuse.search({ $and: [{ title: 'old man' }] })
expect(result.length).toBe(1)
expect(idx(result)).toMatchObject([0])
expect(result[0].matches[0].indices).toMatchObject([
[0, 2],
[4, 6]
])
})
test('Search: AND with multiple entries', () => {
let result = fuse.search({
$and: [{ 'author.lastName': 'Woodhose' }, { title: 'the' }]
})
expect(result.length).toBe(2)
expect(idx(result)).toMatchObject([4, 5])
})
test('Search: AND with multiple entries + exact match', () => {
let result = fuse.search({
$and: [{ 'author.lastName': 'Woodhose' }, { title: "'The" }]
})
expect(result.length).toBe(1)
expect(idx(result)).toMatchObject([4])
})
test('Search: OR with multiple entries', () => {
let result = fuse.search({
$or: [{ title: 'angls' }, { title: 'incmpetnce' }]
})
expect(result.length).toBe(3)
expect(idx(result)).toMatchObject([14, 7, 0])
})
test('Search: OR with multiple entries', () => {
let result = fuse.search({
$or: [
{ title: 'angls' },
{ $and: [{ title: '!dwarf' }, { title: 'bakwrds' }] }
]
})
expect(result.length).toBe(2)
expect(idx(result)).toMatchObject([7, 0])
})
})
describe('Multiple nested conditions', () => {
const list1 = [
{
title: "Old Man's War",
author: {
firstName: 'John',
lastName: 'Scalzi',
age: '61'
}
}
]
const list2 = [
...list1,
{
title: "Old Man's War",
author: {
firstName: 'John',
lastName: 'Scalzi',
age: '62'
}
}
]
const options = {
includeScore: true,
useExtendedSearch: true,
keys: ['title', 'author.firstName', 'author.lastName', 'author.age']
}
const fuse1 = new Fuse(list1, options)
const fuse2 = new Fuse(list2, options)
test('Search: nested AND + OR', () => {
const result = fuse1.search({
$and: [
{ title: 'old' },
{
$or: [{ 'author.firstName': 'j' }, { 'author.lastName': 'Sa' }]
},
{
$or: [{ 'author.age': "'62" }]
}
]
})
expect(result.length).toBe(0)
})
test('Search: deep nested AND + OR', () => {
const result = fuse1.search({
$and: [
{ title: 'old' },
{
$or: [{ 'author.firstName': 'jon' }, { 'author.lastName': 'Sazi' }]
},
{
$or: [
{ 'author.age': "'62" },
{ $and: [{ title: 'old' }, { 'author.age': "'61" }] }
]
}
]
})
expect(result.length).toBe(1)
expect(result[0]).toHaveProperty('score')
expect(result[0].score).toBeGreaterThan(0)
})
test('Search: deep nested AND + OR', () => {
const result = fuse2.search({
$and: [
{ title: 'old' },
{
$and: [{ 'author.firstName': 'jon' }, { 'author.lastName': 'Sazi' }]
},
{
$or: [
{ 'author.age': "'62" },
{ $and: [{ title: 'old' }, { 'author.age': "'62" }] }
]
}
]
})
expect(result.length).toBe(1)
expect(result[0]).toHaveProperty('score')
expect(result[0].score).toBeGreaterThan(0)
})
})
describe('Logical search with dotted keys', () => {
const list = [
{
title: "Old Man's War",
author: {
'first.name': 'John',
'last.name': 'Scalzi',
age: '61'
}
}
]
const options = {
useExtendedSearch: true,
includeScore: true,
keys: [
'title',
['author', 'first.name'],
['author', 'last.name'],
'author.age'
]
}
const fuse = new Fuse(list, options)
test('Search: deep nested AND + OR', () => {
const query = {
$and: [
{
$path: ['author', 'first.name'],
$val: 'jon'
},
{
$path: ['author', 'last.name'],
$val: 'scazi'
}
]
}
const result = fuse.search(query)
expect(result.length).toBe(1)
})
})