Updated @tryghost/url-utils to v0.2.0 (#11004)

no issue

- updates `@tryghost/url-utils` following an internal refactor of the package
- renames `makeAbsoluteUrls` to `htmlRelativeToAbsolute` to better reflect what the function is doing
- renames `getBlogUrl` to `getSiteUrl`
- updates UrlUtils test stubbing util to work with a class
- fixes use of invalid port numbers in tests (max port number is 65535, any higher is an invalid URL that will error with some parsers)
This commit is contained in:
Kevin Ansfield 2019-08-12 09:31:42 +01:00 committed by GitHub
parent 3bd3570592
commit 4f3391cd04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 86 additions and 75 deletions

View File

@ -124,7 +124,7 @@ function getAmperizeHTML(html, post) {
amperize = amperize || new Amperize(); amperize = amperize || new Amperize();
// make relative URLs abolute // make relative URLs abolute
html = urlUtils.makeAbsoluteUrls(html, urlUtils.urlFor('home', true), post.url).html(); html = urlUtils.htmlRelativeToAbsolute(html, urlUtils.urlFor('home', true), post.url).html();
if (!amperizeCache[post.id] || moment(new Date(amperizeCache[post.id].updated_at)).diff(new Date(post.updated_at)) < 0) { if (!amperizeCache[post.id] || moment(new Date(amperizeCache[post.id].updated_at)).diff(new Date(post.updated_at)) < 0) {
return new Promise((resolve) => { return new Promise((resolve) => {

View File

@ -81,7 +81,7 @@ function getImageSizeOptions(options) {
} }
function detectInternalImage(requestedImageUrl) { function detectInternalImage(requestedImageUrl) {
const siteUrl = urlUtils.getBlogUrl(); const siteUrl = urlUtils.getSiteUrl();
const isAbsoluteImage = /https?:\/\//.test(requestedImageUrl); const isAbsoluteImage = /https?:\/\//.test(requestedImageUrl);
const isAbsoluteInternalImage = isAbsoluteImage && requestedImageUrl.startsWith(siteUrl); const isAbsoluteInternalImage = isAbsoluteImage && requestedImageUrl.startsWith(siteUrl);

View File

@ -22,7 +22,7 @@ generateTags = function generateTags(data) {
generateItem = function generateItem(post, siteUrl, secure) { generateItem = function generateItem(post, siteUrl, secure) {
var itemUrl = urlService.getUrlByResourceId(post.id, {secure: secure, absolute: true}), var itemUrl = urlService.getUrlByResourceId(post.id, {secure: secure, absolute: true}),
htmlContent = urlUtils.makeAbsoluteUrls(post.html, siteUrl, itemUrl), htmlContent = urlUtils.htmlRelativeToAbsolute(post.html, siteUrl, itemUrl),
item = { item = {
title: post.title, title: post.title,
// @TODO: DRY this up with data/meta/index & other excerpt code // @TODO: DRY this up with data/meta/index & other excerpt code

View File

@ -3,7 +3,7 @@ const url = require('url');
const urlUtils = require('../../../../../../lib/url-utils'); const urlUtils = require('../../../../../../lib/url-utils');
const handleCanonicalUrl = (canonicalUrl) => { const handleCanonicalUrl = (canonicalUrl) => {
const blogURl = urlUtils.getBlogUrl(); const blogURl = urlUtils.getSiteUrl();
const isSameProtocol = url.parse(canonicalUrl).protocol === url.parse(blogURl).protocol; const isSameProtocol = url.parse(canonicalUrl).protocol === url.parse(blogURl).protocol;
const blogDomain = blogURl.replace(/^http(s?):\/\//, '').replace(/\/$/, ''); const blogDomain = blogURl.replace(/^http(s?):\/\//, '').replace(/\/$/, '');
const absolute = canonicalUrl.replace(/^http(s?):\/\//, ''); const absolute = canonicalUrl.replace(/^http(s?):\/\//, '');
@ -19,7 +19,7 @@ const handleCanonicalUrl = (canonicalUrl) => {
}; };
const handleImageUrl = (imageUrl) => { const handleImageUrl = (imageUrl) => {
const blogDomain = urlUtils.getBlogUrl().replace(/^http(s?):\/\//, '').replace(/\/$/, ''); const blogDomain = urlUtils.getSiteUrl().replace(/^http(s?):\/\//, '').replace(/\/$/, '');
const imageUrlAbsolute = imageUrl.replace(/^http(s?):\/\//, ''); const imageUrlAbsolute = imageUrl.replace(/^http(s?):\/\//, '');
const imagePathRe = new RegExp(`^${blogDomain}/${urlUtils.STATIC_IMAGE_URL_PREFIX}`); const imagePathRe = new RegExp(`^${blogDomain}/${urlUtils.STATIC_IMAGE_URL_PREFIX}`);
@ -31,7 +31,7 @@ const handleImageUrl = (imageUrl) => {
}; };
const handleContentUrls = (content) => { const handleContentUrls = (content) => {
const blogDomain = urlUtils.getBlogUrl().replace(/^http(s?):\/\//, '').replace(/\/$/, ''); const blogDomain = urlUtils.getSiteUrl().replace(/^http(s?):\/\//, '').replace(/\/$/, '');
const imagePathRe = new RegExp(`(http(s?)://)?${blogDomain}/${urlUtils.STATIC_IMAGE_URL_PREFIX}`, 'g'); const imagePathRe = new RegExp(`(http(s?)://)?${blogDomain}/${urlUtils.STATIC_IMAGE_URL_PREFIX}`, 'g');
const matches = _.uniq(content.match(imagePathRe)); const matches = _.uniq(content.match(imagePathRe));

View File

@ -55,7 +55,7 @@ const forPost = (id, attrs, frame) => {
urlOptions.assetsOnly = false; urlOptions.assetsOnly = false;
} }
attrs.html = urlUtils.makeAbsoluteUrls( attrs.html = urlUtils.htmlRelativeToAbsolute(
attrs.html, attrs.html,
urlUtils.urlFor('home', true), urlUtils.urlFor('home', true),
attrs.url, attrs.url,

View File

@ -1,5 +1,5 @@
const urlService = require('../../../../frontend/services/url'); const urlService = require('../../../../frontend/services/url');
const {urlFor, makeAbsoluteUrls} = require('../../../lib/url-utils'); const urlUtils = require('../../../lib/url-utils');
const urlsForPost = (id, attrs, options) => { const urlsForPost = (id, attrs, options) => {
attrs.url = urlService.getUrlByResourceId(id); attrs.url = urlService.getUrlByResourceId(id);
@ -10,23 +10,23 @@ const urlsForPost = (id, attrs, options) => {
if (options && options.context && options.context.public && options.absolute_urls) { if (options && options.context && options.context.public && options.absolute_urls) {
if (attrs.feature_image) { if (attrs.feature_image) {
attrs.feature_image = urlFor('image', {image: attrs.feature_image}, true); attrs.feature_image = urlUtils.urlFor('image', {image: attrs.feature_image}, true);
} }
if (attrs.og_image) { if (attrs.og_image) {
attrs.og_image = urlFor('image', {image: attrs.og_image}, true); attrs.og_image = urlUtils.urlFor('image', {image: attrs.og_image}, true);
} }
if (attrs.twitter_image) { if (attrs.twitter_image) {
attrs.twitter_image = urlFor('image', {image: attrs.twitter_image}, true); attrs.twitter_image = urlUtils.urlFor('image', {image: attrs.twitter_image}, true);
} }
if (attrs.html) { if (attrs.html) {
attrs.html = makeAbsoluteUrls(attrs.html, urlFor('home', true), attrs.url).html(); attrs.html = urlUtils.htmlRelativeToAbsolute(attrs.html, urlUtils.urlFor('home', true), attrs.url).html();
} }
if (attrs.url) { if (attrs.url) {
attrs.url = urlFor({relativeUrl: attrs.url}, true); attrs.url = urlUtils.urlFor({relativeUrl: attrs.url}, true);
} }
} }
@ -54,16 +54,16 @@ const urlsForPost = (id, attrs, options) => {
const urlsForUser = (id, attrs, options) => { const urlsForUser = (id, attrs, options) => {
if (options && options.context && options.context.public && options.absolute_urls) { if (options && options.context && options.context.public && options.absolute_urls) {
attrs.url = urlFor({ attrs.url = urlUtils.urlFor({
relativeUrl: urlService.getUrlByResourceId(id) relativeUrl: urlService.getUrlByResourceId(id)
}, true); }, true);
if (attrs.profile_image) { if (attrs.profile_image) {
attrs.profile_image = urlFor('image', {image: attrs.profile_image}, true); attrs.profile_image = urlUtils.urlFor('image', {image: attrs.profile_image}, true);
} }
if (attrs.cover_image) { if (attrs.cover_image) {
attrs.cover_image = urlFor('image', {image: attrs.cover_image}, true); attrs.cover_image = urlUtils.urlFor('image', {image: attrs.cover_image}, true);
} }
} }
@ -72,12 +72,12 @@ const urlsForUser = (id, attrs, options) => {
const urlsForTag = (id, attrs, options) => { const urlsForTag = (id, attrs, options) => {
if (options && options.context && options.context.public && options.absolute_urls) { if (options && options.context && options.context.public && options.absolute_urls) {
attrs.url = urlFor({ attrs.url = urlUtils.urlFor({
relativeUrl: urlService.getUrlByResourceId(attrs.id) relativeUrl: urlService.getUrlByResourceId(attrs.id)
}, true); }, true);
if (attrs.feature_image) { if (attrs.feature_image) {
attrs.feature_image = urlFor('image', {image: attrs.feature_image}, true); attrs.feature_image = urlUtils.urlFor('image', {image: attrs.feature_image}, true);
} }
} }

View File

@ -3,15 +3,15 @@ const url = require('url');
const urlUtils = require('../../../../../../lib/url-utils'); const urlUtils = require('../../../../../../lib/url-utils');
const handleCanonicalUrl = (canonicalUrl) => { const handleCanonicalUrl = (canonicalUrl) => {
const blogURl = urlUtils.getBlogUrl(); const siteUrl = urlUtils.getSiteUrl();
const isSameProtocol = url.parse(canonicalUrl).protocol === url.parse(blogURl).protocol; const isSameProtocol = url.parse(canonicalUrl).protocol === url.parse(siteUrl).protocol;
const blogDomain = blogURl.replace(/^http(s?):\/\//, '').replace(/\/$/, ''); const siteDomain = siteUrl.replace(/^http(s?):\/\//, '').replace(/\/$/, '');
const absolute = canonicalUrl.replace(/^http(s?):\/\//, ''); const absolute = canonicalUrl.replace(/^http(s?):\/\//, '');
// We only want to transform to a relative URL when the canonical URL matches the current // We only want to transform to a relative URL when the canonical URL matches the current
// Blog URL incl. the same protocol. This allows users to keep e.g. Facebook comments after // Site URL incl. the same protocol. This allows users to keep e.g. Facebook comments after
// a http -> https switch // a http -> https switch
if (absolute.startsWith(blogDomain) && isSameProtocol) { if (absolute.startsWith(siteDomain) && isSameProtocol) {
return urlUtils.absoluteToRelative(canonicalUrl); return urlUtils.absoluteToRelative(canonicalUrl);
} }
@ -19,9 +19,9 @@ const handleCanonicalUrl = (canonicalUrl) => {
}; };
const handleImageUrl = (imageUrl) => { const handleImageUrl = (imageUrl) => {
const blogDomain = urlUtils.getBlogUrl().replace(/^http(s?):\/\//, '').replace(/\/$/, ''); const siteDomain = urlUtils.getSiteUrl().replace(/^http(s?):\/\//, '').replace(/\/$/, '');
const imageUrlAbsolute = imageUrl.replace(/^http(s?):\/\//, ''); const imageUrlAbsolute = imageUrl.replace(/^http(s?):\/\//, '');
const imagePathRe = new RegExp(`^${blogDomain}/${urlUtils.STATIC_IMAGE_URL_PREFIX}`); const imagePathRe = new RegExp(`^${siteDomain}/${urlUtils.STATIC_IMAGE_URL_PREFIX}`);
if (imagePathRe.test(imageUrlAbsolute)) { if (imagePathRe.test(imageUrlAbsolute)) {
return urlUtils.absoluteToRelative(imageUrl); return urlUtils.absoluteToRelative(imageUrl);
@ -31,8 +31,8 @@ const handleImageUrl = (imageUrl) => {
}; };
const handleContentUrls = (content) => { const handleContentUrls = (content) => {
const blogDomain = urlUtils.getBlogUrl().replace(/^http(s?):\/\//, '').replace(/\/$/, ''); const siteDomain = urlUtils.getSiteUrl().replace(/^http(s?):\/\//, '').replace(/\/$/, '');
const imagePathRe = new RegExp(`(http(s?)://)?${blogDomain}/${urlUtils.STATIC_IMAGE_URL_PREFIX}`, 'g'); const imagePathRe = new RegExp(`(http(s?)://)?${siteDomain}/${urlUtils.STATIC_IMAGE_URL_PREFIX}`, 'g');
const matches = _.uniq(content.match(imagePathRe)); const matches = _.uniq(content.match(imagePathRe));

View File

@ -55,7 +55,7 @@ const forPost = (id, attrs, frame) => {
urlOptions.assetsOnly = false; urlOptions.assetsOnly = false;
} }
attrs.html = urlUtils.makeAbsoluteUrls( attrs.html = urlUtils.htmlRelativeToAbsolute(
attrs.html, attrs.html,
urlUtils.urlFor('home', true), urlUtils.urlFor('home', true),
attrs.url, attrs.url,

View File

@ -9,7 +9,7 @@ describe('Unit: canary/utils/serializers/output/utils/url', () => {
beforeEach(() => { beforeEach(() => {
sinon.stub(urlService, 'getUrlByResourceId').returns('getUrlByResourceId'); sinon.stub(urlService, 'getUrlByResourceId').returns('getUrlByResourceId');
sinon.stub(urlUtils, 'urlFor').returns('urlFor'); sinon.stub(urlUtils, 'urlFor').returns('urlFor');
sinon.stub(urlUtils, 'makeAbsoluteUrls').returns({html: sinon.stub()}); sinon.stub(urlUtils, 'htmlRelativeToAbsolute').returns({html: sinon.stub()});
}); });
afterEach(() => { afterEach(() => {
@ -39,8 +39,8 @@ describe('Unit: canary/utils/serializers/output/utils/url', () => {
urlUtils.urlFor.getCall(0).args.should.eql(['image', {image: 'value'}, true]); urlUtils.urlFor.getCall(0).args.should.eql(['image', {image: 'value'}, true]);
urlUtils.urlFor.getCall(1).args.should.eql(['home', true]); urlUtils.urlFor.getCall(1).args.should.eql(['home', true]);
urlUtils.makeAbsoluteUrls.callCount.should.eql(1); urlUtils.htmlRelativeToAbsolute.callCount.should.eql(1);
urlUtils.makeAbsoluteUrls.getCall(0).args.should.eql([ urlUtils.htmlRelativeToAbsolute.getCall(0).args.should.eql([
'## markdown', '## markdown',
'urlFor', 'urlFor',
'getUrlByResourceId', 'getUrlByResourceId',

View File

@ -6,7 +6,7 @@ const url = require('../../../../../../../server/api/v2/utils/serializers/input/
describe('Unit: v2/utils/serializers/input/utils/url', function () { describe('Unit: v2/utils/serializers/input/utils/url', function () {
describe('forPost', function () { describe('forPost', function () {
beforeEach(function () { beforeEach(function () {
sinon.stub(urlUtils, 'getBlogUrl') sinon.stub(urlUtils, 'getSiteUrl')
.returns('https://blogurl.com'); .returns('https://blogurl.com');
}); });

View File

@ -9,7 +9,7 @@ describe('Unit: v2/utils/serializers/output/utils/url', () => {
beforeEach(() => { beforeEach(() => {
sinon.stub(urlService, 'getUrlByResourceId').returns('getUrlByResourceId'); sinon.stub(urlService, 'getUrlByResourceId').returns('getUrlByResourceId');
sinon.stub(urlUtils, 'urlFor').returns('urlFor'); sinon.stub(urlUtils, 'urlFor').returns('urlFor');
sinon.stub(urlUtils, 'makeAbsoluteUrls').returns({html: sinon.stub()}); sinon.stub(urlUtils, 'htmlRelativeToAbsolute').returns({html: sinon.stub()});
}); });
afterEach(() => { afterEach(() => {
@ -39,8 +39,8 @@ describe('Unit: v2/utils/serializers/output/utils/url', () => {
urlUtils.urlFor.getCall(0).args.should.eql(['image', {image: 'value'}, true]); urlUtils.urlFor.getCall(0).args.should.eql(['image', {image: 'value'}, true]);
urlUtils.urlFor.getCall(1).args.should.eql(['home', true]); urlUtils.urlFor.getCall(1).args.should.eql(['home', true]);
urlUtils.makeAbsoluteUrls.callCount.should.eql(1); urlUtils.htmlRelativeToAbsolute.callCount.should.eql(1);
urlUtils.makeAbsoluteUrls.getCall(0).args.should.eql([ urlUtils.htmlRelativeToAbsolute.getCall(0).args.should.eql([
'## markdown', '## markdown',
'urlFor', 'urlFor',
'getUrlByResourceId', 'getUrlByResourceId',

View File

@ -421,7 +421,7 @@ describe('Importer', function () {
}); });
it('can load a file (subdirectory)', function (done) { it('can load a file (subdirectory)', function (done) {
ImageHandler.__set__('urlUtils', urlUtils.getInstance({url: 'http://localhost:82832/subdir'})); ImageHandler.__set__('urlUtils', urlUtils.getInstance({url: 'http://localhost:65535/subdir'}));
var filename = 'test-image.jpeg', var filename = 'test-image.jpeg',
file = [{ file = [{

View File

@ -81,7 +81,7 @@ describe('getAssetUrl', function () {
describe('with /blog subdirectory', function () { describe('with /blog subdirectory', function () {
beforeEach(function () { beforeEach(function () {
getAssetUrl.__set__('urlUtils', urlUtils.getInstance({url: 'http://localhost:82832/blog'})); getAssetUrl.__set__('urlUtils', urlUtils.getInstance({url: 'http://localhost:65535/blog'}));
}); });
it('should return asset url with just context', function () { it('should return asset url with just context', function () {

View File

@ -129,7 +129,7 @@ describe('getPaginatedUrl', function () {
before(function () { before(function () {
sandbox = sinon.createSandbox(); sandbox = sinon.createSandbox();
urlUtils.stubUrlUtils({url: 'http://localhost:82832/blog'}, sandbox); urlUtils.stubUrlUtils({url: 'http://localhost:65535/blog'}, sandbox);
}); });
after(function () { after(function () {
@ -145,8 +145,8 @@ describe('getPaginatedUrl', function () {
var urls = getTestUrls(); var urls = getTestUrls();
// Check results // Check results
urls.should.have.property('next', 'http://localhost:82832/blog/page/3/'); urls.should.have.property('next', 'http://localhost:65535/blog/page/3/');
urls.should.have.property('prev', 'http://localhost:82832/blog/'); urls.should.have.property('prev', 'http://localhost:65535/blog/');
urls.should.have.property('page1', '/blog/'); urls.should.have.property('page1', '/blog/');
urls.should.have.property('page5', '/blog/page/5/'); urls.should.have.property('page5', '/blog/page/5/');
urls.should.have.property('page10', '/blog/page/10/'); urls.should.have.property('page10', '/blog/page/10/');
@ -161,8 +161,8 @@ describe('getPaginatedUrl', function () {
var urls = getTestUrls(); var urls = getTestUrls();
// Check results // Check results
urls.should.have.property('next', 'http://localhost:82832/blog/featured/page/3/'); urls.should.have.property('next', 'http://localhost:65535/blog/featured/page/3/');
urls.should.have.property('prev', 'http://localhost:82832/blog/featured/'); urls.should.have.property('prev', 'http://localhost:65535/blog/featured/');
urls.should.have.property('page1', '/blog/featured/'); urls.should.have.property('page1', '/blog/featured/');
urls.should.have.property('page5', '/blog/featured/page/5/'); urls.should.have.property('page5', '/blog/featured/page/5/');
urls.should.have.property('page10', '/blog/featured/page/10/'); urls.should.have.property('page10', '/blog/featured/page/10/');

View File

@ -22,7 +22,7 @@ describe('{{image}} helper', function () {
before(function () { before(function () {
sandbox = sinon.createSandbox(); sandbox = sinon.createSandbox();
urlUtils.stubUrlUtils({url: 'http://localhost:82832/'}, sandbox); urlUtils.stubUrlUtils({url: 'http://localhost:65535/'}, sandbox);
}); });
after(function () { after(function () {
@ -37,7 +37,7 @@ describe('{{image}} helper', function () {
}); });
it('should output relative url of image if the input is absolute', function () { it('should output relative url of image if the input is absolute', function () {
var rendered = helpers.img_url('http://localhost:82832/content/images/image-relative-url.png', {}); var rendered = helpers.img_url('http://localhost:65535/content/images/image-relative-url.png', {});
should.exist(rendered); should.exist(rendered);
rendered.should.equal('/content/images/image-relative-url.png'); rendered.should.equal('/content/images/image-relative-url.png');
logWarnStub.called.should.be.false(); logWarnStub.called.should.be.false();
@ -46,7 +46,7 @@ describe('{{image}} helper', function () {
it('should output absolute url of image if the option is present ', function () { it('should output absolute url of image if the option is present ', function () {
var rendered = helpers.img_url('/content/images/image-relative-url.png', {hash: {absolute: 'true'}}); var rendered = helpers.img_url('/content/images/image-relative-url.png', {hash: {absolute: 'true'}});
should.exist(rendered); should.exist(rendered);
rendered.should.equal('http://localhost:82832/content/images/image-relative-url.png'); rendered.should.equal('http://localhost:65535/content/images/image-relative-url.png');
logWarnStub.called.should.be.false(); logWarnStub.called.should.be.false();
}); });
@ -87,7 +87,7 @@ describe('{{image}} helper', function () {
before(function () { before(function () {
sandbox = sinon.createSandbox(); sandbox = sinon.createSandbox();
urlUtils.stubUrlUtils({url: 'http://localhost:82832/blog'}, sandbox); urlUtils.stubUrlUtils({url: 'http://localhost:65535/blog'}, sandbox);
}); });
after(function () { after(function () {
@ -103,7 +103,7 @@ describe('{{image}} helper', function () {
it('should output absolute url of image if the option is present ', function () { it('should output absolute url of image if the option is present ', function () {
var rendered = helpers.img_url('/blog/content/images/image-relative-url.png', {hash: {absolute: 'true'}}); var rendered = helpers.img_url('/blog/content/images/image-relative-url.png', {hash: {absolute: 'true'}});
should.exist(rendered); should.exist(rendered);
rendered.should.equal('http://localhost:82832/blog/content/images/image-relative-url.png'); rendered.should.equal('http://localhost:65535/blog/content/images/image-relative-url.png');
}); });
it('should not change output for an external url', function () { it('should not change output for an external url', function () {
@ -118,7 +118,7 @@ describe('{{image}} helper', function () {
before(function () { before(function () {
sandbox = sinon.createSandbox(); sandbox = sinon.createSandbox();
urlUtils.stubUrlUtils({url: 'http://localhost:82832/'}, sandbox); urlUtils.stubUrlUtils({url: 'http://localhost:65535/'}, sandbox);
}); });
after(function () { after(function () {
@ -126,7 +126,7 @@ describe('{{image}} helper', function () {
}); });
it('should output correct url for absolute paths which are internal', function () { it('should output correct url for absolute paths which are internal', function () {
var rendered = helpers.img_url('http://localhost:82832/content/images/my-coole-img.jpg', { var rendered = helpers.img_url('http://localhost:65535/content/images/my-coole-img.jpg', {
hash: { hash: {
size: 'medium' size: 'medium'
}, },

View File

@ -29,7 +29,7 @@ describe('{{url}} helper', function () {
describe('no subdir', function () { describe('no subdir', function () {
before(function () { before(function () {
sandbox = sinon.createSandbox(); sandbox = sinon.createSandbox();
urlUtils.stubUrlUtils({url: 'http://localhost:82832/'}, sandbox); urlUtils.stubUrlUtils({url: 'http://localhost:65535/'}, sandbox);
}); });
after(function () { after(function () {
@ -63,11 +63,11 @@ describe('{{url}} helper', function () {
created_at: new Date(0) created_at: new Date(0)
}); });
urlService.getUrlByResourceId.withArgs(post.id, {absolute: true, secure: undefined, withSubdirectory: true}).returns('http://localhost:82832/slug/'); urlService.getUrlByResourceId.withArgs(post.id, {absolute: true, secure: undefined, withSubdirectory: true}).returns('http://localhost:65535/slug/');
rendered = helpers.url.call(post, {hash: {absolute: 'true'}}); rendered = helpers.url.call(post, {hash: {absolute: 'true'}});
should.exist(rendered); should.exist(rendered);
rendered.string.should.equal('http://localhost:82832/slug/'); rendered.string.should.equal('http://localhost:65535/slug/');
}); });
it('should output an absolute URL with https if the option is present and secure', function () { it('should output an absolute URL with https if the option is present and secure', function () {
@ -81,11 +81,11 @@ describe('{{url}} helper', function () {
secure: true secure: true
}); });
urlService.getUrlByResourceId.withArgs(post.id, {absolute: true, secure: true, withSubdirectory: true}).returns('https://localhost:82832/slug/'); urlService.getUrlByResourceId.withArgs(post.id, {absolute: true, secure: true, withSubdirectory: true}).returns('https://localhost:65535/slug/');
rendered = helpers.url.call(post, {hash: {absolute: 'true'}}); rendered = helpers.url.call(post, {hash: {absolute: 'true'}});
should.exist(rendered); should.exist(rendered);
rendered.string.should.equal('https://localhost:82832/slug/'); rendered.string.should.equal('https://localhost:65535/slug/');
}); });
it('should return the slug with a prefixed /tag/ if the context is a tag', function () { it('should return the slug with a prefixed /tag/ if the context is a tag', function () {
@ -137,7 +137,7 @@ describe('{{url}} helper', function () {
{url: '/bar', label: 'Bar', slug: 'bar', current: true}, {url: '/bar', label: 'Bar', slug: 'bar', current: true},
{hash: {absolute: 'true'}}); {hash: {absolute: 'true'}});
should.exist(rendered); should.exist(rendered);
rendered.string.should.equal('http://localhost:82832/bar'); rendered.string.should.equal('http://localhost:65535/bar');
}); });
it('should return an absolute url with https if context is secure', function () { it('should return an absolute url with https if context is secure', function () {
@ -145,7 +145,7 @@ describe('{{url}} helper', function () {
{url: '/bar', label: 'Bar', slug: 'bar', current: true, secure: true}, {url: '/bar', label: 'Bar', slug: 'bar', current: true, secure: true},
{hash: {absolute: 'true'}}); {hash: {absolute: 'true'}});
should.exist(rendered); should.exist(rendered);
rendered.string.should.equal('https://localhost:82832/bar'); rendered.string.should.equal('https://localhost:65535/bar');
}); });
it('external urls should be retained in a nav context', function () { it('external urls should be retained in a nav context', function () {
@ -158,40 +158,40 @@ describe('{{url}} helper', function () {
it('should handle hosted urls in a nav context', function () { it('should handle hosted urls in a nav context', function () {
rendered = helpers.url.call( rendered = helpers.url.call(
{url: 'http://localhost:82832/qux', label: 'Qux', slug: 'qux', current: true}, {url: 'http://localhost:65535/qux', label: 'Qux', slug: 'qux', current: true},
{hash: {absolute: 'true'}}); {hash: {absolute: 'true'}});
should.exist(rendered); should.exist(rendered);
rendered.string.should.equal('http://localhost:82832/qux'); rendered.string.should.equal('http://localhost:65535/qux');
}); });
it('should handle hosted urls in a nav context with secure', function () { it('should handle hosted urls in a nav context with secure', function () {
rendered = helpers.url.call( rendered = helpers.url.call(
{ {
url: 'http://localhost:82832/qux', label: 'Qux', slug: 'qux', current: true, url: 'http://localhost:65535/qux', label: 'Qux', slug: 'qux', current: true,
secure: true secure: true
}, },
{hash: {absolute: 'true'}}); {hash: {absolute: 'true'}});
should.exist(rendered); should.exist(rendered);
rendered.string.should.equal('https://localhost:82832/qux'); rendered.string.should.equal('https://localhost:65535/qux');
}); });
it('should handle hosted https urls in a nav context with secure', function () { it('should handle hosted https urls in a nav context with secure', function () {
rendered = helpers.url.call( rendered = helpers.url.call(
{ {
url: 'https://localhost:82832/qux', label: 'Qux', slug: 'qux', current: true, url: 'https://localhost:65535/qux', label: 'Qux', slug: 'qux', current: true,
secure: true secure: true
}, },
{hash: {absolute: 'true'}}); {hash: {absolute: 'true'}});
should.exist(rendered); should.exist(rendered);
rendered.string.should.equal('https://localhost:82832/qux'); rendered.string.should.equal('https://localhost:65535/qux');
}); });
it('should handle hosted urls with the wrong protocol in a nav context', function () { it('should handle hosted urls with the wrong protocol in a nav context', function () {
rendered = helpers.url.call( rendered = helpers.url.call(
{url: 'https://localhost:82832/quux', label: 'Quux', slug: 'quux', current: true}, {url: 'https://localhost:65535/quux', label: 'Quux', slug: 'quux', current: true},
{hash: {absolute: 'true'}}); {hash: {absolute: 'true'}});
should.exist(rendered); should.exist(rendered);
rendered.string.should.equal('http://localhost:82832/quux'); rendered.string.should.equal('http://localhost:65535/quux');
}); });
it('should pass through protocol-less URLs regardless of absolute setting', function () { it('should pass through protocol-less URLs regardless of absolute setting', function () {
@ -275,7 +275,7 @@ describe('{{url}} helper', function () {
before(function () { before(function () {
sandbox = sinon.createSandbox(); sandbox = sinon.createSandbox();
urlUtils.stubUrlUtils({url: 'http://localhost:82832/blog'}, sandbox); urlUtils.stubUrlUtils({url: 'http://localhost:65535/blog'}, sandbox);
}); });
after(function () { after(function () {
@ -295,7 +295,7 @@ describe('{{url}} helper', function () {
{url: '/xyzzy', label: 'xyzzy', slug: 'xyzzy', current: true}, {url: '/xyzzy', label: 'xyzzy', slug: 'xyzzy', current: true},
{hash: {absolute: 'true'}}); {hash: {absolute: 'true'}});
should.exist(rendered); should.exist(rendered);
rendered.string.should.equal('http://localhost:82832/blog/xyzzy'); rendered.string.should.equal('http://localhost:65535/blog/xyzzy');
}); });
}); });
}); });

View File

@ -259,10 +259,11 @@ describe('Unit: services/url/UrlGenerator', function () {
}); });
const urlGenerator = new UrlGenerator(router, queue, resources, urls); const urlGenerator = new UrlGenerator(router, queue, resources, urls);
sinon.stub(urlUtils, 'replacePermalink').returns('/url/'); const replacePermalink = sinon.stub().returns('/url/');
sinon.stub(urlUtils, 'replacePermalink').get(() => replacePermalink);
urlGenerator._generateUrl(resource).should.eql('/url/'); urlGenerator._generateUrl(resource).should.eql('/url/');
urlUtils.replacePermalink.calledWith('/:slug/', resource.data).should.be.true(); replacePermalink.calledWith('/:slug/', resource.data).should.be.true();
}); });
}); });

View File

@ -21,9 +21,19 @@ const getInstance = (options) => {
const stubUrlUtils = (options, sandbox) => { const stubUrlUtils = (options, sandbox) => {
const stubInstance = getInstance(options); const stubInstance = getInstance(options);
const classPropNames = Object.getOwnPropertyNames(Object.getPrototypeOf(urlUtils))
.filter(name => name !== 'constructor');
Object.keys(urlUtils).forEach((key) => { classPropNames.forEach((key) => {
sandbox.stub(urlUtils, key).callsFake(stubInstance[key]); if (typeof urlUtils[key] === 'function') {
sandbox.stub(urlUtils, key).callsFake(function () {
return stubInstance[key](...arguments);
});
} else {
sandbox.stub(urlUtils, key).get(function () {
return stubInstance[key];
});
}
}); });
}; };

View File

@ -48,7 +48,7 @@
"@tryghost/members-theme-bindings": "0.2.3", "@tryghost/members-theme-bindings": "0.2.3",
"@tryghost/social-urls": "0.1.1", "@tryghost/social-urls": "0.1.1",
"@tryghost/string": "^0.1.3", "@tryghost/string": "^0.1.3",
"@tryghost/url-utils": "0.1.4", "@tryghost/url-utils": "0.2.0",
"ajv": "6.10.2", "ajv": "6.10.2",
"amperize": "0.6.0", "amperize": "0.6.0",
"analytics-node": "3.3.0", "analytics-node": "3.3.0",

View File

@ -267,10 +267,10 @@
dependencies: dependencies:
unidecode "^0.1.8" unidecode "^0.1.8"
"@tryghost/url-utils@0.1.4": "@tryghost/url-utils@0.2.0":
version "0.1.4" version "0.2.0"
resolved "https://registry.yarnpkg.com/@tryghost/url-utils/-/url-utils-0.1.4.tgz#52e93092bb5f830fb3afc770c5d708b781b936ca" resolved "https://registry.yarnpkg.com/@tryghost/url-utils/-/url-utils-0.2.0.tgz#d32b23122ea78b23a63c6ab25d160cbf4f65e53e"
integrity sha512-1PIIIlDvQmJXS8fM5QLbKp0Xdx3M4Hk53AzskRQWlYiK6BISX5U+4LxwzRg+rWQHhUltMQuQk00DWOZwoe4Ajg== integrity sha512-/Ex9z8RUAfAek8z7EMvnDBIV5P88jwL1X4KwXxZy5udn0aQShvSwsO5euOpUcjBOn2ZsUT3aXYsB+pz7uXm8hw==
dependencies: dependencies:
cheerio "0.22.0" cheerio "0.22.0"
lodash "4.17.11" lodash "4.17.11"