pagev5.test.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /* eslint-disable no-unused-vars */
  2. import { advanceTo } from 'jest-date-mock';
  3. import mongoose from 'mongoose';
  4. import { getInstance } from '../setup-crowi';
  5. describe('PageService page operations with only public pages', () => {
  6. let dummyUser1;
  7. let dummyUser2;
  8. let crowi;
  9. let Page;
  10. let Revision;
  11. let User;
  12. let Tag;
  13. let PageTagRelation;
  14. let Bookmark;
  15. let Comment;
  16. let ShareLink;
  17. let PageRedirect;
  18. let xssSpy;
  19. let rootPage;
  20. // parents
  21. let parentForRename1;
  22. let parentForRename2;
  23. let parentForRename3;
  24. let parentForRename4;
  25. let parentForRename5;
  26. let parentForRename6;
  27. let parentForRename7;
  28. // children
  29. let childForRename1;
  30. let childForRename2;
  31. let childForRename3;
  32. let childForRename4;
  33. let childForRename5;
  34. let childForRename6;
  35. let childForRename7;
  36. // rename
  37. // parents
  38. let parentForDuplicate1;
  39. beforeAll(async() => {
  40. crowi = await getInstance();
  41. await crowi.configManager.updateConfigsInTheSameNamespace('crowi', { 'app:isV5Compatible': true });
  42. User = mongoose.model('User');
  43. Page = mongoose.model('Page');
  44. Revision = mongoose.model('Revision');
  45. Tag = mongoose.model('Tag');
  46. PageTagRelation = mongoose.model('PageTagRelation');
  47. Bookmark = mongoose.model('Bookmark');
  48. Comment = mongoose.model('Comment');
  49. ShareLink = mongoose.model('ShareLink');
  50. PageRedirect = mongoose.model('PageRedirect');
  51. /*
  52. * Common
  53. */
  54. await User.insertMany([
  55. { name: 'dummyUser1', username: 'dummyUser1', email: 'dummyUser1@example.com' },
  56. { name: 'dummyUser2', username: 'dummyUser2', email: 'dummyUser2@example.com' },
  57. ]);
  58. dummyUser1 = await User.findOne({ username: 'dummyUser1' });
  59. dummyUser2 = await User.findOne({ username: 'dummyUser2' });
  60. xssSpy = jest.spyOn(crowi.xss, 'process').mockImplementation(path => path);
  61. /*
  62. * Rename
  63. */
  64. // delete root page if any created by other test file
  65. const pages = await Page.find({ path: '/' });
  66. if (pages.length > 0) {
  67. await Page.deleteOne({ path: '/' });
  68. }
  69. // then create new root page
  70. rootPage = await Page.create('/', 'body', dummyUser1._id, {});
  71. // Create Pages
  72. await Page.insertMany([
  73. // parents
  74. {
  75. path: '/v5_ParentForRename1',
  76. grant: Page.GRANT_PUBLIC,
  77. creator: dummyUser1,
  78. lastUpdateUser: dummyUser1._id,
  79. parent: rootPage._id,
  80. },
  81. {
  82. path: '/v5_ParentForRename2',
  83. grant: Page.GRANT_PUBLIC,
  84. creator: dummyUser1,
  85. lastUpdateUser: dummyUser1._id,
  86. parent: rootPage._id,
  87. isEmpty: true,
  88. },
  89. {
  90. path: '/v5_ParentForRename3',
  91. grant: Page.GRANT_PUBLIC,
  92. creator: dummyUser1,
  93. lastUpdateUser: dummyUser1._id,
  94. parent: rootPage._id,
  95. },
  96. {
  97. path: '/v5_ParentForRename4',
  98. grant: Page.GRANT_PUBLIC,
  99. creator: dummyUser1,
  100. lastUpdateUser: dummyUser1._id,
  101. parent: rootPage._id,
  102. },
  103. {
  104. path: '/v5_ParentForRename5',
  105. grant: Page.GRANT_PUBLIC,
  106. creator: dummyUser1,
  107. lastUpdateUser: dummyUser1._id,
  108. parent: rootPage._id,
  109. },
  110. {
  111. path: '/v5_ParentForRename6',
  112. grant: Page.GRANT_PUBLIC,
  113. creator: dummyUser1,
  114. lastUpdateUser: dummyUser1._id,
  115. parent: rootPage._id,
  116. },
  117. {
  118. path: '/v5_ParentForRename7',
  119. grant: Page.GRANT_PUBLIC,
  120. creator: dummyUser1,
  121. lastUpdateUser: dummyUser1._id,
  122. parent: rootPage._id,
  123. },
  124. // children
  125. {
  126. path: '/v5_ChildForRename1',
  127. grant: Page.GRANT_PUBLIC,
  128. creator: dummyUser1,
  129. lastUpdateUser: dummyUser1._id,
  130. parent: rootPage._id,
  131. },
  132. {
  133. path: '/v5_ChildForRename2',
  134. grant: Page.GRANT_PUBLIC,
  135. creator: dummyUser1,
  136. lastUpdateUser: dummyUser1._id,
  137. parent: rootPage._id,
  138. },
  139. {
  140. path: '/v5_ChildForRename3',
  141. grant: Page.GRANT_PUBLIC,
  142. creator: dummyUser1,
  143. lastUpdateUser: dummyUser1._id,
  144. parent: rootPage._id,
  145. updatedAt: new Date('2021'),
  146. },
  147. {
  148. path: '/v5_ChildForRename4',
  149. grant: Page.GRANT_PUBLIC,
  150. creator: dummyUser1,
  151. lastUpdateUser: dummyUser1._id,
  152. parent: rootPage._id,
  153. },
  154. {
  155. path: '/v5_ChildForRename5',
  156. grant: Page.GRANT_PUBLIC,
  157. creator: dummyUser1,
  158. lastUpdateUser: dummyUser1._id,
  159. parent: rootPage._id,
  160. },
  161. {
  162. path: '/v5_ChildForRename6',
  163. grant: Page.GRANT_RESTRICTED,
  164. creator: dummyUser1,
  165. lastUpdateUser: dummyUser1._id,
  166. parent: rootPage._id,
  167. },
  168. {
  169. path: '/v5_ChildForRename7',
  170. grant: Page.GRANT_PUBLIC,
  171. parent: rootPage._id,
  172. isEmpty: true,
  173. },
  174. ]);
  175. // Find pages as Parent
  176. parentForRename1 = await Page.findOne({ path: '/v5_ParentForRename1' });
  177. parentForRename2 = await Page.findOne({ path: '/v5_ParentForRename2' });
  178. parentForRename3 = await Page.findOne({ path: '/v5_ParentForRename3' });
  179. parentForRename4 = await Page.findOne({ path: '/v5_ParentForRename4' });
  180. parentForRename5 = await Page.findOne({ path: '/v5_ParentForRename5' });
  181. parentForRename6 = await Page.findOne({ path: '/v5_ParentForRename6' });
  182. parentForRename7 = await Page.findOne({ path: '/v5_ParentForRename7' });
  183. // Find pages as Child
  184. childForRename1 = await Page.findOne({ path: '/v5_ChildForRename1' });
  185. childForRename2 = await Page.findOne({ path: '/v5_ChildForRename2' });
  186. childForRename3 = await Page.findOne({ path: '/v5_ChildForRename3' });
  187. childForRename4 = await Page.findOne({ path: '/v5_ChildForRename4' });
  188. childForRename5 = await Page.findOne({ path: '/v5_ChildForRename5' });
  189. childForRename6 = await Page.findOne({ path: '/v5_ChildForRename6' });
  190. childForRename7 = await Page.findOne({ path: '/v5_ChildForRename7' });
  191. // create grandchild
  192. await Page.insertMany([
  193. // Grandchild
  194. {
  195. path: '/v5_ChildForRename5/v5_GrandchildForRename5',
  196. grant: Page.GRANT_PUBLIC,
  197. creator: dummyUser1,
  198. lastUpdateUser: dummyUser1._id,
  199. parent: childForRename5._id,
  200. updatedAt: new Date('2021'),
  201. },
  202. {
  203. path: '/v5_ChildForRename7/v5_GrandchildForRename7',
  204. grant: Page.GRANT_PUBLIC,
  205. creator: dummyUser1,
  206. lastUpdateUser: dummyUser1._id,
  207. parent: childForRename7._id,
  208. },
  209. ]);
  210. /*
  211. * Duplicate
  212. */
  213. const idForPage1 = new mongoose.Types.ObjectId();
  214. const idForRevision1 = new mongoose.Types.ObjectId();
  215. await Page.insertMany([
  216. {
  217. _id: idForPage1,
  218. path: '/v5_ParentForDuplicate1',
  219. grant: Page.GRANT_PUBLIC,
  220. creator: dummyUser1,
  221. lastUpdateUser: dummyUser1._id,
  222. parent: rootPage._id,
  223. revision: idForRevision1,
  224. },
  225. ]);
  226. // Revision
  227. await Revision.insertMany([
  228. {
  229. _id: idForRevision1,
  230. body: 'body1',
  231. format: 'markdown',
  232. pageId: idForPage1,
  233. author: dummyUser1,
  234. },
  235. ]);
  236. parentForDuplicate1 = await Page.findOne({ path: '/v5_ParentForDuplicate1' });
  237. });
  238. describe('Rename', () => {
  239. const renamePage = async(page, newPagePath, user, options) => {
  240. // mock return value
  241. const mockedResumableRenameDescendants = jest.spyOn(crowi.pageService, 'resumableRenameDescendants').mockReturnValue(null);
  242. jest.spyOn(crowi.pageService, 'createAndSendNotifications').mockReturnValue(null);
  243. const renamedPage = await crowi.pageService.renamePage(page, newPagePath, user, options);
  244. // retrieve the arguments passed when calling method resumableRenameDescendants inside renamePage method
  245. const argsForResumableRenameDescendants = mockedResumableRenameDescendants.mock.calls[0];
  246. // restores the original implementation
  247. jest.restoreAllMocks();
  248. // rename descendants
  249. await crowi.pageService.resumableRenameDescendants(...argsForResumableRenameDescendants);
  250. return renamedPage;
  251. };
  252. test('Should NOT rename top page', async() => {
  253. let isThrown = false;
  254. try {
  255. await crowi.pageService.renamePage(rootPage, '/new_root', dummyUser1, {});
  256. }
  257. catch (err) {
  258. isThrown = true;
  259. }
  260. expect(isThrown).toBe(true);
  261. });
  262. test('Should move to under non-empty page', async() => {
  263. // rename target page
  264. const newPath = '/v5_ParentForRename1/renamedChildForRename1';
  265. const renamedPage = await renamePage(childForRename1, newPath, dummyUser1, {});
  266. expect(renamedPage.path).toBe(newPath);
  267. expect(renamedPage.parent).toStrictEqual(parentForRename1._id);
  268. });
  269. test('Should move to under empty page', async() => {
  270. // rename target page
  271. const newPath = '/v5_ParentForRename2/renamedChildForRename2';
  272. const renamedPage = await renamePage(childForRename2, newPath, dummyUser1, {});
  273. expect(renamedPage.path).toBe(newPath);
  274. expect(parentForRename2.isEmpty).toBe(true);
  275. expect(renamedPage.parent).toStrictEqual(parentForRename2._id);
  276. });
  277. test('Should move with option updateMetadata: true', async() => {
  278. // rename target page
  279. const newPath = '/v5_ParentForRename3/renamedChildForRename3';
  280. const oldUdpateAt = childForRename3.updatedAt;
  281. const renamedPage = await renamePage(childForRename3, newPath, dummyUser2, { updateMetadata: true });
  282. expect(renamedPage.path).toBe(newPath);
  283. expect(renamedPage.parent).toStrictEqual(parentForRename3._id);
  284. expect(renamedPage.lastUpdateUser).toStrictEqual(dummyUser2._id);
  285. expect(renamedPage.updatedAt.getFullYear()).toBeGreaterThan(oldUdpateAt.getFullYear());
  286. });
  287. // ****************** TODO ******************
  288. // uncomment the next test when working on 88097
  289. // ******************************************
  290. // test('Should move with option createRedirectPage: true', async() => {
  291. // // rename target page
  292. // const newPath = '/v5_ParentForRename4/renamedChildForRename4';
  293. // const renamedPage = await renamePage(childForRename4, newPath, dummyUser2, { createRedirectPage: true });
  294. // const pageRedirect = await PageRedirect.find({ fromPath: childForRename4.path, toPath: renamedPage.path });
  295. // expect(renamedPage.path).toBe(newPath);
  296. // expect(renamedPage.parent).toStrictEqual(parentForRename4._id);
  297. // expect(pageRedirect.length).toBeGreaterThan(0);
  298. // });
  299. test('Should move with descendants', async() => {
  300. // rename target page
  301. const newPath = '/v5_ParentForRename5/renamedChildForRename5';
  302. const renamedPage = await renamePage(childForRename5, newPath, dummyUser1, {});
  303. // find child of renamed page
  304. const grandchildren = await Page.find({ parent: renamedPage._id });
  305. const grandchild = grandchildren[0];
  306. expect(renamedPage.path).toBe(newPath);
  307. expect(renamedPage.parent).toStrictEqual(parentForRename5._id);
  308. // grandchild's parent should be renamed page
  309. expect(grandchild.parent).toStrictEqual(renamedPage._id);
  310. expect(grandchild.path).toBe('/v5_ParentForRename5/renamedChildForRename5/v5_GrandchildForRename5');
  311. });
  312. test('Should move with same grant', async() => {
  313. // rename target page
  314. const newPath = '/v5_ParentForRename6/renamedChildForRename6';
  315. expect(childForRename6.grant).toBe(Page.GRANT_RESTRICTED);
  316. const renamedPage = await renamePage(childForRename6, newPath, dummyUser1, {});
  317. expect(renamedPage.path).toBe(newPath);
  318. expect(renamedPage.parent).toStrictEqual(parentForRename6._id);
  319. expect(renamedPage.grant).toBe(Page.GRANT_RESTRICTED);
  320. });
  321. test('Should move empty page', async() => {
  322. // rename target page
  323. const newPath = '/v5_ParentForRename7/renamedChildForRename7';
  324. const renamedPage = await renamePage(childForRename7, newPath, dummyUser1, {});
  325. // find child of renamed page
  326. const grandchildren = await Page.find({ parent: renamedPage._id });
  327. const grandchild = grandchildren[0];
  328. expect(renamedPage.path).toBe(newPath);
  329. expect(renamedPage.isEmpty).toBe(true);
  330. expect(renamedPage.parent).toStrictEqual(parentForRename7._id);
  331. // grandchild's parent should be renamed page
  332. expect(grandchild.parent).toStrictEqual(renamedPage._id);
  333. expect(grandchild.path).toBe('/v5_ParentForRename7/renamedChildForRename7/v5_GrandchildForRename7');
  334. });
  335. });
  336. describe('Duplicate', () => {
  337. const duplicate = async(page, newPagePath, user, isRecursively) => {
  338. // mock return value
  339. const mockedResumableDuplicateDescendants = jest.spyOn(crowi.pageService, 'resumableDuplicateDescendants').mockRejectedValue(null);
  340. jest.spyOn(crowi.pageService, 'createAndSendNotifications').mockReturnValue(null);
  341. const duplicatedPage = await crowi.pageService.duplicate(page, newPagePath, user, isRecursively);
  342. // retrieve the arguments passed when calling method resumableDuplicateDescendants inside duplicate method
  343. const argsForResumableDuplicateDescendants = mockedResumableDuplicateDescendants.mock.calls[0];
  344. // restores the original implementation
  345. jest.restoreAllMocks();
  346. // duplicate descendants
  347. if (isRecursively) {
  348. await crowi.pageService.resumableDuplicateDescendants(...argsForResumableDuplicateDescendants);
  349. }
  350. return duplicatedPage;
  351. };
  352. test('Should duplicate single page', async() => {
  353. const newPagePath = '/duplicatedParentForDuplicate1';
  354. const duplicatedPage = await duplicate(parentForDuplicate1, newPagePath, dummyUser1, false);
  355. const duplicatedRevision = await Revision.findOne({ pageId: duplicatedPage._id });
  356. const baseRevision = await Revision.findOne({ pageId: parentForDuplicate1._id });
  357. // new path
  358. expect(duplicatedPage.path).toBe(newPagePath);
  359. expect(duplicatedPage._id).not.toStrictEqual(parentForDuplicate1._id);
  360. expect(duplicatedPage.revision).toStrictEqual(duplicatedRevision._id);
  361. expect(duplicatedRevision.body).toEqual(baseRevision.body);
  362. });
  363. test('Should duplicate multiple pages', async() => {
  364. // a
  365. });
  366. test('Should keep grant', async() => {
  367. // a
  368. });
  369. });
  370. afterAll(async() => {
  371. await Page.remove({});
  372. await User.remove({});
  373. await Revision.remove({});
  374. });
  375. });
  376. describe('PageService page operations with non-public pages', () => {
  377. // TODO: write test code
  378. });