UNPKG

18.8 kBJavaScriptView Raw
1var t = require('../test-lib/test.js');
2var assert = require('assert');
3var _ = require('@sailshq/lodash');
4var request = require('request');
5var Promise = require('bluebird');
6var apos;
7var homeId;
8
9describe('Pages', function() {
10
11 this.timeout(t.timeout);
12
13 after(function(done) {
14 return t.destroy(apos, done);
15 });
16
17 // EXISTENCE
18
19 it('should be a property of the apos object', function(done) {
20 apos = require('../index.js')({
21 root: module,
22 shortName: 'test',
23
24 modules: {
25 'apostrophe-express': {
26 secret: 'xxx',
27 port: 7900
28 },
29 'apostrophe-pages': {
30 park: [],
31 types: [
32 {
33 name: 'home',
34 label: 'Home'
35 },
36 {
37 name: 'testPage',
38 label: 'Test Page'
39 }
40 ]
41 }
42 },
43 afterInit: function(callback) {
44 assert(apos.pages);
45 apos.argv._ = [];
46 return callback(null);
47 },
48 afterListen: function(err) {
49 assert(!err);
50 done();
51 }
52 });
53 });
54
55 // SETUP
56
57 it('should make sure all of the expected indexes are configured', function(done) {
58 var expectedIndexes = ['path'];
59 var actualIndexes = [];
60
61 apos.docs.db.indexInformation(function(err, info) {
62 assert(!err);
63
64 // Extract the actual index info we care about
65 _.each(info, function(index) {
66 actualIndexes.push(index[0][0]);
67 });
68
69 // Now make sure everything in expectedIndexes is in actualIndexes
70 _.each(expectedIndexes, function(index) {
71 assert(_.contains(actualIndexes, index));
72 });
73
74 done();
75 });
76 });
77
78 it('parked homepage exists', function(done) {
79 return apos.pages.find(apos.tasks.getAnonReq(), { level: 0 }).toObject(function(err, home) {
80 assert(!err);
81 assert(home);
82 homeId = home._id;
83 assert(home.slug === '/');
84 assert(home.path === '/');
85 assert(home.type === 'home');
86 assert(home.parked);
87 assert(home.published);
88 done();
89 });
90 });
91
92 it('parked trash can exists', function(done) {
93 return apos.pages.find(apos.tasks.getReq(), { slug: '/trash' }).published(null).trash(null).toObject(function(err, trash) {
94 assert(!err);
95 assert(trash);
96 assert(trash.slug === '/trash');
97 assert(trash.path === '/trash');
98 assert(trash.type === 'trash');
99 assert(trash.parked);
100 assert(!trash.published);
101 // Verify that clonePermanent did its
102 // job and removed properties not meant
103 // to be stored in mongodb
104 assert(!trash._children);
105 done();
106 });
107 });
108
109 it('should be able to use db to insert documents', function(done) {
110 var testItems = [
111 { _id: '1234',
112 type: 'testPage',
113 slug: '/parent',
114 published: true,
115 path: '/parent',
116 level: 1,
117 rank: 0
118 },
119 {
120 _id: '2341',
121 type: 'testPage',
122 slug: '/child',
123 published: true,
124 path: '/parent/child',
125 level: 2,
126 rank: 0
127 },
128 {
129 _id: '4123',
130 type: 'testPage',
131 slug: '/grandchild',
132 published: true,
133 path: '/parent/child/grandchild',
134 level: 3,
135 rank: 0
136 },
137 {
138 _id: '4321',
139 type: 'testPage',
140 slug: '/sibling',
141 published: true,
142 path: '/parent/sibling',
143 level: 2,
144 rank: 1
145
146 },
147 {
148 _id: '4312',
149 type: 'testPage',
150 slug: '/cousin',
151 published: true,
152 path: '/parent/sibling/cousin',
153 level: 3,
154 rank: 0
155 },
156 {
157 _id: '4333',
158 type: 'testPage',
159 slug: '/another-parent',
160 published: true,
161 path: '/another-parent',
162 level: 1,
163 rank: 0
164 }
165 ];
166
167 apos.docs.db.insert(testItems, function(err) {
168 assert(!err);
169 done();
170 });
171
172 });
173
174 // FINDING
175
176 it('should have a find method on pages that returns a cursor', function() {
177 var cursor = apos.pages.find(apos.tasks.getAnonReq());
178 assert(cursor);
179 });
180
181 it('should be able to find the parked homepage', function(done) {
182 var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/' });
183
184 cursor.toObject(function(err, page) {
185 assert(!err);
186 // There should be only 1 result.
187 assert(page);
188 // It should have a path of /
189 assert(page.path === '/');
190 assert(page.rank === 0);
191 done();
192 });
193 });
194
195 it('should be able to find just a single page', function(done) {
196 var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/child' });
197
198 cursor.toObject(function(err, page) {
199 assert(!err);
200 // There should be only 1 result.
201 assert(page);
202 // It should have a path of /parent/child
203 assert(page.path === '/parent/child');
204 done();
205 });
206 });
207
208 it('should be able to include the ancestors of a page', function(done) {
209 var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/child' });
210
211 cursor.ancestors(true).toObject(function(err, page) {
212 assert(!err);
213 // There should be only 1 result.
214 assert(page);
215 // There should be 2 ancestors.
216 assert(page._ancestors.length === 2);
217 // The first ancestor should be the homepage
218 assert.equal(page._ancestors[0].path, '/');
219 // The second ancestor should be 'parent'
220 assert.equal(page._ancestors[1].path, '/parent');
221 done();
222 });
223 });
224
225 it('should be able to include just one ancestor of a page, i.e. the parent', function(done) {
226 var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/child' });
227
228 cursor.ancestors({ depth: 1 }).toObject(function(err, page) {
229 assert(!err);
230 // There should be only 1 result.
231 assert(page);
232 // There should be 1 ancestor returned.
233 assert(page._ancestors.length === 1);
234 // The first ancestor returned should be 'parent'
235 assert.equal(page._ancestors[0].path, '/parent');
236 done();
237 });
238 });
239
240 it('should be able to include the children of the ancestors of a page', function(done) {
241 var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/child' });
242
243 cursor.ancestors({children: 1}).toObject(function(err, page) {
244 assert(!err);
245 // There should be only 1 result.
246 assert(page);
247 // There should be 2 ancestors.
248 assert(page._ancestors.length === 2);
249 // The second ancestor should have children
250 assert(page._ancestors[1]._children);
251 // The first ancestor's child should have a path '/parent/child'
252 assert.equal(page._ancestors[1]._children[0].path, '/parent/child');
253 // The second ancestor's child should have a path '/parent/sibling'
254 assert.equal(page._ancestors[1]._children[1].path, '/parent/sibling');
255 done();
256 });
257 });
258
259 // INSERTING
260
261 it('is able to insert a new page', function(done) {
262 var parentId = '1234';
263
264 var newPage = {
265 slug: '/new-page',
266 published: true,
267 type: 'testPage',
268 title: 'New Page'
269 };
270 apos.pages.insert(apos.tasks.getReq(), parentId, newPage, function(err, page) {
271 // did it return an error?
272 assert(!err);
273 // Is the path generally correct?
274 assert.equal(page.path, '/parent/new-page');
275 done();
276 });
277 });
278
279 it('is able to insert a new page in the correct order', function(done) {
280 var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/new-page' });
281
282 cursor.toObject(function(err, page) {
283 assert(!err);
284 assert(page);
285 assert.equal(page.rank, 2);
286 done();
287 });
288 });
289
290 // INSERTING
291
292 it('is able to insert a new page with promises', function(done) {
293 var parentId = '1234';
294
295 var newPage = {
296 slug: '/new-page-2',
297 published: true,
298 type: 'testPage',
299 title: 'New Page 2'
300 };
301 apos.pages.insert(apos.tasks.getReq(), parentId, newPage).then(function(page) {
302 assert.equal(page.path, '/parent/new-page-2');
303 done();
304 }).catch(function(err) {
305 assert(!err);
306 });
307 });
308
309 it('is able to insert a new page in the correct order with promises', function(done) {
310 var cursor = apos.pages.find(apos.tasks.getAnonReq(), { slug: '/new-page-2' });
311
312 cursor.toObject().then(function(page) {
313 assert.equal(page.rank, 3);
314 done();
315 }).catch(function(err) {
316 assert(!err);
317 });
318 });
319
320 // MOVING
321
322 it('is able to move root/parent/sibling/cousin after root/parent', function(done) {
323 // 'Cousin' _id === 4312
324 // 'Parent' _id === 1234
325 apos.pages.move(apos.tasks.getReq(), '4312', '1234', 'after', function(err) {
326 if (err) {
327 console.log(err);
328 }
329 assert(!err);
330 var cursor = apos.pages.find(apos.tasks.getAnonReq(), {_id: '4312'});
331 cursor.toObject(function(err, page) {
332 if (err) {
333 console.log(err);
334 }
335 assert(!err);
336 // Is the new path correct?
337 assert.equal(page.path, '/cousin');
338 // Is the rank correct?
339 assert.equal(page.rank, 1);
340 return done();
341 });
342 });
343
344 });
345
346 it('is able to move root/cousin before root/parent/child', function(done) {
347 // 'Cousin' _id === 4312
348 // 'Child' _id === 2341
349 apos.pages.move(apos.tasks.getReq(), '4312', '2341', 'before', function(err) {
350 if (err) {
351 console.log(err);
352 }
353 assert(!err);
354 var cursor = apos.pages.find(apos.tasks.getAnonReq(), {_id: '4312'});
355 cursor.toObject(function(err, page) {
356 if (err) {
357 console.log(err);
358 }
359 assert(!err);
360 // Is the new path correct?
361 assert.equal(page.path, '/parent/cousin');
362 // Is the rank correct?
363 assert.equal(page.rank, 0);
364 return done();
365 });
366 });
367 });
368
369 it('is able to move root/parent/cousin inside root/parent/sibling', function(done) {
370 // 'Cousin' _id === 4312
371 // 'Sibling' _id === 4321
372 apos.pages.move(apos.tasks.getReq(), '4312', '4321', 'inside', function(err) {
373 if (err) {
374 console.log(err);
375 }
376 assert(!err);
377 var cursor = apos.pages.find(apos.tasks.getAnonReq(), {_id: '4312'});
378 cursor.toObject(function(err, page) {
379 if (err) {
380 console.log(err);
381 }
382 assert(!err);
383 // Is the new path correct?
384 assert.equal(page.path, '/parent/sibling/cousin');
385 // Is the rank correct?
386 assert.equal(page.rank, 0);
387 return done();
388 });
389 });
390
391 });
392
393 it('moving /parent into /another-parent should also move /parent/sibling', function(done) {
394 apos.pages.move(apos.tasks.getReq(), '1234', '4333', 'inside', function(err) {
395 if (err) {
396 console.log(err);
397 }
398 assert(!err);
399 var cursor = apos.pages.find(apos.tasks.getAnonReq(), {_id: '4321'});
400 cursor.toObject(function(err, page) {
401 if (err) {
402 console.log(err);
403 }
404 assert(!err);
405 // Is the grandchild's path correct?
406 assert.equal(page.path, '/another-parent/parent/sibling');
407 return done();
408 });
409 });
410
411 });
412
413 it('should be able to serve a page', function(done) {
414 return request('http://localhost:7900/child', function(err, response, body) {
415 assert(!err);
416 // Is our status code good?
417 assert.equal(response.statusCode, 200);
418 // Did we get our page back?
419 assert(body.match(/Sing to me, Oh Muse./));
420 // Does the response prove that data.home was available?
421 assert(body.match(/Home: \//));
422 // Does the response prove that data.home._children was available?
423 assert(body.match(/Tab: \/another-parent/));
424 // console.log(body);
425 return done();
426 });
427 });
428
429 it('should not be able to serve a nonexistent page', function(done) {
430 return request('http://localhost:7900/nobodyschild', function(err, response, body) {
431 assert(!err);
432 // Is our status code good?
433 assert.equal(response.statusCode, 404);
434 // Does the response prove that data.home was available?
435 assert(body.match(/Home: \//));
436 // Does the response prove that data.home._children was available?
437 assert(body.match(/Tab: \/another-parent/));
438 // console.log(body);
439 return done();
440 });
441 });
442
443 it('should detect that the home page is an ancestor of any page except itself', function() {
444 assert(
445 apos.pages.isAncestorOf({
446 path: '/'
447 }, {
448 path: '/about'
449 }
450 )
451 );
452 assert(
453 apos.pages.isAncestorOf({
454 path: '/'
455 }, {
456 path: '/about/grandkid'
457 }
458 )
459 );
460 assert(!apos.pages.isAncestorOf({
461 path: '/'
462 }, {
463 path: '/'
464 }));
465 });
466
467 it('should detect a tab as the ancestor of its great grandchild but not someone else\'s', function() {
468 assert(
469 apos.pages.isAncestorOf({
470 path: '/about'
471 }, {
472 path: '/about/test/thing'
473 }
474 )
475 );
476
477 assert(
478 !apos.pages.isAncestorOf({
479 path: '/about'
480 }, {
481 path: '/wiggy/test/thing'
482 }
483 )
484 );
485
486 });
487
488 it('is able to move parent to the trash', function(done) {
489 apos.pages.moveToTrash(apos.tasks.getReq(), '1234', function(err) {
490 if (err) {
491 console.error(err);
492 }
493 assert(!err);
494 var cursor = apos.pages.find(apos.tasks.getAnonReq(), {_id: '1234'});
495 cursor.toObject(function(err, page) {
496 if (err) {
497 console.log(err);
498 }
499 assert(!err);
500 assert(!page);
501 apos.pages.find(apos.tasks.getAnonReq(), { _id: '1234' })
502 .permission(false).trash(null).toObject(function(err, page) {
503 assert(!err);
504 assert.equal(page.path, '/trash/parent');
505 assert(page.trash);
506 assert.equal(page.level, 2);
507 return done();
508 });
509 });
510 });
511 });
512
513 it('is able to insert a new page with the path attempting to follow the slug rather than the title', function(done) {
514 var parentId = homeId;
515
516 var newPage = {
517 slug: '/newish-page',
518 published: true,
519 type: 'testPage',
520 title: 'New Page'
521 };
522 apos.pages.insert(apos.tasks.getReq(), parentId, newPage, function(err, page) {
523 // did it return an error?
524 assert(!err);
525 // Is the path based on the slug rather than the title?
526 assert.equal(page.path, '/newish-page');
527 done();
528 });
529 });
530
531});
532
533describe('Pages with trashInSchema', function() {
534
535 this.timeout(t.timeout);
536
537 after(function(done) {
538 return t.destroy(apos, done);
539 });
540
541 // EXISTENCE
542
543 it('should be a property of the apos object', function(done) {
544 apos = require('../index.js')({
545 root: module,
546 shortName: 'test2',
547
548 modules: {
549 'apostrophe-express': {
550 secret: 'xxx',
551 port: 7901
552 },
553 'apostrophe-docs': {
554 trashInSchema: true
555 },
556 'apostrophe-pages': {
557 park: [],
558 types: [
559 {
560 name: 'home',
561 label: 'Home'
562 },
563 {
564 name: 'testPage',
565 label: 'Test Page'
566 }
567 ]
568 }
569 },
570 afterInit: function(callback) {
571 assert(apos.pages);
572 apos.argv._ = [];
573 return callback(null);
574 },
575 afterListen: function(err) {
576 assert(!err);
577 done();
578 }
579 });
580 });
581
582 it('should be able to use db to insert documents', function(done) {
583 var testItems = [
584 { _id: 'p1',
585 type: 'testPage',
586 slug: '/parent1',
587 path: '/parent1',
588 published: true,
589 level: 1,
590 rank: 0
591 },
592 {
593 _id: 'p1c1',
594 type: 'testPage',
595 slug: '/parent1/child1',
596 path: '/parent1/child1',
597 published: true,
598 level: 2,
599 rank: 0
600 },
601 { _id: 'p2',
602 type: 'testPage',
603 slug: '/parent2',
604 path: '/parent2',
605 published: true,
606 level: 1,
607 rank: 0
608 },
609 {
610 _id: 'p2c2',
611 type: 'testPage',
612 slug: '/parent2/child2',
613 path: '/parent2/child2',
614 published: true,
615 level: 2,
616 rank: 0,
617 trash: true
618 }
619 ];
620
621 apos.docs.db.insert(testItems, function(err) {
622 assert(!err);
623 done();
624 });
625
626 });
627
628 // MOVING
629
630 it('is able to move p2 inside p1', function(done) {
631 // 'Cousin' _id === 4312
632 // 'Parent' _id === 1234
633 apos.pages.move(apos.tasks.getReq(), 'p2', 'p1', 'inside', function(err) {
634 if (err) {
635 console.log(err);
636 }
637 assert(!err);
638 var cursor = apos.pages.find(apos.tasks.getAnonReq(), {_id: 'p2'});
639 cursor.toObject(function(err, page) {
640 if (err) {
641 console.log(err);
642 }
643 assert(!err);
644 // Is the new path correct?
645 assert.equal(page.path, '/parent1/parent2');
646 // Is the new level correct?
647 assert.equal(page.level, 2);
648 return done();
649 });
650 });
651
652 });
653
654 it('p2c2 is now grandchild of p1, but still in trash', function() {
655 return Promise.try(function() {
656 return apos.docs.db.findOne({ _id: 'p2c2' });
657 }).then(function(p2c2) {
658 assert(p2c2.level === 3);
659 assert(p2c2.path === '/parent1/parent2/child2');
660 assert(p2c2.trash);
661 });
662 });
663
664 it('add permissions for a new group to the home page', function() {
665 const req = apos.tasks.getReq();
666 let group;
667 return Promise.try(function() {
668 return apos.groups.insert(req, {
669 title: 'test',
670 permissions: [ 'edit-page' ]
671 });
672 }).then(function(_group) {
673 group = _group;
674 return apos.docs.db.findOne({ slug: '/' });
675 }).then(function(home) {
676 home.editGroupsIds = [ group._id ];
677 const update = Promise.promisify(apos.pages.update);
678 return update(req, home, {});
679 }).then(function() {
680 return apos.docs.db.findOne({ slug: '/' });
681 }).then(function(home) {
682 assert(_.includes(home.docPermissions, 'edit-' + group._id));
683 });
684 });
685
686 it('"apply to subpages": propagate group id to child pages', function() {
687 const req = apos.tasks.getReq();
688 let home;
689 return Promise.try(function() {
690 return apos.docs.db.findOne({ slug: '/' });
691 }).then(function(_home) {
692 home = _home;
693 home.applyToSubpages = true;
694 const update = Promise.promisify(apos.pages.update);
695 return update(req, home, {});
696 }).then(function() {
697 return apos.docs.db.find({ slug: /^\//, trash: { $ne: true } }).toArray();
698 }).then(function(pages) {
699 assert(!_.find(pages, function(page) {
700 return (!_.includes(page.docPermissions, 'edit-' + home.editGroupsIds[0]));
701 }));
702 });
703 });
704});