v5.migration.test.js 11 KB

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