1 | var assert = require('assert');
|
2 | var _ = require('@sailshq/lodash');
|
3 | var async = require('async');
|
4 | var request = require('request');
|
5 | var cheerio = require('cheerio');
|
6 | var fs = require('fs');
|
7 | const get = require('./lib/get');
|
8 |
|
9 | var 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 |
|
51 | var 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 |
|
66 | var 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 |
|
83 | describe('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 |
|
130 | 'default': '/default',
|
131 | 'en': '/en'
|
132 |
|
133 |
|
134 |
|
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 |
|
220 | describe('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 |
|
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 |
|
266 | 'default': '/default',
|
267 | 'en': '/en'
|
268 |
|
269 |
|
270 |
|
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 |
|
319 | assert(xml.indexOf('<0>') === -1);
|
320 |
|
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 |
|
329 | assert(xml.indexOf('<loc>http://example.com/default') === -1);
|
330 | done();
|
331 | });
|
332 | });
|
333 | });
|
334 |
|
335 | describe('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 |
|
455 | describe('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 |
|
500 | 'default': '/default',
|
501 | 'en': '/en'
|
502 |
|
503 |
|
504 |
|
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 |
|