v5.page.test.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. import mongoose from 'mongoose';
  2. import { PageActionType } from '../../../src/server/models/page-operation';
  3. import { getInstance } from '../setup-crowi';
  4. describe('Test page service methods', () => {
  5. let crowi;
  6. let Page;
  7. let Revision;
  8. let User;
  9. let UserGroup;
  10. let UserGroupRelation;
  11. let Tag;
  12. let PageTagRelation;
  13. let Bookmark;
  14. let Comment;
  15. let ShareLink;
  16. let PageRedirect;
  17. let PageOperation;
  18. let xssSpy;
  19. let rootPage;
  20. let dummyUser1;
  21. let dummyUser2;
  22. let globalGroupUser1;
  23. let globalGroupUser2;
  24. let globalGroupUser3;
  25. let globalGroupIsolate;
  26. let globalGroupA;
  27. let globalGroupB;
  28. let globalGroupC;
  29. beforeAll(async() => {
  30. crowi = await getInstance();
  31. await crowi.configManager.updateConfigsInTheSameNamespace('crowi', { 'app:isV5Compatible': true });
  32. User = mongoose.model('User');
  33. UserGroup = mongoose.model('UserGroup');
  34. UserGroupRelation = mongoose.model('UserGroupRelation');
  35. Page = mongoose.model('Page');
  36. Revision = mongoose.model('Revision');
  37. Tag = mongoose.model('Tag');
  38. PageTagRelation = mongoose.model('PageTagRelation');
  39. Bookmark = mongoose.model('Bookmark');
  40. Comment = mongoose.model('Comment');
  41. ShareLink = mongoose.model('ShareLink');
  42. PageRedirect = mongoose.model('PageRedirect');
  43. UserGroup = mongoose.model('UserGroup');
  44. UserGroupRelation = mongoose.model('UserGroupRelation');
  45. PageOperation = mongoose.model('PageOperation');
  46. /*
  47. * Common
  48. */
  49. xssSpy = jest.spyOn(crowi.xss, 'process').mockImplementation(path => path);
  50. // ***********************************************************************************************************
  51. // * Do NOT change properties of globally used documents. Otherwise, it might cause some errors in other tests
  52. // ***********************************************************************************************************
  53. // users
  54. dummyUser1 = await User.findOne({ username: 'v5DummyUser1' });
  55. dummyUser2 = await User.findOne({ username: 'v5DummyUser2' });
  56. globalGroupUser1 = await User.findOne({ username: 'gGroupUser1' });
  57. globalGroupUser2 = await User.findOne({ username: 'gGroupUser2' });
  58. globalGroupUser3 = await User.findOne({ username: 'gGroupUser3' });
  59. // groups
  60. globalGroupIsolate = await UserGroup.findOne({ name: 'globalGroupIsolate' });
  61. globalGroupA = await UserGroup.findOne({ name: 'globalGroupA' });
  62. globalGroupB = await UserGroup.findOne({ name: 'globalGroupB' });
  63. globalGroupC = await UserGroup.findOne({ name: 'globalGroupC' });
  64. // page
  65. rootPage = await Page.findOne({ path: '/' });
  66. /**
  67. * pages
  68. */
  69. const pageId0 = new mongoose.Types.ObjectId();
  70. const pageId1 = new mongoose.Types.ObjectId();
  71. const pageId2 = new mongoose.Types.ObjectId();
  72. const pageId3 = new mongoose.Types.ObjectId();
  73. const pageId4 = new mongoose.Types.ObjectId();
  74. const pageId5 = new mongoose.Types.ObjectId();
  75. const pageId6 = new mongoose.Types.ObjectId();
  76. await Page.insertMany([
  77. {
  78. _id: pageId0,
  79. path: '/POP0',
  80. parent: rootPage._id,
  81. grant: Page.GRANT_PUBLIC,
  82. creator: dummyUser1,
  83. lastUpdateUser: dummyUser1._id,
  84. descendantCount: 0,
  85. isEmpty: false,
  86. },
  87. {
  88. _id: pageId1,
  89. path: '/POP0/renamePOP1',
  90. parent: pageId0._id,
  91. grant: Page.GRANT_PUBLIC,
  92. creator: dummyUser1,
  93. lastUpdateUser: dummyUser1._id,
  94. descendantCount: 2,
  95. isEmpty: false,
  96. },
  97. {
  98. _id: pageId2,
  99. path: '/renamePOP1/renamePOP2',
  100. parent: pageId1,
  101. grant: Page.GRANT_PUBLIC,
  102. creator: dummyUser1,
  103. lastUpdateUser: dummyUser1._id,
  104. descendantCount: 1,
  105. isEmpty: false,
  106. },
  107. {
  108. _id: pageId3,
  109. path: '/renamePOP1/renamePOP2/renamePOP3',
  110. parent: pageId2,
  111. grant: Page.GRANT_PUBLIC,
  112. creator: dummyUser1,
  113. lastUpdateUser: dummyUser1._id,
  114. descendantCount: 0,
  115. isEmpty: false,
  116. },
  117. {
  118. _id: pageId4,
  119. path: '/POP1',
  120. parent: rootPage._id,
  121. grant: Page.GRANT_PUBLIC,
  122. creator: dummyUser1,
  123. lastUpdateUser: dummyUser1._id,
  124. descendantCount: 0,
  125. isEmpty: false,
  126. },
  127. {
  128. _id: pageId5,
  129. path: '/POP1/renamePOP4',
  130. parent: pageId0._id,
  131. grant: Page.GRANT_PUBLIC,
  132. creator: dummyUser1,
  133. lastUpdateUser: dummyUser1._id,
  134. descendantCount: 1,
  135. isEmpty: false,
  136. },
  137. {
  138. _id: pageId6,
  139. path: '/renamePOP4/renamePOP5',
  140. parent: pageId5,
  141. grant: Page.GRANT_PUBLIC,
  142. creator: dummyUser1,
  143. lastUpdateUser: dummyUser1._id,
  144. descendantCount: 0,
  145. isEmpty: false,
  146. },
  147. ]);
  148. /**
  149. * PageOperation
  150. */
  151. const pageOpId1 = new mongoose.Types.ObjectId();
  152. const pageOpId2 = new mongoose.Types.ObjectId();
  153. const pageOpRevisionId1 = new mongoose.Types.ObjectId();
  154. const pageOpRevisionId2 = new mongoose.Types.ObjectId();
  155. await PageOperation.insertMany([
  156. {
  157. _id: pageOpId1,
  158. actionType: 'Rename',
  159. actionStage: 'Sub',
  160. fromPath: '/renamePOP1',
  161. toPath: '/POP0/renamePOP1',
  162. page: {
  163. _id: pageId1,
  164. parent: rootPage._id,
  165. descendantCount: 2,
  166. isEmpty: false,
  167. path: '/renamePOP1',
  168. revision: pageOpRevisionId1,
  169. status: 'published',
  170. grant: 1,
  171. grantedUsers: [],
  172. grantedGroup: null,
  173. creator: dummyUser1._id,
  174. lastUpdateUser: dummyUser1._id,
  175. },
  176. user: {
  177. _id: dummyUser1._id,
  178. },
  179. options: {
  180. createRedirectPage: false,
  181. updateMetadata: true,
  182. },
  183. unprocessableExpiryDate: null,
  184. },
  185. {
  186. _id: pageOpId2,
  187. actionType: 'Rename',
  188. actionStage: 'Sub',
  189. fromPath: '/renamePOP4',
  190. toPath: '/POP1/renamePOP4',
  191. page: {
  192. _id: pageId5,
  193. parent: rootPage._id,
  194. descendantCount: 2,
  195. isEmpty: false,
  196. path: '/renamePOP4',
  197. revision: pageOpRevisionId2,
  198. status: 'published',
  199. grant: 1,
  200. grantedUsers: [],
  201. grantedGroup: null,
  202. creator: dummyUser1._id,
  203. lastUpdateUser: dummyUser1._id,
  204. },
  205. user: {
  206. _id: dummyUser1._id,
  207. },
  208. options: {
  209. createRedirectPage: false,
  210. updateMetadata: true,
  211. },
  212. unprocessableExpiryDate: new Date(5000, 0, 1), // year 5000
  213. },
  214. ]);
  215. });
  216. describe('restart renameOperation', () => {
  217. const resumeRenameSubOperation = async(page) => {
  218. const mockedRenameSubOperation = jest.spyOn(crowi.pageService, 'renameSubOperation').mockReturnValue(null);
  219. await crowi.pageService.resumeRenameSubOperation(page);
  220. const argsForRenameSubOperation = mockedRenameSubOperation.mock.calls[0];
  221. mockedRenameSubOperation.mockRestore();
  222. await crowi.pageService.renameSubOperation(...argsForRenameSubOperation);
  223. };
  224. test('it should successfully restart rename operation', async() => {
  225. // path
  226. const _path0 = '/POP0';
  227. const _path1 = '/POP0/renamePOP1'; // renamed already
  228. const _path2 = '/renamePOP1/renamePOP2'; // not renamed yet
  229. const _path3 = '/renamePOP1/renamePOP2/renamePOP3'; // not renamed yet
  230. // page
  231. const _page0 = await Page.findOne({ path: _path0 });
  232. const _page1 = await Page.findOne({ path: _path1 });
  233. const _page2 = await Page.findOne({ path: _path2 });
  234. const _page3 = await Page.findOne({ path: _path3 });
  235. expect(_page0).toBeTruthy();
  236. expect(_page1).toBeTruthy();
  237. expect(_page2).toBeTruthy();
  238. expect(_page3).toBeTruthy();
  239. // PageOperation
  240. const _pageOperation = await PageOperation.findOne({ 'page._id': _page1._id, actionType: PageActionType.Rename });
  241. expect(_pageOperation).toBeTruthy();
  242. await resumeRenameSubOperation(_page1);
  243. // path
  244. const path0 = '/POP0';
  245. const path1 = '/POP0/renamePOP1';
  246. const path2 = '/POP0/renamePOP1/renamePOP2';
  247. const path3 = '/POP0/renamePOP1/renamePOP2/renamePOP3';
  248. // page
  249. const page0 = await Page.findOne({ path: path0 });
  250. const page1 = await Page.findOne({ path: path1 });
  251. const page2 = await Page.findOne({ path: path2 });
  252. const page3 = await Page.findOne({ path: path3 });
  253. // PageOperation
  254. const pageOperation = await PageOperation.findOne({ _id: _pageOperation._id });
  255. expect(page0.descendantCount).toBe(3);
  256. expect(page0).toBeTruthy();
  257. expect(page1).toBeTruthy();
  258. expect(page2).toBeTruthy();
  259. expect(page3).toBeTruthy();
  260. expect(pageOperation).toBeNull(); // should not exist
  261. expect(page1.parent).toStrictEqual(page0._id);
  262. expect(page2.parent).toStrictEqual(page1._id);
  263. expect(page3.parent).toStrictEqual(page2._id);
  264. expect(page0.descendantCount).toBe(3);
  265. expect(page1.descendantCount).toBe(2);
  266. expect(page2.descendantCount).toBe(1);
  267. expect(page3.descendantCount).toBe(0);
  268. });
  269. test('it should fail and throw error if PageOperation is not found', async() => {
  270. await expect(resumeRenameSubOperation({}))
  271. .rejects.toThrow(new Error('There is nothing to be processed right now'));
  272. });
  273. test.skip('it should fail and throw error if the current time is behind unprocessableExpiryDate', async() => {
  274. const _path0 = '/POP1';
  275. const _path1 = '/POP1/renamePOP4'; // renamed already
  276. const _path2 = '/renamePOP4/renamePOP5'; // not renamed yet
  277. const _page0 = await Page.findOne({ path: _path0 });
  278. const _page1 = await Page.findOne({ path: _path1 });
  279. const _page2 = await Page.findOne({ path: _path2 });
  280. const _pageOperation = await PageOperation.findOne({ 'page._id': _page1._id, actionType: PageActionType.Rename });
  281. expect(_page0).toBeTruthy();
  282. expect(_page1).toBeTruthy();
  283. expect(_page2).toBeTruthy();
  284. expect(_pageOperation).toBeTruthy();
  285. const promise = resumeRenameSubOperation(_page1._id);
  286. await expect(promise).rejects.toThrow(new Error('it did not restart rename operation because it is currently being processed'));
  287. });
  288. });
  289. });