v5.migration.test.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. const mongoose = require('mongoose');
  2. const { getInstance } = require('../setup-crowi');
  3. describe('V5 page migration', () => {
  4. let crowi;
  5. let Page;
  6. let User;
  7. let UserGroup;
  8. let UserGroupRelation;
  9. let testUser1;
  10. let rootPage;
  11. const groupIdIsolate = new mongoose.Types.ObjectId();
  12. const groupIdA = new mongoose.Types.ObjectId();
  13. const groupIdB = new mongoose.Types.ObjectId();
  14. const groupIdC = new mongoose.Types.ObjectId();
  15. const pageId1 = new mongoose.Types.ObjectId();
  16. const pageId2 = new mongoose.Types.ObjectId();
  17. const pageId3 = new mongoose.Types.ObjectId();
  18. const pageId4 = new mongoose.Types.ObjectId();
  19. const pageId5 = new mongoose.Types.ObjectId();
  20. const pageId6 = new mongoose.Types.ObjectId();
  21. beforeAll(async() => {
  22. jest.restoreAllMocks();
  23. crowi = await getInstance();
  24. Page = mongoose.model('Page');
  25. User = mongoose.model('User');
  26. UserGroup = mongoose.model('UserGroup');
  27. UserGroupRelation = mongoose.model('UserGroupRelation');
  28. await crowi.configManager.updateConfigsInTheSameNamespace('crowi', { 'app:isV5Compatible': true });
  29. await User.insertMany([{ name: 'testUser1', username: 'testUser1', email: 'testUser1@example.com' }]);
  30. testUser1 = await User.findOne({ username: 'testUser1' });
  31. rootPage = await Page.findOne({ path: '/' });
  32. await UserGroup.insertMany([
  33. {
  34. _id: groupIdIsolate,
  35. name: 'groupIsolate',
  36. },
  37. {
  38. _id: groupIdA,
  39. name: 'groupA',
  40. },
  41. {
  42. _id: groupIdB,
  43. name: 'groupB',
  44. parent: groupIdA,
  45. },
  46. {
  47. _id: groupIdC,
  48. name: 'groupC',
  49. parent: groupIdB,
  50. },
  51. ]);
  52. await UserGroupRelation.insertMany([
  53. {
  54. relatedGroup: groupIdIsolate,
  55. relatedUser: testUser1._id,
  56. },
  57. {
  58. relatedGroup: groupIdA,
  59. relatedUser: testUser1._id,
  60. },
  61. {
  62. relatedGroup: groupIdB,
  63. relatedUser: testUser1._id,
  64. },
  65. {
  66. relatedGroup: groupIdC,
  67. relatedUser: testUser1._id,
  68. },
  69. ]);
  70. await Page.insertMany([
  71. {
  72. path: '/private1',
  73. grant: Page.GRANT_OWNER,
  74. creator: testUser1,
  75. lastUpdateUser: testUser1,
  76. grantedUsers: [testUser1._id],
  77. },
  78. {
  79. path: '/dummyParent/private1',
  80. grant: Page.GRANT_OWNER,
  81. creator: testUser1,
  82. lastUpdateUser: testUser1,
  83. grantedUsers: [testUser1._id],
  84. },
  85. {
  86. path: '/dummyParent/private1/private2',
  87. grant: Page.GRANT_OWNER,
  88. creator: testUser1,
  89. lastUpdateUser: testUser1,
  90. grantedUsers: [testUser1._id],
  91. },
  92. {
  93. path: '/dummyParent/private1/private3',
  94. grant: Page.GRANT_OWNER,
  95. creator: testUser1,
  96. lastUpdateUser: testUser1,
  97. grantedUsers: [testUser1._id],
  98. },
  99. {
  100. _id: pageId1,
  101. path: '/normalize_1',
  102. parent: rootPage._id,
  103. grant: Page.GRANT_PUBLIC,
  104. isEmpty: true,
  105. },
  106. {
  107. _id: pageId2,
  108. path: '/normalize_1/normalize_2',
  109. parent: pageId1,
  110. grant: Page.GRANT_USER_GROUP,
  111. grantedGroup: groupIdB,
  112. grantedUsers: [testUser1._id],
  113. },
  114. {
  115. _id: pageId3,
  116. path: '/normalize_1',
  117. grant: Page.GRANT_USER_GROUP,
  118. grantedGroup: groupIdA,
  119. grantedUsers: [testUser1._id],
  120. },
  121. {
  122. _id: pageId4,
  123. path: '/normalize_4',
  124. parent: rootPage._id,
  125. grant: Page.GRANT_PUBLIC,
  126. isEmpty: true,
  127. },
  128. {
  129. _id: pageId5,
  130. path: '/normalize_4/normalize_5',
  131. parent: pageId4,
  132. grant: Page.GRANT_USER_GROUP,
  133. grantedGroup: groupIdA,
  134. grantedUsers: [testUser1._id],
  135. },
  136. {
  137. _id: pageId6,
  138. path: '/normalize_4',
  139. grant: Page.GRANT_USER_GROUP,
  140. grantedGroup: groupIdIsolate,
  141. grantedUsers: [testUser1._id],
  142. },
  143. {
  144. path: '/normalize_7/normalize_8_g1',
  145. grant: Page.GRANT_USER_GROUP,
  146. creator: testUser1,
  147. grantedGroup: groupIdA,
  148. grantedUsers: [testUser1._id],
  149. },
  150. {
  151. path: '/normalize_7/normalize_8_g1/normalize_9_g2',
  152. grant: Page.GRANT_USER_GROUP,
  153. creator: testUser1,
  154. grantedGroup: groupIdB,
  155. grantedUsers: [testUser1._id],
  156. },
  157. {
  158. path: '/normalize_7/normalize_8_g3',
  159. grant: Page.GRANT_USER_GROUP,
  160. creator: testUser1,
  161. grantedGroup: groupIdC,
  162. grantedUsers: [testUser1._id],
  163. },
  164. ]);
  165. });
  166. // https://github.com/jest-community/eslint-plugin-jest/blob/v24.3.5/docs/rules/expect-expect.md#assertfunctionnames
  167. // pass unless the data is one of [false, 0, '', null, undefined, NaN]
  168. const expectAllToBeTruthy = (dataList) => {
  169. dataList.forEach((data, i) => {
  170. if (data == null) { console.log(`index: ${i}`) }
  171. expect(data).toBeTruthy();
  172. });
  173. };
  174. describe('normalizeParentRecursivelyByPages()', () => {
  175. const normalizeParentRecursivelyByPages = async(pages, user) => {
  176. return crowi.pageService.normalizeParentRecursivelyByPages(pages, user);
  177. };
  178. test('should migrate all pages specified by pageIds', async() => {
  179. jest.restoreAllMocks();
  180. const pagesToRun = await Page.find({ path: { $in: ['/private1', '/dummyParent/private1'] } });
  181. // migrate
  182. await normalizeParentRecursivelyByPages(pagesToRun, testUser1);
  183. const migratedPages = await Page.find({
  184. path: {
  185. $in: ['/private1', '/dummyParent', '/dummyParent/private1', '/dummyParent/private1/private2', '/dummyParent/private1/private3'],
  186. },
  187. });
  188. const migratedPagePaths = migratedPages.filter(doc => doc.parent != null).map(doc => doc.path);
  189. const expected = ['/private1', '/dummyParent', '/dummyParent/private1', '/dummyParent/private1/private2', '/dummyParent/private1/private3'];
  190. expect(migratedPagePaths.sort()).toStrictEqual(expected.sort());
  191. });
  192. test('should normalize all pages with usergroup set and create empty parent page from no data', async() => {
  193. const page8 = await Page.findOne({ path: '/normalize_7/normalize_8_g1' });
  194. const page9 = await Page.findOne({ path: '/normalize_7/normalize_8_g1/normalize_9_g2' });
  195. const page10 = await Page.findOne({ path: '/normalize_7/normalize_8_g3' });
  196. expectAllToBeTruthy([page8, page9, page10]);
  197. await normalizeParentRecursivelyByPages([page8, page9, page10], testUser1);
  198. const page7 = await Page.findOne({ path: '/normalize_7' });
  199. const page8AF = await Page.findOne({ path: '/normalize_7/normalize_8_g1' });
  200. const page9AF = await Page.findOne({ path: '/normalize_7/normalize_8_g1/normalize_9_g2' });
  201. const page10AF = await Page.findOne({ path: '/normalize_7/normalize_8_g3' });
  202. expectAllToBeTruthy([page7, page8AF, page9AF, page10AF]);
  203. expect(page7.parent).toStrictEqual(rootPage._id);
  204. expect(page8AF.parent).toStrictEqual(page7._id);
  205. expect(page9AF.parent).toStrictEqual(page8AF._id);
  206. expect(page10AF.parent).toStrictEqual(page7._id);
  207. });
  208. });
  209. describe('normalizeAllPublicPages()', () => {
  210. jest.setTimeout(60000);
  211. let createPagePaths;
  212. let allPossiblePagePaths;
  213. beforeAll(async() => {
  214. createPagePaths = [
  215. '/publicA', '/publicA/privateB', '/publicA/privateB/publicC', '/parenthesis/(a)[b]{c}d', '/parenthesis/(a)[b]{c}d/public', '/migratedD',
  216. ];
  217. allPossiblePagePaths = [...createPagePaths, '/parenthesis', '/'];
  218. // initialize pages for test
  219. await Page.insertMany([
  220. {
  221. path: '/publicA',
  222. grant: Page.GRANT_PUBLIC,
  223. creator: testUser1,
  224. lastUpdateUser: testUser1,
  225. },
  226. {
  227. path: '/publicA/privateB',
  228. grant: Page.GRANT_OWNER,
  229. creator: testUser1,
  230. lastUpdateUser: testUser1,
  231. grantedUsers: [testUser1._id],
  232. },
  233. {
  234. path: '/publicA/privateB/publicC',
  235. grant: Page.GRANT_PUBLIC,
  236. creator: testUser1,
  237. lastUpdateUser: testUser1,
  238. },
  239. {
  240. path: '/parenthesis/(a)[b]{c}d',
  241. grant: Page.GRANT_PUBLIC,
  242. creator: testUser1,
  243. lastUpdateUser: testUser1,
  244. },
  245. {
  246. path: '/parenthesis/(a)[b]{c}d/public',
  247. grant: Page.GRANT_PUBLIC,
  248. creator: testUser1,
  249. lastUpdateUser: testUser1,
  250. },
  251. ]);
  252. const parent = await Page.find({ path: '/' });
  253. await Page.insertMany([
  254. {
  255. path: '/migratedD',
  256. grant: Page.GRANT_PUBLIC,
  257. creator: testUser1,
  258. lastUpdateUser: testUser1,
  259. parent: parent._id,
  260. },
  261. ]);
  262. // migrate
  263. await crowi.pageService.normalizeAllPublicPages(Page.GRANT_PUBLIC);
  264. jest.setTimeout(30000);
  265. });
  266. test('should migrate all public pages', async() => {
  267. const migratedPages = await Page.find({
  268. path: {
  269. $in: allPossiblePagePaths,
  270. },
  271. parent: { $ne: null },
  272. });
  273. const migratedEmptyPages = await Page.find({
  274. path: {
  275. $in: allPossiblePagePaths,
  276. },
  277. isEmpty: true,
  278. parent: { $ne: null },
  279. });
  280. const nonMigratedPages = await Page.find({
  281. path: {
  282. $in: allPossiblePagePaths,
  283. },
  284. parent: null,
  285. });
  286. const migratedPaths = migratedPages.map(page => page.path).sort();
  287. const migratedEmptyPaths = migratedEmptyPages.map(page => page.path).sort();
  288. const nonMigratedPaths = nonMigratedPages.map(page => page.path).sort();
  289. const expectedMigratedPaths = allPossiblePagePaths.filter(path => path !== '/').sort();
  290. const expectedMigratedEmptyPaths = ['/publicA/privateB', '/parenthesis'].sort();
  291. const expectedNonMigratedPaths = ['/publicA/privateB', '/'].sort();
  292. expect(migratedPaths).toStrictEqual(expectedMigratedPaths);
  293. expect(migratedEmptyPaths).toStrictEqual(expectedMigratedEmptyPaths);
  294. expect(nonMigratedPaths).toStrictEqual(expectedNonMigratedPaths);
  295. });
  296. });
  297. describe('normalizeParentByPageId()', () => {
  298. const normalizeParentByPageId = async(page, user) => {
  299. return crowi.pageService.normalizeParentByPageId(page, user);
  300. };
  301. test('it should normalize not v5 page with usergroup that has parent group', async() => {
  302. const page1 = await Page.findOne({ _id: pageId1, path: '/normalize_1', isEmpty: true });
  303. const page2 = await Page.findOne({ _id: pageId2, path: '/normalize_1/normalize_2', parent: page1._id });
  304. const page3 = await Page.findOne({ _id: pageId3, path: '/normalize_1' }); // NOT v5
  305. expectAllToBeTruthy([page1, page2, page3]);
  306. await normalizeParentByPageId(page3, testUser1);
  307. // AF => After Migration
  308. const page3AF = await Page.findOne({ _id: pageId3, path: '/normalize_1' }); // v5 compatible
  309. const page2AF = await Page.findOne({ _id: pageId2, path: '/normalize_1/normalize_2', parent: page3AF._id });
  310. const page1AF = await Page.findOne({ _id: pageId1, path: '/normalize_1', isEmpty: true });
  311. expectAllToBeTruthy([page3AF, page2AF]);
  312. expect(page1AF).toBeNull();
  313. expect(page3AF.parent).toStrictEqual(rootPage._id);
  314. expect(page2AF.parent).toStrictEqual(page3AF._id);
  315. });
  316. test('it should normalize not v5 page with usergroup that has no parent or child group', async() => {
  317. const page4 = await Page.findOne({ _id: pageId4, path: '/normalize_4', isEmpty: true });
  318. const page5 = await Page.findOne({ _id: pageId5, path: '/normalize_4/normalize_5', parent: page4._id });
  319. const page6 = await Page.findOne({ _id: pageId6, path: '/normalize_4' }); // NOT v5
  320. expectAllToBeTruthy([page4, page5, page6]);
  321. let isThrown;
  322. try {
  323. await normalizeParentByPageId(page6, testUser1);
  324. }
  325. catch (err) {
  326. isThrown = true;
  327. }
  328. // AF => After Migration
  329. const page4AF = await Page.findOne({ _id: pageId4, path: '/normalize_4', isEmpty: true });
  330. const page5AF = await Page.findOne({ _id: pageId5, path: '/normalize_4/normalize_5', parent: page4._id });
  331. const page6AF = await Page.findOne({ _id: pageId6, path: '/normalize_4' }); // NOT v5
  332. expect(isThrown).toBeTruthy();
  333. expect(page4AF).toStrictEqual(page4);
  334. expect(page5AF).toStrictEqual(page5);
  335. expect(page6AF).toStrictEqual(page6);
  336. });
  337. });
  338. test('replace private parents with empty pages', async() => {
  339. const replacedPathPages = await Page.find({ path: '/publicA/privateB' }); // ex-private page
  340. const _newEmptyPage = replacedPathPages.filter(page => page.parent != null)[0];
  341. const newEmptyPage = {
  342. path: _newEmptyPage.path,
  343. grant: _newEmptyPage.grant,
  344. isEmpty: _newEmptyPage.isEmpty,
  345. };
  346. const expectedNewEmptyPage = {
  347. path: '/publicA/privateB',
  348. grant: Page.GRANT_PUBLIC,
  349. isEmpty: true,
  350. };
  351. const _privatePage = replacedPathPages.filter(page => page.parent == null)[0];
  352. const privatePage = {
  353. path: _privatePage.path,
  354. grant: _privatePage.grant,
  355. isEmpty: _privatePage.isEmpty,
  356. };
  357. const expectedPrivatePage = {
  358. path: '/publicA/privateB',
  359. grant: Page.GRANT_OWNER,
  360. isEmpty: false,
  361. };
  362. expect(replacedPathPages.length).toBe(2);
  363. expect(newEmptyPage).toStrictEqual(expectedNewEmptyPage);
  364. expect(privatePage).toStrictEqual(expectedPrivatePage);
  365. });
  366. });