const should = require('should'); const sinon = require('sinon'); const ObjectId = require('bson-objectid'); const _ = require('lodash'); const testUtils = require('../../../utils'); const urlUtils = require('../../../../core/shared/url-utils'); const IndexGenerator = require('../../../../core/frontend/services/sitemap/index-generator'); const PostGenerator = require('../../../../core/frontend/services/sitemap/post-generator'); const PageGenerator = require('../../../../core/frontend/services/sitemap/page-generator'); const TagGenerator = require('../../../../core/frontend/services/sitemap/tag-generator'); const UserGenerator = require('../../../../core/frontend/services/sitemap/user-generator'); should.Assertion.add('ValidUrlNode', function (options) { // Check urlNode looks correct /*eslint no-invalid-this: "off"*/ let urlNode = this.obj; let flatNode; urlNode.should.be.an.Object().with.key('url'); urlNode.url.should.be.an.Array(); if (options.withImage) { urlNode.url.should.have.lengthOf(3); } else { urlNode.url.should.have.lengthOf(2); } /** * A urlNode looks something like: * { url: * [ { loc: 'http://127.0.0.1:2369/author/' }, * { lastmod: '2014-12-22T11:54:00.100Z' }, * { 'image:image': [ * { 'image:loc': 'post-100.jpg' }, * { 'image:caption': 'post-100.jpg' } * ] } * ] } */ flatNode = _.extend.apply(_, urlNode.url); if (options.withImage) { flatNode.should.be.an.Object().with.keys('loc', 'lastmod', 'image:image'); } else { flatNode.should.be.an.Object().with.keys('loc', 'lastmod'); } }); describe('Generators', function () { let generator; afterEach(function () { sinon.restore(); }); describe('IndexGenerator', function () { beforeEach(function () { generator = new IndexGenerator({ types: { posts: new PostGenerator(), pages: new PageGenerator(), tags: new TagGenerator(), authors: new UserGenerator() } }); }); describe('fn: getXml', function () { it('default', function () { const xml = generator.getXml(); xml.should.match(/sitemap-tags.xml/); xml.should.match(/sitemap-posts.xml/); xml.should.match(/sitemap-pages.xml/); xml.should.match(/sitemap-authors.xml/); }); }); }); describe('PostGenerator', function () { beforeEach(function () { generator = new PostGenerator(); }); describe('fn: createNodeFromDatum', function () { it('adds an image:image element if post has a cover image', function () { const urlNode = generator.createUrlNodeFromDatum('https://myblog.com/test/', testUtils.DataGenerator.forKnex.createPost({ feature_image: 'post-100.jpg', page: false, slug: 'test' })); urlNode.should.be.a.ValidUrlNode({withImage: true}); }); }); describe('fn: getXml', function () { beforeEach(function () { sinon.stub(urlUtils, 'urlFor'); }); it('get cached xml', function () { sinon.spy(generator, 'generateXmlFromNodes'); generator.siteMapContent = 'something'; generator.getXml().should.eql('something'); generator.siteMapContent = null; generator.generateXmlFromNodes.called.should.eql(false); }); it('compare content output', function () { let idxFirst; let idxSecond; let idxThird; urlUtils.urlFor.withArgs('image', {image: 'post-100.jpg'}, true).returns('http://my-ghost-blog.com/images/post-100.jpg'); urlUtils.urlFor.withArgs('image', {image: 'post-200.jpg'}, true).returns('http://my-ghost-blog.com/images/post-200.jpg'); urlUtils.urlFor.withArgs('image', {image: 'post-300.jpg'}, true).returns('http://my-ghost-blog.com/images/post-300.jpg'); urlUtils.urlFor.withArgs('sitemap_xsl', true).returns('http://my-ghost-blog.com/sitemap.xsl'); generator.addUrl('http://my-ghost-blog.com/url/100/', testUtils.DataGenerator.forKnex.createPost({ feature_image: 'post-100.jpg', created_at: (Date.UTC(2014, 11, 22, 12) - 360000) + 100, updated_at: null, published_at: null, slug: '100' })); generator.addUrl('http://my-ghost-blog.com/url/200/', testUtils.DataGenerator.forKnex.createPost({ created_at: (Date.UTC(2014, 11, 22, 12) - 360000) + 200, updated_at: null, published_at: null, slug: '200' })); generator.addUrl('http://my-ghost-blog.com/url/300/', testUtils.DataGenerator.forKnex.createPost({ created_at: (Date.UTC(2014, 11, 22, 12) - 360000) + 300, feature_image: 'post-300.jpg', updated_at: null, published_at: null, slug: '300' })); const xml = generator.getXml(); xml.should.containEql('http://my-ghost-blog.com/url/100/'); xml.should.containEql('http://my-ghost-blog.com/url/200/'); xml.should.containEql('http://my-ghost-blog.com/url/300/'); xml.should.containEql('http://my-ghost-blog.com/images/post-100.jpg'); // This should NOT be present xml.should.not.containEql('http://my-ghost-blog.com/images/post-200.jpg'); xml.should.containEql('http://my-ghost-blog.com/images/post-300.jpg'); // Validate order newest to oldest idxFirst = xml.indexOf('http://my-ghost-blog.com/url/300/'); idxSecond = xml.indexOf('http://my-ghost-blog.com/url/200/'); idxThird = xml.indexOf('http://my-ghost-blog.com/url/100/'); idxFirst.should.be.below(idxSecond); idxSecond.should.be.below(idxThird); }); }); describe('fn: removeUrl', function () { let post; beforeEach(function () { post = testUtils.DataGenerator.forKnex.createPost(); generator.nodeLookup[post.id] = 'node'; }); afterEach(function () { generator.nodeLookup = {}; generator.nodeTimeLookup = {}; }); it('remove none existend url', function () { generator.removeUrl('https://myblog.com/blog/podcast/featured/', testUtils.DataGenerator.forKnex.createPost()); Object.keys(generator.nodeLookup).length.should.eql(1); }); it('remove existing url', function () { generator.removeUrl('https://myblog.com/blog/test/', post); Object.keys(generator.nodeLookup).length.should.eql(0); }); }); }); describe('PageGenerator', function () { beforeEach(function () { generator = new PageGenerator(); }); describe('fn: getXml', function () { it('add', function () { generator.addUrl('http://my-ghost-blog.com/home/', {id: 'identifier1', staticRoute: true}); generator.addUrl('http://my-ghost-blog.com/magic/', {id: 'identifier2', staticRoute: false}); generator.addUrl('http://my-ghost-blog.com/subscribe/', {id: ObjectId().toHexString(), page: 1}); generator.getXml(); generator.siteMapContent.should.containEql('http://my-ghost-blog.com/home/'); generator.siteMapContent.should.containEql('http://my-ghost-blog.com/magic/'); generator.siteMapContent.should.containEql('http://my-ghost-blog.com/subscribe/'); // should exist exactly one time generator.siteMapContent.match(//g).length.should.eql(3); }); }); }); describe('TagGenerator', function () { beforeEach(function () { generator = new TagGenerator(); }); }); describe('UserGenerator', function () { beforeEach(function () { generator = new UserGenerator(); }); describe('fn: validateImageUrl', function () { it('image url is localhost', function () { generator.validateImageUrl('http://localhost:2368/content/images/1.jpg').should.be.true(); }); it('image url is https', function () { generator.validateImageUrl('https://myblog.com/content/images/1.png').should.be.true(); }); it('image url is external', function () { generator.validateImageUrl('https://myblog.com/1.jpg').should.be.true(); }); it('no host', function () { generator.validateImageUrl('/content/images/1.jpg').should.be.false(); }); }); }); });