|
|
@@ -8,6 +8,8 @@ const mongoose = require('mongoose');
|
|
|
|
|
|
const { getInstance } = require('../setup-crowi');
|
|
|
|
|
|
+let rootPage;
|
|
|
+let dummyUser1;
|
|
|
let testUser1;
|
|
|
let testUser2;
|
|
|
let parentTag;
|
|
|
@@ -79,6 +81,10 @@ describe('PageService', () => {
|
|
|
testUser1 = await User.findOne({ username: 'someone1' });
|
|
|
testUser2 = await User.findOne({ username: 'someone2' });
|
|
|
|
|
|
+ dummyUser1 = await User.findOne({ username: 'v5DummyUser1' });
|
|
|
+
|
|
|
+ rootPage = await Page.findOne({ path: '/' });
|
|
|
+
|
|
|
await Page.insertMany([
|
|
|
{
|
|
|
path: '/parentForRename1',
|
|
|
@@ -290,6 +296,92 @@ describe('PageService', () => {
|
|
|
]);
|
|
|
|
|
|
xssSpy = jest.spyOn(crowi.xss, 'process').mockImplementation(path => path);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * getParentAndFillAncestors
|
|
|
+ */
|
|
|
+ const pageIdPAF1 = new mongoose.Types.ObjectId();
|
|
|
+ const pageIdPAF2 = new mongoose.Types.ObjectId();
|
|
|
+ const pageIdPAF3 = new mongoose.Types.ObjectId();
|
|
|
+
|
|
|
+ await Page.insertMany([
|
|
|
+ {
|
|
|
+ _id: pageIdPAF1,
|
|
|
+ path: '/PAF1',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ creator: dummyUser1,
|
|
|
+ lastUpdateUser: dummyUser1._id,
|
|
|
+ isEmpty: false,
|
|
|
+ parent: rootPage._id,
|
|
|
+ descendantCount: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ _id: pageIdPAF2,
|
|
|
+ path: '/emp_anc3',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ isEmpty: true,
|
|
|
+ descendantCount: 1,
|
|
|
+ parent: rootPage._id,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path: '/emp_anc3/PAF3',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ creator: dummyUser1,
|
|
|
+ lastUpdateUser: dummyUser1._id,
|
|
|
+ isEmpty: false,
|
|
|
+ descendantCount: 0,
|
|
|
+ parent: pageIdPAF2,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ _id: pageIdPAF3,
|
|
|
+ path: '/emp_anc4',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ isEmpty: true,
|
|
|
+ descendantCount: 1,
|
|
|
+ parent: rootPage._id,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path: '/emp_anc4/PAF4',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ creator: dummyUser1,
|
|
|
+ lastUpdateUser: dummyUser1._id,
|
|
|
+ isEmpty: false,
|
|
|
+ descendantCount: 0,
|
|
|
+ parent: pageIdPAF3,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path: '/emp_anc4',
|
|
|
+ grant: Page.GRANT_OWNER,
|
|
|
+ grantedUsers: [dummyUser1._id],
|
|
|
+ creator: dummyUser1,
|
|
|
+ lastUpdateUser: dummyUser1._id,
|
|
|
+ isEmpty: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path: '/get_parent_A',
|
|
|
+ creator: dummyUser1,
|
|
|
+ lastUpdateUser: dummyUser1,
|
|
|
+ parent: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path: '/get_parent_A/get_parent_B',
|
|
|
+ creator: dummyUser1,
|
|
|
+ lastUpdateUser: dummyUser1,
|
|
|
+ parent: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path: '/get_parent_C',
|
|
|
+ creator: dummyUser1,
|
|
|
+ lastUpdateUser: dummyUser1,
|
|
|
+ parent: rootPage._id,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ path: '/get_parent_C/get_parent_D',
|
|
|
+ creator: dummyUser1,
|
|
|
+ lastUpdateUser: dummyUser1,
|
|
|
+ parent: null,
|
|
|
+ },
|
|
|
+ ]);
|
|
|
});
|
|
|
|
|
|
describe('rename page without using renameDescendantsWithStreamSpy', () => {
|
|
|
@@ -723,4 +815,182 @@ describe('PageService', () => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
+ describe('getParentAndFillAncestors', () => {
|
|
|
+ test('return parent if exist', async() => {
|
|
|
+ const page1 = await Page.findOne({ path: '/PAF1' });
|
|
|
+ const parent = await crowi.pageService.getParentAndFillAncestorsByUser(dummyUser1, page1.path);
|
|
|
+ expect(parent).toBeTruthy();
|
|
|
+ expect(page1.parent).toStrictEqual(parent._id);
|
|
|
+ });
|
|
|
+ test('create parent and ancestors when they do not exist, and return the new parent', async() => {
|
|
|
+ const path1 = '/emp_anc1';
|
|
|
+ const path2 = '/emp_anc1/emp_anc2';
|
|
|
+ const path3 = '/emp_anc1/emp_anc2/PAF2';
|
|
|
+ const _page1 = await Page.findOne({ path: path1 }); // not exist
|
|
|
+ const _page2 = await Page.findOne({ path: path2 }); // not exist
|
|
|
+ const _page3 = await Page.findOne({ path: path3 }); // not exist
|
|
|
+ expect(_page1).toBeNull();
|
|
|
+ expect(_page2).toBeNull();
|
|
|
+ expect(_page3).toBeNull();
|
|
|
+
|
|
|
+ const parent = await crowi.pageService.getParentAndFillAncestorsByUser(dummyUser1, path3);
|
|
|
+ const page1 = await Page.findOne({ path: path1 });
|
|
|
+ const page2 = await Page.findOne({ path: path2 });
|
|
|
+ const page3 = await Page.findOne({ path: path3 });
|
|
|
+
|
|
|
+ expect(parent._id).toStrictEqual(page2._id);
|
|
|
+ expect(parent.path).toStrictEqual(page2.path);
|
|
|
+ expect(parent.parent).toStrictEqual(page2.parent);
|
|
|
+
|
|
|
+ expect(parent).toBeTruthy();
|
|
|
+ expect(page1).toBeTruthy();
|
|
|
+ expect(page2).toBeTruthy();
|
|
|
+ expect(page3).toBeNull();
|
|
|
+
|
|
|
+ expect(page1.parent).toStrictEqual(rootPage._id);
|
|
|
+ expect(page2.parent).toStrictEqual(page1._id);
|
|
|
+ });
|
|
|
+ test('return parent even if the parent page is empty', async() => {
|
|
|
+ const path1 = '/emp_anc3';
|
|
|
+ const path2 = '/emp_anc3/PAF3';
|
|
|
+ const _page1 = await Page.findOne({ path: path1, isEmpty: true });
|
|
|
+ const _page2 = await Page.findOne({ path: path2, isEmpty: false });
|
|
|
+ expect(_page1).toBeTruthy();
|
|
|
+ expect(_page2).toBeTruthy();
|
|
|
+
|
|
|
+ const parent = await crowi.pageService.getParentAndFillAncestorsByUser(dummyUser1, _page2.path);
|
|
|
+ const page1 = await Page.findOne({ path: path1, isEmpty: true }); // parent
|
|
|
+ const page2 = await Page.findOne({ path: path2, isEmpty: false });
|
|
|
+
|
|
|
+ // check for the parent (should be the same as page1)
|
|
|
+ expect(parent._id).toStrictEqual(page1._id);
|
|
|
+ expect(parent.path).toStrictEqual(page1.path);
|
|
|
+ expect(parent.parent).toStrictEqual(page1.parent);
|
|
|
+
|
|
|
+ expect(page1.parent).toStrictEqual(rootPage._id);
|
|
|
+ expect(page2.parent).toStrictEqual(page1._id);
|
|
|
+ });
|
|
|
+ test('should find parent while NOT updating private legacy page\'s parent', async() => {
|
|
|
+ const path1 = '/emp_anc4';
|
|
|
+ const path2 = '/emp_anc4/PAF4';
|
|
|
+ const _page1 = await Page.findOne({ path: path1, isEmpty: true, grant: Page.GRANT_PUBLIC });
|
|
|
+ const _page2 = await Page.findOne({ path: path2, isEmpty: false, grant: Page.GRANT_PUBLIC });
|
|
|
+ const _page3 = await Page.findOne({ path: path1, isEmpty: false, grant: Page.GRANT_OWNER });
|
|
|
+ expect(_page1).toBeTruthy();
|
|
|
+ expect(_page2).toBeTruthy();
|
|
|
+ expect(_page3).toBeTruthy();
|
|
|
+ expect(_page3.parent).toBeNull();
|
|
|
+
|
|
|
+ const parent = await crowi.pageService.getParentAndFillAncestorsByUser(dummyUser1, _page2.path);
|
|
|
+ const page1 = await Page.findOne({ path: path1, isEmpty: true, grant: Page.GRANT_PUBLIC });
|
|
|
+ const page2 = await Page.findOne({ path: path2, isEmpty: false, grant: Page.GRANT_PUBLIC });
|
|
|
+ const page3 = await Page.findOne({ path: path1, isEmpty: false, grant: Page.GRANT_OWNER });
|
|
|
+ expect(page1).toBeTruthy();
|
|
|
+ expect(page2).toBeTruthy();
|
|
|
+ expect(page3).toBeTruthy();
|
|
|
+ expect(page3.parent).toBeNull(); // parent property of page in private legacy pages should be null
|
|
|
+
|
|
|
+ expect(page1._id).toStrictEqual(parent._id);
|
|
|
+ expect(page2.parent).toStrictEqual(parent._id);
|
|
|
+
|
|
|
+ });
|
|
|
+ test('should find parent while NOT creating unnecessary empty pages with all v4 public pages', async() => {
|
|
|
+ // All pages does not have parent (v4 schema)
|
|
|
+ const _pageA = await Page.findOne({
|
|
|
+ path: '/get_parent_A',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ isEmpty: false,
|
|
|
+ parent: null,
|
|
|
+ });
|
|
|
+ const _pageAB = await Page.findOne({
|
|
|
+ path: '/get_parent_A/get_parent_B',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ isEmpty: false,
|
|
|
+ parent: null,
|
|
|
+ });
|
|
|
+ const _emptyA = await Page.findOne({
|
|
|
+ path: '/get_parent_A',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ isEmpty: true,
|
|
|
+ });
|
|
|
+ const _emptyAB = await Page.findOne({
|
|
|
+ path: '/get_parent_A/get_parent_B',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ isEmpty: true,
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(_pageA).not.toBeNull();
|
|
|
+ expect(_pageAB).not.toBeNull();
|
|
|
+ expect(_emptyA).toBeNull();
|
|
|
+ expect(_emptyAB).toBeNull();
|
|
|
+
|
|
|
+ const parent = await crowi.pageService.getParentAndFillAncestorsByUser(dummyUser1, '/get_parent_A/get_parent_B/get_parent_C');
|
|
|
+
|
|
|
+ const pageA = await Page.findOne({ path: '/get_parent_A', grant: Page.GRANT_PUBLIC, isEmpty: false });
|
|
|
+ const pageAB = await Page.findOne({ path: '/get_parent_A/get_parent_B', grant: Page.GRANT_PUBLIC, isEmpty: false });
|
|
|
+ const emptyA = await Page.findOne({ path: '/get_parent_A', grant: Page.GRANT_PUBLIC, isEmpty: true });
|
|
|
+ const emptyAB = await Page.findOne({ path: '/get_parent_A/get_parent_B', grant: Page.GRANT_PUBLIC, isEmpty: true });
|
|
|
+
|
|
|
+ // -- Check existance
|
|
|
+ expect(parent).not.toBeNull();
|
|
|
+ expect(pageA).not.toBeNull();
|
|
|
+ expect(pageAB).not.toBeNull();
|
|
|
+ expect(emptyA).toBeNull();
|
|
|
+ expect(emptyAB).toBeNull();
|
|
|
+
|
|
|
+ // -- Check parent
|
|
|
+ expect(pageA.parent).not.toBeNull();
|
|
|
+ expect(pageAB.parent).not.toBeNull();
|
|
|
+ });
|
|
|
+ test('should find parent while NOT creating unnecessary empty pages with some v5 public pages', async() => {
|
|
|
+ const _pageC = await Page.findOne({
|
|
|
+ path: '/get_parent_C',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ isEmpty: false,
|
|
|
+ parent: { $ne: null },
|
|
|
+ });
|
|
|
+ const _pageCD = await Page.findOne({
|
|
|
+ path: '/get_parent_C/get_parent_D',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ isEmpty: false,
|
|
|
+ });
|
|
|
+ const _emptyC = await Page.findOne({
|
|
|
+ path: '/get_parent_C',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ isEmpty: true,
|
|
|
+ });
|
|
|
+ const _emptyCD = await Page.findOne({
|
|
|
+ path: '/get_parent_C/get_parent_D',
|
|
|
+ grant: Page.GRANT_PUBLIC,
|
|
|
+ isEmpty: true,
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(_pageC).not.toBeNull();
|
|
|
+ expect(_pageCD).not.toBeNull();
|
|
|
+ expect(_emptyC).toBeNull();
|
|
|
+ expect(_emptyCD).toBeNull();
|
|
|
+
|
|
|
+ const parent = await crowi.pageService.getParentAndFillAncestorsByUser(dummyUser1, '/get_parent_C/get_parent_D/get_parent_E');
|
|
|
+
|
|
|
+ const pageC = await Page.findOne({ path: '/get_parent_C', grant: Page.GRANT_PUBLIC, isEmpty: false });
|
|
|
+ const pageCD = await Page.findOne({ path: '/get_parent_C/get_parent_D', grant: Page.GRANT_PUBLIC, isEmpty: false });
|
|
|
+ const emptyC = await Page.findOne({ path: '/get_parent_C', grant: Page.GRANT_PUBLIC, isEmpty: true });
|
|
|
+ const emptyCD = await Page.findOne({ path: '/get_parent_C/get_parent_D', grant: Page.GRANT_PUBLIC, isEmpty: true });
|
|
|
+
|
|
|
+ // -- Check existance
|
|
|
+ expect(parent).not.toBeNull();
|
|
|
+ expect(pageC).not.toBeNull();
|
|
|
+ expect(pageCD).not.toBeNull();
|
|
|
+ expect(emptyC).toBeNull();
|
|
|
+ expect(emptyCD).toBeNull();
|
|
|
+
|
|
|
+ // -- Check parent attribute
|
|
|
+ expect(pageC.parent).toStrictEqual(rootPage._id);
|
|
|
+ expect(pageCD.parent).toStrictEqual(pageC._id);
|
|
|
+
|
|
|
+ // -- Check the found parent
|
|
|
+ expect(parent.toObject()).toStrictEqual(pageCD.toObject());
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
});
|