index_test.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. module('lunr.Index')
  2. test("defining what fields to index", function () {
  3. var idx = new lunr.Index
  4. idx.field('foo')
  5. deepEqual(idx._fields[0], {name: 'foo', boost: 1})
  6. })
  7. test("giving a particular field a weighting", function () {
  8. var idx = new lunr.Index
  9. idx.field('foo', { boost: 10 })
  10. deepEqual(idx._fields[0], {name: 'foo', boost: 10})
  11. })
  12. test('default reference should be id', function () {
  13. var idx = new lunr.Index
  14. equal(idx._ref, 'id')
  15. })
  16. test("defining the reference field for the index", function () {
  17. var idx = new lunr.Index
  18. idx.ref('foo')
  19. deepEqual(idx._ref, 'foo')
  20. })
  21. test("default tokenizer should be the lunr.tokenizer", function () {
  22. var idx = new lunr.Index
  23. equal(idx.tokenizerFn, lunr.tokenizer)
  24. })
  25. test("using a custom tokenizer", function () {
  26. var idx = new lunr.Index,
  27. fn = function () {}
  28. lunr.tokenizer.registerFunction(fn, 'test')
  29. idx.tokenizer(fn)
  30. equal(idx.tokenizerFn, fn)
  31. })
  32. test('adding a document to the index', function () {
  33. var idx = new lunr.Index,
  34. doc = {id: 1, body: 'this is a test'}
  35. idx.field('body')
  36. idx.add(doc)
  37. equal(idx.documentStore.length, 1)
  38. ok(!!idx.documentStore.get(1))
  39. })
  40. test('adding a document with an empty field', function () {
  41. var idx = new lunr.Index,
  42. doc = {id: 1, body: 'test', title: ''}
  43. idx.field('title')
  44. idx.field('body')
  45. idx.add(doc)
  46. ok(!isNaN(idx.tokenStore.get('test')[1].tf))
  47. })
  48. test('ignore empty tokens', function () {
  49. var idx = new lunr.Index,
  50. doc = {id: 1, body: 'test ???'}
  51. idx.field('body')
  52. idx.pipeline.add(lunr.trimmer)
  53. idx.add(doc)
  54. var tokens = idx.documentStore.get(1).toArray()
  55. equal(tokens.length, 1)
  56. deepEqual(tokens, ['test']) // ??? should be ignored
  57. })
  58. test('triggering add events', function () {
  59. var idx = new lunr.Index,
  60. doc = {id: 1, body: 'this is a test'},
  61. callbackCalled = false,
  62. callbackArgs = []
  63. idx.on('add', function (doc, index) {
  64. callbackCalled = true
  65. callbackArgs = Array.prototype.slice.call(arguments)
  66. })
  67. idx.field('body')
  68. idx.add(doc)
  69. ok(callbackCalled)
  70. equal(callbackArgs.length, 2)
  71. deepEqual(callbackArgs[0], doc)
  72. deepEqual(callbackArgs[1], idx)
  73. })
  74. test('silencing add events', function () {
  75. var idx = new lunr.Index,
  76. doc = {id: 1, body: 'this is a test'},
  77. callbackCalled = false,
  78. callbackArgs = []
  79. idx.on('add', function (doc, index) {
  80. callbackCalled = true
  81. callbackArgs = Array.prototype.slice.call(arguments)
  82. })
  83. idx.field('body')
  84. idx.add(doc, false)
  85. ok(!callbackCalled)
  86. })
  87. test('removing a document from the index', function () {
  88. var idx = new lunr.Index,
  89. doc = {id: 1, body: 'this is a test'}
  90. idx.field('body')
  91. equal(idx.documentStore.length, 0)
  92. idx.add(doc)
  93. equal(idx.documentStore.length, 1)
  94. idx.remove(doc)
  95. equal(idx.documentStore.length, 0)
  96. })
  97. test('triggering remove events', function () {
  98. var idx = new lunr.Index,
  99. doc = {id: 1, body: 'this is a test'},
  100. callbackCalled = false,
  101. callbackArgs = []
  102. idx.on('remove', function (doc, index) {
  103. callbackCalled = true
  104. callbackArgs = Array.prototype.slice.call(arguments)
  105. })
  106. idx.field('body')
  107. idx.add(doc)
  108. idx.remove(doc)
  109. ok(callbackCalled)
  110. equal(callbackArgs.length, 2)
  111. deepEqual(callbackArgs[0], doc)
  112. deepEqual(callbackArgs[1], idx)
  113. })
  114. test('silencing remove events', function () {
  115. var idx = new lunr.Index,
  116. doc = {id: 1, body: 'this is a test'},
  117. callbackCalled = false,
  118. callbackArgs = []
  119. idx.on('remove', function (doc, index) {
  120. callbackCalled = true
  121. callbackArgs = Array.prototype.slice.call(arguments)
  122. })
  123. idx.field('body')
  124. idx.add(doc)
  125. idx.remove(doc, false)
  126. ok(!callbackCalled)
  127. })
  128. test('removing a non-existent document from the index', function () {
  129. var idx = new lunr.Index,
  130. doc = {id: 1, body: 'this is a test'},
  131. doc2 = {id: 2, body: 'i dont exist'},
  132. callbackCalled = false
  133. idx.on('remove', function (doc, index) {
  134. callbackCalled = true
  135. })
  136. idx.field('body')
  137. equal(idx.documentStore.length, 0)
  138. idx.add(doc)
  139. equal(idx.documentStore.length, 1)
  140. idx.remove(doc2)
  141. equal(idx.documentStore.length, 1)
  142. ok(!callbackCalled)
  143. })
  144. test('updating a document', function () {
  145. var idx = new lunr.Index,
  146. doc = {id: 1, body: 'foo'}
  147. idx.field('body')
  148. idx.add(doc)
  149. equal(idx.documentStore.length, 1)
  150. ok(idx.tokenStore.has('foo'))
  151. doc.body = 'bar'
  152. idx.update(doc)
  153. equal(idx.documentStore.length, 1)
  154. ok(idx.tokenStore.has('bar'))
  155. })
  156. test('emitting update events', function () {
  157. var idx = new lunr.Index,
  158. doc = {id: 1, body: 'foo'},
  159. addCallbackCalled = false,
  160. removeCallbackCalled = false,
  161. updateCallbackCalled = false,
  162. callbackArgs = []
  163. idx.field('body')
  164. idx.add(doc)
  165. equal(idx.documentStore.length, 1)
  166. ok(idx.tokenStore.has('foo'))
  167. idx.on('update', function (doc, index) {
  168. updateCallbackCalled = true
  169. callbackArgs = Array.prototype.slice.call(arguments)
  170. })
  171. idx.on('add', function () {
  172. addCallbackCalled = true
  173. })
  174. idx.on('remove', function () {
  175. removeCallbackCalled = true
  176. })
  177. doc.body = 'bar'
  178. idx.update(doc)
  179. ok(updateCallbackCalled)
  180. equal(callbackArgs.length, 2)
  181. deepEqual(callbackArgs[0], doc)
  182. deepEqual(callbackArgs[1], idx)
  183. ok(!addCallbackCalled)
  184. ok(!removeCallbackCalled)
  185. })
  186. test('silencing update events', function () {
  187. var idx = new lunr.Index,
  188. doc = {id: 1, body: 'foo'},
  189. callbackCalled = false
  190. idx.field('body')
  191. idx.add(doc)
  192. equal(idx.documentStore.length, 1)
  193. ok(idx.tokenStore.has('foo'))
  194. idx.on('update', function (doc, index) {
  195. callbackCalled = true
  196. })
  197. doc.body = 'bar'
  198. idx.update(doc, false)
  199. ok(!callbackCalled)
  200. })
  201. test('serialising', function () {
  202. var idx = new lunr.Index,
  203. mockDocumentStore = { toJSON: function () { return 'documentStore' }},
  204. mockTokenStore = { toJSON: function () { return 'tokenStore' }},
  205. mockCorpusTokens = { toJSON: function () { return 'corpusTokens' }},
  206. mockPipeline = { toJSON: function () { return 'pipeline' }}
  207. idx.documentStore = mockDocumentStore
  208. idx.tokenStore = mockTokenStore
  209. idx.corpusTokens = mockCorpusTokens
  210. idx.pipeline = mockPipeline
  211. idx.ref('id')
  212. idx.field('title', { boost: 10 })
  213. idx.field('body')
  214. deepEqual(idx.toJSON(), {
  215. version: '@VERSION', // this is what the lunr version is set to before being built
  216. fields: [
  217. { name: 'title', boost: 10 },
  218. { name: 'body', boost: 1 }
  219. ],
  220. ref: 'id',
  221. documentStore: 'documentStore',
  222. tokenStore: 'tokenStore',
  223. corpusTokens: 'corpusTokens',
  224. pipeline: 'pipeline',
  225. tokenizer: 'default'
  226. })
  227. })
  228. test('loading a serialised index', function () {
  229. var serialisedData = {
  230. version: '@VERSION', // this is what the lunr version is set to before being built
  231. fields: [
  232. { name: 'title', boost: 10 },
  233. { name: 'body', boost: 1 }
  234. ],
  235. ref: 'id',
  236. documentStore: { store: {}, length: 0 },
  237. tokenStore: { root: {}, length: 0 },
  238. corpusTokens: [],
  239. pipeline: ['stopWordFilter', 'stemmer'],
  240. tokenizer: 'default'
  241. }
  242. var idx = lunr.Index.load(serialisedData)
  243. deepEqual(idx._fields, serialisedData.fields)
  244. equal(idx._ref, 'id')
  245. })
  246. test('idf cache with reserved words', function () {
  247. var idx = new lunr.Index
  248. var troublesomeTokens = [
  249. 'constructor',
  250. '__proto__',
  251. 'hasOwnProperty',
  252. 'isPrototypeOf',
  253. 'propertyIsEnumerable',
  254. 'toLocaleString',
  255. 'toString',
  256. 'valueOf'
  257. ]
  258. troublesomeTokens.forEach(function (token) {
  259. equal(typeof(idx.idf(token)), 'number', 'Using token: ' + token)
  260. })
  261. })
  262. test('using a plugin', function () {
  263. var idx = new lunr.Index,
  264. ctx, args,
  265. plugin = function () {
  266. ctx = this
  267. args = Array.prototype.slice.call(arguments)
  268. this.pluginLoaded = true
  269. }
  270. idx.use(plugin, 'foo', 'bar')
  271. equal(ctx, idx)
  272. deepEqual(args, [idx, 'foo', 'bar'])
  273. ok(idx.pluginLoaded)
  274. })