search-service.test.js 6.3 KB

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