2
0

v5.page.test.ts 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. import { addSeconds } from 'date-fns/addSeconds';
  2. import mongoose from 'mongoose';
  3. import { PageActionStage, PageActionType } from '../../../src/interfaces/page-operation';
  4. import { getInstance } from '../setup-crowi';
  5. describe('Test page service methods', () => {
  6. let crowi;
  7. let Page;
  8. let Revision;
  9. let User;
  10. let Tag;
  11. let Bookmark;
  12. let Comment;
  13. let ShareLink;
  14. let PageRedirect;
  15. let PageOperation;
  16. let rootPage;
  17. let dummyUser1;
  18. let dummyUser2;
  19. let globalGroupUser1;
  20. let globalGroupUser2;
  21. let globalGroupUser3;
  22. let pageOpId1;
  23. let pageOpId2;
  24. let pageOpId3;
  25. let pageOpId4;
  26. let pageOpId5;
  27. let pageOpId6;
  28. beforeAll(async() => {
  29. crowi = await getInstance();
  30. await crowi.configManager.updateConfig('app:isV5Compatible', true);
  31. User = mongoose.model('User');
  32. Page = mongoose.model('Page');
  33. Revision = mongoose.model('Revision');
  34. Tag = mongoose.model('Tag');
  35. Bookmark = mongoose.model('Bookmark');
  36. Comment = mongoose.model('Comment');
  37. ShareLink = mongoose.model('ShareLink');
  38. PageRedirect = mongoose.model('PageRedirect');
  39. PageOperation = mongoose.model('PageOperation');
  40. /*
  41. * Common
  42. */
  43. // ***********************************************************************************************************
  44. // * Do NOT change properties of globally used documents. Otherwise, it might cause some errors in other tests
  45. // ***********************************************************************************************************
  46. // users
  47. dummyUser1 = await User.findOne({ username: 'v5DummyUser1' });
  48. dummyUser2 = await User.findOne({ username: 'v5DummyUser2' });
  49. globalGroupUser1 = await User.findOne({ username: 'gGroupUser1' });
  50. globalGroupUser2 = await User.findOne({ username: 'gGroupUser2' });
  51. globalGroupUser3 = await User.findOne({ username: 'gGroupUser3' });
  52. // page
  53. rootPage = await Page.findOne({ path: '/' });
  54. /**
  55. * pages
  56. */
  57. const pageId0 = new mongoose.Types.ObjectId();
  58. const pageId1 = new mongoose.Types.ObjectId();
  59. const pageId2 = new mongoose.Types.ObjectId();
  60. const pageId3 = new mongoose.Types.ObjectId();
  61. const pageId4 = new mongoose.Types.ObjectId();
  62. const pageId5 = new mongoose.Types.ObjectId();
  63. const pageId6 = new mongoose.Types.ObjectId();
  64. const pageId7 = new mongoose.Types.ObjectId();
  65. const pageId8 = new mongoose.Types.ObjectId();
  66. const pageId9 = new mongoose.Types.ObjectId();
  67. const pageId10 = new mongoose.Types.ObjectId();
  68. const pageId11 = new mongoose.Types.ObjectId();
  69. const pageId12 = new mongoose.Types.ObjectId();
  70. const pageId13 = new mongoose.Types.ObjectId();
  71. const pageId14 = new mongoose.Types.ObjectId();
  72. const pageId15 = new mongoose.Types.ObjectId();
  73. const pageId16 = new mongoose.Types.ObjectId();
  74. const pageId17 = new mongoose.Types.ObjectId();
  75. const pageId18 = new mongoose.Types.ObjectId();
  76. const pageId19 = new mongoose.Types.ObjectId();
  77. const pageId20 = new mongoose.Types.ObjectId();
  78. await Page.insertMany([
  79. {
  80. _id: pageId0,
  81. path: '/resume_rename_0',
  82. parent: rootPage._id,
  83. grant: Page.GRANT_PUBLIC,
  84. creator: dummyUser1,
  85. lastUpdateUser: dummyUser1._id,
  86. descendantCount: 1,
  87. isEmpty: false,
  88. },
  89. {
  90. _id: pageId1,
  91. path: '/resume_rename_0/resume_rename_1',
  92. parent: pageId0,
  93. grant: Page.GRANT_PUBLIC,
  94. creator: dummyUser1,
  95. lastUpdateUser: dummyUser1._id,
  96. descendantCount: 2,
  97. isEmpty: false,
  98. },
  99. {
  100. _id: pageId2,
  101. path: '/resume_rename_1/resume_rename_2',
  102. parent: pageId1,
  103. grant: Page.GRANT_PUBLIC,
  104. creator: dummyUser1,
  105. lastUpdateUser: dummyUser1._id,
  106. descendantCount: 1,
  107. isEmpty: false,
  108. },
  109. {
  110. _id: pageId3,
  111. path: '/resume_rename_1/resume_rename_2/resume_rename_3',
  112. parent: pageId2,
  113. grant: Page.GRANT_PUBLIC,
  114. creator: dummyUser1,
  115. lastUpdateUser: dummyUser1._id,
  116. descendantCount: 0,
  117. isEmpty: false,
  118. },
  119. {
  120. _id: pageId4,
  121. path: '/resume_rename_4',
  122. parent: rootPage._id,
  123. grant: Page.GRANT_PUBLIC,
  124. creator: dummyUser1,
  125. lastUpdateUser: dummyUser1._id,
  126. descendantCount: 0,
  127. isEmpty: false,
  128. },
  129. {
  130. _id: pageId5,
  131. path: '/resume_rename_4/resume_rename_5',
  132. parent: pageId4,
  133. grant: Page.GRANT_PUBLIC,
  134. creator: dummyUser1,
  135. lastUpdateUser: dummyUser1._id,
  136. descendantCount: 1,
  137. isEmpty: false,
  138. },
  139. {
  140. _id: pageId6,
  141. path: '/resume_rename_5/resume_rename_6',
  142. parent: pageId5,
  143. grant: Page.GRANT_PUBLIC,
  144. creator: dummyUser1,
  145. lastUpdateUser: dummyUser1._id,
  146. descendantCount: 0,
  147. isEmpty: false,
  148. },
  149. {
  150. _id: pageId7,
  151. path: '/resume_rename_7',
  152. parent: rootPage._id,
  153. grant: Page.GRANT_PUBLIC,
  154. creator: dummyUser1,
  155. lastUpdateUser: dummyUser1._id,
  156. descendantCount: 0,
  157. isEmpty: false,
  158. },
  159. {
  160. _id: pageId8,
  161. path: '/resume_rename_8',
  162. parent: rootPage._id,
  163. grant: Page.GRANT_PUBLIC,
  164. creator: dummyUser1,
  165. lastUpdateUser: dummyUser1._id,
  166. descendantCount: 1,
  167. isEmpty: false,
  168. },
  169. {
  170. _id: pageId9,
  171. path: '/resume_rename_8/resume_rename_9',
  172. parent: pageId8,
  173. grant: Page.GRANT_PUBLIC,
  174. creator: dummyUser1,
  175. lastUpdateUser: dummyUser1._id,
  176. descendantCount: 1,
  177. isEmpty: false,
  178. },
  179. {
  180. path: '/resume_rename_9/resume_rename_10',
  181. parent: pageId9,
  182. grant: Page.GRANT_PUBLIC,
  183. creator: dummyUser1,
  184. lastUpdateUser: dummyUser1._id,
  185. descendantCount: 0,
  186. isEmpty: false,
  187. },
  188. {
  189. _id: pageId10,
  190. path: '/resume_rename_11',
  191. parent: rootPage._id,
  192. grant: Page.GRANT_PUBLIC,
  193. creator: dummyUser1,
  194. lastUpdateUser: dummyUser1._id,
  195. descendantCount: 3,
  196. isEmpty: false,
  197. },
  198. {
  199. _id: pageId11,
  200. path: '/resume_rename_11/resume_rename_12',
  201. parent: pageId10,
  202. grant: Page.GRANT_PUBLIC,
  203. creator: dummyUser1,
  204. lastUpdateUser: dummyUser1._id,
  205. descendantCount: 2,
  206. isEmpty: false,
  207. },
  208. {
  209. _id: pageId12,
  210. path: '/resume_rename_11/resume_rename_12/resume_rename_13',
  211. parent: pageId11,
  212. grant: Page.GRANT_PUBLIC,
  213. creator: dummyUser1,
  214. lastUpdateUser: dummyUser1._id,
  215. descendantCount: 1,
  216. isEmpty: false,
  217. },
  218. {
  219. path: '/resume_rename_11/resume_rename_12/resume_rename_13/resume_rename_14',
  220. parent: pageId12,
  221. grant: Page.GRANT_PUBLIC,
  222. creator: dummyUser1,
  223. lastUpdateUser: dummyUser1._id,
  224. descendantCount: 0,
  225. isEmpty: false,
  226. },
  227. {
  228. _id: pageId13,
  229. path: '/resume_rename_15',
  230. parent: rootPage._id,
  231. grant: Page.GRANT_PUBLIC,
  232. creator: dummyUser1,
  233. lastUpdateUser: dummyUser1._id,
  234. descendantCount: 2,
  235. isEmpty: false,
  236. },
  237. {
  238. _id: pageId14,
  239. path: '/resume_rename_15/resume_rename_16',
  240. parent: pageId13,
  241. grant: Page.GRANT_PUBLIC,
  242. creator: dummyUser1,
  243. lastUpdateUser: dummyUser1._id,
  244. descendantCount: 0,
  245. isEmpty: false,
  246. },
  247. {
  248. _id: pageId15,
  249. path: '/resume_rename_15/resume_rename_17',
  250. parent: pageId13,
  251. grant: Page.GRANT_PUBLIC,
  252. creator: dummyUser1,
  253. lastUpdateUser: dummyUser1._id,
  254. descendantCount: 1,
  255. isEmpty: false,
  256. },
  257. {
  258. _id: pageId16,
  259. path: '/resume_rename_15/resume_rename_17/resume_rename_18',
  260. parent: pageId15,
  261. grant: Page.GRANT_PUBLIC,
  262. creator: dummyUser1,
  263. lastUpdateUser: dummyUser1._id,
  264. descendantCount: 1,
  265. isEmpty: false,
  266. },
  267. {
  268. _id: pageId17,
  269. path: '/resume_rename_15/resume_rename_17/resume_rename_18/resume_rename_19',
  270. parent: pageId16,
  271. grant: Page.GRANT_PUBLIC,
  272. creator: dummyUser1,
  273. lastUpdateUser: dummyUser1._id,
  274. descendantCount: 0,
  275. isEmpty: false,
  276. },
  277. {
  278. _id: pageId18,
  279. path: '/fix_descendantCount_1',
  280. parent: rootPage._id,
  281. grant: Page.GRANT_PUBLIC,
  282. creator: dummyUser1,
  283. lastUpdateUser: dummyUser1._id,
  284. descendantCount: 100, // broken
  285. isEmpty: false,
  286. },
  287. {
  288. _id: pageId19,
  289. path: '/fix_descendantCount_1/fix_descendantCount_2',
  290. parent: pageId18,
  291. grant: Page.GRANT_PUBLIC,
  292. creator: dummyUser1,
  293. lastUpdateUser: dummyUser1._id,
  294. descendantCount: 100, // broken
  295. isEmpty: true,
  296. },
  297. {
  298. path: '/fix_descendantCount_1/fix_descendantCount_2/fix_descendantCount_3',
  299. parent: pageId19,
  300. grant: Page.GRANT_PUBLIC,
  301. creator: dummyUser1,
  302. lastUpdateUser: dummyUser1._id,
  303. descendantCount: 100, // broken
  304. isEmpty: false,
  305. },
  306. {
  307. _id: pageId20,
  308. path: '/fix_descendantCount_4',
  309. parent: rootPage._id,
  310. grant: Page.GRANT_PUBLIC,
  311. creator: dummyUser1,
  312. lastUpdateUser: dummyUser1._id,
  313. descendantCount: 100, // broken
  314. isEmpty: false,
  315. },
  316. {
  317. path: '/fix_descendantCount_4/fix_descendantCount_5',
  318. parent: pageId20,
  319. grant: Page.GRANT_PUBLIC,
  320. creator: dummyUser1,
  321. lastUpdateUser: dummyUser1._id,
  322. descendantCount: 100, // broken
  323. isEmpty: false,
  324. },
  325. ]);
  326. /**
  327. * PageOperation
  328. */
  329. pageOpId1 = new mongoose.Types.ObjectId();
  330. pageOpId2 = new mongoose.Types.ObjectId();
  331. pageOpId3 = new mongoose.Types.ObjectId();
  332. pageOpId4 = new mongoose.Types.ObjectId();
  333. const pageOpRevisionId1 = new mongoose.Types.ObjectId();
  334. const pageOpRevisionId2 = new mongoose.Types.ObjectId();
  335. const pageOpRevisionId3 = new mongoose.Types.ObjectId();
  336. const pageOpRevisionId4 = new mongoose.Types.ObjectId();
  337. await PageOperation.insertMany([
  338. {
  339. _id: pageOpId1,
  340. actionType: 'Rename',
  341. actionStage: 'Sub',
  342. fromPath: '/resume_rename_1',
  343. toPath: '/resume_rename_0/resume_rename_1',
  344. page: {
  345. _id: pageId1,
  346. parent: rootPage._id,
  347. descendantCount: 2,
  348. isEmpty: false,
  349. path: '/resume_rename_1',
  350. revision: pageOpRevisionId1,
  351. status: 'published',
  352. grant: 1,
  353. grantedUsers: [],
  354. grantedGroups: [],
  355. creator: dummyUser1._id,
  356. lastUpdateUser: dummyUser1._id,
  357. },
  358. user: {
  359. _id: dummyUser1._id,
  360. },
  361. options: {
  362. createRedirectPage: false,
  363. updateMetadata: true,
  364. },
  365. unprocessableExpiryDate: null,
  366. },
  367. {
  368. _id: pageOpId2,
  369. actionType: 'Rename',
  370. actionStage: 'Sub',
  371. fromPath: '/resume_rename_5',
  372. toPath: '/resume_rename_4/resume_rename_5',
  373. page: {
  374. _id: pageId5,
  375. parent: rootPage._id,
  376. descendantCount: 2,
  377. isEmpty: false,
  378. path: '/resume_rename_5',
  379. revision: pageOpRevisionId2,
  380. status: 'published',
  381. grant: 1,
  382. grantedUsers: [],
  383. grantedGroups: [],
  384. creator: dummyUser1._id,
  385. lastUpdateUser: dummyUser1._id,
  386. },
  387. user: {
  388. _id: dummyUser1._id,
  389. },
  390. options: {
  391. createRedirectPage: false,
  392. updateMetadata: true,
  393. },
  394. unprocessableExpiryDate: new Date(),
  395. },
  396. {
  397. _id: pageOpId3,
  398. actionType: 'Rename',
  399. actionStage: 'Sub',
  400. fromPath: '/resume_rename_7',
  401. // toPath NOT exist
  402. page: {
  403. _id: pageId7,
  404. parent: rootPage._id,
  405. descendantCount: 2,
  406. isEmpty: false,
  407. path: '/resume_rename_7',
  408. revision: pageOpRevisionId3,
  409. status: 'published',
  410. grant: 1,
  411. grantedUsers: [],
  412. grantedGroups: [],
  413. creator: dummyUser1._id,
  414. lastUpdateUser: dummyUser1._id,
  415. },
  416. user: {
  417. _id: dummyUser1._id,
  418. },
  419. options: {
  420. createRedirectPage: false,
  421. updateMetadata: true,
  422. },
  423. unprocessableExpiryDate: new Date(),
  424. },
  425. {
  426. _id: pageOpId4,
  427. actionType: 'Rename',
  428. actionStage: 'Sub',
  429. fromPath: '/resume_rename_9',
  430. toPath: '/resume_rename_8/resume_rename_9',
  431. page: {
  432. _id: pageId9,
  433. parent: rootPage._id,
  434. descendantCount: 1,
  435. isEmpty: false,
  436. path: '/resume_rename_9',
  437. revision: pageOpRevisionId4,
  438. status: 'published',
  439. grant: Page.GRANT_PUBLIC,
  440. grantedUsers: [],
  441. grantedGroups: [],
  442. creator: dummyUser1._id,
  443. lastUpdateUser: dummyUser1._id,
  444. },
  445. user: {
  446. _id: dummyUser1._id,
  447. },
  448. options: {
  449. createRedirectPage: false,
  450. updateMetadata: true,
  451. },
  452. unprocessableExpiryDate: null,
  453. },
  454. ]);
  455. });
  456. describe('restart renameOperation', () => {
  457. const resumeRenameSubOperation = async(renamePage, pageOp, activity?) => {
  458. const mockedPathsAndDescendantCountOfAncestors = jest.spyOn(crowi.pageService, 'fixPathsAndDescendantCountOfAncestors').mockReturnValue(null);
  459. await crowi.pageService.resumeRenameSubOperation(renamePage, pageOp, activity);
  460. const argsForRenameSubOperation = mockedPathsAndDescendantCountOfAncestors.mock.calls[0];
  461. mockedPathsAndDescendantCountOfAncestors.mockRestore();
  462. await crowi.pageService.fixPathsAndDescendantCountOfAncestors(...argsForRenameSubOperation);
  463. };
  464. test('it should successfully restart rename operation', async() => {
  465. // paths before renaming
  466. const _path0 = '/resume_rename_0'; // out of renaming scope
  467. const _path1 = '/resume_rename_0/resume_rename_1'; // renamed already
  468. const _path2 = '/resume_rename_1/resume_rename_2'; // not renamed yet
  469. const _path3 = '/resume_rename_1/resume_rename_2/resume_rename_3'; // not renamed yet
  470. // paths after renaming
  471. const path0 = '/resume_rename_0';
  472. const path1 = '/resume_rename_0/resume_rename_1';
  473. const path2 = '/resume_rename_0/resume_rename_1/resume_rename_2';
  474. const path3 = '/resume_rename_0/resume_rename_1/resume_rename_2/resume_rename_3';
  475. // activity options
  476. const activity = 'randomActivityId';
  477. // page
  478. const _page0 = await Page.findOne({ path: _path0 });
  479. const _page1 = await Page.findOne({ path: _path1 });
  480. const _page2 = await Page.findOne({ path: _path2 });
  481. const _page3 = await Page.findOne({ path: _path3 });
  482. expect(_page0).toBeTruthy();
  483. expect(_page1).toBeTruthy();
  484. expect(_page2).toBeTruthy();
  485. expect(_page3).toBeTruthy();
  486. expect(_page0.descendantCount).toBe(1);
  487. expect(_page1.descendantCount).toBe(2);
  488. expect(_page2.descendantCount).toBe(1);
  489. expect(_page3.descendantCount).toBe(0);
  490. // page operation
  491. const fromPath = '/resume_rename_1';
  492. const toPath = '/resume_rename_0/resume_rename_1';
  493. const _pageOperation = await PageOperation.findOne({
  494. _id: pageOpId1, fromPath, toPath, 'page._id': _page1._id, actionType: PageActionType.Rename, actionStage: PageActionStage.Sub,
  495. });
  496. expect(_pageOperation).toBeTruthy();
  497. // rename
  498. await resumeRenameSubOperation(_page1, _pageOperation, activity);
  499. // page
  500. const page0 = await Page.findById(_page0._id);
  501. const page1 = await Page.findById(_page1._id);
  502. const page2 = await Page.findById(_page2._id);
  503. const page3 = await Page.findById(_page3._id);
  504. expect(page0).toBeTruthy();
  505. expect(page1).toBeTruthy();
  506. expect(page2).toBeTruthy();
  507. expect(page3).toBeTruthy();
  508. // check paths after renaming
  509. expect(page0.path).toBe(path0);
  510. expect(page1.path).toBe(path1);
  511. expect(page2.path).toBe(path2);
  512. expect(page3.path).toBe(path3);
  513. // page operation
  514. const pageOperation = await PageOperation.findById(_pageOperation._id);
  515. expect(pageOperation).toBeNull(); // should not exist
  516. expect(page0.descendantCount).toBe(3);
  517. expect(page1.descendantCount).toBe(2);
  518. expect(page2.descendantCount).toBe(1);
  519. expect(page3.descendantCount).toBe(0);
  520. });
  521. test('it should successfully restart rename operation when unprocessableExpiryDate is null', async() => {
  522. // paths before renaming
  523. const _path0 = '/resume_rename_8'; // out of renaming scope
  524. const _path1 = '/resume_rename_8/resume_rename_9'; // renamed already
  525. const _path2 = '/resume_rename_9/resume_rename_10'; // not renamed yet
  526. // paths after renaming
  527. const path0 = '/resume_rename_8';
  528. const path1 = '/resume_rename_8/resume_rename_9';
  529. const path2 = '/resume_rename_8/resume_rename_9/resume_rename_10';
  530. // activity options
  531. const activityParameters = {
  532. ip: '::ffff:127.0.0.1',
  533. endpoint: '/_api/v3/pages/rename',
  534. activityId: '62e291bc10e0ab61bd691794',
  535. };
  536. // page
  537. const _page0 = await Page.findOne({ path: _path0 });
  538. const _page1 = await Page.findOne({ path: _path1 });
  539. const _page2 = await Page.findOne({ path: _path2 });
  540. expect(_page0).toBeTruthy();
  541. expect(_page1).toBeTruthy();
  542. expect(_page2).toBeTruthy();
  543. expect(_page0.descendantCount).toBe(1);
  544. expect(_page1.descendantCount).toBe(1);
  545. expect(_page2.descendantCount).toBe(0);
  546. // page operation
  547. const fromPath = '/resume_rename_9';
  548. const toPath = '/resume_rename_8/resume_rename_9';
  549. const _pageOperation = await PageOperation.findOne({
  550. _id: pageOpId4, fromPath, toPath, 'page._id': _page1._id, actionType: PageActionType.Rename, actionStage: PageActionStage.Sub,
  551. });
  552. expect(_pageOperation).toBeTruthy();
  553. // rename
  554. await resumeRenameSubOperation(_page1, _pageOperation, activityParameters);
  555. // page
  556. const page0 = await Page.findById(_page0._id);
  557. const page1 = await Page.findById(_page1._id);
  558. const page2 = await Page.findById(_page2._id);
  559. expect(page0).toBeTruthy();
  560. expect(page1).toBeTruthy();
  561. expect(page2).toBeTruthy();
  562. // check paths after renaming
  563. expect(page0.path).toBe(path0);
  564. expect(page1.path).toBe(path1);
  565. expect(page2.path).toBe(path2);
  566. // page operation
  567. const pageOperation = await PageOperation.findById(_pageOperation._id);
  568. expect(pageOperation).toBeNull(); // should not exist
  569. // others
  570. expect(page1.parent).toStrictEqual(page0._id);
  571. expect(page2.parent).toStrictEqual(page1._id);
  572. expect(page0.descendantCount).toBe(2);
  573. expect(page1.descendantCount).toBe(1);
  574. expect(page2.descendantCount).toBe(0);
  575. });
  576. test('it should fail and throw error if the current time is behind unprocessableExpiryDate', async() => {
  577. // path before renaming
  578. const _path0 = '/resume_rename_4'; // out of renaming scope
  579. const _path1 = '/resume_rename_4/resume_rename_5'; // renamed already
  580. const _path2 = '/resume_rename_5/resume_rename_6'; // not renamed yet
  581. // page
  582. const _page0 = await Page.findOne({ path: _path0 });
  583. const _page1 = await Page.findOne({ path: _path1 });
  584. const _page2 = await Page.findOne({ path: _path2 });
  585. expect(_page0).toBeTruthy();
  586. expect(_page1).toBeTruthy();
  587. expect(_page2).toBeTruthy();
  588. // page operation
  589. const fromPath = '/resume_rename_5';
  590. const toPath = '/resume_rename_4/resume_rename_5';
  591. const _pageOperation = await PageOperation.findOne({
  592. _id: pageOpId2, fromPath, toPath, 'page._id': _page1._id, actionType: PageActionType.Rename, actionStage: PageActionStage.Sub,
  593. });
  594. expect(_pageOperation).toBeTruthy();
  595. // Make `unprocessableExpiryDate` 15 seconds ahead of current time.
  596. // The number 15 seconds has no meaning other than placing time in the furue.
  597. const pageOperation = await PageOperation.findByIdAndUpdate(_pageOperation._id, { unprocessableExpiryDate: addSeconds(new Date(), 15) }, { new: true });
  598. expect(pageOperation).toBeTruthy();
  599. await expect(resumeRenameSubOperation(_page1, pageOperation)).rejects.toThrow(new Error('This page operation is currently being processed'));
  600. // cleanup
  601. await PageOperation.findByIdAndDelete(pageOperation._id);
  602. });
  603. test('Missing property(toPath) for PageOperation should throw error', async() => {
  604. // page
  605. const _path1 = '/resume_rename_7';
  606. const _page1 = await Page.findOne({ path: _path1 });
  607. expect(_page1).toBeTruthy();
  608. // page operation
  609. const pageOperation = await PageOperation.findOne({
  610. _id: pageOpId3, 'page._id': _page1._id, actionType: PageActionType.Rename, actionStage: PageActionStage.Sub,
  611. });
  612. expect(pageOperation).toBeTruthy();
  613. const promise = resumeRenameSubOperation(_page1, pageOperation);
  614. await expect(promise).rejects.toThrow(new Error(`Property toPath is missing which is needed to resume rename operation(${pageOperation._id})`));
  615. // cleanup
  616. await PageOperation.findByIdAndDelete(pageOperation._id);
  617. });
  618. });
  619. describe('updateDescendantCountOfPagesWithPaths', () => {
  620. test('should fix descendantCount of pages with one of the given paths', async() => {
  621. // path
  622. const _path1 = '/fix_descendantCount_1';
  623. const _path2 = '/fix_descendantCount_1/fix_descendantCount_2'; // empty
  624. const _path3 = '/fix_descendantCount_1/fix_descendantCount_2/fix_descendantCount_3';
  625. const _path4 = '/fix_descendantCount_4';
  626. const _path5 = '/fix_descendantCount_4/fix_descendantCount_5';
  627. // page
  628. const _page1 = await Page.findOne({ path: _path1 });
  629. const _page2 = await Page.findOne({ path: _path2 });
  630. const _page3 = await Page.findOne({ path: _path3 });
  631. const _page4 = await Page.findOne({ path: _path4 });
  632. const _page5 = await Page.findOne({ path: _path5 });
  633. // check existance
  634. expect(_page1).toBeTruthy();
  635. expect(_page2).toBeTruthy();
  636. expect(_page3).toBeTruthy();
  637. expect(_page4).toBeTruthy();
  638. expect(_page5).toBeTruthy();
  639. // check descendantCount (all broken)
  640. expect(_page1.descendantCount).toBe(100);
  641. expect(_page2.descendantCount).toBe(100);
  642. expect(_page3.descendantCount).toBe(100);
  643. expect(_page4.descendantCount).toBe(100);
  644. expect(_page5.descendantCount).toBe(100);
  645. // check isEmpty
  646. expect(_page1.isEmpty).toBe(false);
  647. expect(_page2.isEmpty).toBe(true);
  648. expect(_page3.isEmpty).toBe(false);
  649. expect(_page4.isEmpty).toBe(false);
  650. expect(_page5.isEmpty).toBe(false);
  651. // check parent
  652. expect(_page1.parent).toStrictEqual(rootPage._id);
  653. expect(_page2.parent).toStrictEqual(_page1._id);
  654. expect(_page3.parent).toStrictEqual(_page2._id);
  655. expect(_page4.parent).toStrictEqual(rootPage._id);
  656. expect(_page5.parent).toStrictEqual(_page4._id);
  657. await crowi.pageService.updateDescendantCountOfPagesWithPaths([_path1, _path2, _path3, _path4, _path5]);
  658. // page
  659. const page1 = await Page.findById(_page1._id);
  660. const page2 = await Page.findById(_page2._id);
  661. const page3 = await Page.findById(_page3._id);
  662. const page4 = await Page.findById(_page4._id);
  663. const page5 = await Page.findById(_page5._id);
  664. // check existance
  665. expect(page1).toBeTruthy();
  666. expect(page2).toBeTruthy();
  667. expect(page3).toBeTruthy();
  668. expect(page4).toBeTruthy();
  669. expect(page5).toBeTruthy();
  670. // check descendantCount (all fixed)
  671. expect(page1.descendantCount).toBe(1);
  672. expect(page2.descendantCount).toBe(1);
  673. expect(page3.descendantCount).toBe(0);
  674. expect(page4.descendantCount).toBe(1);
  675. expect(page5.descendantCount).toBe(0);
  676. // check isEmpty
  677. expect(page1.isEmpty).toBe(false);
  678. expect(page2.isEmpty).toBe(true);
  679. expect(page3.isEmpty).toBe(false);
  680. expect(page4.isEmpty).toBe(false);
  681. expect(page5.isEmpty).toBe(false);
  682. // check parent
  683. expect(page1.parent).toStrictEqual(rootPage._id);
  684. expect(page2.parent).toStrictEqual(page1._id);
  685. expect(page3.parent).toStrictEqual(page2._id);
  686. expect(page4.parent).toStrictEqual(rootPage._id);
  687. expect(page5.parent).toStrictEqual(page4._id);
  688. });
  689. });
  690. });