apostrophe
Version:
The Apostrophe Content Management System.
705 lines (631 loc) • 18.8 kB
JavaScript
var t = require('../test-lib/test.js');
var assert = require('assert');
var _ = require('@sailshq/lodash');
var request = require('request');
var Promise = require('bluebird');
var apos;
var homeId;
describe('Pages', function() {
this.timeout(t.timeout);
after(function(done) {
return t.destroy(apos, done);
});
// EXISTENCE
it('should be a property of the apos object', function(done) {
apos = require('../index.js')({
root: module,
shortName: 'test',
modules: {
'apostrophe-express': {
secret: 'xxx',
port: 7900
},
'apostrophe-pages': {
park: [],
types: [
{
name: 'home',
label: 'Home'
},
{
name: 'testPage',
label: 'Test Page'
}
]
}
},
afterInit: function(callback) {
assert(apos.pages);
apos.argv._ = [];
return callback(null);
},
afterListen: function(err) {
assert(!err);
done();
}
});
});
// SETUP
it('should make sure all of the expected indexes are configured', function(done) {
var expectedIndexes = ['path'];
var actualIndexes = [];
apos.docs.db.indexInformation(function(err, info) {
assert(!err);
// Extract the actual index info we care about
_.each(info, function(index) {
actualIndexes.push(index[0][0]);
});
// Now make sure everything in expectedIndexes is in actualIndexes
_.each(expectedIndexes, function(index) {
assert(_.contains(actualIndexes, index));
});
done();
});
});
it('parked homepage exists', function(done) {
return apos.pages.find(apos.tasks.getAnonReq(), { level: 0 }).toObject(function(err, home) {
assert(!err);
assert(home);
homeId = home._id;
assert(home.slug === '/');
assert(home.path === '/');
assert(home.type === 'home');
assert(home.parked);
assert(home.published);
done();
});
});
it('parked trash can exists', function(done) {
return apos.pages.find(apos.tasks.getReq(), { slug: '/trash' }).published(null).trash(null).toObject(function(err, trash) {
assert(!err);
assert(trash);
assert(trash.slug === '/trash');
assert(trash.path === '/trash');
assert(trash.type === 'trash');
assert(trash.parked);
assert(!trash.published);
// Verify that clonePermanent did its
// job and removed properties not meant
// to be stored in mongodb
assert(!trash._children);
done();
});
});
it('should be able to use db to insert documents', function(done) {
var testItems = [
{ _id: '1234',
type: 'testPage',
slug: '/parent',
published: true,
path: '/parent',
level: 1,
rank: 0
},
{
_id: '2341',
type: 'testPage',
slug: '/child',
published: true,
path: '/parent/child',
level: 2,
rank: 0
},
{
_id: '4123',
type: 'testPage',
slug: '/grandchild',
published: true,
path: '/parent/child/grandchild',
level: 3,
rank: 0
},
{
_id: '4321',
type: 'testPage',
slug: '/sibling',
published: true,
path: '/parent/sibling',
level: 2,
rank: 1
},
{
_id: '4312',
type: 'testPage',
slug: '/cousin',
published: true,
path: '/parent/sibling/cousin',
level: 3,
rank: 0
},
{
_id: '4333',
type: 'testPage',
slug: '/another-parent',
published: true,
path: '/another-parent',
level: 1,
rank: 0
}
];
apos.docs.db.insert(testItems, function(err) {
assert(!err);
done();
});
});
// FINDING
it('should have a find method on pages that returns a cursor', function() {
var cursor = apos.pages.find(apos.tasks.getAnonReq());
assert(cursor);
});
it('should be able to find the parked homepage', function(done) {
var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/' });
cursor.toObject(function(err, page) {
assert(!err);
// There should be only 1 result.
assert(page);
// It should have a path of /
assert(page.path === '/');
assert(page.rank === 0);
done();
});
});
it('should be able to find just a single page', function(done) {
var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/child' });
cursor.toObject(function(err, page) {
assert(!err);
// There should be only 1 result.
assert(page);
// It should have a path of /parent/child
assert(page.path === '/parent/child');
done();
});
});
it('should be able to include the ancestors of a page', function(done) {
var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/child' });
cursor.ancestors(true).toObject(function(err, page) {
assert(!err);
// There should be only 1 result.
assert(page);
// There should be 2 ancestors.
assert(page._ancestors.length === 2);
// The first ancestor should be the homepage
assert.equal(page._ancestors[0].path, '/');
// The second ancestor should be 'parent'
assert.equal(page._ancestors[1].path, '/parent');
done();
});
});
it('should be able to include just one ancestor of a page, i.e. the parent', function(done) {
var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/child' });
cursor.ancestors({ depth: 1 }).toObject(function(err, page) {
assert(!err);
// There should be only 1 result.
assert(page);
// There should be 1 ancestor returned.
assert(page._ancestors.length === 1);
// The first ancestor returned should be 'parent'
assert.equal(page._ancestors[0].path, '/parent');
done();
});
});
it('should be able to include the children of the ancestors of a page', function(done) {
var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/child' });
cursor.ancestors({children: 1}).toObject(function(err, page) {
assert(!err);
// There should be only 1 result.
assert(page);
// There should be 2 ancestors.
assert(page._ancestors.length === 2);
// The second ancestor should have children
assert(page._ancestors[1]._children);
// The first ancestor's child should have a path '/parent/child'
assert.equal(page._ancestors[1]._children[0].path, '/parent/child');
// The second ancestor's child should have a path '/parent/sibling'
assert.equal(page._ancestors[1]._children[1].path, '/parent/sibling');
done();
});
});
// INSERTING
it('is able to insert a new page', function(done) {
var parentId = '1234';
var newPage = {
slug: '/new-page',
published: true,
type: 'testPage',
title: 'New Page'
};
apos.pages.insert(apos.tasks.getReq(), parentId, newPage, function(err, page) {
// did it return an error?
assert(!err);
// Is the path generally correct?
assert.equal(page.path, '/parent/new-page');
done();
});
});
it('is able to insert a new page in the correct order', function(done) {
var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/new-page' });
cursor.toObject(function(err, page) {
assert(!err);
assert(page);
assert.equal(page.rank, 2);
done();
});
});
// INSERTING
it('is able to insert a new page with promises', function(done) {
var parentId = '1234';
var newPage = {
slug: '/new-page-2',
published: true,
type: 'testPage',
title: 'New Page 2'
};
apos.pages.insert(apos.tasks.getReq(), parentId, newPage).then(function(page) {
assert.equal(page.path, '/parent/new-page-2');
done();
}).catch(function(err) {
assert(!err);
});
});
it('is able to insert a new page in the correct order with promises', function(done) {
var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/new-page-2' });
cursor.toObject().then(function(page) {
assert.equal(page.rank, 3);
done();
}).catch(function(err) {
assert(!err);
});
});
// MOVING
it('is able to move root/parent/sibling/cousin after root/parent', function(done) {
// 'Cousin' _id === 4312
// 'Parent' _id === 1234
apos.pages.move(apos.tasks.getReq(), '4312', '1234', 'after', function(err) {
if (err) {
console.log(err);
}
assert(!err);
var cursor = apos.pages.find(apos.tasks.getAnonReq(), {_id: '4312'});
cursor.toObject(function(err, page) {
if (err) {
console.log(err);
}
assert(!err);
// Is the new path correct?
assert.equal(page.path, '/cousin');
// Is the rank correct?
assert.equal(page.rank, 1);
return done();
});
});
});
it('is able to move root/cousin before root/parent/child', function(done) {
// 'Cousin' _id === 4312
// 'Child' _id === 2341
apos.pages.move(apos.tasks.getReq(), '4312', '2341', 'before', function(err) {
if (err) {
console.log(err);
}
assert(!err);
var cursor = apos.pages.find(apos.tasks.getAnonReq(), {_id: '4312'});
cursor.toObject(function(err, page) {
if (err) {
console.log(err);
}
assert(!err);
// Is the new path correct?
assert.equal(page.path, '/parent/cousin');
// Is the rank correct?
assert.equal(page.rank, 0);
return done();
});
});
});
it('is able to move root/parent/cousin inside root/parent/sibling', function(done) {
// 'Cousin' _id === 4312
// 'Sibling' _id === 4321
apos.pages.move(apos.tasks.getReq(), '4312', '4321', 'inside', function(err) {
if (err) {
console.log(err);
}
assert(!err);
var cursor = apos.pages.find(apos.tasks.getAnonReq(), {_id: '4312'});
cursor.toObject(function(err, page) {
if (err) {
console.log(err);
}
assert(!err);
// Is the new path correct?
assert.equal(page.path, '/parent/sibling/cousin');
// Is the rank correct?
assert.equal(page.rank, 0);
return done();
});
});
});
it('moving /parent into /another-parent should also move /parent/sibling', function(done) {
apos.pages.move(apos.tasks.getReq(), '1234', '4333', 'inside', function(err) {
if (err) {
console.log(err);
}
assert(!err);
var cursor = apos.pages.find(apos.tasks.getAnonReq(), {_id: '4321'});
cursor.toObject(function(err, page) {
if (err) {
console.log(err);
}
assert(!err);
// Is the grandchild's path correct?
assert.equal(page.path, '/another-parent/parent/sibling');
return done();
});
});
});
it('should be able to serve a page', function(done) {
return request('http://localhost:7900/child', function(err, response, body) {
assert(!err);
// Is our status code good?
assert.equal(response.statusCode, 200);
// Did we get our page back?
assert(body.match(/Sing to me, Oh Muse./));
// Does the response prove that data.home was available?
assert(body.match(/Home: \//));
// Does the response prove that data.home._children was available?
assert(body.match(/Tab: \/another-parent/));
// console.log(body);
return done();
});
});
it('should not be able to serve a nonexistent page', function(done) {
return request('http://localhost:7900/nobodyschild', function(err, response, body) {
assert(!err);
// Is our status code good?
assert.equal(response.statusCode, 404);
// Does the response prove that data.home was available?
assert(body.match(/Home: \//));
// Does the response prove that data.home._children was available?
assert(body.match(/Tab: \/another-parent/));
// console.log(body);
return done();
});
});
it('should detect that the home page is an ancestor of any page except itself', function() {
assert(
apos.pages.isAncestorOf({
path: '/'
}, {
path: '/about'
}
)
);
assert(
apos.pages.isAncestorOf({
path: '/'
}, {
path: '/about/grandkid'
}
)
);
assert(!apos.pages.isAncestorOf({
path: '/'
}, {
path: '/'
}));
});
it('should detect a tab as the ancestor of its great grandchild but not someone else\'s', function() {
assert(
apos.pages.isAncestorOf({
path: '/about'
}, {
path: '/about/test/thing'
}
)
);
assert(
!apos.pages.isAncestorOf({
path: '/about'
}, {
path: '/wiggy/test/thing'
}
)
);
});
it('is able to move parent to the trash', function(done) {
apos.pages.moveToTrash(apos.tasks.getReq(), '1234', function(err) {
if (err) {
console.error(err);
}
assert(!err);
var cursor = apos.pages.find(apos.tasks.getAnonReq(), {_id: '1234'});
cursor.toObject(function(err, page) {
if (err) {
console.log(err);
}
assert(!err);
assert(!page);
apos.pages.find(apos.tasks.getAnonReq(), { _id: '1234' })
.permission(false).trash(null).toObject(function(err, page) {
assert(!err);
assert.equal(page.path, '/trash/parent');
assert(page.trash);
assert.equal(page.level, 2);
return done();
});
});
});
});
it('is able to insert a new page with the path attempting to follow the slug rather than the title', function(done) {
var parentId = homeId;
var newPage = {
slug: '/newish-page',
published: true,
type: 'testPage',
title: 'New Page'
};
apos.pages.insert(apos.tasks.getReq(), parentId, newPage, function(err, page) {
// did it return an error?
assert(!err);
// Is the path based on the slug rather than the title?
assert.equal(page.path, '/newish-page');
done();
});
});
});
describe('Pages with trashInSchema', function() {
this.timeout(t.timeout);
after(function(done) {
return t.destroy(apos, done);
});
// EXISTENCE
it('should be a property of the apos object', function(done) {
apos = require('../index.js')({
root: module,
shortName: 'test2',
modules: {
'apostrophe-express': {
secret: 'xxx',
port: 7901
},
'apostrophe-docs': {
trashInSchema: true
},
'apostrophe-pages': {
park: [],
types: [
{
name: 'home',
label: 'Home'
},
{
name: 'testPage',
label: 'Test Page'
}
]
}
},
afterInit: function(callback) {
assert(apos.pages);
apos.argv._ = [];
return callback(null);
},
afterListen: function(err) {
assert(!err);
done();
}
});
});
it('should be able to use db to insert documents', function(done) {
var testItems = [
{ _id: 'p1',
type: 'testPage',
slug: '/parent1',
path: '/parent1',
published: true,
level: 1,
rank: 0
},
{
_id: 'p1c1',
type: 'testPage',
slug: '/parent1/child1',
path: '/parent1/child1',
published: true,
level: 2,
rank: 0
},
{ _id: 'p2',
type: 'testPage',
slug: '/parent2',
path: '/parent2',
published: true,
level: 1,
rank: 0
},
{
_id: 'p2c2',
type: 'testPage',
slug: '/parent2/child2',
path: '/parent2/child2',
published: true,
level: 2,
rank: 0,
trash: true
}
];
apos.docs.db.insert(testItems, function(err) {
assert(!err);
done();
});
});
// MOVING
it('is able to move p2 inside p1', function(done) {
// 'Cousin' _id === 4312
// 'Parent' _id === 1234
apos.pages.move(apos.tasks.getReq(), 'p2', 'p1', 'inside', function(err) {
if (err) {
console.log(err);
}
assert(!err);
var cursor = apos.pages.find(apos.tasks.getAnonReq(), {_id: 'p2'});
cursor.toObject(function(err, page) {
if (err) {
console.log(err);
}
assert(!err);
// Is the new path correct?
assert.equal(page.path, '/parent1/parent2');
// Is the new level correct?
assert.equal(page.level, 2);
return done();
});
});
});
it('p2c2 is now grandchild of p1, but still in trash', function() {
return Promise.try(function() {
return apos.docs.db.findOne({ _id: 'p2c2' });
}).then(function(p2c2) {
assert(p2c2.level === 3);
assert(p2c2.path === '/parent1/parent2/child2');
assert(p2c2.trash);
});
});
it('add permissions for a new group to the home page', function() {
const req = apos.tasks.getReq();
let group;
return Promise.try(function() {
return apos.groups.insert(req, {
title: 'test',
permissions: [ 'edit-page' ]
});
}).then(function(_group) {
group = _group;
return apos.docs.db.findOne({ slug: '/' });
}).then(function(home) {
home.editGroupsIds = [ group._id ];
const update = Promise.promisify(apos.pages.update);
return update(req, home, {});
}).then(function() {
return apos.docs.db.findOne({ slug: '/' });
}).then(function(home) {
assert(_.includes(home.docPermissions, 'edit-' + group._id));
});
});
it('"apply to subpages": propagate group id to child pages', function() {
const req = apos.tasks.getReq();
let home;
return Promise.try(function() {
return apos.docs.db.findOne({ slug: '/' });
}).then(function(_home) {
home = _home;
home.applyToSubpages = true;
const update = Promise.promisify(apos.pages.update);
return update(req, home, {});
}).then(function() {
return apos.docs.db.find({ slug: /^\//, trash: { $ne: true } }).toArray();
}).then(function(pages) {
assert(!_.find(pages, function(page) {
return (!_.includes(page.docPermissions, 'edit-' + home.editGroupsIds[0]));
}));
});
});
});