/* eslint-disable no-regex-spaces */ const should = require('should'); const sinon = require('sinon'); const _ = require('lodash'); const moment = require('moment'); const testUtils = require('../../utils'); const testUrlUtils = require('../../utils/urlUtils'); const configUtils = require('../../utils/configUtils'); const themes = require('../../../core/frontend/services/themes'); const models = require('../../../core/server/models'); const imageLib = require('../../../core/server/lib/image'); const routing = require('../../../core/frontend/services/routing'); const urlService = require('../../../core/frontend/services/url'); const helpers = require('../../../core/frontend/helpers'); const proxy = require('../../../core/frontend/services/proxy'); const settingsCache = proxy.settingsCache; describe('{{ghost_head}} helper', function () { let posts = []; let tags = []; let authors = []; let users = []; const makeFixtures = () => { const {createPost, createUser, createTag} = testUtils.DataGenerator.forKnex; /** TAGS - used for tag pages */ tags.push(createTag({ meta_description: 'tag meta description', name: 'tagtitle', meta_title: 'tag meta title', feature_image: '/content/images/tag-image.png' })); tags.push(createTag({ meta_description: '', description: 'tag description', name: 'tagtitle', meta_title: '', feature_image: '/content/images/tag-image.png' })); tags.push(createTag({ description: '', meta_description: '', name: 'tagtitle', meta_title: '', feature_image: '/content/images/tag-image.png' })); tags.push(createTag({ meta_description: 'tag meta description', title: 'tagtitle', meta_title: 'tag meta title', feature_image: '/content/images/tag-image.png' })); /** USERS - used for author PAGES */ users.push(createUser({ name: 'Author name', slug: 'AuthorName', bio: 'Author bio', profile_image: '/content/images/test-author-image.png', cover_image: '/content/images/author-cover-image.png', website: 'http://authorwebsite.com', facebook: 'testuser', twitter: '@testuser' })); users.push(createUser({ name: 'Author name', slug: 'AuthorName1', bio: 'Author bio', profile_image: '/content/images/test-author-image.png', cover_image: '/content/images/author-cover-image.png', website: 'http://authorwebsite.com' })); /** AUTHORS - related to posts */ authors.push(createUser({// Author 0 profile_image: '/content/images/test-author-image.png', website: 'http://authorwebsite.com', facebook: 'testuser', twitter: '@testuser' })); authors.push(createUser({// Author 1 name: 'Author name', slug: 'author2', profile_image: '/content/images/test-author-image.png', website: 'http://authorwebsite.com', bio: 'Author bio', facebook: 'testuser', twitter: '@testuser' })); authors.push(createUser({// Author 2 name: 'Author name', slug: 'author3', profile_image: '/content/images/test-author-image.png', website: 'http://authorwebsite.com', facebook: 'testuser', twitter: '@testuser', bio: 'Author bio' })); authors.push(createUser({// Author 3 name: 'Author name', url: 'http://testauthorurl.com', slug: 'author4', profile_image: '/content/images/test-author-image.png', website: 'http://authorwebsite.com', facebook: 'testuser', twitter: '@testuser' })); authors.push(createUser({// Author 4 name: 'Author name' })); authors.push(createUser({// Author 5 name: 'Author name', url: 'http://testauthorurl.com', slug: 'author8', profile_image: null, website: 'http://authorwebsite.com', facebook: 'testuser', twitter: '@testuser' })); /** POSTS */ posts.push(createPost({// Post 0 meta_description: 'all about our site', title: 'About', feature_image: '/content/images/test-image-about.png', page: true, authors: [authors[0]], primary_author: authors[0] })); posts.push(createPost({// Post 1 meta_description: 'all about our site', title: 'About', feature_image: '/content/images/test-image-about.png', og_image: '/content/images/test-og-image.png', og_title: 'Custom Facebook title', og_description: 'Custom Facebook description', twitter_image: '/content/images/test-twitter-image.png', twitter_title: 'Custom Twitter title', twitter_description: 'Custom Twitter description', page: true, authors: [authors[0]], primary_author: authors[0] })); posts.push(createPost({// Post 2 meta_description: 'site description', title: 'Welcome to Ghost', feature_image: '/content/images/test-image.png', og_title: 'Custom Facebook title', og_description: 'Custom Facebook description', twitter_image: '/content/images/test-twitter-image.png', published_at: moment('2008-05-31T19:18:15').toDate(), updated_at: moment('2014-10-06T15:23:54').toDate(), tags: [ createTag({name: 'tag1'}), createTag({name: 'tag2'}), createTag({name: 'tag3'}) ], authors: [authors[1]], primary_author: authors[1] })); posts.push(createPost({// Post 3 meta_description: 'site description', custom_excerpt: 'post custom excerpt', title: 'Welcome to Ghost', feature_image: '/content/images/test-image.png', og_image: '/content/images/test-facebook-image.png', twitter_image: '/content/images/test-twitter-image.png', twitter_title: 'Custom Twitter title', tags: [ createTag({name: 'tag1'}), createTag({name: 'tag2'}), createTag({name: 'tag3'}) ], authors: [ authors[2] ], primary_author: authors[2] })); posts.push(createPost({// Post 4 title: 'Welcome to Ghost', mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('This is a short post'), authors: [ authors[3] ], primary_author: authors[3] })); posts.push(createPost({// Post 5 meta_description: 'site description', title: 'Welcome to Ghost', feature_image: '/content/images/test-image.png', og_image: '/content/images/test-facebook-image.png', og_title: 'Custom Facebook title', twitter_image: '/content/images/test-twitter-image.png', twitter_title: 'Custom Twitter title', tags: [ createTag({name: 'tag1'}), createTag({name: 'tag2'}), createTag({name: 'tag3'}) ], authors: [ authors[3] ], primary_author: authors[3] })); posts.push(createPost({// Post 6 meta_description: 'site "test" description', title: 'title', meta_title: 'Welcome to Ghost "test"', feature_image: '/content/images/test-image.png', tags: [ createTag({name: 'tag1'}), createTag({name: 'tag2'}), createTag({name: 'tag3'}) ], authors: [ authors[3] ], primary_author: authors[3] })); posts.push(createPost({// Post 7 meta_description: 'site description', title: 'Welcome to Ghost', feature_image: '/content/images/test-image.png', tags: [], authors: [ authors[3] ], primary_author: authors[3] })); posts.push(createPost({// Post 8 meta_description: 'site description', title: 'Welcome to Ghost', feature_image: null, tags: [ createTag({name: 'tag1'}), createTag({name: 'tag2'}), createTag({name: 'tag3'}) ], authors: [ authors[5] ], primary_author: authors[5] })); posts.push(createPost({// Post 9 title: 'Welcome to Ghost', mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('This is a short post'), tags: [ createTag({name: 'tag1'}), createTag({name: 'tag2'}), createTag({name: 'tag3'}) ], authors: [ authors[4] ], primary_author: authors[4] })); }; before(function () { // @TODO: remove when visibility is refactored out of models models.init(); }); beforeEach(function () { sinon.stub(urlService, 'getUrlByResourceId').returns('https://mysite.com/fakeauthor/'); // @TODO: this is a LOT of mocking :/ sinon.stub(routing.registry, 'getRssUrl').returns('http://localhost:65530/rss/'); sinon.stub(imageLib.imageSize, 'getImageSizeFromUrl').resolves(); sinon.stub(themes, 'getActive').returns({ engine: () => 'v2' }); sinon.stub(settingsCache, 'get'); settingsCache.get.withArgs('title').returns('Ghost'); settingsCache.get.withArgs('description').returns('site description'); settingsCache.get.withArgs('cover_image').returns('/content/images/site-cover.png'); settingsCache.get.withArgs('amp').returns(true); makeFixtures(); }); afterEach(function () { sinon.restore(); configUtils.restore(); }); describe('without Code Injection', function () { let sandbox; beforeEach(function () { sandbox = sinon.createSandbox(); testUrlUtils.stubUrlUtils({url: 'http://localhost:65530/'}, sandbox); }); afterEach(function () { sandbox.restore(); }); it('returns meta tag string on paginated index page without structured data and schema', function (done) { // @TODO: later we can extend this fn with an `meta` object e.g. locals.meta helpers.ghost_head(testUtils.createHbsResponse({ locals: { relativeUrl: '/page/2/', context: ['paged', 'index'], safeVersion: '0.3' } })).then(function (rendered) { should.exist(rendered); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.not.match(//); done(); }).catch(done); }); it('returns structured data on first index page', function (done) { helpers.ghost_head(testUtils.createHbsResponse({ locals: { relativeUrl: '/', context: ['home', 'index'], safeVersion: '0.3' } })).then(function (rendered) { should.exist(rendered); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(//); rendered.string.should.match(/