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