1
0
mirror of https://github.com/nextapps-de/flexsearch.git synced 2025-10-01 15:46:40 +02:00
Files
flexsearch/test/test.js
Thomas Wilkerling 2de3f31fe6 FIX tests
2021-06-05 13:39:02 +02:00

2969 lines
85 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

if(typeof module !== "undefined"){
var env = (process.argv[3] === "test" ? "min" : process.argv[3] === "test/" ? "light" : process.argv[3] === "test/test.js" ? "pre" : "");
var expect = require("chai").expect;
var FlexSearch = require("../" + (env ? "dist/": "") + "flexsearch" + (env ? "." + env : "") + ".js");
//require("../lang/en.min.js");
}
var flexsearch_default;
var flexsearch_sync;
var flexsearch_async;
var flexsearch_worker;
var flexsearch_cache;
var flexsearch_icase;
var flexsearch_simple;
var flexsearch_advanced;
var flexsearch_extra;
var flexsearch_custom;
var flexsearch_strict;
var flexsearch_forward;
var flexsearch_reverse;
var flexsearch_full;
var flexsearch_ngram;
// ------------------------------------------------------------------------
// Acceptance Tests
// ------------------------------------------------------------------------
describe("Initialize", function(){
it("Should have been initialized successfully", function(){
flexsearch_default = new FlexSearch();
flexsearch_sync = new FlexSearch({
tokenize: "forward",
//encode: false,
async: false,
worker: false
});
flexsearch_async = FlexSearch({
tokenize: "forward",
//encode: false,
async: true,
worker: false
});
flexsearch_icase = new FlexSearch({
charset: "latin:default",
async: false,
worker: false
});
flexsearch_simple = FlexSearch({
charset: "latin:simple",
async: false,
worker: false
});
flexsearch_advanced = new FlexSearch({
charset: "latin:advanced",
async: false,
worker: false
});
flexsearch_extra = FlexSearch({
charset: "latin:extra",
async: false,
worker: false
});
flexsearch_custom = new FlexSearch({
encode: test_encoder,
async: false,
worker: false
});
flexsearch_strict = new FlexSearch({
charset: "latin",
tokenize: "strict",
async: false,
worker: false
});
flexsearch_forward = new FlexSearch({
charset: "latin",
tokenize: "forward",
async: false,
worker: false
});
flexsearch_reverse = new FlexSearch({
charset: "latin",
tokenize: "reverse",
resolution: 10,
async: false,
worker: false
});
flexsearch_full = new FlexSearch({
charset: "latin",
tokenize: "full",
async: false,
worker: false
});
flexsearch_ngram = new FlexSearch({
charset: "latin:advanced",
tokenize: "ngram",
async: false,
worker: false
});
flexsearch_cache = new FlexSearch({
charset: "latin",
tokenize: "reverse",
cache: 2
});
it("Should have correct constructors", function(){
expect(flexsearch_default).to.be.an.instanceOf(FlexSearch);
expect(flexsearch_sync).to.be.an.instanceOf(FlexSearch);
expect(flexsearch_async).to.be.an.instanceOf(FlexSearch);
});
it("Should have correct uuids", function(){
expect(flexsearch_default.id).to.equal(0);
expect(flexsearch_sync.id).to.equal(1);
expect(flexsearch_async.id).to.equal(2);
expect(flexsearch_icase.id).to.equal(3);
expect(flexsearch_simple.id).to.equal(4);
expect(flexsearch_advanced.id).to.equal(5);
expect(flexsearch_extra.id).to.equal(6);
});
});
it("Should have all provided methods", function(){
expect(flexsearch_default).to.respondTo("search");
expect(flexsearch_default).to.respondTo("add");
expect(flexsearch_default).to.respondTo("update");
expect(flexsearch_default).to.respondTo("remove");
expect(flexsearch_default).to.respondTo("clear");
expect(flexsearch_default).to.respondTo("init");
expect(flexsearch_default).to.respondTo("destroy");
expect(flexsearch_default).to.hasOwnProperty("length");
expect(flexsearch_default).to.hasOwnProperty("index");
if(env !== "light"){
expect(flexsearch_default).to.respondTo("where");
expect(flexsearch_default).to.respondTo("find");
}
if(env !== "light" && env !== "min"){
expect(flexsearch_default).to.respondTo("info");
}
});
it("Should have the correct options", function(){
if(env !== "light"){
expect(flexsearch_default.async).to.not.equal(true);
expect(flexsearch_sync.async).to.not.equal(true);
expect(flexsearch_async.async).to.equal(true);
}
if((env !== "light") && (env !== "min") && (env !== "pre")){
expect(flexsearch_default.tokenize).to.equal("forward");
expect(flexsearch_strict.tokenize).to.equal("strict");
expect(flexsearch_forward.tokenize).to.equal("forward");
expect(flexsearch_reverse.tokenize).to.equal("reverse");
expect(flexsearch_full.tokenize).to.equal("full");
expect(flexsearch_ngram.tokenize).to.equal("ngram");
}
// not available in compiled version:
if(typeof flexsearch_custom.encoder !== "undefined"){
expect(flexsearch_custom.encoder).to.equal(test_encoder);
}
});
});
describe("Add (Sync)", function(){
it("Should have been added to the index", function(){
flexsearch_sync.add(0, "foo");
flexsearch_sync.add(2, "bar");
flexsearch_sync.add(1, "foobar");
expect(flexsearch_sync.index).to.have.members(["0", "1", "2"]);
expect(flexsearch_sync.length).to.equal(3);
});
it("Should not have been added to the index", function(){
flexsearch_sync.add("foo");
flexsearch_sync.add(3);
flexsearch_sync.add(null, "foobar");
flexsearch_sync.add(void 0, "foobar");
flexsearch_sync.add(3, null);
flexsearch_sync.add(3, false);
flexsearch_sync.add(3, []);
flexsearch_sync.add(3, {});
flexsearch_sync.add(3, function(){});
expect(flexsearch_sync.length).to.equal(3);
flexsearch_extra.add(3, "");
flexsearch_extra.add(3, " ");
flexsearch_extra.add(3, " ");
flexsearch_extra.add(3, " - ");
if(env !== "light"){
expect(flexsearch_extra.length).to.equal(0);
}
else{
expect(flexsearch_extra.length).to.equal(1);
}
});
});
describe("Search (Sync)", function(){
it("Should have been matched from index", function(){
expect(flexsearch_sync.search("foo")).to.have.members([0, 1]);
expect(flexsearch_sync.search("bar")).to.include(2);
expect(flexsearch_sync.search("foobar")).to.include(1);
expect(flexsearch_sync.search("foo foo")).to.have.members([0, 1]);
expect(flexsearch_sync.search("foo foo")).to.have.members([0, 1]);
if(env !== "light"){
flexsearch_extra.add(4, "Thomas");
flexsearch_extra.add(5, "Arithmetic");
flexsearch_extra.add(6, "Mahagoni");
expect(flexsearch_extra.search("tomass")).to.include(4);
expect(flexsearch_extra.search("arytmetik")).to.include(5);
expect(flexsearch_extra.search("mahagony")).to.include(6);
}
});
it("Should have been limited", function(){
expect(flexsearch_sync.search("foo", 1)).to.include(0);
expect(flexsearch_sync.search({query: "foo", limit: 1})).to.include(0);
expect(flexsearch_sync.search("foo", 1)).to.not.include(1);
});
it("Should not have been matched from index", function(){
expect(flexsearch_sync.search("barfoo")).to.have.lengthOf(0);
expect(flexsearch_sync.search("")).to.have.lengthOf(0);
expect(flexsearch_sync.search(" ")).to.have.lengthOf(0);
expect(flexsearch_sync.search(" - ")).to.have.lengthOf(0);
expect(flexsearch_sync.search(" o ")).to.have.lengthOf(0);
});
});
describe("Update (Sync)", function(){
it("Should have been updated to the index", function(){
flexsearch_sync.update(0, "bar");
flexsearch_sync.update(2, "foobar");
flexsearch_sync.update(1, "foo");
expect(flexsearch_sync.length).to.equal(3);
expect(flexsearch_sync.search("foo")).to.have.members([2, 1]);
expect(flexsearch_sync.search("bar")).to.include(0);
expect(flexsearch_sync.search("bar")).to.not.include(2);
expect(flexsearch_sync.search("foobar")).to.include(2);
// bypass update:
flexsearch_sync.add(2, "bar");
flexsearch_sync.add(0, "foo");
flexsearch_sync.add(1, "foobar");
expect(flexsearch_sync.length).to.equal(3);
expect(flexsearch_sync.search("foo")).to.have.members([0, 1]);
expect(flexsearch_sync.search("bar")).to.include(2);
expect(flexsearch_sync.search("foobar")).to.include(1);
});
it("Should not have been updated to the index", function(){
flexsearch_sync.update("foo");
flexsearch_sync.update(0);
flexsearch_sync.update(null, "foobar");
flexsearch_sync.update(void 0, "foobar");
flexsearch_sync.update(1, null);
flexsearch_sync.update(2, false);
flexsearch_sync.update(0, []);
flexsearch_sync.update(1, {});
flexsearch_sync.update(2, function(){});
expect(flexsearch_sync.length).to.equal(3);
expect(flexsearch_sync.search("foo")).to.have.members([0, 1]);
expect(flexsearch_sync.search("bar")).to.include(2);
expect(flexsearch_sync.search("foobar")).to.include(1);
});
});
describe("Remove (Sync)", function(){
it("Should have been removed from the index", function(){
flexsearch_sync.remove(0);
flexsearch_sync.remove(2);
flexsearch_sync.remove(1);
expect(flexsearch_sync.length).to.equal(0);
expect(flexsearch_sync.search("foo")).to.have.lengthOf(0);
expect(flexsearch_sync.search("bar")).to.have.lengthOf(0);
expect(flexsearch_sync.search("foobar")).to.have.lengthOf(0);
});
});
// ------------------------------------------------------------------------
// Scoring
// ------------------------------------------------------------------------
describe("Apply Sort by Scoring", function(){
it("Should have been sorted properly by scoring", function(){
flexsearch_sync.add(0, "foo bar foobar");
flexsearch_sync.add(2, "bar foo foobar");
flexsearch_sync.add(1, "foobar foo bar");
expect(flexsearch_sync.length).to.equal(3);
expect(flexsearch_sync.search("foo")[0]).to.equal(0);
expect(flexsearch_sync.search("foo")[1]).to.equal(1);
expect(flexsearch_sync.search("foo")[2]).to.equal(2);
expect(flexsearch_sync.search("bar")[0]).to.equal(2);
expect(flexsearch_sync.search("bar")[1]).to.equal(0); // partial scoring!
expect(flexsearch_sync.search("bar")[2]).to.equal(1);
expect(flexsearch_sync.search("foobar")[0]).to.equal(1);
expect(flexsearch_sync.search("foobar")[1]).to.equal(0);
expect(flexsearch_sync.search("foobar")[2]).to.equal(2);
});
it("Should have been sorted properly by threshold", function(){
flexsearch_reverse.add(0, "foobarxxx foobarfoobarfoobarxxx foobarfoobarfoobaryyy foobarfoobarfoobarzzz");
expect(flexsearch_reverse.search("xxx").length).to.equal(1);
expect(flexsearch_reverse.search("yyy").length).to.equal(1);
expect(flexsearch_reverse.search("zzz").length).to.equal(1);
expect(flexsearch_reverse.search({query: "xxx", threshold: 2}).length).to.equal(1);
expect(flexsearch_reverse.search({query: "xxx", threshold: 3}).length).to.equal(1);
expect(flexsearch_reverse.search({query: "xxx", threshold: 5}).length).to.equal(1);
expect(flexsearch_reverse.search({query: "xxx", threshold: 7}).length).to.equal(0); // <-- stop
expect(flexsearch_reverse.search({query: "yyy", threshold: 0}).length).to.equal(1);
expect(flexsearch_reverse.search({query: "yyy", threshold: 2}).length).to.equal(1);
expect(flexsearch_reverse.search({query: "yyy", threshold: 5}).length).to.equal(0); // <-- stop
expect(flexsearch_reverse.search({query: "zzz", threshold: 0}).length).to.equal(1);
expect(flexsearch_reverse.search({query: "zzz", threshold: 1}).length).to.equal(1);
expect(flexsearch_reverse.search({query: "zzz", threshold: 3}).length).to.equal(0); // <-- stop
});
});
// ------------------------------------------------------------------------
// Async Tests
// ------------------------------------------------------------------------
if(env !== "light"){
describe("Add (Async)", function(){
it("Should have been added to the index", function(done){
var index = new FlexSearch();
expect(index.length).to.equal(0);
index.add(0, "foo", function(){
expect(index.length).to.equal(1);
done();
});
expect(index.length).to.equal(0);
});
it("Should have been added to the index", function(done){
expect(flexsearch_async.length).to.equal(0);
flexsearch_async.add(0, "foo", function(){
done();
});
expect(flexsearch_async.length).to.equal(0);
});
it("Should have been added to the index", function(done){
expect(flexsearch_async.length).to.equal(1);
flexsearch_async.add(2, "bar");
flexsearch_async.add(1, "foobar");
expect(flexsearch_async.length).to.equal(1);
setTimeout(function(){
expect(flexsearch_async.length).to.equal(3);
expect(flexsearch_async.index).to.have.members(["0", "1", "2"]);
done();
}, 25);
});
it("Should not have been added to the index", function(done){
flexsearch_async.add("foo");
flexsearch_async.add(3);
flexsearch_async.add(null, "foobar");
flexsearch_async.add(void 0, "foobar");
flexsearch_async.add(3, null);
flexsearch_async.add(3, false);
flexsearch_async.add(3, []);
flexsearch_async.add(3, {});
flexsearch_async.add(3, function(){});
setTimeout(function(){
expect(flexsearch_async.length).to.equal(3);
expect(flexsearch_async.index).to.have.members(["0", "1", "2"]);
done();
}, 25);
});
});
describe("Search (Async)", function(){
it("Should have been matched from index", function(done){
var index = new FlexSearch({doc: {id: "id", field: "title"}});
var data = {id: 0, title: "foo"};
index.add(data);
index.search("foo", function(result){
expect(result).to.have.members([data]);
done();
});
});
it("Should have been matched from index", function(done){
flexsearch_async.search("foo", function(result){
expect(result).to.have.members([0, 1]);
});
flexsearch_async.search("bar", function(result){
expect(result).to.include(2);
});
flexsearch_async.search("foobar", function(result){
expect(result).to.include(1);
done();
});
});
it("Should have been limited", function(done){
flexsearch_async.search("foo", 1, function(result){
expect(result).to.include(0);
expect(result).to.not.include(1);
done();
});
});
it("Should not have been matched from index", function(done){
flexsearch_async.search("barfoo", function(result){
expect(result).to.have.lengthOf(0);
});
flexsearch_async.search("", function(result){
expect(result).to.have.lengthOf(0);
});
flexsearch_async.search(" ", function(result){
expect(result).to.have.lengthOf(0);
});
flexsearch_async.search(" o ", function(result){
expect(result).to.have.lengthOf(0);
done();
});
});
});
describe("Update (Async)", function(){
it("Should have been updated to the index", function(done){
flexsearch_async.update(0, "bar");
flexsearch_async.update(2, "foobar");
flexsearch_async.update(1, "foo");
setTimeout(function(){
expect(flexsearch_async.length).to.equal(3);
flexsearch_async.search("foo", function(result){
expect(result).to.have.members([2, 1]);
});
flexsearch_async.search("bar", function(result){
expect(result).to.include(0);
});
flexsearch_async.search("bar", function(result){
expect(result).to.not.include(2);
});
flexsearch_async.search("foobar", function(result){
expect(result).to.include(2);
done();
});
}, 25);
});
it("Should not have been updated to the index", function(done){
flexsearch_async.update("foo");
flexsearch_async.update(0);
flexsearch_async.update(null, "foobar");
flexsearch_async.update(void 0, "foobar");
flexsearch_async.update(1, null);
flexsearch_async.update(2, false);
flexsearch_async.update(0, []);
flexsearch_async.update(1, {});
flexsearch_async.update(2, function(){});
setTimeout(function(){
expect(flexsearch_async.length).to.equal(3);
flexsearch_async.search("foo").then(function(result){
expect(result).to.have.members([2, 1]);
});
flexsearch_async.search("bar").then(function(result){
expect(result).to.include(0);
});
flexsearch_async.search("bar").then(function(result){
expect(result).to.not.include(2);
});
flexsearch_async.search("foobar").then(function(result){
expect(result).to.include(2);
done();
});
}, 25);
});
});
describe("Remove (Async)", function(){
it("Should have been removed from the index", function(done){
var index = new FlexSearch();
index.add(0, "foo");
expect(index.length).to.equal(1);
index.remove(0, function(){
expect(index.length).to.equal(0);
done();
});
expect(index.length).to.equal(1);
});
it("Should have been removed from the index", function(done){
expect(flexsearch_async.length).to.equal(3);
flexsearch_async.remove(0, function(){
expect(flexsearch_async.length).to.equal(2);
done();
});
expect(flexsearch_async.length).to.equal(3);
});
it("Should have been removed from the index", function(done){
flexsearch_async.remove(2);
flexsearch_async.remove(1).then(function(){
expect(flexsearch_async.length).to.equal(0);
});
expect(flexsearch_async.length).to.equal(2);
flexsearch_async.search("foo", function(result){
expect(result).to.have.lengthOf(0);
});
flexsearch_async.search("bar", function(result){
expect(result).to.have.lengthOf(0);
});
flexsearch_async.search("foobar", function(result){
expect(result).to.have.lengthOf(0);
done();
});
});
});
// ------------------------------------------------------------------------
// Worker Tests
// ------------------------------------------------------------------------
if(typeof Worker !== "undefined" && !this._phantom){
describe("Add (Worker)", function(){
it("Should support worker", function(){
flexsearch_worker = new FlexSearch({
charset: "latin:default",
tokenize: "reverse",
async: false,
worker: 4
});
});
it("Should have been added to the index", function(done){
flexsearch_worker.add(0, "foo");
flexsearch_worker.add(2, "bar");
flexsearch_worker.add(1, "foobar");
setTimeout(function(){
expect(flexsearch_worker.length).to.equal(3);
expect(flexsearch_worker.index).to.have.members(["0", "1", "2"]);
flexsearch_worker.search("foo", function(result){
expect(result).to.have.length(2);
expect(result).to.have.members([0, 1]);
done();
});
}, 25);
});
it("Should not have been added to the index", function(done){
flexsearch_worker.add("foo");
flexsearch_worker.add(3);
flexsearch_worker.add(null, "foobar");
flexsearch_worker.add(void 0, "foobar");
flexsearch_worker.add(4, null);
flexsearch_worker.add(5, false);
flexsearch_worker.add(6, []);
flexsearch_worker.add(7, {});
flexsearch_worker.add(8, function(){
});
setTimeout(function(){
expect(flexsearch_worker.length).to.equal(3);
expect(flexsearch_worker.index).to.have.members(["0", "1", "2"]);
done();
}, 25);
});
});
describe("Search (Worker)", function(){
it("Should have been matched from index", function(done){
flexsearch_worker.search("foo", function(result){
expect(result).to.have.lengthOf(2);
flexsearch_worker.search("bar", function(result){
expect(result).to.have.lengthOf(2);
flexsearch_worker.search("foobar", function(result){
expect(result).to.have.lengthOf(1);
done();
});
});
});
});
it("Should have been limited", function(done){
flexsearch_worker.search("foo", 1, function(result){
expect(result).to.have.lengthOf(1);
done();
});
});
it("Should not have been matched from index", function(done){
flexsearch_worker.search("barfoo", function(result){
expect(result).to.have.lengthOf(0);
flexsearch_worker.search("", function(result){
expect(result).to.have.lengthOf(0);
flexsearch_worker.search(" ", function(result){
expect(result).to.have.lengthOf(0);
flexsearch_worker.search(" o ", function(result){
expect(result).to.have.lengthOf(1);
flexsearch_worker.search(" fob ", function(result){
expect(result).to.have.lengthOf(0);
done();
});
});
});
});
});
});
});
describe("Update (Worker)", function(){
it("Should have been updated to the index", function(done){
flexsearch_worker.update(0, "bar");
flexsearch_worker.update(2, "foobar");
flexsearch_worker.update(1, "foo", function(){
expect(flexsearch_worker.length).to.equal(3);
flexsearch_worker.search("foo", function(results){
expect(results).to.have.members([2, 1]);
flexsearch_worker.search("bar", function(results){
expect(results).to.have.members([0, 2]);
flexsearch_worker.search("foobar", function(results){
expect(results).to.have.members([2]);
done();
});
});
});
});
});
});
describe("Remove (Worker)", function(){
it("Should have been removed from the index", function(done){
expect(flexsearch_worker.length).to.equal(3);
flexsearch_worker.remove(0);
flexsearch_worker.remove(2);
flexsearch_worker.remove(1);
expect(flexsearch_worker.length).to.equal(0);
flexsearch_worker.search("foo", function(results){
expect(results).to.not.include(1);
expect(results).to.not.include(2);
flexsearch_worker.search("bar", function(results){
expect(results).to.not.include(0);
expect(results).to.not.include(2);
flexsearch_worker.search("foobar", function(results){
expect(results).to.not.include(2);
done();
});
});
});
});
if((env !== "light") && (env !== "min")){
it("Should have been debug mode activated", function(){
flexsearch_worker.info();
});
}
});
}
describe("Worker Not Supported", function(){
it("Should not support worker", function(){
if(typeof Worker !== "undefined"){
Worker = void 0;
}
flexsearch_worker = new FlexSearch({
encode: false,
async: false,
worker: 4
});
if((env !== "min") && (env !== "pre")){
expect(flexsearch_worker.info().worker).to.equal(false);
}
});
});
}
// ------------------------------------------------------------------------
// Phonetic Tests
// ------------------------------------------------------------------------
describe("Encoding", function(){
it("Should have been encoded properly: iCase", function(){
expect(flexsearch_icase.encode("Björn-Phillipp Mayer")).to.eql(flexsearch_icase.encode("björn-phillipp mayer"));
});
if(env !== "light"){
it("Should have been encoded properly: Simple", function(){
expect(flexsearch_simple.encode("Björn-Phillipp Mayer")).to.eql(flexsearch_simple.encode("bjorn/phillipp mayer"));
});
it("Should have been encoded properly: Advanced", function(){
expect(flexsearch_advanced.encode("Björn-Phillipp Mayer")).to.eql(flexsearch_advanced.encode("bjoern filip mair"));
});
it("Should have been encoded properly: Extra", function(){
expect(flexsearch_extra.encode("Björn-Phillipp Mayer")).to.eql(flexsearch_extra.encode("bjorm filib mayr"));
});
}
it("Should have been encoded properly: Custom Encoder", function(){
expect(flexsearch_custom.encode("Björn-Phillipp Mayer")).to.eql("-[BJÖRN-PHILLIPP MAYER]-");
});
// it("Should have been encoded properly: Custom Encoder", function(){
//
// FlexSearch.registerEncoder("custom", test_encoder);
//
// expect(FlexSearch.encode("custom", "Björn-Phillipp Mayer")).to.eql(flexsearch_custom.encode("Björn-Phillipp Mayer"));
// });
});
// ------------------------------------------------------------------------
// Word Break
// ------------------------------------------------------------------------
describe("CJK Word Break", function(){
it("Should have been tokenized properly", function(){
var index = FlexSearch({
charset: "cjk"
});
index.add(0, "서울시가 잠이 든 시간에 아무 말, 미뤄, 미뤄");
expect(index.search("든")).to.include(0);
expect(index.search("시간에")).to.include(0);
index.add(1, "一个单词");
expect(index.search("单词")).to.include(1);
});
});
describe("Cyrillic Word Break", function(){
it("Should have been tokenized properly", function(){
var index = FlexSearch({
charset: "cyrillic",
tokenize: "reverse"
});
index.add(0, "Фообар");
expect(index.search("Фообар")).to.include(0);
expect(index.search("бар")).to.include(0);
});
});
describe("Arabic Word Break", function(){
it("Should have been tokenized properly", function(){
var index = FlexSearch({
charset: "arabic"
});
index.add(0, "لكن لا بد أن أوضح لك أن كل");
expect(index.search("بد أن")).to.include(0);
});
});
// ------------------------------------------------------------------------
// Right-To-Left
// ------------------------------------------------------------------------
describe("RTL Support", function(){
it("Should have been scored properly", function(){
var index = new FlexSearch({
tokenize: "reverse",
rtl: true
});
index.add(0, "54321 4 3 2 1 0");
index.add(1, "0 1 2 3 4 54321");
index.add(2, "0 1 2 3 4 12345");
expect(index.search("5")[0]).to.equal(2);
expect(index.search("5")[1]).to.equal(1);
expect(index.search("5")[2]).to.equal(0);
});
});
// ------------------------------------------------------------------------
// Contextual Indexing
// ------------------------------------------------------------------------
describe("Context", function(){
it("Should have been added properly to the context", function(){
var flexsearch_depth = new FlexSearch({
tokenize: "strict",
depth: 2,
async: false,
worker: false
});
flexsearch_depth.add(0, "zero one two three four five six seven eight nine ten");
expect(flexsearch_depth.length).to.equal(1);
expect(flexsearch_depth.search("zero one")).to.include(0);
expect(flexsearch_depth.search("zero two")).to.include(0);
expect(flexsearch_depth.search("zero three").length).to.equal(0);
expect(flexsearch_depth.search("three seven").length).to.equal(0);
expect(flexsearch_depth.search("three five seven")).to.include(0);
expect(flexsearch_depth.search("eight six four")).to.include(0);
// TODO
// expect(flexsearch_depth.search("three seven five")).to.include(0);
expect(flexsearch_depth.search("three foobar seven").length).to.equal(0);
expect(flexsearch_depth.search("eight ten")).to.include(0);
expect(flexsearch_depth.search("seven ten").length).to.equal(0);
flexsearch_depth.add(1, "1 2 3 1 4 2 5 1");
expect(flexsearch_depth.search("1")).to.include(1);
expect(flexsearch_depth.search("1 5")).to.include(1);
expect(flexsearch_depth.search("2 4 1")).to.include(1);
});
});
// ------------------------------------------------------------------------
// Tokenizer Tests
// ------------------------------------------------------------------------
describe("Options", function(){
it("Should have been added properly to the index: Strict", function(){
flexsearch_strict.add(0, "björn phillipp mayer");
expect(flexsearch_strict.length).to.equal(1);
expect(flexsearch_strict.search("björn phillipp")).to.include(0);
expect(flexsearch_strict.search("björn mayer")).to.include(0);
});
it("Should have been added properly to the index: Forward", function(){
flexsearch_forward.add(0, "björn phillipp mayer");
expect(flexsearch_forward.length).to.equal(1);
expect(flexsearch_forward.search("bjö phil may")).to.have.lengthOf(1);
expect(flexsearch_forward.search("bjö phil may")).to.include(0);
});
it("Should have been added properly to the index: Inverse", function(){
flexsearch_reverse.add(0, "björn phillipp mayer");
expect(flexsearch_reverse.length).to.equal(1);
expect(flexsearch_reverse.search("jörn phil er")).to.have.lengthOf(1);
expect(flexsearch_reverse.search("jörn lipp er")).to.have.lengthOf(1);
expect(flexsearch_reverse.search("jörn lipp er")).to.include(0);
});
it("Should have been added properly to the index: Full", function(){
flexsearch_full.add(0, "björn phillipp mayer");
expect(flexsearch_full.length).to.equal(1);
expect(flexsearch_full.search("jör illi may")).to.have.lengthOf(1);
expect(flexsearch_full.search("jör illi may")).to.include(0);
});
if(env !== "light"){
it("Should have been added properly to the index: Full", function(){
flexsearch_ngram.add(0, "björn-phillipp mayer");
expect(flexsearch_ngram.length).to.equal(1);
expect(flexsearch_ngram.search("mayer")).to.have.lengthOf(1);
expect(flexsearch_ngram.search("philip meier")).to.have.lengthOf(1);
expect(flexsearch_ngram.search("philip meier")).to.include(0);
expect(flexsearch_ngram.search("björn meier")).to.have.lengthOf(1);
expect(flexsearch_ngram.search("björn meier")).to.include(0);
expect(flexsearch_ngram.search("björn-peter mayer")).to.have.lengthOf(0);
});
}
});
// ------------------------------------------------------------------------
// Filter Tests
// ------------------------------------------------------------------------
describe("Filter", function(){
it("Should have been filtered properly", function(){
var index = new FlexSearch({
tokenize: "strict",
filter: ["in", "the"]
});
index.add(0, "Today in the morning.");
expect(index.length).to.equal(1);
expect(index.search("today in the morning.")).to.include(0);
expect(index.search("today morning")).to.include(0);
expect(index.search("in the")).to.have.length(0);
});
// it("Should have been filtered properly (custom function)", function(){
//
// var index = new FlexSearch({
//
// tokenize: "strict",
// filter: function(word){
// return word.length > 3;
// }
// });
//
// index.add(0, "Today in the morning.");
//
// expect(index.length).to.equal(1);
// expect(index.search("today in the morning.")).to.include(0);
// expect(index.search("today morning")).to.include(0);
// expect(index.search("in the")).to.have.length(0);
// });
});
describe("Stemmer", function(){
it("Should have been stemmed properly", function(){
var index = new FlexSearch({
tokenize: "reverse",
stemmer: {
"ization": "ize",
"tional": "tion"
}
});
index.add(0, "Just a multinational colonization.");
expect(index.length).to.equal(1);
expect(index.search("Just a multinational colonization.")).to.include(0);
expect(index.search("multinational colonization")).to.include(0);
expect(index.search("tional tion")).to.have.length(0);
});
it("Should have been stemmed properly (custom function)", function(){
var stems = {
"ization": "ize",
"tional": "tion"
};
var index = new FlexSearch({
tokenize: "strict",
stemmer: function(word){
return stems[word] || word;
}
});
index.add(0, "Just a multinational colonization.");
expect(index.length).to.equal(1);
expect(index.search("Just a multinational colonization.")).to.include(0);
expect(index.search("multinational colonization")).to.include(0);
expect(index.search("tional tion")).to.have.length(0);
});
});
describe("Custom Language", function(){
it("Should have been applied properly", function(){
var index = new FlexSearch({
tokenize: "reverse",
filter: ["a", "an"],
stemmer: {
"ization": "ize",
"tional": "tion"
}
});
index.add(0, "Just a multinational colonization.");
expect(index.length).to.equal(1);
expect(index.search("Just a multinational colonization.")).to.include(0);
expect(index.search("Just an multinational colonization.")).to.include(0);
expect(index.search("multinational colonization")).to.include(0);
expect(index.search("tional tion")).to.have.length(0);
FlexSearch.registerLanguage("custom", {
filter: ["a", "an"],
stemmer: {
"ization": "ize",
"tional": "tion"
}
});
index = new FlexSearch({
tokenize: "reverse",
lang: "custom"
});
index.add(0, "Just a multinational colonization.");
expect(index.length).to.equal(1);
expect(index.search("Just a multinational colonization.")).to.include(0);
expect(index.search("Just an multinational colonization.")).to.include(0);
expect(index.search("multinational colonization")).to.include(0);
expect(index.search("tional tion")).to.have.length(0);
});
});
// ------------------------------------------------------------------------
// Relevance Tests
// ------------------------------------------------------------------------
describe("Relevance", function(){
it("Should have been sorted by relevance properly", function(){
var index = new FlexSearch({
charset: "latin:advanced",
tokenize: "strict"
});
index.add(0, "1 2 3 2 4 1 5 3");
index.add(1, "zero one two three four five six seven eight nine ten");
index.add(2, "four two zero one three ten five seven eight six nine");
expect(index.search("1")).to.have.members([0]);
expect(index.search("one")).to.have.members([1, 2]);
expect(index.search("one two")).to.have.members([1, 2]);
expect(index.search("four one")).to.have.members([1, 2]);
index = new FlexSearch({
charset: "latin:advanced",
tokenize: "strict",
threshold: 5,
depth: 3
});
index.add(0, "1 2 3 2 4 1 5 3");
index.add(1, "zero one two three four five six seven eight nine ten");
index.add(2, "four two zero one three ten five seven eight six nine");
expect(index.search("1")).to.have.members([0]);
expect(index.search("one")).to.have.members([1, 2]);
expect(index.search("one two")).to.have.members([1, 2]);
expect(index.search("four one")).to.have.members([1, 2]);
index = new FlexSearch({
charset: "latin:extra",
tokenize: "strict",
threshold: 5,
depth: 3
});
index.add(0, "1 2 3 2 4 1 5 3");
index.add(1, "zero one two three four five six seven eight nine ten");
index.add(2, "five two zero one three four ten seven eight six nine");
expect(index.search("1 3 4")).to.have.members([0]);
expect(index.search("1 5 3 4")).to.have.members([0]);
expect(index.search("1 3 4 7")).to.have.lengthOf(0);
expect(index.search("one")).to.have.members([1, 2]);
expect(index.search("one three")).to.have.members([1, 2]);
expect(index.search("three one")).to.have.members([1, 2]);
expect(index.search("zero five one ten")).to.have.members([2]);
});
});
// ------------------------------------------------------------------------
// Suggestion Tests
// ------------------------------------------------------------------------
if(env !== "light") describe("Suggestions", function(){
it("Should have been suggested properly by relevance", function(){
var index = new FlexSearch({
charset: "latin:advanced",
tokenize: "strict"
});
index.add(0, "1 2 3 2 4 1 5 3");
index.add(1, "zero one two three four five six seven eight nine ten");
index.add(2, "four two zero one three ten five seven eight six nine");
expect(index.search("1 3 4 7", { suggest: false })).to.have.lengthOf(0);
expect(index.search("1 3 4 7", { suggest: true })).to.have.members([0]);
expect(index.search("1 3 9 7", { suggest: true })).to.have.members([0]);
expect(index.search("foobar one two", { suggest: true })).to.have.members([1, 2]);
expect(index.search("one foobar two", { suggest: true })).to.have.members([1, 2]);
expect(index.search("one two foobar", { suggest: true })).to.have.members([1, 2]);
expect(index.search("zero one foobar two foobar", { suggest: true })).to.have.members([1, 2]);
});
it("Should have been suggested properly by context", function(){
var index = new FlexSearch({
charset: "latin:advanced",
tokenize: "strict",
depth: 3
});
index.add(1, "zero one two three four five six seven eight nine ten");
index.add(2, "four two zero one three ten five seven eight six nine");
expect(index.search("foobar one", { suggest: true })).to.have.members([1, 2]);
expect(index.search("foobar foobar foobar one foobar foobar foobar", { suggest: true })).to.have.members([1, 2]);
expect(index.search("foobar one two", { suggest: true })).to.have.members([1, 2]);
expect(index.search("one foobar two", { suggest: true })).to.have.members([1, 2]);
expect(index.search("one two foobar", { suggest: true })).to.have.members([1, 2]);
expect(index.search("foobar one foobar two foobar", { suggest: true })).to.have.members([1, 2]);
expect(index.search("zero one foobar two foobar", { suggest: true })).to.have.members([1, 2]);
});
});
// ------------------------------------------------------------------------
// Where Clause
// ------------------------------------------------------------------------
if((env === "") || (env === "min") || (env === "pre")) describe("Where/Find", function(){
var data = [{
id: 0,
title: "Title 1",
cat: "1",
flag: false
},{
id: 1,
title: "Title 2",
cat: "2",
flag: false
},{
id: 2,
title: "Title 3",
cat: "1",
flag: true
}];
it("Should have been found properly", function(){
var index = new FlexSearch({
doc: {
id: "id",
field: "title"
}
});
index.add(data);
expect(index.length).to.equal(3);
expect(index.index).to.have.members(["0", "1", "2"]);
expect(index.find(0)).to.equal(data[0]);
expect(index.find("id", 0)).to.equal(data[0]);
expect(index.where("id", 0)).to.have.members([data[0]]);
expect(index.find(function(val){return val.id === 0;})).to.equal(data[0]);
expect(index.find({id: 1})).to.equal(data[1]);
expect(index.where({id: 1})).to.have.members([data[1]]);
expect(index.where(function(val){return val.id === 1;})).to.have.members([data[1]]);
expect(index.find({cat: "1"})).to.equal(data[0]);
expect(index.find({cat: "2"})).to.equal(data[1]);
expect(index.find({cat: "2", flag: true})).to.equal(null);
expect(index.find(data[2])).to.equal(data[2]);
expect(index.where(data[2])).to.have.members([data[2]]);
expect(index.where({cat: "1"})).to.have.members([data[0], data[2]]);
expect(index.search("title", {sort: "cat"})[1]).to.equal(data[2]);
expect(index.search("title")).to.have.members(data);
expect(index.search("title", {
where: {
cat: "1"
}
})).to.have.members([data[0], data[2]]);
expect(index.search("title", {
where: {
cat: "1",
flag: true
}
})).to.have.members([data[2]]);
});
it("Should have been tagged properly", function(){
var index = new FlexSearch({
doc: {
id: "id",
field: "title",
tag : "cat"
}
});
index.add(data);
expect(index.length).to.equal(3);
expect(index.index).to.have.members(["0", "1", "2"]);
expect(index.where({cat: "1"})).to.have.members([data[0], data[2]]);
expect(index.where("cat", "1")).to.have.members([data[0], data[2]]);
expect(index.where("cat", "1", 1)).to.have.members([data[0]]);
expect(index.where({
cat: "1",
flag: true
})).to.have.members([data[2]]);
expect(index.where({
flag: true,
cat: "1"
})).to.have.members([data[2]]);
expect(index.search("title", {
where: {
cat: "1"
}
})).to.have.members([data[0], data[2]]);
expect(index.search("title", {
where: {
cat: "1"
},
limit: 1
})).to.have.members([data[0]]);
expect(index.search("title", {
where: {
cat: "3"
}
})).to.have.lengthOf(0);
expect(index.search("foobar", {
where: {
cat: "1"
}
})).to.have.lengthOf(0);
// -----------------------------------------
index = new FlexSearch({
doc: {
id: "id",
field: ["title"],
tag : ["cat"]
}
});
index.add(data);
expect(index.length).to.equal(3);
expect(index.index).to.have.members(["0", "1", "2"]);
expect(index.where({cat: "1"})).to.have.members([data[0], data[2]]);
expect(index.search("title", {
where: {
cat: "1"
}
})).to.have.members([data[0], data[2]]);
expect(index.search("title", {
where: {
cat: "3"
}
})).to.have.lengthOf(0);
expect(index.search("foobar", {
where: {
cat: "1"
}
})).to.have.lengthOf(0);
// ------------------------------------
index = new FlexSearch({
doc: {
id: "id",
field: "data:title",
tag : "data:cat"
}
});
data = [{
id: 0,
data: {
title: "Title 1",
cat: "1",
flag: false
}
},{
id: 1,
data: {
title: "Title 2",
cat: "2",
flag: false
}
},{
id: 2,
data: {
title: "Title 3",
cat: "1",
flag: true
}
}];
index.add(data);
expect(index.where({"data:cat": "1"})).to.have.members([data[0], data[2]]);
expect(index.where("data:cat", "1")).to.have.members([data[0], data[2]]);
expect(index.where("data:cat", "1", 1)).to.have.members([data[0]]);
expect(index.where({
"data:cat": "1",
"data:flag": true
})).to.have.members([data[2]]);
expect(index.where({
"data:flag": true,
"data:cat": "1"
})).to.have.members([data[2]]);
});
});
// ------------------------------------------------------------------------
// Multi-Field Documents
// ------------------------------------------------------------------------
if(env !== "light") describe("Index Multi-Field Documents", function(){
var data = [{
id: 2,
data:{
title: "Title 3",
body: "Body 3"
}
},{
id: 1,
data:{
title: "Title 2",
body: "Body 2"
}
},{
id: 0,
data:{
title: "Title 1",
body: "Body 1"
}
}];
var update = [{
id: 0,
data:{
title: "Foo 1",
body: "Bar 1"
}
},{
id: 1,
data:{
title: "Foo 2",
body: "Bar 2"
}
},{
id: 2,
data:{
title: "Foo 3",
body: "Bar 3"
}
}];
it("Should have been indexed properly", function(){
var index = new FlexSearch({
doc: {
id: "id",
field: [
"data:title",
"data:body"
]
}
});
index.add(data);
if(env === ""){
expect(index.doc.index["data:title"].length).to.equal(3);
expect(index.doc.index["data:body"].length).to.equal(3);
}
expect(index.search({field: "data:body", query: "body"})).to.have.members(data);
expect(index.search({field: "data:title", query: "title"})).to.have.members(data);
expect(index.search({field: "data:body", query: "title"})).to.have.lengthOf(0);
expect(index.search({field: "data:title", query: "body"})).to.have.lengthOf(0);
expect(index.search({field: "data:body", query: "body"})).to.have.members(data);
expect(index.search({field: ["data:title"], query: "title"})).to.have.members(data);
expect(index.search({field: ["data:title", "data:body"], query: "body"})).to.have.lengthOf(3);
expect(index.search({field: ["data:body", "data:title"], query: "title"})).to.have.lengthOf(3);
expect(index.search({field: ["data:title", "data:body"], query: "body"})).to.have.members(data);
expect(index.search({field: ["data:body", "data:title"], query: "title"})).to.have.members(data);
expect(index.search({field: ["data:title", "data:body"], query: "body", bool: "and"})).to.have.lengthOf(0);
expect(index.search({field: ["data:body", "data:title"], query: "title", bool: "and"})).to.have.lengthOf(0);
expect(index.search({field: ["data:title", "data:body"], query: "body", bool: "or"})).to.have.members(data);
expect(index.search({field: ["data:body", "data:title"], query: "title", bool: "or"})).to.have.members(data);
expect(index.search("body", {field: "data:body"})).to.have.members(data);
expect(index.search("title", {field: ["data:title"]})).to.have.members(data);
expect(index.search({query: "body", bool: "or"})).to.have.members(data);
expect(index.search("title", {bool: "or"})).to.have.members(data);
expect(index.search({
field: "data:title",
query: "title"
})).to.have.members(data);
expect(index.search([{
field: "data:title",
query: "body",
bool: "or"
},{
field: "data:body",
query: "body",
bool: "or"
}])).to.have.members(data);
expect(index.search("title", {
field: "data:title"
})).to.have.members(data);
expect(index.search("title", {
field: "data:body"
})).to.have.lengthOf(0);
expect(index.search("body", [{
field: "data:title",
bool: "or"
},{
field: "data:body",
bool: "or"
}])).to.have.members(data);
index.update(update);
expect(index.search("foo", {bool: "or"})).not.to.have.members(data);
expect(index.search("bar", {bool: "or"})).not.to.have.members(data);
expect(index.search("foo", {bool: "or"})).to.have.members(update);
expect(index.search("bar", {bool: "or"})).to.have.members(update);
expect(index.search("foo", {field: "data:title"})).not.to.have.members(data);
expect(index.search("bar", {field: "data:body"})).not.to.have.members(data);
expect(index.search("foo", {field: "data:title"})).to.have.members(update);
expect(index.search("bar", {field: "data:body"})).to.have.members(update);
index.remove(update);
if(env === ""){
expect(index.doc.index["data:title"].length).to.equal(0);
expect(index.doc.index["data:body"].length).to.equal(0);
}
});
it("Should have been indexed properly (custom fields)", function(){
var index = new FlexSearch({
doc: {
id: "id",
field: {
"data:title": {
charset: "latin:advanced",
tokenize: "reverse"
},
"data:body": {
charset: "latin:default",
tokenize: "strict"
}
}
}
});
index.add(data);
if(env === ""){
expect(index.doc.index["data:title"].length).to.equal(3);
expect(index.doc.index["data:body"].length).to.equal(3);
}
expect(index.search({field: "data:body", query: "body"})).to.have.members(data);
expect(index.search({field: "data:title", query: "tle"})).to.have.members(data);
expect(index.search({field: "data:body", query: "title"})).to.have.lengthOf(0);
expect(index.search({field: "data:title", query: "body"})).to.have.lengthOf(0);
expect(index.search({field: ["data:title", "data:body"], query: "body", bool: "or"})).to.have.members(data);
expect(index.search({field: ["data:body", "data:title"], query: "tle", bool: "or"})).to.have.members(data);
expect(index.search({field: ["data:body"], query: "body", bool: "or"})).to.have.members(data);
expect(index.search({field: "data:title", query: "tle", bool: "or"})).to.have.members(data);
expect(index.search({query: "body", bool: "or"})).to.have.members(data);
expect(index.search("tle", {bool: "or"})).to.have.members(data);
expect(index.search({query: "body", field: "data:body"})).to.have.members(data);
expect(index.search("tle", {field: "data:title"})).to.have.members(data);
expect(index.search({
field: "data:title",
query: "tle"
})).to.have.members(data);
expect(index.search([{
field: "data:title",
query: "body",
bool: "or"
},{
field: "data:body",
query: "body",
bool: "or"
}])).to.have.members(data);
expect(index.search("tle", {
field: "data:title"
})).to.have.members(data);
expect(index.search("tle", {
field: "data:body"
})).to.have.lengthOf(0);
expect(index.search("body", [{
field: "data:title",
bool: "or"
},{
field: "data:body",
bool: "or"
}])).to.have.members(data);
index.update(update);
expect(index.search("foo", {bool: "or"})).not.to.have.members(data);
expect(index.search("bar", {bool: "or"})).not.to.have.members(data);
expect(index.search("foo", {bool: "or"})).to.have.members(update);
expect(index.search("bar", {bool: "or"})).to.have.members(update);
expect(index.search("foo", {field: "data:title"})).not.to.have.members(data);
expect(index.search("bar", {field: "data:body"})).not.to.have.members(data);
expect(index.search("foo", {field: "data:title"})).to.have.members(update);
expect(index.search("bar", {field: "data:body"})).to.have.members(update);
index.remove(update);
if(env === ""){
expect(index.doc.index["data:title"].length).to.equal(0);
expect(index.doc.index["data:body"].length).to.equal(0);
}
});
it("Should have been unique results", function(){
var index = new FlexSearch({
doc: {
id: "id",
field: ["field1", "field2"]
}
});
var docs = [{
id: 1,
field1: "phrase",
field2: "phrase"
}];
index.add(docs);
expect(index.search("phrase")).to.have.lengthOf(1);
expect(index.search("phrase")).to.have.members(docs);
});
/*
it("Should have been indexed properly (tag)", function(){
var index = new FlexSearch({
doc: {
id: "id",
field: "data:body",
tag: "data:title"
}
});
index.add(data);
expect(index.doc.index[0].length).to.equal(3);
expect(index.doc.index[1].length).to.equal(3);
expect(index.search({field: "data:body", query: "body"})).to.have.members(data);
expect(index.search({field: "data:title", query: "title"})).to.have.lengthOf(0);
expect(index.search({field: "data:title", query: "Title 1"})).to.have.members(data[0]);
expect(index.search({field: "data:body", query: "title"})).to.have.lengthOf(0);
expect(index.search({field: "data:title", query: "body"})).to.have.lengthOf(0);
expect(index.search({field: ["data:title", "data:body"], query: "body"})).to.have.members(data);
expect(index.search({field: ["data:body", "data:title"], query: "title"})).to.have.members(data);
expect(index.search({query: "body"})).to.have.members(data);
expect(index.search("title")).to.have.members(data);
expect(index.search({
field: "data:title",
query: "title",
boost: 2
})).to.have.members(data);
expect(index.search([{
field: "data:title",
query: "body",
boost: 2
},{
field: "data:body",
query: "body",
boost: 2
}])).to.have.members(data);
expect(index.search("title", {
field: "data:title",
boost: 2
})).to.have.members(data);
expect(index.search("title", {
field: "data:body",
boost: 2
})).to.have.lengthOf(0);
expect(index.search("body", [{
field: "data:title",
boost: 2
},{
field: "data:body",
boost: 2
}])).to.have.members(data);
index.update(update);
expect(index.search("foo")).not.to.have.members(data);
expect(index.search("bar")).not.to.have.members(data);
expect(index.search("foo")).to.have.members(update);
expect(index.search("bar")).to.have.members(update);
index.remove(update);
expect(index.doc.index[0].length).to.equal(0);
expect(index.doc.index[1].length).to.equal(0);
});
*/
/*
it("Should have been boosted properly", function(){
var index = new FlexSearch({
tokenize: "strict",
depth: 3,
doc: {
id: "id",
field: ["title", "body"]
}
});
index.add([{
id: 0,
title: "1 2 3 4 5",
body: "1 2 3 4 5"
},{
id: 1,
title: "1 2 3 4 5",
body: "1 2 5 4 3" // <-- body
},{
id: 2,
title: "1 2 5 4 3", // <-- title
body: "1 2 3 4 5"
}]);
expect(index.search([{
field: "title",
query: "5",
boost: 0.1
},{
field: "body",
query: "5",
boost: 9
}])[0].id).to.equal(1);
expect(index.search([{
field: "title",
query: "5",
boost: 9
},{
field: "body",
query: "5",
boost: 0.1
}])[0].id).to.equal(2);
});
*/
it("Should have been sorted properly", function(){
var index = new FlexSearch({
doc: {
id: "id",
field: "data:title"
}
});
index.add(data);
var results = index.search({
field: "data:title",
query: "title"
});
expect(results[0]).to.equal(data[0]);
expect(results[1]).to.equal(data[1]);
expect(results[2]).to.equal(data[2]);
results = index.search({
query: "title",
field: "data:title",
sort: function(a, b){
const diff = a.id - b.id;
return (diff < 0 ? -1 : (diff ? 1 : 0));
}
});
expect(results[0]).to.equal(data[2]);
expect(results[1]).to.equal(data[1]);
expect(results[2]).to.equal(data[0]);
results = index.search({
query: "title",
field: "data:title",
sort: "id"
});
expect(results[0]).to.equal(data[2]);
expect(results[1]).to.equal(data[1]);
expect(results[2]).to.equal(data[0]);
results = index.search({
query: "title",
field: "data:title",
sort: "data:title"
});
expect(results[0]).to.eql(data[2]);
expect(results[1]).to.eql(data[1]);
expect(results[2]).to.eql(data[0]);
});
it("Should have been sorted suggested and paged", function(){
var index = new FlexSearch({
doc: {
id: "id",
field: ["data:title", "data:body"]
}
});
index.add(data);
var results = index.search({
field: "data:title",
query: "title",
suggest: true,
page: true,
limit: 2
});
expect(results.result).to.have.members([data[0], data[1]]);
results = index.search({
field: "data:title",
query: "title",
suggest: true,
page: results.next,
limit: 2
});
expect(results.result).to.have.members([data[2]]);
results = index.search({
field: "data:title",
query: "foobar title foobar title foobar",
suggest: true,
page: true,
limit: 2
});
expect(results.result).to.have.members([data[0], data[1]]);
results = index.search({
field: "data:title",
query: "foobar title foobar title foobar",
suggest: true,
page: results.next,
limit: 2
});
expect(results.result).to.have.members([data[2]]);
results = index.search([{
field: "data:title",
query: "title undefined",
bool: "and",
suggest: true,
limit: 2
},{
field: "data:body",
query: "undefined",
bool: "not"
}]);
expect(results).to.have.members([data[0], data[1]]);
});
if((!env || (env === "pre")) && (typeof require !== "undefined") && !this._phantom){
require("./test.es6.js");
}
});
if(env !== "light") describe("Pagination", function(){
it("Should have been properly paged", function(){
var index = new FlexSearch();
index.add(0, "test").add(1, "test").add(2, "test").add(3, "test").add(4, "test");
expect(index.index).to.have.members(["0", "1", "2", "3", "4"]);
expect(index.search("test")).to.have.lengthOf(5);
expect(index.search("test", 2)).to.have.lengthOf(2);
expect(index.search("test", {
page: true,
limit: 2
})).to.have.keys(["page", "next", "result"]);
var result = index.search("test", {
page: true,
limit: 2
});
expect(result.result).to.have.members([0, 1]);
result = index.search("test", {
page: result.next,
limit: 2
});
expect(result.result).to.have.members([2, 3]);
result = index.search("test", {
page: result.page,
limit: 2
});
expect(result.result).to.have.members([2, 3]);
result = index.search("test", {
page: result.next,
limit: 2
});
expect(result.result).to.have.members([4]);
});
it("Should have been properly paged (suggestion)", function(){
var index = new FlexSearch();
index.add(0, "foo bar").add(1, "foo bar").add(2, "foo bar test").add(3, "foo bar").add(4, "foo bar");
expect(index.index).to.have.members(["0", "1", "2", "3", "4"]);
expect(index.search("foo")).to.have.lengthOf(5);
expect(index.search("foo", 2)).to.have.lengthOf(2);
var result = index.search("foo undefined bar", {
suggest: true,
page: true,
limit: 2
});
expect(result).to.have.keys(["page", "next", "result"]);
expect(result.result).to.have.members([0, 1]);
result = index.search("foo bar test", {
suggest: true,
page: true,
limit: 2
});
expect(result.result).to.have.members([2, 0]);
result = index.search("foo undefined bar", {
suggest: true,
page: true,
limit: 2
});
expect(result.result).to.have.members([0, 1]);
result = index.search("foo undefined bar", {
suggest: true,
page: result.next,
limit: 2
});
expect(result.result).to.have.members([2, 3]);
result = index.search("foo undefined bar", {
suggest: true,
page: result.page,
limit: 2
});
expect(result.result).to.have.members([2, 3]);
result = index.search("foo undefined bar", {
suggest: true,
page: result.next,
limit: 2
});
expect(result.result).to.have.members([4]);
});
it("Should have been properly paged (documents)", function(){
var data = [{
id: 0,
title: "Title 1",
body: "Body 1"
},{
id: 1,
title: "Title 2",
body: "Body 2"
},{
id: 2,
title: "Title 3",
body: "Body 3"
},{
id: 3,
title: "Title 4",
body: "Body 4"
},{
id: 4,
title: "Title 5",
body: "Body 5"
}];
var index = new FlexSearch({
doc: {
id: "id",
field: ["title", "body"]
}
});
index.add(data);
if(env === ""){
expect(index.doc.index["title"].index).to.have.members(["0", "1", "2", "3", "4"]);
expect(index.doc.index["body"].index).to.have.members(["0", "1", "2", "3", "4"]);
}
expect(index.search("title")).to.have.lengthOf(5);
expect(index.search("title", 2)).to.have.lengthOf(2);
expect(index.search("title", {
page: true,
limit: 2
})).to.have.keys(["page", "next", "result"]);
var result = index.search("title", {
page: true,
limit: 2
});
expect(result.result).to.have.members([data[0], data[1]]);
result = index.search("title", {
page: result.next,
limit: 2
});
expect(result.result).to.have.members([data[2], data[3]]);
result = index.search("title", {
page: result.page,
limit: 2
});
expect(result.result).to.have.members([data[2], data[3]]);
result = index.search("title", {
page: result.next,
limit: 2
});
expect(result.result).to.have.members([data[4]]);
});
});
// describe("Custom Split", function(){
//
// it("Should have been split properly", function(){
//
// var index = FlexSearch({
// encode: false,
// split: /\s+/,
// tokenize: "reverse"
// });
//
// index.add(0, "Фообар");
//
// expect(index.search("Фообар")).to.include(0);
// expect(index.search("бар")).to.include(0);
// expect(index.search("Фоо")).to.include(0);
// });
// });
describe("Github Issues", function(){
if(env !== "light") it("#48", function(){
const fs = new FlexSearch({
charset: "latin:extra",
tokenize: "full",
threshold: 1,
depth: 4,
resolution: 9,
async: false,
worker: 1,
cache: true,
suggest: true,
doc: {
id: "id",
field: [ "intent", "text" ]
}
});
const doc = [{
id: 0,
intent: "intent",
text: "text"
},{
id: 1,
intent: "intent",
text: "howdy - how are you doing"
}];
fs.add(doc);
expect(fs.search("howdy", { bool: "or" })).to.have.members([doc[1]]);
expect(fs.search("howdy -", { bool: "or" })).to.have.members([doc[1]]);
});
if(env !== "light") it("#54", function(){
var docs = [{
id: 1,
title: "Roaming Inquiry",
content: "Some content"
}, {
id: 2,
title: "New Service",
content: "This is not roaming-inquiry"
}];
var index = new FlexSearch({
doc: {
id: "id",
field: ["title", "content"]
}
});
index.add(docs);
expect(index.search("roaming")).to.have.members([docs[0], docs[1]]);
});
});
if(env !== "light") describe("Operators", function(){
var data = [{
id: 2,
title: "Title 3",
body: "Body 3",
blacklist: "x1"
},{
id: 1,
title: "Title 2",
body: "Body 2",
blacklist: "x2"
},{
id: 0,
title: "Title 1",
body: "Body 1",
blacklist: "x3"
}];
var index = new FlexSearch({
tokenize: "forward",
doc: {
id: "id",
field: ["title", "body", "blacklist"]
}
});
it("Should have been properly applied logic", function(){
index.add(data);
expect(index.search([{
field: "title",
query: "title",
bool: "and"
},{
field: "body",
query: "body",
bool: "and"
},{
field: "blacklist",
query: "xxx",
bool: "not"
}])).to.have.members(data);
expect(index.search([{
field: "title",
query: "title",
bool: "and"
},{
field: "body",
query: "title",
bool: "and"
},{
field: "blacklist",
query: "xxx",
bool: "not"
}])).to.have.length(0);
expect(index.search([{
field: "title",
query: "title",
bool: "and"
},{
field: "body",
query: "title",
bool: "or"
},{
field: "blacklist",
query: "xxx",
bool: "not"
}])).to.have.members(data);
expect(index.search([{
field: "title",
query: "title",
bool: "and"
},{
field: "body",
query: "title",
bool: "or"
}])).to.have.members(data);
expect(index.search([{
field: "title",
query: "title",
bool: "and"
},{
field: "body",
query: "title",
bool: "or"
},{
field: "blacklist",
query: "x1",
bool: "not"
}])).to.have.members([data[1], data[2]]);
expect(index.search([{
field: "title",
query: "body",
bool: "or"
},{
field: "body",
query: "title",
bool: "or"
},{
field: "blacklist",
query: "x1",
bool: "not"
}])).to.have.length(0);
expect(index.search([{
field: "blacklist",
query: "x1",
bool: "not"
},{
field: "title",
query: "title",
bool: "or"
},{
field: "body",
query: "body",
bool: "or"
}])).to.have.members([data[1], data[2]]);
expect(index.search([{
field: "title",
query: "body",
bool: "or"
},{
field: "body",
query: "body",
bool: "and"
},{
field: "blacklist",
query: "x2",
bool: "not"
}])).to.have.members([data[0], data[2]]);
expect(index.search([{
field: "blacklist",
query: "x2",
bool: "not"
},{
field: "title",
query: "body",
bool: "or"
},{
field: "body",
query: "body",
bool: "and"
}])).to.have.members([data[0], data[2]]);
expect(index.search([{
field: "title",
query: "body",
bool: "or"
},{
field: "blacklist",
query: "x2",
bool: "not"
},{
field: "body",
query: "body",
bool: "and"
}])).to.have.members([data[0], data[2]]);
expect(index.search([{
field: "title",
query: "title",
bool: "and"
},{
field: "body",
query: "body",
bool: "and"
},{
field: "blacklist",
query: "x",
bool: "not"
}])).to.have.length(0);
expect(index.search([{
field: "title",
query: "title",
bool: "not"
},{
field: "body",
query: "body",
bool: "not"
},{
field: "blacklist",
query: "x",
bool: "not"
}])).to.have.length(0);
});
});
describe("Reserved Words", function(){
it("Should have been indexed properly", function(){
var index = new FlexSearch({
encode: function(str){ return [str]; },
tokenize: "strict",
threshold: 0,
depth: 3
});
var array = Object.getOwnPropertyNames({}.__proto__);
array = array.concat(Object.getOwnPropertyNames(index));
array.push("prototype");
array.push("constructor");
array.push("__proto__");
if(env !== "min"){
array.push("concat");
array.push("hasOwnProperty");
array.push("length");
}
for(var i = 0; i < array.length; i++){
index.add(array[i], array[i]);
}
for(var i = 0; i < array.length; i++){
// TODO: this word is reserved and can't be indexed
if(array[i] === "_ctx"){
continue;
}
expect(index.search(array[i])).to.have.members([array[i]]);
}
});
});
// ------------------------------------------------------------------------
// Export / Import
// ------------------------------------------------------------------------
if(env !== "light") describe("Export / Import", function(){
var data;
it("Should have been exported properly", function(){
var index = new FlexSearch("match");
index.add(0, "foo");
index.add(1, "bar");
index.add(2, "foobar");
data = index.export();
if(env === ""){
expect(data).to.equal(JSON.stringify(
[
index._map,
index._ctx,
Object.keys(index._ids)
]
));
}
});
it("Should have been imported properly", function(){
var index = new FlexSearch("match");
index.import(data);
expect(index.length).to.equal(3);
expect(index.search("foo")).to.have.lengthOf(2);
expect(index.search("bar")).to.have.lengthOf(2);
expect(index.search("foobar")).to.have.lengthOf(1);
expect(index.search("foobar")[0]).to.equal(2);
});
it("Should have been exported properly (documents)", function(){
var index = new FlexSearch({
tokenize: "strict",
threshold: 1,
resolution: 3,
depth: 1,
doc: {
id: "id",
field: ["title", "content"]
}
});
var docs = [{
id: 1,
title: "Title 2",
content: "foobar"
},{
id: 0,
title: "Title 1",
content: "foo"
},{
id: 2,
title: "Title 3",
content: "bar"
}];
index.add(docs);
data = index.export();
if(env === ""){
expect(index.doc.index["title"].length).to.equal(3);
expect(data).to.equal(JSON.stringify([
[
index.doc.index["title"]._map,
index.doc.index["title"]._ctx,
Object.keys(index.doc.index["title"]._ids)
],
[
index.doc.index["content"]._map,
index.doc.index["content"]._ctx,
Object.keys(index.doc.index["content"]._ids)
],
index._doc
]));
}
});
it("Should have been imported properly (documents)", function(){
var index = new FlexSearch({
tokenize: "strict",
threshold: 1,
resolution: 3,
depth: 1,
doc: {
id: "id",
field: ["title", "content"]
}
});
index.import(data);
if(env === ""){
expect(index.doc.index["title"].length).to.equal(3);
expect(index.doc.index["content"].length).to.equal(3);
}
expect(index.search("foo")).to.have.lengthOf(1);
expect(index.search("bar")).to.have.lengthOf(1);
expect(index.search("foobar")).to.have.lengthOf(1);
expect(index.search("foobar")[0].id).to.equal(1);
});
});
// ------------------------------------------------------------------------
// Presets
// ------------------------------------------------------------------------
describe("Presets", function(){
it("Should have been properly initialized", function(){
expect(FlexSearch("memory").length).to.equal(0);
expect(FlexSearch("speed").length).to.equal(0);
expect(FlexSearch("match").length).to.equal(0);
expect(FlexSearch("score").length).to.equal(0);
expect(FlexSearch("balance").length).to.equal(0);
expect(FlexSearch("fast").length).to.equal(0);
});
it("Should have been properly extended", function(){
var index = FlexSearch("fast");
index.add(0, "foobar");
expect(index.search("bar")).to.have.lengthOf(0);
index = FlexSearch({preset: "speed", id: "test", tokenize: "reverse"});
expect(index.id).to.equal("test");
index.add(0, "foobar");
expect(index.search("bar")).to.have.lengthOf(1);
expect(index.search("bar")).to.have.members([0])
});
});
// ------------------------------------------------------------------------
// Feature Tests
// ------------------------------------------------------------------------
describe("Add Matchers", function(){
it("Should have been added properly", function(){
flexsearch_forward.init({
tokenize: "forward",
matcher: {
"1": "a",
"2": "b",
"3": "c",
"7": "e",
"8": "f",
"[456]": "d"
}
}).add(0, "12345678");
expect(flexsearch_forward.search("12345678")).to.include(0);
expect(flexsearch_forward.search("abcd")).to.include(0);
expect(flexsearch_forward.encode("12345678")).to.eql(["abcdddef"]);
});
});
// ------------------------------------------------------------------------
// Caching
// ------------------------------------------------------------------------
if(env !== "light"){
describe("Caching", function(){
it("Should have been cached properly", function(){
flexsearch_cache.add(0, "foo")
.add(1, "bar")
.add(2, "foobar");
// fetch:
expect(flexsearch_cache.search("foo")).to.have.members([0, 2]);
expect(flexsearch_cache.search("bar")).to.have.members([1, 2]);
expect(flexsearch_cache.search("foobar")).to.include(2);
// cache:
expect(flexsearch_cache.search("foo")).to.have.members([0, 2]);
expect(flexsearch_cache.search("bar")).to.have.members([1, 2]);
expect(flexsearch_cache.search("foobar")).to.include(2);
// update:
flexsearch_cache.remove(2).update(1, "foo").add(3, "foobar");
// fetch:
expect(flexsearch_cache.search("foo")).to.have.members([0, 1, 3]);
expect(flexsearch_cache.search("bar")).to.include(3);
expect(flexsearch_cache.search("foobar")).to.include(3);
// cache:
expect(flexsearch_cache.search("foo")).to.have.members([0, 1, 3]);
expect(flexsearch_cache.search("bar")).to.include(3);
expect(flexsearch_cache.search("foobar")).to.include(3);
});
});
}
// ------------------------------------------------------------------------
// Debug Information
// ------------------------------------------------------------------------
if(env !== "light" && env !== "min"){
describe("Debug", function(){
it("Should have been debug mode activated", function(){
var info = flexsearch_cache.info();
expect(info).to.have.keys([
"id",
//"chars",
"cache",
"items",
"matcher",
//"memory",
//"sequences",
"resolution",
"worker",
"contextual",
"depth",
"threshold"
]);
});
});
}
// ------------------------------------------------------------------------
// Destroy
// ------------------------------------------------------------------------
describe("Destroy", function(){
it("Should have been destroyed properly", function(){
var index = FlexSearch()
.add(0, "foo")
.add(1, "bar");
expect(index.search("foo")).to.include(0);
expect(index.search("bar")).to.include(1);
index.destroy();
expect(index.search("foo")).to.have.lengthOf(0);
expect(index.search("bar")).to.have.lengthOf(0);
});
if(env !== "light") it("Should have been destroyed properly (documents)", function(){
var data = [{id: 0, title: "foo"}, {id: 1, title: "bar"}];
var index = FlexSearch({doc: {id: "id", field: "title"}})
.add(data)
.add(data);
expect(index.search("foo")).to.have.members([data[0]]);
expect(index.search("bar")).to.have.members([data[1]]);
index.destroy();
expect(index.search("foo")).to.have.lengthOf(0);
expect(index.search("bar")).to.have.lengthOf(0);
});
});
// ------------------------------------------------------------------------
// Chaining
// ------------------------------------------------------------------------
describe("Chaining", function(){
it("Should have been chained properly", function(){
var index = FlexSearch({tokenize: "forward", matcher: {"â": "a"}})
.add(0, "foo")
.add(1, "bar");
expect(index.search("foo")).to.include(0);
expect(index.search("bar")).to.include(1);
expect(index.encode("bâr")).to.eql(["bar"]);
index.remove(0).update(1, "foo").add(2, "foobâr");
expect(index.search("foo")).to.have.members([1, 2]);
expect(index.search("bar")).to.have.lengthOf(0);
expect(index.search("foobar")).to.include(2);
index.clear().add(0, "foo").add(1, "bar");
expect(index.search("foo")).to.include(0);
expect(index.search("bar")).to.include(1);
expect(index.search("foobar")).to.have.lengthOf(0);
flexsearch_cache.destroy().init().add(0, "foo").add(1, "bar");
expect(flexsearch_cache.search("foo")).to.include(0);
expect(flexsearch_cache.search("bar")).to.include(1);
expect(flexsearch_cache.search("foobar")).to.have.lengthOf(0);
});
});
/* Test Helpers */
function test_encoder(str){
return "-[" + str.toUpperCase() + "]-";
}