query_lexer_test.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. suite('lunr.QueryLexer', function () {
  2. suite('#run', function () {
  3. var lex = function (str) {
  4. var lexer = new lunr.QueryLexer(str)
  5. lexer.run()
  6. return lexer
  7. }
  8. suite('single term', function () {
  9. setup(function () {
  10. this.lexer = lex('foo')
  11. })
  12. test('produces 1 lexeme', function () {
  13. assert.lengthOf(this.lexer.lexemes, 1)
  14. })
  15. suite('lexeme', function () {
  16. setup(function () {
  17. this.lexeme = this.lexer.lexemes[0]
  18. })
  19. test('#type', function () {
  20. assert.equal(lunr.QueryLexer.TERM, this.lexeme.type)
  21. })
  22. test('#str', function () {
  23. assert.equal('foo', this.lexeme.str)
  24. })
  25. test('#start', function () {
  26. assert.equal(0, this.lexeme.start)
  27. })
  28. test('#end', function () {
  29. assert.equal(3, this.lexeme.end)
  30. })
  31. })
  32. })
  33. // embedded hyphens should not be confused with
  34. // presence operators
  35. suite('single term with hyphen', function () {
  36. setup(function () {
  37. this.lexer = lex('foo-bar')
  38. })
  39. test('produces 2 lexeme', function () {
  40. assert.lengthOf(this.lexer.lexemes, 2)
  41. })
  42. suite('lexeme', function () {
  43. setup(function () {
  44. this.fooLexeme = this.lexer.lexemes[0]
  45. this.barLexeme = this.lexer.lexemes[1]
  46. })
  47. test('#type', function () {
  48. assert.equal(lunr.QueryLexer.TERM, this.fooLexeme.type)
  49. assert.equal(lunr.QueryLexer.TERM, this.barLexeme.type)
  50. })
  51. test('#str', function () {
  52. assert.equal('foo', this.fooLexeme.str)
  53. assert.equal('bar', this.barLexeme.str)
  54. })
  55. test('#start', function () {
  56. assert.equal(0, this.fooLexeme.start)
  57. assert.equal(4, this.barLexeme.start)
  58. })
  59. test('#end', function () {
  60. assert.equal(3, this.fooLexeme.end)
  61. assert.equal(7, this.barLexeme.end)
  62. })
  63. })
  64. })
  65. suite('term escape char', function () {
  66. setup(function () {
  67. this.lexer = lex("foo\\:bar")
  68. })
  69. test('produces 1 lexeme', function () {
  70. assert.lengthOf(this.lexer.lexemes, 1)
  71. })
  72. suite('lexeme', function () {
  73. setup(function () {
  74. this.lexeme = this.lexer.lexemes[0]
  75. })
  76. test('#type', function () {
  77. assert.equal(lunr.QueryLexer.TERM, this.lexeme.type)
  78. })
  79. test('#str', function () {
  80. assert.equal('foo:bar', this.lexeme.str)
  81. })
  82. test('#start', function () {
  83. assert.equal(0, this.lexeme.start)
  84. })
  85. test('#end', function () {
  86. assert.equal(8, this.lexeme.end)
  87. })
  88. })
  89. })
  90. suite('multiple terms', function () {
  91. setup(function () {
  92. this.lexer = lex('foo bar')
  93. })
  94. test('produces 2 lexems', function () {
  95. assert.lengthOf(this.lexer.lexemes, 2)
  96. })
  97. suite('lexemes', function () {
  98. setup(function () {
  99. this.fooLexeme = this.lexer.lexemes[0]
  100. this.barLexeme = this.lexer.lexemes[1]
  101. })
  102. test('#type', function () {
  103. assert.equal(lunr.QueryLexer.TERM, this.fooLexeme.type)
  104. assert.equal(lunr.QueryLexer.TERM, this.barLexeme.type)
  105. })
  106. test('#str', function () {
  107. assert.equal('foo', this.fooLexeme.str)
  108. assert.equal('bar', this.barLexeme.str)
  109. })
  110. test('#start', function () {
  111. assert.equal(0, this.fooLexeme.start)
  112. assert.equal(4, this.barLexeme.start)
  113. })
  114. test('#end', function () {
  115. assert.equal(3, this.fooLexeme.end)
  116. assert.equal(7, this.barLexeme.end)
  117. })
  118. })
  119. })
  120. suite('multiple terms with presence', function () {
  121. setup(function () {
  122. this.lexer = lex('+foo +bar')
  123. })
  124. test('produces 2 lexems', function () {
  125. assert.lengthOf(this.lexer.lexemes, 4)
  126. })
  127. suite('lexemes', function () {
  128. setup(function () {
  129. this.fooPresenceLexeme = this.lexer.lexemes[0]
  130. this.fooTermLexeme = this.lexer.lexemes[1]
  131. this.barPresenceLexeme = this.lexer.lexemes[2]
  132. this.barTermLexeme = this.lexer.lexemes[3]
  133. })
  134. test('#type', function () {
  135. assert.equal(lunr.QueryLexer.TERM, this.fooTermLexeme.type)
  136. assert.equal(lunr.QueryLexer.TERM, this.barTermLexeme.type)
  137. assert.equal(lunr.QueryLexer.PRESENCE, this.fooPresenceLexeme.type)
  138. assert.equal(lunr.QueryLexer.PRESENCE, this.barPresenceLexeme.type)
  139. })
  140. test('#str', function () {
  141. assert.equal('foo', this.fooTermLexeme.str)
  142. assert.equal('bar', this.barTermLexeme.str)
  143. assert.equal('+', this.fooPresenceLexeme.str)
  144. assert.equal('+', this.barPresenceLexeme.str)
  145. })
  146. })
  147. })
  148. suite('multiple terms with presence and fuzz', function () {
  149. setup(function () {
  150. this.lexer = lex('+foo~1 +bar')
  151. })
  152. test('produces n lexemes', function () {
  153. assert.lengthOf(this.lexer.lexemes, 5)
  154. })
  155. suite('lexemes', function () {
  156. setup(function () {
  157. this.fooPresenceLexeme = this.lexer.lexemes[0]
  158. this.fooTermLexeme = this.lexer.lexemes[1]
  159. this.fooFuzzLexeme = this.lexer.lexemes[2]
  160. this.barPresenceLexeme = this.lexer.lexemes[3]
  161. this.barTermLexeme = this.lexer.lexemes[4]
  162. })
  163. test('#type', function () {
  164. assert.equal(lunr.QueryLexer.PRESENCE, this.fooPresenceLexeme.type)
  165. assert.equal(lunr.QueryLexer.TERM, this.fooTermLexeme.type)
  166. assert.equal(lunr.QueryLexer.EDIT_DISTANCE, this.fooFuzzLexeme.type)
  167. assert.equal(lunr.QueryLexer.PRESENCE, this.barPresenceLexeme.type)
  168. assert.equal(lunr.QueryLexer.TERM, this.barTermLexeme.type)
  169. })
  170. })
  171. })
  172. suite('separator length > 1', function () {
  173. setup(function () {
  174. this.lexer = lex('foo bar')
  175. })
  176. test('produces 2 lexems', function () {
  177. assert.lengthOf(this.lexer.lexemes, 2)
  178. })
  179. suite('lexemes', function () {
  180. setup(function () {
  181. this.fooLexeme = this.lexer.lexemes[0]
  182. this.barLexeme = this.lexer.lexemes[1]
  183. })
  184. test('#type', function () {
  185. assert.equal(lunr.QueryLexer.TERM, this.fooLexeme.type)
  186. assert.equal(lunr.QueryLexer.TERM, this.barLexeme.type)
  187. })
  188. test('#str', function () {
  189. assert.equal('foo', this.fooLexeme.str)
  190. assert.equal('bar', this.barLexeme.str)
  191. })
  192. test('#start', function () {
  193. assert.equal(0, this.fooLexeme.start)
  194. assert.equal(7, this.barLexeme.start)
  195. })
  196. test('#end', function () {
  197. assert.equal(3, this.fooLexeme.end)
  198. assert.equal(10, this.barLexeme.end)
  199. })
  200. })
  201. })
  202. suite('hyphen (-) considered a seperator', function () {
  203. setup(function () {
  204. this.lexer = lex('foo-bar')
  205. })
  206. test('produces 1 lexeme', function () {
  207. assert.lengthOf(this.lexer.lexemes, 2)
  208. })
  209. })
  210. suite('term with field', function () {
  211. setup(function () {
  212. this.lexer = lex('title:foo')
  213. })
  214. test('produces 2 lexems', function () {
  215. assert.lengthOf(this.lexer.lexemes, 2)
  216. })
  217. suite('lexemes', function () {
  218. setup(function () {
  219. this.fieldLexeme = this.lexer.lexemes[0]
  220. this.termLexeme = this.lexer.lexemes[1]
  221. })
  222. test('#type', function () {
  223. assert.equal(lunr.QueryLexer.FIELD, this.fieldLexeme.type)
  224. assert.equal(lunr.QueryLexer.TERM, this.termLexeme.type)
  225. })
  226. test('#str', function () {
  227. assert.equal('title', this.fieldLexeme.str)
  228. assert.equal('foo', this.termLexeme.str)
  229. })
  230. test('#start', function () {
  231. assert.equal(0, this.fieldLexeme.start)
  232. assert.equal(6, this.termLexeme.start)
  233. })
  234. test('#end', function () {
  235. assert.equal(5, this.fieldLexeme.end)
  236. assert.equal(9, this.termLexeme.end)
  237. })
  238. })
  239. })
  240. suite('term with field with escape char', function () {
  241. setup(function () {
  242. this.lexer = lex("ti\\:tle:foo")
  243. })
  244. test('produces 1 lexeme', function () {
  245. assert.lengthOf(this.lexer.lexemes, 2)
  246. })
  247. suite('lexeme', function () {
  248. setup(function () {
  249. this.fieldLexeme = this.lexer.lexemes[0]
  250. this.termLexeme = this.lexer.lexemes[1]
  251. })
  252. test('#type', function () {
  253. assert.equal(lunr.QueryLexer.FIELD, this.fieldLexeme.type)
  254. assert.equal(lunr.QueryLexer.TERM, this.termLexeme.type)
  255. })
  256. test('#str', function () {
  257. assert.equal('ti:tle', this.fieldLexeme.str)
  258. assert.equal('foo', this.termLexeme.str)
  259. })
  260. test('#start', function () {
  261. assert.equal(0, this.fieldLexeme.start)
  262. assert.equal(8, this.termLexeme.start)
  263. })
  264. test('#end', function () {
  265. assert.equal(7, this.fieldLexeme.end)
  266. assert.equal(11, this.termLexeme.end)
  267. })
  268. })
  269. })
  270. suite('term with presence required', function () {
  271. setup(function () {
  272. this.lexer = lex('+foo')
  273. })
  274. test('produces 2 lexemes', function () {
  275. assert.lengthOf(this.lexer.lexemes, 2)
  276. })
  277. suite('lexemes', function () {
  278. setup(function () {
  279. this.presenceLexeme = this.lexer.lexemes[0]
  280. this.termLexeme = this.lexer.lexemes[1]
  281. })
  282. test('#type', function () {
  283. assert.equal(lunr.QueryLexer.PRESENCE, this.presenceLexeme.type)
  284. assert.equal(lunr.QueryLexer.TERM, this.termLexeme.type)
  285. })
  286. test('#str', function () {
  287. assert.equal('+', this.presenceLexeme.str)
  288. assert.equal('foo', this.termLexeme.str)
  289. })
  290. test('#start', function () {
  291. assert.equal(1, this.termLexeme.start)
  292. assert.equal(0, this.presenceLexeme.start)
  293. })
  294. test('#end', function () {
  295. assert.equal(4, this.termLexeme.end)
  296. assert.equal(1, this.presenceLexeme.end)
  297. })
  298. })
  299. })
  300. suite('term with field with presence required', function () {
  301. setup(function () {
  302. this.lexer = lex('+title:foo')
  303. })
  304. test('produces 3 lexemes', function () {
  305. assert.lengthOf(this.lexer.lexemes, 3)
  306. })
  307. suite('lexemes', function () {
  308. setup(function () {
  309. this.presenceLexeme = this.lexer.lexemes[0]
  310. this.fieldLexeme = this.lexer.lexemes[1]
  311. this.termLexeme = this.lexer.lexemes[2]
  312. })
  313. test('#type', function () {
  314. assert.equal(lunr.QueryLexer.PRESENCE, this.presenceLexeme.type)
  315. assert.equal(lunr.QueryLexer.FIELD, this.fieldLexeme.type)
  316. assert.equal(lunr.QueryLexer.TERM, this.termLexeme.type)
  317. })
  318. test('#str', function () {
  319. assert.equal('+', this.presenceLexeme.str)
  320. assert.equal('title', this.fieldLexeme.str)
  321. assert.equal('foo', this.termLexeme.str)
  322. })
  323. test('#start', function () {
  324. assert.equal(0, this.presenceLexeme.start)
  325. assert.equal(1, this.fieldLexeme.start)
  326. assert.equal(7, this.termLexeme.start)
  327. })
  328. test('#end', function () {
  329. assert.equal(1, this.presenceLexeme.end)
  330. assert.equal(6, this.fieldLexeme.end)
  331. assert.equal(10, this.termLexeme.end)
  332. })
  333. })
  334. })
  335. suite('term with presence prohibited', function () {
  336. setup(function () {
  337. this.lexer = lex('-foo')
  338. })
  339. test('produces 2 lexemes', function () {
  340. assert.lengthOf(this.lexer.lexemes, 2)
  341. })
  342. suite('lexemes', function () {
  343. setup(function () {
  344. this.presenceLexeme = this.lexer.lexemes[0]
  345. this.termLexeme = this.lexer.lexemes[1]
  346. })
  347. test('#type', function () {
  348. assert.equal(lunr.QueryLexer.PRESENCE, this.presenceLexeme.type)
  349. assert.equal(lunr.QueryLexer.TERM, this.termLexeme.type)
  350. })
  351. test('#str', function () {
  352. assert.equal('-', this.presenceLexeme.str)
  353. assert.equal('foo', this.termLexeme.str)
  354. })
  355. test('#start', function () {
  356. assert.equal(1, this.termLexeme.start)
  357. assert.equal(0, this.presenceLexeme.start)
  358. })
  359. test('#end', function () {
  360. assert.equal(4, this.termLexeme.end)
  361. assert.equal(1, this.presenceLexeme.end)
  362. })
  363. })
  364. })
  365. suite('term with edit distance', function () {
  366. setup(function () {
  367. this.lexer = lex('foo~2')
  368. })
  369. test('produces 2 lexems', function () {
  370. assert.lengthOf(this.lexer.lexemes, 2)
  371. })
  372. suite('lexemes', function () {
  373. setup(function () {
  374. this.termLexeme = this.lexer.lexemes[0]
  375. this.editDistanceLexeme = this.lexer.lexemes[1]
  376. })
  377. test('#type', function () {
  378. assert.equal(lunr.QueryLexer.TERM, this.termLexeme.type)
  379. assert.equal(lunr.QueryLexer.EDIT_DISTANCE, this.editDistanceLexeme.type)
  380. })
  381. test('#str', function () {
  382. assert.equal('foo', this.termLexeme.str)
  383. assert.equal('2', this.editDistanceLexeme.str)
  384. })
  385. test('#start', function () {
  386. assert.equal(0, this.termLexeme.start)
  387. assert.equal(4, this.editDistanceLexeme.start)
  388. })
  389. test('#end', function () {
  390. assert.equal(3, this.termLexeme.end)
  391. assert.equal(5, this.editDistanceLexeme.end)
  392. })
  393. })
  394. })
  395. suite('term with boost', function () {
  396. setup(function () {
  397. this.lexer = lex('foo^10')
  398. })
  399. test('produces 2 lexems', function () {
  400. assert.lengthOf(this.lexer.lexemes, 2)
  401. })
  402. suite('lexemes', function () {
  403. setup(function () {
  404. this.termLexeme = this.lexer.lexemes[0]
  405. this.boostLexeme = this.lexer.lexemes[1]
  406. })
  407. test('#type', function () {
  408. assert.equal(lunr.QueryLexer.TERM, this.termLexeme.type)
  409. assert.equal(lunr.QueryLexer.BOOST, this.boostLexeme.type)
  410. })
  411. test('#str', function () {
  412. assert.equal('foo', this.termLexeme.str)
  413. assert.equal('10', this.boostLexeme.str)
  414. })
  415. test('#start', function () {
  416. assert.equal(0, this.termLexeme.start)
  417. assert.equal(4, this.boostLexeme.start)
  418. })
  419. test('#end', function () {
  420. assert.equal(3, this.termLexeme.end)
  421. assert.equal(6, this.boostLexeme.end)
  422. })
  423. })
  424. })
  425. suite('term with field, boost and edit distance', function () {
  426. setup(function () {
  427. this.lexer = lex('title:foo^10~5')
  428. })
  429. test('produces 4 lexems', function () {
  430. assert.lengthOf(this.lexer.lexemes, 4)
  431. })
  432. suite('lexemes', function () {
  433. setup(function () {
  434. this.fieldLexeme = this.lexer.lexemes[0]
  435. this.termLexeme = this.lexer.lexemes[1]
  436. this.boostLexeme = this.lexer.lexemes[2]
  437. this.editDistanceLexeme = this.lexer.lexemes[3]
  438. })
  439. test('#type', function () {
  440. assert.equal(lunr.QueryLexer.FIELD, this.fieldLexeme.type)
  441. assert.equal(lunr.QueryLexer.TERM, this.termLexeme.type)
  442. assert.equal(lunr.QueryLexer.BOOST, this.boostLexeme.type)
  443. assert.equal(lunr.QueryLexer.EDIT_DISTANCE, this.editDistanceLexeme.type)
  444. })
  445. test('#str', function () {
  446. assert.equal('title', this.fieldLexeme.str)
  447. assert.equal('foo', this.termLexeme.str)
  448. assert.equal('10', this.boostLexeme.str)
  449. assert.equal('5', this.editDistanceLexeme.str)
  450. })
  451. test('#start', function () {
  452. assert.equal(0, this.fieldLexeme.start)
  453. assert.equal(6, this.termLexeme.start)
  454. assert.equal(10, this.boostLexeme.start)
  455. assert.equal(13, this.editDistanceLexeme.start)
  456. })
  457. test('#end', function () {
  458. assert.equal(5, this.fieldLexeme.end)
  459. assert.equal(9, this.termLexeme.end)
  460. assert.equal(12, this.boostLexeme.end)
  461. assert.equal(14, this.editDistanceLexeme.end)
  462. })
  463. })
  464. })
  465. })
  466. })