v5.page.test.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. import mongoose from 'mongoose';
  2. import { getInstance } from '../setup-crowi';
  3. describe('Page', () => {
  4. let crowi;
  5. let Page;
  6. let Revision;
  7. let User;
  8. let Tag;
  9. let PageTagRelation;
  10. let Bookmark;
  11. let Comment;
  12. let ShareLink;
  13. let PageRedirect;
  14. let xssSpy;
  15. let rootPage;
  16. let dummyUser1;
  17. // pass unless the data is one of [false, 0, '', null, undefined, NaN]
  18. const expectAllToBeTruthy = (dataList) => {
  19. dataList.forEach((data, i) => {
  20. if (data == null) { console.log(`index: ${i}`) }
  21. expect(data).toBeTruthy();
  22. });
  23. };
  24. beforeAll(async() => {
  25. crowi = await getInstance();
  26. await crowi.configManager.updateConfigsInTheSameNamespace('crowi', { 'app:isV5Compatible': true });
  27. jest.restoreAllMocks();
  28. User = mongoose.model('User');
  29. Page = mongoose.model('Page');
  30. Revision = mongoose.model('Revision');
  31. Tag = mongoose.model('Tag');
  32. PageTagRelation = mongoose.model('PageTagRelation');
  33. Bookmark = mongoose.model('Bookmark');
  34. Comment = mongoose.model('Comment');
  35. ShareLink = mongoose.model('ShareLink');
  36. PageRedirect = mongoose.model('PageRedirect');
  37. dummyUser1 = await User.findOne({ username: 'v5DummyUser1' });
  38. rootPage = await Page.findOne({ path: '/' });
  39. const pageIdCreate1 = new mongoose.Types.ObjectId();
  40. const pageIdCreate2 = new mongoose.Types.ObjectId();
  41. const pageIdCreate3 = new mongoose.Types.ObjectId();
  42. const pageIdCreate4 = new mongoose.Types.ObjectId();
  43. /**
  44. * create
  45. * mc_ => model create
  46. * emp => empty => page with isEmpty: true
  47. * pub => public => GRANT_PUBLIC
  48. */
  49. await Page.insertMany([
  50. {
  51. _id: pageIdCreate1,
  52. path: '/v5_empty_create_4',
  53. grant: Page.GRANT_PUBLIC,
  54. parent: rootPage._id,
  55. isEmpty: true,
  56. },
  57. {
  58. path: '/v5_empty_create_4/v5_create_5',
  59. grant: Page.GRANT_PUBLIC,
  60. creator: dummyUser1,
  61. lastUpdateUser: dummyUser1._id,
  62. parent: pageIdCreate1,
  63. isEmpty: false,
  64. },
  65. {
  66. _id: pageIdCreate2,
  67. path: '/mc4_top/mc1_emp',
  68. grant: Page.GRANT_PUBLIC,
  69. creator: dummyUser1,
  70. lastUpdateUser: dummyUser1._id,
  71. parent: rootPage._id,
  72. isEmpty: true,
  73. },
  74. {
  75. path: '/mc4_top/mc1_emp/mc2_pub',
  76. grant: Page.GRANT_PUBLIC,
  77. creator: dummyUser1,
  78. lastUpdateUser: dummyUser1._id,
  79. parent: pageIdCreate2,
  80. isEmpty: false,
  81. },
  82. {
  83. path: '/mc5_top/mc3_awl',
  84. grant: Page.GRANT_RESTRICTED,
  85. creator: dummyUser1,
  86. lastUpdateUser: dummyUser1._id,
  87. isEmpty: false,
  88. },
  89. {
  90. _id: pageIdCreate3,
  91. path: '/mc4_top',
  92. grant: Page.GRANT_PUBLIC,
  93. creator: dummyUser1,
  94. lastUpdateUser: dummyUser1._id,
  95. isEmpty: false,
  96. parent: rootPage._id,
  97. descendantCount: 1,
  98. },
  99. {
  100. _id: pageIdCreate4,
  101. path: '/mc5_top',
  102. grant: Page.GRANT_PUBLIC,
  103. creator: dummyUser1,
  104. lastUpdateUser: dummyUser1._id,
  105. isEmpty: false,
  106. parent: rootPage._id,
  107. descendantCount: 0,
  108. },
  109. ]);
  110. /**
  111. * update
  112. * mup_ => model update
  113. * emp => empty => page with isEmpty: true
  114. * pub => public => GRANT_PUBLIC
  115. * awl => Anyone with the link => GRANT_RESTRICTED
  116. */
  117. const pageIdUpd1 = new mongoose.Types.ObjectId();
  118. const pageIdUpd2 = new mongoose.Types.ObjectId();
  119. const pageIdUpd3 = new mongoose.Types.ObjectId();
  120. const pageIdUpd4 = new mongoose.Types.ObjectId();
  121. const pageIdUpd5 = new mongoose.Types.ObjectId();
  122. const pageIdUpd6 = new mongoose.Types.ObjectId();
  123. const pageIdUpd7 = new mongoose.Types.ObjectId();
  124. const pageIdUpd8 = new mongoose.Types.ObjectId();
  125. const pageIdUpd9 = new mongoose.Types.ObjectId();
  126. const pageIdUpd10 = new mongoose.Types.ObjectId();
  127. const pageIdUpd11 = new mongoose.Types.ObjectId();
  128. const pageIdUpd12 = new mongoose.Types.ObjectId();
  129. await Page.insertMany([
  130. {
  131. _id: pageIdUpd1,
  132. path: '/mup13_top/mup1_emp',
  133. grant: Page.GRANT_PUBLIC,
  134. parent: pageIdUpd8._id,
  135. isEmpty: true,
  136. },
  137. {
  138. _id: pageIdUpd2,
  139. path: '/mup13_top/mup1_emp/mup2_pub',
  140. grant: Page.GRANT_PUBLIC,
  141. parent: pageIdUpd1._id,
  142. creator: dummyUser1,
  143. lastUpdateUser: dummyUser1._id,
  144. isEmpty: false,
  145. },
  146. {
  147. _id: pageIdUpd3,
  148. path: '/mup14_top/mup6_pub',
  149. grant: Page.GRANT_PUBLIC,
  150. creator: dummyUser1,
  151. lastUpdateUser: dummyUser1._id,
  152. parent: pageIdUpd9,
  153. isEmpty: false,
  154. descendantCount: 1,
  155. },
  156. {
  157. path: '/mup14_top/mup6_pub/mup7_pub',
  158. grant: Page.GRANT_PUBLIC,
  159. creator: dummyUser1,
  160. lastUpdateUser: dummyUser1._id,
  161. parent: pageIdUpd3,
  162. isEmpty: false,
  163. descendantCount: 0,
  164. },
  165. {
  166. _id: pageIdUpd4,
  167. path: '/mup15_top/mup8_pub',
  168. grant: Page.GRANT_PUBLIC,
  169. creator: dummyUser1,
  170. lastUpdateUser: dummyUser1._id,
  171. parent: pageIdUpd10._id,
  172. isEmpty: false,
  173. },
  174. {
  175. _id: pageIdUpd5,
  176. path: '/mup16_top/mup9_pub/mup10_pub/mup11_awl',
  177. grant: Page.GRANT_RESTRICTED,
  178. creator: dummyUser1,
  179. lastUpdateUser: dummyUser1._id,
  180. isEmpty: false,
  181. },
  182. {
  183. _id: pageIdUpd6,
  184. path: '/mup17_top/mup12_emp',
  185. isEmpty: true,
  186. parent: pageIdUpd12._id,
  187. descendantCount: 1,
  188. },
  189. {
  190. _id: pageIdUpd7,
  191. path: '/mup17_top/mup12_emp',
  192. grant: Page.GRANT_RESTRICTED,
  193. creator: dummyUser1,
  194. lastUpdateUser: dummyUser1._id,
  195. isEmpty: false,
  196. },
  197. {
  198. path: '/mup17_top/mup12_emp/mup18_pub',
  199. isEmpty: false,
  200. creator: dummyUser1,
  201. lastUpdateUser: dummyUser1._id,
  202. parent: pageIdUpd6._id,
  203. },
  204. {
  205. _id: pageIdUpd8,
  206. path: '/mup13_top',
  207. grant: Page.GRANT_PUBLIC,
  208. creator: dummyUser1,
  209. lastUpdateUser: dummyUser1._id,
  210. isEmpty: false,
  211. parent: rootPage._id,
  212. descendantCount: 2,
  213. },
  214. {
  215. _id: pageIdUpd9,
  216. path: '/mup14_top',
  217. grant: Page.GRANT_PUBLIC,
  218. creator: dummyUser1,
  219. lastUpdateUser: dummyUser1._id,
  220. isEmpty: false,
  221. parent: rootPage._id,
  222. descendantCount: 2,
  223. },
  224. {
  225. _id: pageIdUpd10,
  226. path: '/mup15_top',
  227. grant: Page.GRANT_PUBLIC,
  228. creator: dummyUser1,
  229. lastUpdateUser: dummyUser1._id,
  230. isEmpty: false,
  231. parent: rootPage._id,
  232. descendantCount: 1,
  233. },
  234. {
  235. _id: pageIdUpd11,
  236. path: '/mup16_top',
  237. grant: Page.GRANT_PUBLIC,
  238. creator: dummyUser1,
  239. lastUpdateUser: dummyUser1._id,
  240. isEmpty: false,
  241. parent: rootPage._id,
  242. descendantCount: 0,
  243. },
  244. {
  245. _id: pageIdUpd12,
  246. path: '/mup17_top',
  247. grant: Page.GRANT_PUBLIC,
  248. creator: dummyUser1,
  249. lastUpdateUser: dummyUser1._id,
  250. isEmpty: false,
  251. parent: rootPage._id,
  252. descendantCount: 1,
  253. },
  254. ]);
  255. });
  256. describe('create', () => {
  257. test('Should create single page', async() => {
  258. const page = await Page.create('/v5_create1', 'create1', dummyUser1, {});
  259. expect(page).toBeTruthy();
  260. expect(page.parent).toStrictEqual(rootPage._id);
  261. });
  262. test('Should create empty-child and non-empty grandchild', async() => {
  263. const grandchildPage = await Page.create('/v5_empty_create2/v5_create_3', 'grandchild', dummyUser1, {});
  264. const childPage = await Page.findOne({ path: '/v5_empty_create2' });
  265. expect(childPage.isEmpty).toBe(true);
  266. expect(grandchildPage).toBeTruthy();
  267. expect(childPage).toBeTruthy();
  268. expect(childPage.parent).toStrictEqual(rootPage._id);
  269. expect(grandchildPage.parent).toStrictEqual(childPage._id);
  270. });
  271. test('Should create on empty page', async() => {
  272. const beforeCreatePage = await Page.findOne({ path: '/v5_empty_create_4' });
  273. expect(beforeCreatePage.isEmpty).toBe(true);
  274. const childPage = await Page.create('/v5_empty_create_4', 'body', dummyUser1, {});
  275. const grandchildPage = await Page.findOne({ parent: childPage._id });
  276. expect(childPage).toBeTruthy();
  277. expect(childPage.isEmpty).toBe(false);
  278. expect(childPage.revision.body).toBe('body');
  279. expect(grandchildPage).toBeTruthy();
  280. expect(childPage.parent).toStrictEqual(rootPage._id);
  281. expect(grandchildPage.parent).toStrictEqual(childPage._id);
  282. });
  283. describe('Creating a page using existing path', () => {
  284. test('with grant RESTRICTED should only create the page and change nothing else', async() => {
  285. const pathT = '/mc4_top';
  286. const path1 = '/mc4_top/mc1_emp';
  287. const path2 = '/mc4_top/mc1_emp/mc2_pub';
  288. const pageT = await Page.findOne({ path: pathT, descendantCount: 1 });
  289. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  290. const page2 = await Page.findOne({ path: path2 });
  291. const page3 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  292. expect(pageT).toBeTruthy();
  293. expect(page1).toBeTruthy();
  294. expect(page2).toBeTruthy();
  295. expect(page3).toBeNull();
  296. // use existing path
  297. await Page.create(path1, 'new body', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  298. const _pageT = await Page.findOne({ path: pathT });
  299. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  300. const _page2 = await Page.findOne({ path: path2 });
  301. const _page3 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  302. expect(_pageT).toBeTruthy();
  303. expect(_page1).toBeTruthy();
  304. expect(_page2).toBeTruthy();
  305. expect(_page3).toBeTruthy();
  306. expect(_pageT.descendantCount).toBe(1);
  307. });
  308. });
  309. describe('Creating a page under a page with grant RESTRICTED', () => {
  310. test('will create a new empty page with the same path as the grant RESTRECTED page and become a parent', async() => {
  311. const pathT = '/mc5_top';
  312. const path1 = '/mc5_top/mc3_awl';
  313. const pathN = '/mc5_top/mc3_awl/mc4_pub'; // used to create
  314. const pageT = await Page.findOne({ path: pathT });
  315. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  316. const page2 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  317. expect(pageT).toBeTruthy();
  318. expect(page1).toBeTruthy();
  319. expect(page2).toBeNull();
  320. await Page.create(pathN, 'new body', dummyUser1, { grant: Page.GRANT_PUBLIC });
  321. const _pageT = await Page.findOne({ path: pathT });
  322. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  323. const _page2 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC, isEmpty: true });
  324. expect(_pageT).toBeTruthy();
  325. expect(_page1).toBeTruthy();
  326. expect(_page2).toBeTruthy();
  327. const createdPage = await Page.findOne({ path: pathN, grant: Page.GRANT_PUBLIC });
  328. expect(createdPage).toBeTruthy();
  329. expect(createdPage.parent).toStrictEqual(_page2._id);
  330. expect(_pageT.descendantCount).toStrictEqual(1);
  331. });
  332. });
  333. });
  334. describe('update', () => {
  335. describe('Changing grant from PUBLIC to RESTRICTED of', () => {
  336. test('an only-child page will delete its empty parent page', async() => {
  337. const pathT = '/mup13_top';
  338. const path1 = '/mup13_top/mup1_emp';
  339. const path2 = '/mup13_top/mup1_emp/mup2_pub';
  340. const pageT = await Page.findOne({ path: pathT, descendantCount: 2 });
  341. const page1 = await Page.findOne({ path: path1 });
  342. const page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC });
  343. const options = { grant: Page.GRANT_RESTRICTED, grantUserGroupId: null };
  344. expectAllToBeTruthy([pageT, page1, page2]);
  345. await Page.updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, options);
  346. const _pageT = await Page.findOne({ path: pathT });
  347. const _page1 = await Page.findOne({ path: path1 });
  348. const _page2 = await Page.findOne({ path: path2 });
  349. expect(_page2).toBeTruthy();
  350. expect(_page1).toBeNull();
  351. expect(_page2.grant).toBe(Page.GRANT_RESTRICTED);
  352. expect(_pageT.descendantCount).toBe(1);
  353. });
  354. test('a page that has children will create an empty page with the same path and it becomes a new parent', async() => {
  355. const pathT = '/mup14_top';
  356. const path1 = '/mup14_top/mup6_pub';
  357. const path2 = '/mup14_top/mup6_pub/mup7_pub';
  358. const top = await Page.findOne({ path: pathT, descendantCount: 2 });
  359. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  360. const page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC });
  361. expect(top).toBeTruthy();
  362. expect(page1).toBeTruthy();
  363. expect(page2).toBeTruthy();
  364. await Page.updatePage(page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  365. const _top = await Page.findOne({ path: pathT });
  366. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  367. const _page2 = await Page.findOne({ path: path2 });
  368. const _pageN = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  369. expect(_page1).toBeTruthy();
  370. expect(_page2).toBeTruthy();
  371. expect(_pageN).toBeTruthy();
  372. expect(_page1.parent).toBeNull();
  373. expect(_page2.parent).toStrictEqual(_pageN._id);
  374. expect(_pageN.parent).toStrictEqual(top._id);
  375. expect(_pageN.isEmpty).toBe(true);
  376. expect(_pageN.descendantCount).toBe(1);
  377. expect(_top.descendantCount).toBe(1);
  378. });
  379. test('of a leaf page will NOT have an empty page with the same path', async() => {
  380. const path1 = '/mup15_top';
  381. const path2 = '/mup15_top/mup8_pub';
  382. const top = await Page.findOne({ path: path1, descendantCount: 1 });
  383. const page = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC });
  384. const count = await Page.count({ path: path2 });
  385. expect(top).toBeTruthy();
  386. expect(page).toBeTruthy();
  387. expect(count).toBe(1);
  388. await Page.updatePage(page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: 2 });
  389. // AU => After Update
  390. const _top = await Page.findOne({ path: path1 });
  391. const _page = await Page.findOne({ path: path2 });
  392. const notExistantPage = await Page.findOne({ path: path2, isEmpty: true });
  393. const _count = await Page.count({ path: path2 });
  394. expect(_page).toBeTruthy();
  395. expect(_count).toBe(1);
  396. expect(notExistantPage).toBeNull();
  397. expect(_page.grant).toBe(Page.GRANT_RESTRICTED);
  398. expect(_top.descendantCount).toBe(0);
  399. });
  400. });
  401. describe('Changing grant from RESTRICTED to PUBLIC of', () => {
  402. test('a page will create ancestors if they do not exist', async() => {
  403. const top = await Page.findOne({ path: '/mup16_top' });
  404. const page = await Page.findOne({ path: '/mup16_top/mup9_pub/mup10_pub/mup11_awl', grant: Page.GRANT_RESTRICTED });
  405. const page1 = await Page.findOne({ path: '/mup16_top/mup9_pub' });
  406. const page2 = await Page.findOne({ path: '/mup16_top/mup9_pub/mup10_pub' });
  407. expect(top).toBeTruthy();
  408. expect(page).toBeTruthy();
  409. expect(page1).toBeNull();
  410. expect(page2).toBeNull();
  411. await Page.updatePage(page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: 1 });
  412. const topAF = await Page.findOne({ _id: top._id });
  413. const pageAF = await Page.findOne({ _id: page._id });
  414. const page1AF = await Page.findOne({ path: '/mup16_top/mup9_pub' });
  415. const page2AF = await Page.findOne({ path: '/mup16_top/mup9_pub/mup10_pub' });
  416. expect(pageAF).toBeTruthy();
  417. expect(page1AF).toBeTruthy();
  418. expect(page2AF).toBeTruthy();
  419. expect(pageAF.grant).toBe(Page.GRANT_PUBLIC);
  420. expect(pageAF.parent).toStrictEqual(page2AF._id);
  421. expect(page1AF.isEmpty).toBe(true);
  422. expect(page1AF.parent).toStrictEqual(top._id);
  423. expect(page2AF.isEmpty).toBe(true);
  424. expect(page2AF.parent).toStrictEqual(page1AF._id);
  425. expect(topAF.descendantCount).toBe(1);
  426. });
  427. test('a page will replace an empty page with the same path if any', async() => {
  428. const top = await Page.findOne({ path: '/mup17_top', descendantCount: 1 });
  429. const page1 = await Page.findOne({ path: '/mup17_top/mup12_emp', isEmpty: true });
  430. const page2 = await Page.findOne({ path: '/mup17_top/mup12_emp', grant: Page.GRANT_RESTRICTED, isEmpty: false });
  431. const page3 = await Page.findOne({ path: '/mup17_top/mup12_emp/mup18_pub' });
  432. expect(top).toBeTruthy();
  433. expect(page1).toBeTruthy();
  434. expect(page2).toBeTruthy();
  435. expect(page3).toBeTruthy();
  436. await Page.updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_PUBLIC });
  437. const topAF = await Page.findOne({ _id: top._id });
  438. const page1AF = await Page.findOne({ _id: page1._id });
  439. const page2AF = await Page.findOne({ _id: page2._id });
  440. const page3AF = await Page.findOne({ _id: page3._id });
  441. expect(page1AF).toBeNull();
  442. expect(page2AF).toBeTruthy();
  443. expect(page3AF).toBeTruthy();
  444. expect(page2AF.grant).toBe(Page.GRANT_PUBLIC);
  445. expect(page2AF.parent).toStrictEqual(topAF._id);
  446. expect(page3AF.parent).toStrictEqual(page2AF._id);
  447. expect(topAF.descendantCount).toBe(2);
  448. });
  449. });
  450. });
  451. });