v5.page.test.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  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 top = await Page.findOne({ path: '/mc4_top', descendantCount: 1 });
  286. const page1 = await Page.findOne({ path: '/mc4_top/mc1_emp' });
  287. const page2 = await Page.findOne({ path: '/mc4_top/mc1_emp/mc2_pub' });
  288. const count = await Page.count({ path: '/mc4_top/mc1_emp' });
  289. expectAllToBeTruthy([top, page1, page2]);
  290. expect(count).toBe(1);
  291. await Page.create('/mc4_top/mc1_emp', 'new body', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  292. // AF => After Create
  293. const topAF = await Page.findOne({ _id: top._id });
  294. const page1AF = await Page.findOne({ _id: page1._id });
  295. const page2AF = await Page.findOne({ _id: page2._id });
  296. const countAF = await Page.count({ path: '/mc4_top/mc1_emp' });
  297. const newPage = await Page.find({ path: '/mc4_top/mc1_emp', grant: Page.GRANT_RESTRICTED });
  298. expectAllToBeTruthy([topAF, page1AF, page2AF, newPage]);
  299. expect(countAF).toBe(2);
  300. expect(topAF.descendantCount).toBe(1);
  301. });
  302. });
  303. describe('Creating a page under a page with grant RESTRICTED', () => {
  304. test('will create a new empty page with the same path as the grant RESTRECTED page and become a parent', async() => {
  305. const top = await Page.findOne({ path: '/mc5_top' });
  306. const page1 = await Page.findOne({ path: '/mc5_top/mc3_awl', grant: Page.GRANT_RESTRICTED });
  307. const count = await Page.count({ path: '/mc5_top/mc3_awl' });
  308. expectAllToBeTruthy([top, page1]);
  309. expect(count).toBe(1);
  310. await Page.create('/mc5_top/mc3_awl/mc4_pub', 'new body', dummyUser1, { grant: Page.GRANT_PUBLIC });
  311. // AF => After Create
  312. const topAF = await Page.findOne({ _id: top._id });
  313. const page1AF = await Page.findOne({ path: '/mc5_top/mc3_awl', grant: Page.GRANT_RESTRICTED });
  314. const countAF = await Page.count({ path: '/mc5_top/mc3_awl' });
  315. const createdPage = await Page.findOne({ path: '/mc5_top/mc3_awl/mc4_pub', grant: Page.GRANT_PUBLIC });
  316. const createdPageParent = await Page.findOne({ path: '/mc5_top/mc3_awl', grant: Page.GRANT_PUBLIC, isEmpty: true });
  317. expectAllToBeTruthy([page1AF, createdPageParent, createdPage]);
  318. expect(countAF).toBe(2);
  319. expect(createdPage.parent).toStrictEqual(createdPageParent._id);
  320. expect(createdPageParent.parent).toStrictEqual(topAF._id);
  321. expect(topAF.descendantCount).toStrictEqual(1);
  322. });
  323. });
  324. });
  325. describe('update', () => {
  326. describe('Changing grant from PUBLIC to RESTRICTED of', () => {
  327. test('an only-child page will delete its empty parent page', async() => {
  328. const top = await Page.findOne({ path: '/mup13_top', descendantCount: 2 });
  329. const page1 = await Page.findOne({ path: '/mup13_top/mup1_emp', isEmpty: true });
  330. const page2 = await Page.findOne({ path: '/mup13_top/mup1_emp/mup2_pub' });
  331. const options = { grant: 2, grantUserGroupId: null };
  332. expectAllToBeTruthy([top, page1, page2]);
  333. await Page.updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, options);
  334. // AU => After Update
  335. const topAF = await Page.findOne({ _id: top._id });
  336. const page1AU = await Page.findOne({ _id: page1._id });
  337. const page2AU = await Page.findOne({ _id: page2._id });
  338. expect(page2AU).toBeTruthy();
  339. expect(page1AU).toBeNull();
  340. expect(topAF.descendantCount).toBe(1);
  341. });
  342. test('a page that has children will create an empty page with the same path and it becomes a new parent', async() => {
  343. const top = await Page.findOne({ path: '/mup14_top', descendantCount: 2 });
  344. const page1 = await Page.findOne({ path: '/mup14_top/mup6_pub', grant: Page.GRANT_PUBLIC });
  345. const page2 = await Page.findOne({ path: '/mup14_top/mup6_pub/mup7_pub', grant: Page.GRANT_PUBLIC });
  346. const count = await Page.count({ path: '/mup14_top/mup6_pub' });
  347. expectAllToBeTruthy([top, page1, page2]);
  348. expect(count).toBe(1);
  349. await Page.updatePage(page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: 2 });
  350. // AU => After Update
  351. const topAF = await Page.findOne({ _id: top._id });
  352. const page1AF = await Page.findOne({ _id: page1._id });
  353. const page2AF = await Page.findOne({ _id: page2._id });
  354. const newlyCreatedPage = await Page.findOne({ _id: { $ne: page1._id }, path: '/mup14_top/mup6_pub' });
  355. const countAF = await Page.count({ path: '/mup14_top/mup6_pub' });
  356. expectAllToBeTruthy([page1AF, page2AF, newlyCreatedPage]);
  357. expect(countAF).toBe(2);
  358. expect(page1AF.grant).toBe(Page.GRANT_RESTRICTED);
  359. expect(page1AF.parent).toBeNull();
  360. expect(page2AF.grant).toBe(Page.GRANT_PUBLIC);
  361. expect(page2AF.parent).toStrictEqual(newlyCreatedPage._id);
  362. expect(newlyCreatedPage.isEmpty).toBe(true);
  363. expect(newlyCreatedPage.grant).toBe(Page.GRANT_PUBLIC);
  364. expect(newlyCreatedPage.parent).toStrictEqual(top._id);
  365. expect(topAF.descendantCount).toBe(1);
  366. });
  367. test('of a leaf page will NOT have an empty page with the same path', async() => {
  368. const top = await Page.findOne({ path: '/mup15_top', descendantCount: 1 });
  369. const page = await Page.findOne({ path: '/mup15_top/mup8_pub', grant: Page.GRANT_PUBLIC });
  370. const count = await Page.count({ path: '/mup15_top/mup8_pub' });
  371. expectAllToBeTruthy([top, page]);
  372. expect(count).toBe(1);
  373. await Page.updatePage(page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: 2 });
  374. // AU => After Update
  375. const topAF = await Page.findOne({ _id: top._id });
  376. const pageAF = await Page.findOne({ _id: page._id });
  377. const notExistantPage = await Page.findOne({ path: '/mup15_top/mup8_pub', isEmpty: true });
  378. const countAF = await Page.count({ path: '/mup15_top/mup8_pub' });
  379. expectAllToBeTruthy([pageAF]);
  380. expect(countAF).toBe(1);
  381. expect(notExistantPage).toBeNull();
  382. expect(pageAF.grant).toBe(Page.GRANT_RESTRICTED);
  383. expect(topAF.descendantCount).toBe(0);
  384. });
  385. });
  386. describe('Changing grant from RESTRICTED to PUBLIC of', () => {
  387. test('a page will create ancestors if they do not exist', async() => {
  388. const top = await Page.findOne({ path: '/mup16_top' });
  389. const page = await Page.findOne({ path: '/mup16_top/mup9_pub/mup10_pub/mup11_awl', grant: Page.GRANT_RESTRICTED });
  390. const page1 = await Page.findOne({ path: '/mup16_top/mup9_pub' });
  391. const page2 = await Page.findOne({ path: '/mup16_top/mup9_pub/mup10_pub' });
  392. expectAllToBeTruthy([top, page]);
  393. expect(page1).toBeNull();
  394. expect(page2).toBeNull();
  395. await Page.updatePage(page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: 1 });
  396. const topAF = await Page.findOne({ _id: top._id });
  397. const pageAF = await Page.findOne({ _id: page._id });
  398. const page1AF = await Page.findOne({ path: '/mup16_top/mup9_pub' });
  399. const page2AF = await Page.findOne({ path: '/mup16_top/mup9_pub/mup10_pub' });
  400. expectAllToBeTruthy([pageAF, page1AF, page2AF]);
  401. expect(pageAF.grant).toBe(Page.GRANT_PUBLIC);
  402. expect(pageAF.parent).toStrictEqual(page2AF._id);
  403. expect(page1AF.isEmpty).toBe(true);
  404. expect(page1AF.parent).toStrictEqual(top._id);
  405. expect(page2AF.isEmpty).toBe(true);
  406. expect(page2AF.parent).toStrictEqual(page1AF._id);
  407. expect(topAF.descendantCount).toBe(1);
  408. });
  409. test('a page will replace an empty page with the same path if any', async() => {
  410. const top = await Page.findOne({ path: '/mup17_top', descendantCount: 1 });
  411. const page1 = await Page.findOne({ path: '/mup17_top/mup12_emp', isEmpty: true });
  412. const page2 = await Page.findOne({ path: '/mup17_top/mup12_emp', grant: Page.GRANT_RESTRICTED, isEmpty: false });
  413. const page3 = await Page.findOne({ path: '/mup17_top/mup12_emp/mup18_pub' });
  414. expect(top).toBeTruthy();
  415. expect(page1).toBeTruthy();
  416. expect(page2).toBeTruthy();
  417. expect(page3).toBeTruthy();
  418. await Page.updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_PUBLIC });
  419. const topAF = await Page.findOne({ _id: top._id });
  420. const page1AF = await Page.findOne({ _id: page1._id });
  421. const page2AF = await Page.findOne({ _id: page2._id });
  422. const page3AF = await Page.findOne({ _id: page3._id });
  423. expect(page1AF).toBeNull();
  424. expect(page2AF).toBeTruthy();
  425. expect(page3AF).toBeTruthy();
  426. expect(page2AF.grant).toBe(Page.GRANT_PUBLIC);
  427. expect(page2AF.parent).toStrictEqual(topAF._id);
  428. expect(page3AF.parent).toStrictEqual(page2AF._id);
  429. expect(topAF.descendantCount).toBe(2);
  430. });
  431. });
  432. });
  433. });