UNPKG

15.6 kBJavaScriptView Raw
1var assert = require('assert');
2var _ = require('@sailshq/lodash');
3var async = require('async');
4var request = require('request');
5var cheerio = require('cheerio');
6var fs = require('fs');
7const get = require('./lib/get');
8
9var parkedPages = [
10 {
11 title: 'Tab One',
12 type: 'default',
13 slug: '/tab-one',
14 _children: [
15 {
16 title: 'Tab One Child One',
17 type: 'default',
18 slug: '/tab-one/child-one'
19 },
20 {
21 title: 'Tab One Child Two',
22 type: 'default',
23 slug: '/tab-one/child-two'
24 },
25 ]
26 },
27 {
28 title: 'Tab Two',
29 type: 'default',
30 slug: '/tab-two',
31 _children: [
32 {
33 title: 'Tab Two Child One',
34 type: 'default',
35 slug: '/tab-two/child-one'
36 },
37 {
38 title: 'Tab Two Child Two',
39 type: 'default',
40 slug: '/tab-two/child-two'
41 },
42 ]
43 },
44 {
45 title: 'Products',
46 type: 'products-page',
47 slug: '/products'
48 }
49];
50
51var parkedPageTypes = [
52 {
53 name: 'home',
54 label: 'Home'
55 },
56 {
57 name: 'default',
58 label: 'Default'
59 },
60 {
61 name: 'products',
62 label: 'Products'
63 }
64];
65
66var workflowLocales = [
67 {
68 name: 'default',
69 private: true,
70 children: [
71 {
72 name: 'fr',
73 label: 'French'
74 },
75 {
76 name: 'en',
77 label: 'English'
78 }
79 ]
80 }
81];
82
83describe('Apostrophe Sitemap: workflow: hostname and prefixes with perLocale', function() {
84
85 var apos;
86
87 this.timeout(5000);
88
89 after(function(done) {
90 try {
91 require('apostrophe/test-lib/util').destroy(apos, done);
92 } catch (e) {
93 console.warn('Old version of apostrophe does not export test-lib/util library, just dropping old test db');
94 apos.db.dropDatabase();
95 setTimeout(done, 1000);
96 }
97 });
98
99 it('perLocale: should be a property of the apos object', function(done) {
100 apos = require('apostrophe')({
101 testModule: true,
102 baseUrl: 'http://localhost:7777',
103 modules: {
104 'apostrophe-express': {
105 port: 7777
106 },
107 'apostrophe-site-map': {
108 perLocale: true
109 },
110 'apostrophe-pages': {
111 park: _.cloneDeep(parkedPages),
112 types: _.cloneDeep(parkedPageTypes)
113 },
114 'products': {
115 extend: 'apostrophe-pieces',
116 name: 'product'
117 },
118 'products-pages': {
119 extend: 'apostrophe-pieces-pages'
120 },
121 'apostrophe-workflow': {
122 locales: _.cloneDeep(workflowLocales),
123 hostnames: {
124 'fr': 'exemple.fr',
125 'default': 'example.com',
126 'en': 'example.com'
127 },
128 prefixes: {
129 // Even private locales must be distinguishable by hostname and/or prefix
130 'default': '/default',
131 'en': '/en'
132 // We don't need prefixes for fr because
133 // that hostname is not shared with other
134 // locales
135 }
136 }
137 },
138 afterInit: function(callback) {
139 assert(apos.modules['apostrophe-site-map']);
140 assert(apos.modules['apostrophe-workflow']);
141 return callback(null);
142 },
143 afterListen: function(err) {
144 done();
145 }
146 });
147 });
148
149 it('insert a product for test purposes', function(done) {
150 var product = _.assign(apos.modules.products.newInstance(), {
151 title: 'Cheese',
152 slug: 'cheese'
153 });
154 apos.modules.products.insert(apos.tasks.getReq(), product, function(err) {
155 assert(!err);
156 done();
157 });
158 });
159
160 it('make sure everything is published and out of the trash for test purposes', function(done) {
161 return apos.docs.db.update({}, {
162 $set: {
163 trash: false,
164 published: true
165 }
166 }, {
167 multi: true
168 }, function(err, count) {
169 assert(!err);
170 done();
171 });
172 });
173
174 it('should generate a suitable sitemap index', function(done) {
175 this.timeout(10000);
176 get('http://localhost:7777/sitemaps/index.xml', function(err, xml) {
177 if (err) {
178 console.error(err);
179 }
180 assert(!err);
181 assert(xml);
182 assert(xml.indexOf('http://localhost:7777/sitemaps/fr.xml') !== -1);
183 assert(xml.indexOf('http://localhost:7777/sitemaps/en.xml') !== -1);
184 assert(xml.indexOf('http://localhost:7777/sitemaps/default.xml') === -1);
185 done();
186 });
187 });
188
189 it('should generate an fr sitemap', function(done) {
190 get('http://localhost:7777/sitemaps/fr.xml', function(err, xml) {
191 assert(!err);
192 assert(xml.indexOf('<loc>http://exemple.fr/</loc>') !== -1);
193 assert(xml.indexOf('<loc>http://exemple.fr/tab-two/child-two</loc>') !== -1);
194 assert(xml.indexOf('<loc>http://exemple.fr/products/cheese</loc>') !== -1);
195 done();
196 });
197 });
198
199 it('should generate an en sitemap', function(done) {
200 get('http://localhost:7777/sitemaps/en.xml', function(err, xml) {
201 assert(!err);
202 assert(xml);
203 assert(xml.indexOf('<loc>http://example.com/en/</loc>') !== -1);
204 assert(xml.indexOf('<loc>http://example.com/en/tab-two/child-two</loc>') !== -1);
205 assert(xml.indexOf('<loc>http://example.com/en/products/cheese</loc>') !== -1);
206 done();
207 });
208 });
209
210 it('should NOT generate a default sitemap', function(done) {
211 get('http://localhost:7777/sitemaps/default.xml', function(err, xml) {
212 assert(err);
213 assert(!xml);
214 done();
215 });
216 });
217
218});
219
220describe('Apostrophe Sitemap: workflow: hostname and prefixes without perLocale', function() {
221 var apos;
222
223 this.timeout(5000);
224
225 after(function(done) {
226 try {
227 require('apostrophe/test-lib/util').destroy(apos, done);
228 } catch (e) {
229 console.warn('Old version of apostrophe does not export test-lib/util library, just dropping old test db');
230 apos.db.dropDatabase();
231 setTimeout(done, 1000);
232 }
233 });
234
235 it('should initialize', function(done) {
236 apos = require('apostrophe')({
237 testModule: true,
238 baseUrl: 'http://localhost:7778',
239 modules: {
240 'apostrophe-express': {
241 port: 7778
242 },
243 'apostrophe-site-map': {
244 // perLocale is not set
245 },
246 'apostrophe-pages': {
247 park: _.cloneDeep(parkedPages),
248 types: _.cloneDeep(parkedPageTypes)
249 },
250 'products': {
251 extend: 'apostrophe-pieces',
252 name: 'product'
253 },
254 'products-pages': {
255 extend: 'apostrophe-pieces-pages'
256 },
257 'apostrophe-workflow': {
258 locales: _.cloneDeep(workflowLocales),
259 hostnames: {
260 'fr': 'exemple.fr',
261 'default': 'example.com',
262 'en': 'example.com'
263 },
264 prefixes: {
265 // Even private locales must be distinguishable by hostname and/or prefix
266 'default': '/default',
267 'en': '/en'
268 // We don't need prefixes for fr because
269 // that hostname is not shared with other
270 // locales
271 }
272 }
273 },
274 afterInit: function(callback) {
275 assert(apos.modules['apostrophe-site-map']);
276 assert(apos.modules['apostrophe-workflow']);
277 return callback(null);
278 },
279 afterListen: function(err) {
280 done();
281 }
282 });
283 });
284
285 it('insert a product for test purposes', function(done) {
286 var product = _.assign(apos.modules.products.newInstance(), {
287 title: 'Cheese',
288 slug: 'cheese'
289 });
290 apos.modules.products.insert(apos.tasks.getReq(), product, function(err) {
291 assert(!err);
292 done();
293 });
294 });
295
296 it('make sure everything is published and out of the trash for test purposes', function(done) {
297 return apos.docs.db.update({}, {
298 $set: {
299 trash: false,
300 published: true
301 }
302 }, {
303 multi: true
304 }, function(err, count) {
305 assert(!err);
306 done();
307 });
308 });
309
310 it('should generate a suitable all-in-one sitemap', function(done) {
311 this.timeout(5000);
312 get('http://localhost:7778/sitemap.xml', function(err, xml) {
313 if (err) {
314 console.error(err);
315 }
316 assert(!err);
317 assert(xml);
318 // Watch out for bad markup due to array of locales being naively XMLized
319 assert(xml.indexOf('<0>') === -1);
320 // No sub-sitemaps in this mode
321 assert(xml.indexOf('http://localhost:7778/sitemaps/fr.xml') === -1);
322 assert(xml.indexOf('<loc>http://exemple.fr/</loc>') !== -1);
323 assert(xml.indexOf('<loc>http://exemple.fr/tab-two/child-two</loc>') !== -1);
324 assert(xml.indexOf('<loc>http://exemple.fr/products/cheese</loc>') !== -1);
325 assert(xml.indexOf('<loc>http://example.com/en/</loc>') !== -1);
326 assert(xml.indexOf('<loc>http://example.com/en/tab-two/child-two</loc>') !== -1);
327 assert(xml.indexOf('<loc>http://example.com/en/products/cheese</loc>') !== -1);
328 // No default locale in sitemap (it is private)
329 assert(xml.indexOf('<loc>http://example.com/default') === -1);
330 done();
331 });
332 });
333});
334
335describe('Apostrophe Sitemap: workflow: legacy subdomains option', function() {
336
337 var apos;
338 this.timeout(5000);
339
340 after(function(done) {
341 try {
342 require('apostrophe/test-lib/util').destroy(apos, done);
343 } catch (e) {
344 console.warn('Old version of apostrophe does not export test-lib/util library, just dropping old test db');
345 apos.db.dropDatabase();
346 setTimeout(done, 1000);
347 }
348 });
349
350 it('should be a property of the apos object', function(done) {
351 apos = require('apostrophe')({
352 testModule: true,
353 baseUrl: 'http://localhost:7779',
354 modules: {
355 'apostrophe-express': {
356 port: 7779
357 },
358 'apostrophe-site-map': {
359 perLocale: true
360 },
361 'apostrophe-pages': {
362 park: _.cloneDeep(parkedPages),
363 types: _.cloneDeep(parkedPageTypes)
364 },
365 'products': {
366 extend: 'apostrophe-pieces',
367 name: 'product'
368 },
369 'products-pages': {
370 extend: 'apostrophe-pieces-pages'
371 },
372 'apostrophe-workflow': {
373 locales: _.cloneDeep(workflowLocales),
374 subdomains: true
375 }
376 },
377 afterInit: function(callback) {
378 assert(apos.modules['apostrophe-site-map']);
379 assert(apos.modules['apostrophe-workflow']);
380 return callback(null);
381 },
382 afterListen: function(err) {
383 done();
384 }
385 });
386 });
387
388 it('insert a product for test purposes', function(done) {
389 var product = _.assign(apos.modules.products.newInstance(), {
390 title: 'Cheese',
391 slug: 'cheese'
392 });
393 apos.modules.products.insert(apos.tasks.getReq(), product, function(err) {
394 assert(!err);
395 done();
396 });
397 });
398
399 it('make sure everything is published and out of the trash for test purposes', function(done) {
400 return apos.docs.db.update({}, {
401 $set: {
402 trash: false,
403 published: true
404 }
405 }, {
406 multi: true
407 }, function(err, count) {
408 assert(!err);
409 done();
410 });
411 });
412
413 it('should generate a suitable sitemap index', function(done) {
414 get('http://localhost:7779/sitemaps/index.xml', function(err, xml) {
415 assert(!err);
416 assert(xml);
417 assert(xml.indexOf('http://localhost:7779/sitemaps/fr.xml') !== -1);
418 assert(xml.indexOf('http://localhost:7779/sitemaps/en.xml') !== -1);
419 assert(xml.indexOf('http://localhost:7779/sitemaps/default.xml') === -1);
420 done();
421 });
422 });
423
424 it('should generate an fr sitemap', function(done) {
425 get('http://localhost:7779/sitemaps/fr.xml', function(err, xml) {
426 assert(!err);
427 assert(xml.indexOf('<loc>http://fr.localhost:7779/</loc>') !== -1);
428 assert(xml.indexOf('<loc>http://fr.localhost:7779/tab-two/child-two</loc>') !== -1);
429 assert(xml.indexOf('<loc>http://fr.localhost:7779/products/cheese</loc>') !== -1);
430 done();
431 });
432 });
433
434 it('should generate an en sitemap', function(done) {
435 get('http://localhost:7779/sitemaps/en.xml', function(err, xml) {
436 assert(!err);
437 assert(xml);
438 assert(xml.indexOf('<loc>http://en.localhost:7779/</loc>') !== -1);
439 assert(xml.indexOf('<loc>http://en.localhost:7779/tab-two/child-two</loc>') !== -1);
440 assert(xml.indexOf('<loc>http://en.localhost:7779/products/cheese</loc>') !== -1);
441 done();
442 });
443 });
444
445 it('should NOT generate a default sitemap', function(done) {
446 get('http://localhost:7779/sitemaps/default.xml', function(err, xml) {
447 assert(err);
448 assert(!xml);
449 done();
450 });
451 });
452
453});
454
455describe('Apostrophe Sitemap: workflow: single sitemap with hreflang alternatives', function() {
456
457 var apos;
458
459 this.timeout(5000);
460
461 after(function(done) {
462 try {
463 require('apostrophe/test-lib/util').destroy(apos, done);
464 } catch (e) {
465 console.warn('Old version of apostrophe does not export test-lib/util library, just dropping old test db');
466 apos.db.dropDatabase();
467 setTimeout(done, 1000);
468 }
469 });
470
471 it('should initialize', function(done) {
472 apos = require('apostrophe')({
473 testModule: true,
474 baseUrl: 'http://localhost:7790',
475 modules: {
476 'apostrophe-express': {
477 port: 7790
478 },
479 'apostrophe-site-map': {},
480 'apostrophe-pages': {
481 park: _.cloneDeep(parkedPages),
482 types: _.cloneDeep(parkedPageTypes)
483 },
484 'products': {
485 extend: 'apostrophe-pieces',
486 name: 'product'
487 },
488 'products-pages': {
489 extend: 'apostrophe-pieces-pages'
490 },
491 'apostrophe-workflow': {
492 locales: _.cloneDeep(workflowLocales),
493 hostnames: {
494 'fr': 'exemple.fr',
495 'default': 'example.com',
496 'en': 'example.com'
497 },
498 prefixes: {
499 // Even private locales must be distinguishable by hostname and/or prefix
500 'default': '/default',
501 'en': '/en'
502 // We don't need prefixes for fr because
503 // that hostname is not shared with other
504 // locales
505 }
506 }
507 },
508 afterInit: function(callback) {
509 assert(apos.modules['apostrophe-site-map']);
510 assert(apos.modules['apostrophe-workflow']);
511 return callback(null);
512 },
513 afterListen: function(err) {
514 done();
515 }
516 });
517 });
518
519 it('should generate <xhtml:link hreflang> tags', function(done) {
520 this.timeout(10000);
521 get('http://localhost:7790/sitemap.xml', function(err, xml) {
522 if (err) {
523 console.error(err);
524 }
525 assert(!err);
526 assert(xml);
527
528 var $ = cheerio.load(xml, { xmlMode: true });
529
530 var urlTags = $('url').map(function() {
531 return {
532 loc: $(this).find('loc').text(),
533 xhtmlLinks: $(this).find('xhtml\\:link').map(function() {
534 return {
535 hreflang: $(this).attr('hreflang'),
536 href: $(this).attr('href')
537 };
538 }).get()
539 };
540 }).get();
541
542 assert.deepEqual(urlTags, [
543 {
544 loc: 'http://exemple.fr/',
545 xhtmlLinks: [
546 { hreflang: 'fr', href: 'http://exemple.fr/' },
547 { hreflang: 'en', href: 'http://example.com/en/' }
548 ]
549 },
550 {
551 loc: 'http://example.com/en/',
552 xhtmlLinks: [
553 { hreflang: 'en', href: 'http://example.com/en/' },
554 { hreflang: 'fr', href: 'http://exemple.fr/' }
555 ]
556 }
557 ]);
558
559 done();
560 });
561 });
562
563});
564