v5.page.test.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  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. /**
  42. * create
  43. * mc_ => model create
  44. * emp => empty => page with isEmpty: true
  45. * pub => public => GRANT_PUBLIC
  46. */
  47. await Page.insertMany([
  48. {
  49. _id: pageIdCreate1,
  50. path: '/v5_empty_create_4',
  51. grant: Page.GRANT_PUBLIC,
  52. parent: rootPage._id,
  53. isEmpty: true,
  54. },
  55. {
  56. path: '/v5_empty_create_4/v5_create_5',
  57. grant: Page.GRANT_PUBLIC,
  58. creator: dummyUser1,
  59. lastUpdateUser: dummyUser1._id,
  60. parent: pageIdCreate1,
  61. isEmpty: false,
  62. },
  63. {
  64. _id: pageIdCreate2,
  65. path: '/mc1_emp',
  66. grant: Page.GRANT_PUBLIC,
  67. creator: dummyUser1,
  68. lastUpdateUser: dummyUser1._id,
  69. parent: rootPage._id,
  70. isEmpty: true,
  71. },
  72. {
  73. path: '/mc1_emp/mc2_pub',
  74. grant: Page.GRANT_PUBLIC,
  75. creator: dummyUser1,
  76. lastUpdateUser: dummyUser1._id,
  77. parent: pageIdCreate2,
  78. isEmpty: false,
  79. },
  80. {
  81. path: '/mc3_awl',
  82. grant: Page.GRANT_RESTRICTED,
  83. creator: dummyUser1,
  84. lastUpdateUser: dummyUser1._id,
  85. isEmpty: false,
  86. },
  87. ]);
  88. /**
  89. * update
  90. * mup_ => model update
  91. * emp => empty => page with isEmpty: true
  92. * pub => public => GRANT_PUBLIC
  93. * awl => Anyone with the link => GRANT_RESTRICTED
  94. */
  95. const pageIdUpd1 = new mongoose.Types.ObjectId();
  96. const pageIdUpd2 = new mongoose.Types.ObjectId();
  97. const pageIdUpd3 = new mongoose.Types.ObjectId();
  98. const pageIdUpd4 = new mongoose.Types.ObjectId();
  99. const pageIdUpd5 = new mongoose.Types.ObjectId();
  100. const pageIdUpd6 = new mongoose.Types.ObjectId();
  101. const pageIdUpd7 = new mongoose.Types.ObjectId();
  102. const pageIdUpd8 = new mongoose.Types.ObjectId();
  103. const pageIdUpd9 = new mongoose.Types.ObjectId();
  104. const pageIdUpd10 = new mongoose.Types.ObjectId();
  105. const pageIdUpd11 = new mongoose.Types.ObjectId();
  106. const pageIdUpd12 = new mongoose.Types.ObjectId();
  107. const pageIdUpd13 = new mongoose.Types.ObjectId();
  108. await Page.insertMany([
  109. {
  110. _id: pageIdUpd1,
  111. path: '/mup13_top/mup1_emp',
  112. grant: Page.GRANT_PUBLIC,
  113. parent: pageIdUpd9._id,
  114. isEmpty: true,
  115. },
  116. {
  117. _id: pageIdUpd2,
  118. path: '/mup13_top/mup1_emp/mup2_pub',
  119. grant: Page.GRANT_PUBLIC,
  120. parent: pageIdUpd1._id,
  121. creator: dummyUser1,
  122. lastUpdateUser: dummyUser1._id,
  123. isEmpty: false,
  124. },
  125. {
  126. _id: pageIdUpd4,
  127. path: '/mup14_top/mup6_pub',
  128. grant: Page.GRANT_PUBLIC,
  129. creator: dummyUser1,
  130. lastUpdateUser: dummyUser1._id,
  131. parent: pageIdUpd10,
  132. isEmpty: false,
  133. descendantCount: 1,
  134. },
  135. {
  136. path: '/mup14_top/mup6_pub/mup7_pub',
  137. grant: Page.GRANT_PUBLIC,
  138. creator: dummyUser1,
  139. lastUpdateUser: dummyUser1._id,
  140. parent: pageIdUpd4,
  141. isEmpty: false,
  142. descendantCount: 0,
  143. },
  144. {
  145. _id: pageIdUpd5,
  146. path: '/mup15_top/mup8_pub',
  147. grant: Page.GRANT_PUBLIC,
  148. creator: dummyUser1,
  149. lastUpdateUser: dummyUser1._id,
  150. parent: pageIdUpd11._id,
  151. isEmpty: false,
  152. },
  153. {
  154. _id: pageIdUpd6,
  155. path: '/mup16_top/mup9_pub/mup10_pub/mup11_awl',
  156. grant: Page.GRANT_RESTRICTED,
  157. creator: dummyUser1,
  158. lastUpdateUser: dummyUser1._id,
  159. isEmpty: false,
  160. },
  161. {
  162. _id: pageIdUpd7,
  163. path: '/mup17_top/mup12_emp',
  164. isEmpty: true,
  165. parent: pageIdUpd13._id,
  166. },
  167. {
  168. _id: pageIdUpd8,
  169. path: '/mup17_top/mup12_emp',
  170. grant: Page.GRANT_RESTRICTED,
  171. creator: dummyUser1,
  172. lastUpdateUser: dummyUser1._id,
  173. isEmpty: false,
  174. },
  175. {
  176. _id: pageIdUpd9,
  177. path: '/mup13_top',
  178. grant: Page.GRANT_PUBLIC,
  179. creator: dummyUser1,
  180. lastUpdateUser: dummyUser1._id,
  181. isEmpty: false,
  182. parent: rootPage._id,
  183. descendantCount: 2,
  184. },
  185. {
  186. _id: pageIdUpd10,
  187. path: '/mup14_top',
  188. grant: Page.GRANT_PUBLIC,
  189. creator: dummyUser1,
  190. lastUpdateUser: dummyUser1._id,
  191. isEmpty: false,
  192. parent: rootPage._id,
  193. descendantCount: 2,
  194. },
  195. {
  196. _id: pageIdUpd11,
  197. path: '/mup15_top',
  198. grant: Page.GRANT_PUBLIC,
  199. creator: dummyUser1,
  200. lastUpdateUser: dummyUser1._id,
  201. isEmpty: false,
  202. parent: rootPage._id,
  203. descendantCount: 1,
  204. },
  205. {
  206. _id: pageIdUpd12,
  207. path: '/mup16_top',
  208. grant: Page.GRANT_PUBLIC,
  209. creator: dummyUser1,
  210. lastUpdateUser: dummyUser1._id,
  211. isEmpty: false,
  212. parent: rootPage._id,
  213. descendantCount: 0,
  214. },
  215. {
  216. _id: pageIdUpd13,
  217. path: '/mup17_top',
  218. grant: Page.GRANT_PUBLIC,
  219. creator: dummyUser1,
  220. lastUpdateUser: dummyUser1._id,
  221. isEmpty: false,
  222. parent: rootPage._id,
  223. descendantCount: 0,
  224. },
  225. ]);
  226. });
  227. describe('create', () => {
  228. test('Should create single page', async() => {
  229. const page = await Page.create('/v5_create1', 'create1', dummyUser1, {});
  230. expect(page).toBeTruthy();
  231. expect(page.parent).toStrictEqual(rootPage._id);
  232. });
  233. test('Should create empty-child and non-empty grandchild', async() => {
  234. const grandchildPage = await Page.create('/v5_empty_create2/v5_create_3', 'grandchild', dummyUser1, {});
  235. const childPage = await Page.findOne({ path: '/v5_empty_create2' });
  236. expect(childPage.isEmpty).toBe(true);
  237. expect(grandchildPage).toBeTruthy();
  238. expect(childPage).toBeTruthy();
  239. expect(childPage.parent).toStrictEqual(rootPage._id);
  240. expect(grandchildPage.parent).toStrictEqual(childPage._id);
  241. });
  242. test('Should create on empty page', async() => {
  243. const beforeCreatePage = await Page.findOne({ path: '/v5_empty_create_4' });
  244. expect(beforeCreatePage.isEmpty).toBe(true);
  245. const childPage = await Page.create('/v5_empty_create_4', 'body', dummyUser1, {});
  246. const grandchildPage = await Page.findOne({ parent: childPage._id });
  247. expect(childPage).toBeTruthy();
  248. expect(childPage.isEmpty).toBe(false);
  249. expect(childPage.revision.body).toBe('body');
  250. expect(grandchildPage).toBeTruthy();
  251. expect(childPage.parent).toStrictEqual(rootPage._id);
  252. expect(grandchildPage.parent).toStrictEqual(childPage._id);
  253. });
  254. describe('Creating a page using existing path', () => {
  255. test('with grant RESTRICTED should only create the page and change nothing else', async() => {
  256. const page1 = await Page.findOne({ path: '/mc1_emp' });
  257. const page2 = await Page.findOne({ path: '/mc1_emp/mc2_pub' });
  258. const count = await Page.count({ path: '/mc1_emp' });
  259. expectAllToBeTruthy([page1, page2]);
  260. expect(count).toBe(1);
  261. await Page.create('/mc1_emp', 'new body', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  262. // AF => After Create
  263. const page1AF = await Page.findOne({ _id: page1._id });
  264. const page2AF = await Page.findOne({ _id: page2._id });
  265. const countAF = await Page.count({ path: '/mc1_emp' });
  266. const newPage = await Page.find({ path: '/mc1_emp', grant: Page.GRANT_RESTRICTED });
  267. expectAllToBeTruthy([page1AF, page2AF, newPage]);
  268. expect(countAF).toBe(2);
  269. });
  270. });
  271. describe('Creating a page under a page with grant RESTRICTED', () => {
  272. test('will create a new empty page with the same path as the grant RESTRECTED page and become a parent', async() => {
  273. const page1 = await Page.findOne({ path: '/mc3_awl', grant: Page.GRANT_RESTRICTED });
  274. const count = await Page.count({ path: '/mc3_awl' });
  275. expectAllToBeTruthy([page1]);
  276. expect(count).toBe(1);
  277. await Page.create('/mc3_awl/mc4_pub', 'new body', dummyUser1, { grant: Page.GRANT_PUBLIC });
  278. // AF => After Create
  279. const page1AF = await Page.findOne({ path: '/mc3_awl', grant: Page.GRANT_RESTRICTED });
  280. const countAF = await Page.count({ path: '/mc3_awl' });
  281. const newPage = await Page.findOne({ path: '/mc3_awl/mc4_pub', grant: Page.GRANT_PUBLIC });
  282. const newPageParent = await Page.findOne({ path: '/mc3_awl', grant: Page.GRANT_PUBLIC, isEmpty: true });
  283. expectAllToBeTruthy([page1AF, newPageParent, newPage]);
  284. expect(countAF).toBe(2);
  285. expect(newPage.parent).toStrictEqual(newPageParent._id);
  286. expect(newPageParent.parent).toStrictEqual(rootPage._id);
  287. });
  288. });
  289. });
  290. describe('update', () => {
  291. describe('Changing grant from PUBLIC to RESTRICTED of', () => {
  292. test('an only-child page will delete its empty parent page', async() => {
  293. const top = await Page.findOne({ path: '/mup13_top', descendantCount: 2 });
  294. const page1 = await Page.findOne({ path: '/mup13_top/mup1_emp', isEmpty: true });
  295. const page2 = await Page.findOne({ path: '/mup13_top/mup1_emp/mup2_pub' });
  296. const options = { grant: 2, grantUserGroupId: null };
  297. expectAllToBeTruthy([top, page1, page2]);
  298. await Page.updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, options);
  299. // AU => After Update
  300. const topAF = await Page.findOne({ _id: top._id });
  301. const page1AU = await Page.findOne({ _id: page1._id });
  302. const page2AU = await Page.findOne({ _id: page2._id });
  303. expect(page2AU).toBeTruthy();
  304. expect(page1AU).toBeNull();
  305. expect(topAF.descendantCount).toBe(1);
  306. });
  307. test('a page that has children will create an empty page with the same path and it becomes a new parent', async() => {
  308. const top = await Page.findOne({ path: '/mup14_top', descendantCount: 2 });
  309. const page1 = await Page.findOne({ path: '/mup14_top/mup6_pub', grant: Page.GRANT_PUBLIC });
  310. const page2 = await Page.findOne({ path: '/mup14_top/mup6_pub/mup7_pub', grant: Page.GRANT_PUBLIC });
  311. const count = await Page.count({ path: '/mup14_top/mup6_pub' });
  312. expectAllToBeTruthy([top, page1, page2]);
  313. expect(count).toBe(1);
  314. await Page.updatePage(page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: 2 });
  315. // AU => After Update
  316. const topAF = await Page.findOne({ _id: top._id });
  317. const page1AF = await Page.findOne({ _id: page1._id });
  318. const page2AF = await Page.findOne({ _id: page2._id });
  319. const newlyCreatedPage = await Page.findOne({ _id: { $ne: page1._id }, path: '/mup14_top/mup6_pub' });
  320. const countAF = await Page.count({ path: '/mup14_top/mup6_pub' });
  321. expectAllToBeTruthy([page1AF, page2AF, newlyCreatedPage]);
  322. expect(countAF).toBe(2);
  323. expect(page1AF.grant).toBe(Page.GRANT_RESTRICTED);
  324. expect(page1AF.parent).toBeNull();
  325. expect(page2AF.grant).toBe(Page.GRANT_PUBLIC);
  326. expect(page2AF.parent).toStrictEqual(newlyCreatedPage._id);
  327. expect(newlyCreatedPage.isEmpty).toBe(true);
  328. expect(newlyCreatedPage.grant).toBe(Page.GRANT_PUBLIC);
  329. expect(newlyCreatedPage.parent).toStrictEqual(top._id);
  330. expect(topAF.descendantCount).toBe(1);
  331. });
  332. test('of a leaf page will NOT have an empty page with the same path', async() => {
  333. const top = await Page.findOne({ path: '/mup15_top', descendantCount: 1 });
  334. const page = await Page.findOne({ path: '/mup15_top/mup8_pub', grant: Page.GRANT_PUBLIC });
  335. const count = await Page.count({ path: '/mup15_top/mup8_pub' });
  336. expectAllToBeTruthy([top, page]);
  337. expect(count).toBe(1);
  338. await Page.updatePage(page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: 2 });
  339. // AU => After Update
  340. const topAF = await Page.findOne({ _id: top._id });
  341. const pageAF = await Page.findOne({ _id: page._id });
  342. const emptyPage = await Page.findOne({ path: '/mup15_top/mup8_pub', isEmpty: true });
  343. const countAF = await Page.count({ path: '/mup15_top/mup8_pub' });
  344. expectAllToBeTruthy([pageAF]);
  345. expect(countAF).toBe(1);
  346. expect(emptyPage).toBeNull();
  347. expect(pageAF.grant).toBe(Page.GRANT_RESTRICTED);
  348. expect(topAF.descendantCount).toBe(0);
  349. });
  350. });
  351. describe('Changing grant from RESTRICTED to PUBLIC of', () => {
  352. test('a page will create ancestors if they do not exist', async() => {
  353. const top = await Page.findOne({ path: '/mup16_top' });
  354. const page = await Page.findOne({ path: '/mup16_top/mup9_pub/mup10_pub/mup11_awl', grant: Page.GRANT_RESTRICTED });
  355. const page1 = await Page.findOne({ path: '/mup16_top/mup9_pub' });
  356. const page2 = await Page.findOne({ path: '/mup16_top/mup9_pub/mup10_pub' });
  357. expectAllToBeTruthy([top, page]);
  358. expect(page1).toBeNull();
  359. expect(page2).toBeNull();
  360. await Page.updatePage(page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: 1 });
  361. const topAF = await Page.findOne({ path: '/mup16_top' });
  362. const pageAF = await Page.findOne({ _id: page._id });
  363. const page1AF = await Page.findOne({ path: '/mup16_top/mup9_pub' });
  364. const page2AF = await Page.findOne({ path: '/mup16_top/mup9_pub/mup10_pub' });
  365. expectAllToBeTruthy([pageAF, page1AF, page2AF]);
  366. expect(pageAF.grant).toBe(Page.GRANT_PUBLIC);
  367. expect(pageAF.parent).toStrictEqual(page2AF._id);
  368. expect(page1AF.isEmpty).toBe(true);
  369. expect(page1AF.parent).toStrictEqual(top._id);
  370. expect(page2AF.isEmpty).toBe(true);
  371. expect(page2AF.parent).toStrictEqual(page1AF._id);
  372. expect(topAF.descendantCount).toBe(1);
  373. });
  374. test('a page will replace an empty page with the same path if any', async() => {
  375. const top = await Page.findOne({ path: '/mup17_top', descendantCount: 0 });
  376. const page1 = await Page.findOne({ path: '/mup17_top/mup12_emp', isEmpty: true });
  377. const page2 = await Page.findOne({ path: '/mup17_top/mup12_emp', grant: Page.GRANT_RESTRICTED, isEmpty: false });
  378. expectAllToBeTruthy([top, page1, page2]);
  379. await Page.updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: 1 });
  380. const topAF = await Page.findOne({ _id: top._id });
  381. const page1AF = await Page.findOne({ _id: page1._id });
  382. const page2AF = await Page.findOne({ _id: page2._id });
  383. expect(page1AF).toBeNull();
  384. expect(page2AF).toBeTruthy();
  385. expect(page2AF.grant).toBe(Page.GRANT_PUBLIC);
  386. expect(page2AF.parent).toStrictEqual(topAF._id);
  387. expect(topAF.descendantCount).toBe(1);
  388. });
  389. });
  390. });
  391. });