search-service.test.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * !! TODO: https://redmine.weseek.co.jp/issues/92050 Fix & adjust test !!
  3. */
  4. import mongoose from 'mongoose';
  5. import NamedQuery from '~/server/models/named-query';
  6. import SearchService from '~/server/service/search';
  7. const { getInstance } = require('../../setup-crowi');
  8. describe('SearchService test', () => {
  9. let crowi;
  10. let searchService;
  11. const DEFAULT = 'FullTextSearch';
  12. const PRIVATE_LEGACY_PAGES = 'PrivateLegacyPages';
  13. // let NamedQuery;
  14. let dummyAliasOf;
  15. let namedQuery1;
  16. let namedQuery2;
  17. const dummyFullTextSearchDelegator = {
  18. search() {
  19. return;
  20. },
  21. };
  22. beforeAll(async () => {
  23. crowi = await getInstance();
  24. searchService = new SearchService(crowi);
  25. searchService.nqDelegators = {
  26. ...searchService.nqDelegators,
  27. [DEFAULT]: dummyFullTextSearchDelegator, // override with dummy full-text search delegator
  28. };
  29. dummyAliasOf =
  30. 'match -notmatch "phrase" -"notphrase" prefix:/pre1 -prefix:/pre2 tag:Tag1 -tag:Tag2';
  31. await NamedQuery.insertMany([
  32. { name: 'named_query1', delegatorName: PRIVATE_LEGACY_PAGES },
  33. { name: 'named_query2', aliasOf: dummyAliasOf },
  34. ]);
  35. namedQuery1 = await NamedQuery.findOne({ name: 'named_query1' });
  36. namedQuery2 = await NamedQuery.findOne({ name: 'named_query2' });
  37. });
  38. describe('parseQueryString()', () => {
  39. test('should parse queryString', async () => {
  40. const queryString =
  41. 'match -notmatch "phrase" -"notphrase" prefix:/pre1 -prefix:/pre2 tag:Tag1 -tag:Tag2';
  42. const terms = await searchService.parseQueryString(queryString);
  43. const expected = {
  44. // QueryTerms
  45. match: ['match'],
  46. not_match: ['notmatch'],
  47. phrase: ['"phrase"'],
  48. not_phrase: ['"notphrase"'],
  49. prefix: ['/pre1'],
  50. not_prefix: ['/pre2'],
  51. tag: ['Tag1'],
  52. not_tag: ['Tag2'],
  53. };
  54. expect(terms).toStrictEqual(expected);
  55. });
  56. });
  57. describe('parseSearchQuery()', () => {
  58. test('should return result with delegatorName', async () => {
  59. const queryString = '/';
  60. const nqName = 'named_query1';
  61. const parsedQuery = await searchService.parseSearchQuery(
  62. queryString,
  63. nqName,
  64. );
  65. const expected = {
  66. queryString,
  67. delegatorName: PRIVATE_LEGACY_PAGES,
  68. terms: {
  69. match: ['/'],
  70. not_match: [],
  71. phrase: [],
  72. not_phrase: [],
  73. prefix: [],
  74. not_prefix: [],
  75. tag: [],
  76. not_tag: [],
  77. },
  78. };
  79. expect(parsedQuery).toStrictEqual(expected);
  80. });
  81. test('should return result with expanded aliasOf value', async () => {
  82. const queryString = '/';
  83. const nqName = 'named_query2';
  84. const parsedQuery = await searchService.parseSearchQuery(
  85. queryString,
  86. nqName,
  87. );
  88. const expected = {
  89. queryString: dummyAliasOf,
  90. terms: {
  91. match: ['match'],
  92. not_match: ['notmatch'],
  93. phrase: ['"phrase"'],
  94. not_phrase: ['"notphrase"'],
  95. prefix: ['/pre1'],
  96. not_prefix: ['/pre2'],
  97. tag: ['Tag1'],
  98. not_tag: ['Tag2'],
  99. },
  100. };
  101. expect(parsedQuery).toStrictEqual(expected);
  102. });
  103. });
  104. describe('resolve()', () => {
  105. test('should resolve as full-text search delegator', async () => {
  106. const parsedQuery = {
  107. queryString: dummyAliasOf,
  108. terms: {
  109. match: ['match'],
  110. not_match: ['notmatch'],
  111. phrase: ['"phrase"'],
  112. not_phrase: ['"notphrase"'],
  113. prefix: ['/pre1'],
  114. not_prefix: ['/pre2'],
  115. tag: ['Tag1'],
  116. not_tag: ['Tag2'],
  117. },
  118. };
  119. const [delegator, data] = await searchService.resolve(parsedQuery);
  120. const expectedData = parsedQuery;
  121. expect(data).toStrictEqual(expectedData);
  122. expect(typeof delegator.search).toBe('function');
  123. });
  124. test('should resolve as custom search delegator', async () => {
  125. const queryString = '/';
  126. const parsedQuery = {
  127. queryString,
  128. delegatorName: PRIVATE_LEGACY_PAGES,
  129. terms: {
  130. match: ['/'],
  131. not_match: [],
  132. phrase: [],
  133. not_phrase: [],
  134. prefix: [],
  135. not_prefix: [],
  136. tag: [],
  137. not_tag: [],
  138. },
  139. };
  140. const [delegator, data] = await searchService.resolve(parsedQuery);
  141. const expectedData = {
  142. queryString: '/',
  143. terms: parsedQuery.terms,
  144. };
  145. expect(data).toStrictEqual(expectedData);
  146. expect(typeof delegator.search).toBe('function');
  147. });
  148. });
  149. describe('searchKeyword()', () => {
  150. test('should search with custom search delegator', async () => {
  151. const Page = mongoose.model('Page');
  152. const User = mongoose.model('User');
  153. await User.insertMany([
  154. {
  155. name: 'dummyuser1',
  156. username: 'dummyuser1',
  157. email: 'dummyuser1@example.com',
  158. },
  159. {
  160. name: 'dummyuser2',
  161. username: 'dummyuser2',
  162. email: 'dummyuser2@example.com',
  163. },
  164. ]);
  165. const testUser1 = await User.findOne({ username: 'dummyuser1' });
  166. const testUser2 = await User.findOne({ username: 'dummyuser2' });
  167. await Page.insertMany([
  168. {
  169. path: '/user1',
  170. grant: Page.GRANT_PUBLIC,
  171. creator: testUser1,
  172. lastUpdateUser: testUser1,
  173. },
  174. {
  175. path: '/user1_owner',
  176. grant: Page.GRANT_OWNER,
  177. creator: testUser1,
  178. lastUpdateUser: testUser1,
  179. grantedUsers: [testUser1._id],
  180. },
  181. {
  182. path: '/user2_public',
  183. grant: Page.GRANT_PUBLIC,
  184. creator: testUser2,
  185. lastUpdateUser: testUser2,
  186. },
  187. ]);
  188. const page1 = await Page.findOne({ path: '/user1' });
  189. await Page.insertMany([
  190. {
  191. path: '/user1/hasParent',
  192. grant: Page.GRANT_PUBLIC,
  193. creator: testUser1,
  194. lastUpdateUser: testUser1,
  195. parent: page1,
  196. },
  197. ]);
  198. const queryString = '/';
  199. const nqName = 'named_query1';
  200. const [result, delegatorName] = await searchService.searchKeyword(
  201. queryString,
  202. nqName,
  203. testUser1,
  204. null,
  205. { offset: 0, limit: 100 },
  206. );
  207. const resultPaths = result.data.map((page) => page.path);
  208. const flag =
  209. resultPaths.includes('/user1') &&
  210. resultPaths.includes('/user1_owner') &&
  211. resultPaths.includes('/user2_public');
  212. expect(flag).toBe(true);
  213. expect(delegatorName).toBe(PRIVATE_LEGACY_PAGES);
  214. });
  215. });
  216. });