v5.migration.test.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  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. test('should normalize', async() => {
  209. });
  210. });
  211. describe('normalizeAllPublicPages()', () => {
  212. jest.setTimeout(60000);
  213. let createPagePaths;
  214. let allPossiblePagePaths;
  215. beforeAll(async() => {
  216. createPagePaths = [
  217. '/publicA', '/publicA/privateB', '/publicA/privateB/publicC', '/parenthesis/(a)[b]{c}d', '/parenthesis/(a)[b]{c}d/public', '/migratedD',
  218. ];
  219. allPossiblePagePaths = [...createPagePaths, '/parenthesis', '/'];
  220. // initialize pages for test
  221. await Page.insertMany([
  222. {
  223. path: '/publicA',
  224. grant: Page.GRANT_PUBLIC,
  225. creator: testUser1,
  226. lastUpdateUser: testUser1,
  227. },
  228. {
  229. path: '/publicA/privateB',
  230. grant: Page.GRANT_OWNER,
  231. creator: testUser1,
  232. lastUpdateUser: testUser1,
  233. grantedUsers: [testUser1._id],
  234. },
  235. {
  236. path: '/publicA/privateB/publicC',
  237. grant: Page.GRANT_PUBLIC,
  238. creator: testUser1,
  239. lastUpdateUser: testUser1,
  240. },
  241. {
  242. path: '/parenthesis/(a)[b]{c}d',
  243. grant: Page.GRANT_PUBLIC,
  244. creator: testUser1,
  245. lastUpdateUser: testUser1,
  246. },
  247. {
  248. path: '/parenthesis/(a)[b]{c}d/public',
  249. grant: Page.GRANT_PUBLIC,
  250. creator: testUser1,
  251. lastUpdateUser: testUser1,
  252. },
  253. ]);
  254. const parent = await Page.find({ path: '/' });
  255. await Page.insertMany([
  256. {
  257. path: '/migratedD',
  258. grant: Page.GRANT_PUBLIC,
  259. creator: testUser1,
  260. lastUpdateUser: testUser1,
  261. parent: parent._id,
  262. },
  263. ]);
  264. // migrate
  265. await crowi.pageService.normalizeAllPublicPages(Page.GRANT_PUBLIC);
  266. jest.setTimeout(30000);
  267. });
  268. test('should migrate all public pages', async() => {
  269. const migratedPages = await Page.find({
  270. path: {
  271. $in: allPossiblePagePaths,
  272. },
  273. parent: { $ne: null },
  274. });
  275. const migratedEmptyPages = await Page.find({
  276. path: {
  277. $in: allPossiblePagePaths,
  278. },
  279. isEmpty: true,
  280. parent: { $ne: null },
  281. });
  282. const nonMigratedPages = await Page.find({
  283. path: {
  284. $in: allPossiblePagePaths,
  285. },
  286. parent: null,
  287. });
  288. const migratedPaths = migratedPages.map(page => page.path).sort();
  289. const migratedEmptyPaths = migratedEmptyPages.map(page => page.path).sort();
  290. const nonMigratedPaths = nonMigratedPages.map(page => page.path).sort();
  291. const expectedMigratedPaths = allPossiblePagePaths.filter(path => path !== '/').sort();
  292. const expectedMigratedEmptyPaths = ['/publicA/privateB', '/parenthesis'].sort();
  293. const expectedNonMigratedPaths = ['/publicA/privateB', '/'].sort();
  294. expect(migratedPaths).toStrictEqual(expectedMigratedPaths);
  295. expect(migratedEmptyPaths).toStrictEqual(expectedMigratedEmptyPaths);
  296. expect(nonMigratedPaths).toStrictEqual(expectedNonMigratedPaths);
  297. });
  298. });
  299. describe('normalizeParentByPageId()', () => {
  300. const normalizeParentByPageId = async(page, user) => {
  301. return crowi.pageService.normalizeParentByPageId(page, user);
  302. };
  303. test('it should normalize not v5 page with usergroup that has parent group', async() => {
  304. const page1 = await Page.findOne({ _id: pageId1, path: '/normalize_1', isEmpty: true });
  305. const page2 = await Page.findOne({ _id: pageId2, path: '/normalize_1/normalize_2', parent: page1._id });
  306. const page3 = await Page.findOne({ _id: pageId3, path: '/normalize_1' }); // NOT v5
  307. expectAllToBeTruthy([page1, page2, page3]);
  308. await normalizeParentByPageId(page3, testUser1);
  309. // AF => After Migration
  310. const page3AF = await Page.findOne({ _id: pageId3, path: '/normalize_1' }); // v5 compatible
  311. const page2AF = await Page.findOne({ _id: pageId2, path: '/normalize_1/normalize_2', parent: page3AF._id });
  312. const page1AF = await Page.findOne({ _id: pageId1, path: '/normalize_1', isEmpty: true });
  313. expectAllToBeTruthy([page3AF, page2AF]);
  314. expect(page1AF).toBeNull();
  315. expect(page3AF.parent).toStrictEqual(rootPage._id);
  316. expect(page2AF.parent).toStrictEqual(page3AF._id);
  317. });
  318. test('it should normalize not v5 page with usergroup that has no parent or child group', async() => {
  319. const page4 = await Page.findOne({ _id: pageId4, path: '/normalize_4', isEmpty: true });
  320. const page5 = await Page.findOne({ _id: pageId5, path: '/normalize_4/normalize_5', parent: page4._id });
  321. const page6 = await Page.findOne({ _id: pageId6, path: '/normalize_4' }); // NOT v5
  322. expectAllToBeTruthy([page4, page5, page6]);
  323. let isThrown;
  324. try {
  325. await normalizeParentByPageId(page6, testUser1);
  326. }
  327. catch (err) {
  328. isThrown = true;
  329. }
  330. // AF => After Migration
  331. const page4AF = await Page.findOne({ _id: pageId4, path: '/normalize_4', isEmpty: true });
  332. const page5AF = await Page.findOne({ _id: pageId5, path: '/normalize_4/normalize_5', parent: page4._id });
  333. const page6AF = await Page.findOne({ _id: pageId6, path: '/normalize_4' }); // NOT v5
  334. expect(isThrown).toBeTruthy();
  335. expect(page4AF).toStrictEqual(page4);
  336. expect(page5AF).toStrictEqual(page5);
  337. expect(page6AF).toStrictEqual(page6);
  338. });
  339. });
  340. test('replace private parents with empty pages', async() => {
  341. const replacedPathPages = await Page.find({ path: '/publicA/privateB' }); // ex-private page
  342. const _newEmptyPage = replacedPathPages.filter(page => page.parent != null)[0];
  343. const newEmptyPage = {
  344. path: _newEmptyPage.path,
  345. grant: _newEmptyPage.grant,
  346. isEmpty: _newEmptyPage.isEmpty,
  347. };
  348. const expectedNewEmptyPage = {
  349. path: '/publicA/privateB',
  350. grant: Page.GRANT_PUBLIC,
  351. isEmpty: true,
  352. };
  353. const _privatePage = replacedPathPages.filter(page => page.parent == null)[0];
  354. const privatePage = {
  355. path: _privatePage.path,
  356. grant: _privatePage.grant,
  357. isEmpty: _privatePage.isEmpty,
  358. };
  359. const expectedPrivatePage = {
  360. path: '/publicA/privateB',
  361. grant: Page.GRANT_OWNER,
  362. isEmpty: false,
  363. };
  364. expect(replacedPathPages.length).toBe(2);
  365. expect(newEmptyPage).toStrictEqual(expectedNewEmptyPage);
  366. expect(privatePage).toStrictEqual(expectedPrivatePage);
  367. });
  368. });