0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-20 22:42:53 -05:00
ghost/test/unit/lib/image/image-size_spec.js

539 lines
24 KiB
JavaScript
Raw Normal View History

const should = require('should');
const sinon = require('sinon');
const rewire = require('rewire');
const nock = require('nock');
const path = require('path');
const configUtils = require('../../../utils/configUtils');
const urlUtils = require('../../../../core/shared/url-utils');
const errors = require('@tryghost/errors');
const storage = require('../../../../core/server/adapters/storage');
describe('lib/image: image size', function () {
let imageSize;
let sizeOf;
let sizeOfSpy;
let probeSizeOf;
let probeSizeOfSpy;
let originalStoragePath;
// use a 1x1 gif in nock responses because it's really small and easy to work with
const GIF1x1 = Buffer.from('R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==', 'base64');
beforeEach(function () {
imageSize = rewire('../../../../core/server/lib/image/image-size');
sizeOf = imageSize.__get__('sizeOf');
sizeOfSpy = sinon.spy(sizeOf);
probeSizeOf = imageSize.__get__('probeSizeOf');
probeSizeOfSpy = sinon.spy(probeSizeOf);
originalStoragePath = storage.getStorage().storagePath;
});
afterEach(function () {
sinon.restore();
configUtils.restore();
storage.getStorage().storagePath = originalStoragePath;
});
it('[success] should have an image size function', function () {
should.exist(imageSize.getImageSizeFromUrl);
should.exist(imageSize.getImageSizeFromStoragePath);
});
describe('getImageSizeFromUrl', function () {
it('[success] should return image dimensions from probe request for probe-supported extension', function (done) {
const url = 'http://img.stockfresh.com/files/f/feedough/x/11/1540353_20925115.jpg';
const expectedImageObject = {
height: 1,
url: 'http://img.stockfresh.com/files/f/feedough/x/11/1540353_20925115.jpg',
width: 1
};
const requestMock = nock('http://img.stockfresh.com')
.get('/files/f/feedough/x/11/1540353_20925115.jpg')
.reply(200, GIF1x1);
imageSize.getImageSizeFromUrl(url).then(function (res) {
probeSizeOfSpy.should.have.been.called;
sizeOfSpy.should.not.have.been.called;
requestMock.isDone().should.be.true();
should.exist(res);
res.width.should.be.equal(expectedImageObject.width);
res.height.should.be.equal(expectedImageObject.height);
res.url.should.be.equal(expectedImageObject.url);
done();
}).catch(done);
});
it('[success] should return image dimensions from fetch request for non-probe-supported extension', function (done) {
const url = 'https://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.ico';
const expectedImageObject = {
height: 1,
url: 'https://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.ico',
width: 1
};
const requestMock = nock('https://static.wixstatic.com')
.get('/media/355241_d31358572a2542c5a44738ddcb59e7ea.ico')
.reply(200, GIF1x1);
imageSize.getImageSizeFromUrl(url).then(function (res) {
sizeOfSpy.should.have.been.called;
probeSizeOfSpy.should.not.have.been.called;
requestMock.isDone().should.be.true();
should.exist(res);
res.width.should.be.equal(expectedImageObject.width);
res.height.should.be.equal(expectedImageObject.height);
res.url.should.be.equal(expectedImageObject.url);
done();
}).catch(done);
});
it('[success] should return image dimensions when no image extension given', function (done) {
const url = 'https://www.zomato.com/logo/18163505/minilogo';
const expectedImageObject = {
height: 1,
url: 'https://www.zomato.com/logo/18163505/minilogo',
width: 1
};
const requestMock = nock('https://www.zomato.com')
.get('/logo/18163505/minilogo')
.reply(200, GIF1x1);
imageSize.getImageSizeFromUrl(url).then(function (res) {
probeSizeOfSpy.should.have.been.called;
requestMock.isDone().should.be.true();
should.exist(res);
res.width.should.be.equal(expectedImageObject.width);
res.height.should.be.equal(expectedImageObject.height);
res.url.should.be.equal(expectedImageObject.url);
done();
}).catch(done);
});
it('[success] should returns largest image value for .ico files', function (done) {
const url = 'https://super-website.com/media/icon.ico';
const expectedImageObject = {
height: 64,
url: 'https://super-website.com/media/icon.ico',
width: 64
};
const requestMock = nock('https://super-website.com')
.get('/media/icon.ico')
.replyWithFile(200, path.join(__dirname, '/../../../utils/fixtures/images/favicon_multi_sizes.ico'));
imageSize.getImageSizeFromUrl(url).then(function (res) {
requestMock.isDone().should.be.true();
should.exist(res);
res.width.should.be.equal(expectedImageObject.width);
res.height.should.be.equal(expectedImageObject.height);
res.url.should.be.equal(expectedImageObject.url);
done();
}).catch(done);
});
🐛 Fix invalid image URLs not being cached and causing timeouts (#8986) refs #8868 * 📐 Use request util in image-size - swapped the usage of `got` for requests with the request util * 💄 Use catch predicates - Uses catch predicates instead of conditionals in `getImageSizeFromUrl` - Return `NotFoundError` if applicable in `getImageSizeFromFilePath` as the caller function `cachedImageSizeFromUrl` is differentiating those between this error and others. * 🐛 Fixed ImageObject URL & simplify no protocol URL logic - Using `ImageObject` as a global var resulted in having the `url` property being the same for all requests coming in. - The logic that checked for an existing protocol (e. g. gravatar URLs) was overly complicated. Refactored it to be more simple. - Passing the correct value to `fetchDimensionsFromBuffer` as the population of `imageObject.url` happens there. These are used in our structured data and need to be full URLs (in case of locally stored files) or the original URL (in case of URLs missing the protocol) - Added two more debug logs in `getCachedImageSizeFromUrl` so it's logged when an image is added to the cache even tho it was returned as error. * 👀 Differentiate error codes between request and storage * 🔥 Remove not needed `Promise.resolve()` We're always resolving the result in `getCachedImageSizeFromUrl`, so there's no need to return the values with a `Promise.resolve()`. The caller fn uses waits for the Promises to be fulfilled. * ☂️ Wrap already rejected predicate errors in catch all * Use errorDetails instead of context * ☂️ Support /assets/ image paths - adds a guard that checks the image URL for `/assets/` in the beginning and passes a completed URL to the request util to try and fetch the image size - adds tests
2017-09-12 18:53:18 +07:00
it('[success] should return image dimensions asset path images', function (done) {
const url = '/assets/img/logo.png?v=d30c3d1e41';
const expectedImageObject = {
height: 1,
url: 'http://myblog.com/assets/img/logo.png?v=d30c3d1e41',
width: 1
};
const urlForStub = sinon.stub(urlUtils, 'urlFor');
🐛 Fix invalid image URLs not being cached and causing timeouts (#8986) refs #8868 * 📐 Use request util in image-size - swapped the usage of `got` for requests with the request util * 💄 Use catch predicates - Uses catch predicates instead of conditionals in `getImageSizeFromUrl` - Return `NotFoundError` if applicable in `getImageSizeFromFilePath` as the caller function `cachedImageSizeFromUrl` is differentiating those between this error and others. * 🐛 Fixed ImageObject URL & simplify no protocol URL logic - Using `ImageObject` as a global var resulted in having the `url` property being the same for all requests coming in. - The logic that checked for an existing protocol (e. g. gravatar URLs) was overly complicated. Refactored it to be more simple. - Passing the correct value to `fetchDimensionsFromBuffer` as the population of `imageObject.url` happens there. These are used in our structured data and need to be full URLs (in case of locally stored files) or the original URL (in case of URLs missing the protocol) - Added two more debug logs in `getCachedImageSizeFromUrl` so it's logged when an image is added to the cache even tho it was returned as error. * 👀 Differentiate error codes between request and storage * 🔥 Remove not needed `Promise.resolve()` We're always resolving the result in `getCachedImageSizeFromUrl`, so there's no need to return the values with a `Promise.resolve()`. The caller fn uses waits for the Promises to be fulfilled. * ☂️ Wrap already rejected predicate errors in catch all * Use errorDetails instead of context * ☂️ Support /assets/ image paths - adds a guard that checks the image URL for `/assets/` in the beginning and passes a completed URL to the request util to try and fetch the image size - adds tests
2017-09-12 18:53:18 +07:00
urlForStub.withArgs('home').returns('http://myblog.com/');
const urlGetSubdirStub = sinon.stub(urlUtils, 'getSubdir');
🐛 Fix invalid image URLs not being cached and causing timeouts (#8986) refs #8868 * 📐 Use request util in image-size - swapped the usage of `got` for requests with the request util * 💄 Use catch predicates - Uses catch predicates instead of conditionals in `getImageSizeFromUrl` - Return `NotFoundError` if applicable in `getImageSizeFromFilePath` as the caller function `cachedImageSizeFromUrl` is differentiating those between this error and others. * 🐛 Fixed ImageObject URL & simplify no protocol URL logic - Using `ImageObject` as a global var resulted in having the `url` property being the same for all requests coming in. - The logic that checked for an existing protocol (e. g. gravatar URLs) was overly complicated. Refactored it to be more simple. - Passing the correct value to `fetchDimensionsFromBuffer` as the population of `imageObject.url` happens there. These are used in our structured data and need to be full URLs (in case of locally stored files) or the original URL (in case of URLs missing the protocol) - Added two more debug logs in `getCachedImageSizeFromUrl` so it's logged when an image is added to the cache even tho it was returned as error. * 👀 Differentiate error codes between request and storage * 🔥 Remove not needed `Promise.resolve()` We're always resolving the result in `getCachedImageSizeFromUrl`, so there's no need to return the values with a `Promise.resolve()`. The caller fn uses waits for the Promises to be fulfilled. * ☂️ Wrap already rejected predicate errors in catch all * Use errorDetails instead of context * ☂️ Support /assets/ image paths - adds a guard that checks the image URL for `/assets/` in the beginning and passes a completed URL to the request util to try and fetch the image size - adds tests
2017-09-12 18:53:18 +07:00
urlGetSubdirStub.returns('');
const requestMock = nock('http://myblog.com')
🐛 Fix invalid image URLs not being cached and causing timeouts (#8986) refs #8868 * 📐 Use request util in image-size - swapped the usage of `got` for requests with the request util * 💄 Use catch predicates - Uses catch predicates instead of conditionals in `getImageSizeFromUrl` - Return `NotFoundError` if applicable in `getImageSizeFromFilePath` as the caller function `cachedImageSizeFromUrl` is differentiating those between this error and others. * 🐛 Fixed ImageObject URL & simplify no protocol URL logic - Using `ImageObject` as a global var resulted in having the `url` property being the same for all requests coming in. - The logic that checked for an existing protocol (e. g. gravatar URLs) was overly complicated. Refactored it to be more simple. - Passing the correct value to `fetchDimensionsFromBuffer` as the population of `imageObject.url` happens there. These are used in our structured data and need to be full URLs (in case of locally stored files) or the original URL (in case of URLs missing the protocol) - Added two more debug logs in `getCachedImageSizeFromUrl` so it's logged when an image is added to the cache even tho it was returned as error. * 👀 Differentiate error codes between request and storage * 🔥 Remove not needed `Promise.resolve()` We're always resolving the result in `getCachedImageSizeFromUrl`, so there's no need to return the values with a `Promise.resolve()`. The caller fn uses waits for the Promises to be fulfilled. * ☂️ Wrap already rejected predicate errors in catch all * Use errorDetails instead of context * ☂️ Support /assets/ image paths - adds a guard that checks the image URL for `/assets/` in the beginning and passes a completed URL to the request util to try and fetch the image size - adds tests
2017-09-12 18:53:18 +07:00
.get('/assets/img/logo.png?v=d30c3d1e41')
.reply(200, GIF1x1);
🐛 Fix invalid image URLs not being cached and causing timeouts (#8986) refs #8868 * 📐 Use request util in image-size - swapped the usage of `got` for requests with the request util * 💄 Use catch predicates - Uses catch predicates instead of conditionals in `getImageSizeFromUrl` - Return `NotFoundError` if applicable in `getImageSizeFromFilePath` as the caller function `cachedImageSizeFromUrl` is differentiating those between this error and others. * 🐛 Fixed ImageObject URL & simplify no protocol URL logic - Using `ImageObject` as a global var resulted in having the `url` property being the same for all requests coming in. - The logic that checked for an existing protocol (e. g. gravatar URLs) was overly complicated. Refactored it to be more simple. - Passing the correct value to `fetchDimensionsFromBuffer` as the population of `imageObject.url` happens there. These are used in our structured data and need to be full URLs (in case of locally stored files) or the original URL (in case of URLs missing the protocol) - Added two more debug logs in `getCachedImageSizeFromUrl` so it's logged when an image is added to the cache even tho it was returned as error. * 👀 Differentiate error codes between request and storage * 🔥 Remove not needed `Promise.resolve()` We're always resolving the result in `getCachedImageSizeFromUrl`, so there's no need to return the values with a `Promise.resolve()`. The caller fn uses waits for the Promises to be fulfilled. * ☂️ Wrap already rejected predicate errors in catch all * Use errorDetails instead of context * ☂️ Support /assets/ image paths - adds a guard that checks the image URL for `/assets/` in the beginning and passes a completed URL to the request util to try and fetch the image size - adds tests
2017-09-12 18:53:18 +07:00
imageSize.getImageSizeFromUrl(url).then(function (res) {
probeSizeOfSpy.should.have.been.called;
🐛 Fix invalid image URLs not being cached and causing timeouts (#8986) refs #8868 * 📐 Use request util in image-size - swapped the usage of `got` for requests with the request util * 💄 Use catch predicates - Uses catch predicates instead of conditionals in `getImageSizeFromUrl` - Return `NotFoundError` if applicable in `getImageSizeFromFilePath` as the caller function `cachedImageSizeFromUrl` is differentiating those between this error and others. * 🐛 Fixed ImageObject URL & simplify no protocol URL logic - Using `ImageObject` as a global var resulted in having the `url` property being the same for all requests coming in. - The logic that checked for an existing protocol (e. g. gravatar URLs) was overly complicated. Refactored it to be more simple. - Passing the correct value to `fetchDimensionsFromBuffer` as the population of `imageObject.url` happens there. These are used in our structured data and need to be full URLs (in case of locally stored files) or the original URL (in case of URLs missing the protocol) - Added two more debug logs in `getCachedImageSizeFromUrl` so it's logged when an image is added to the cache even tho it was returned as error. * 👀 Differentiate error codes between request and storage * 🔥 Remove not needed `Promise.resolve()` We're always resolving the result in `getCachedImageSizeFromUrl`, so there's no need to return the values with a `Promise.resolve()`. The caller fn uses waits for the Promises to be fulfilled. * ☂️ Wrap already rejected predicate errors in catch all * Use errorDetails instead of context * ☂️ Support /assets/ image paths - adds a guard that checks the image URL for `/assets/` in the beginning and passes a completed URL to the request util to try and fetch the image size - adds tests
2017-09-12 18:53:18 +07:00
requestMock.isDone().should.be.true();
should.exist(res);
res.width.should.be.equal(expectedImageObject.width);
res.height.should.be.equal(expectedImageObject.height);
res.url.should.be.equal(expectedImageObject.url);
done();
}).catch(done);
});
it('[success] should return image dimensions for gravatar images request', function (done) {
const url = '//www.gravatar.com/avatar/ef6dcde5c99bb8f685dd451ccc3e050a?s=250&d=mm&r=x';
const expectedImageObject = {
height: 1,
url: '//www.gravatar.com/avatar/ef6dcde5c99bb8f685dd451ccc3e050a?s=250&d=mm&r=x',
width: 1
};
const requestMock = nock('http://www.gravatar.com')
.get('/avatar/ef6dcde5c99bb8f685dd451ccc3e050a?s=250&d=mm&r=x')
.reply(200, GIF1x1);
imageSize.getImageSizeFromUrl(url).then(function (res) {
probeSizeOfSpy.should.have.been.called;
requestMock.isDone().should.be.true();
should.exist(res);
res.width.should.be.equal(expectedImageObject.width);
res.height.should.be.equal(expectedImageObject.height);
res.url.should.be.equal(expectedImageObject.url);
done();
}).catch(done);
});
it('[success] can handle redirect (probe-image-size)', function (done) {
const url = 'http://noimagehere.com/files/f/feedough/x/11/1540353_20925115.jpg';
const expectedImageObject = {
height: 1,
url: 'http://noimagehere.com/files/f/feedough/x/11/1540353_20925115.jpg',
width: 1
};
const requestMock = nock('http://noimagehere.com')
.get('/files/f/feedough/x/11/1540353_20925115.jpg')
.reply(301, null, {
location: 'http://someredirectedurl.com/files/f/feedough/x/11/1540353_20925115.jpg'
});
const secondRequestMock = nock('http://someredirectedurl.com')
.get('/files/f/feedough/x/11/1540353_20925115.jpg')
.reply(200, GIF1x1);
imageSize.getImageSizeFromUrl(url).then(function (res) {
probeSizeOfSpy.should.have.been.called;
requestMock.isDone().should.be.true();
secondRequestMock.isDone().should.be.true();
should.exist(res);
res.width.should.be.equal(expectedImageObject.width);
res.height.should.be.equal(expectedImageObject.height);
res.url.should.be.equal(expectedImageObject.url);
done();
}).catch(done);
});
it('[success] can handle redirect (image-size)', function (done) {
const url = 'http://noimagehere.com/files/f/feedough/x/11/1540353_20925115.gif';
const expectedImageObject = {
height: 1,
url: 'http://noimagehere.com/files/f/feedough/x/11/1540353_20925115.gif',
width: 1
};
const requestMock = nock('http://noimagehere.com')
.get('/files/f/feedough/x/11/1540353_20925115.gif')
.reply(301, null, {
location: 'http://someredirectedurl.com/files/f/feedough/x/11/1540353_20925115.gif'
});
const secondRequestMock = nock('http://someredirectedurl.com')
.get('/files/f/feedough/x/11/1540353_20925115.gif')
.reply(200, GIF1x1);
imageSize.getImageSizeFromUrl(url).then(function (res) {
sizeOfSpy.should.have.been.called;
requestMock.isDone().should.be.true();
secondRequestMock.isDone().should.be.true();
should.exist(res);
res.width.should.be.equal(expectedImageObject.width);
res.height.should.be.equal(expectedImageObject.height);
res.url.should.be.equal(expectedImageObject.url);
done();
}).catch(done);
});
it('[success] should switch to local file storage if available', function (done) {
const url = '/content/images/favicon.png';
const expectedImageObject = {
height: 100,
url: 'http://myblog.com/content/images/favicon.png',
width: 100
};
storage.getStorage().storagePath = path.join(__dirname, '../../../../test/utils/fixtures/images/');
const urlForStub = sinon.stub(urlUtils, 'urlFor');
urlForStub.withArgs('image').returns('http://myblog.com/content/images/favicon.png');
urlForStub.withArgs('home').returns('http://myblog.com/');
const urlGetSubdirStub = sinon.stub(urlUtils, 'getSubdir');
urlGetSubdirStub.returns('');
const requestMock = nock('http://myblog.com')
.get('/content/images/favicon.png')
.reply(200, {
body: '<Buffer 2c be a4 40 f7 87 73 1e 57 2c c1 e4 0d 79 03 95 42 f0 42 2e 41 95 27 c9 5c 35 a7 71 2c 09 5a 57 d3 04 1e 83 03 28 07 96 b0 c8 88 65 07 7a d1 d6 63 50>'
});
imageSize.getImageSizeFromUrl(url).then(function (res) {
requestMock.isDone().should.be.false();
should.exist(res);
should.exist(res.width);
res.width.should.be.equal(expectedImageObject.width);
should.exist(res.height);
res.height.should.be.equal(expectedImageObject.height);
should.exist(res.url);
res.url.should.be.equal(expectedImageObject.url);
done();
}).catch(done);
});
it('[failure] can handle an error with statuscode not 200 (probe-image-size)', function (done) {
const url = 'http://noimagehere.com/files/f/feedough/x/11/1540353_20925115.jpg';
const requestMock = nock('http://noimagehere.com')
.get('/files/f/feedough/x/11/1540353_20925115.jpg')
.reply(404);
imageSize.getImageSizeFromUrl(url)
.catch(function (err) {
probeSizeOfSpy.should.have.been.called;
requestMock.isDone().should.be.true();
should.exist(err);
err.errorType.should.be.equal('NotFoundError');
err.message.should.be.equal('Image not found.');
done();
});
});
it('[failure] can handle an error with statuscode not 200 (image-size)', function (done) {
const url = 'http://noimagehere.com/files/f/feedough/x/11/1540353_20925115.gif';
const requestMock = nock('http://noimagehere.com')
.get('/files/f/feedough/x/11/1540353_20925115.gif')
.reply(404);
imageSize.getImageSizeFromUrl(url)
.catch(function (err) {
sizeOfSpy.should.have.been.called;
requestMock.isDone().should.be.true();
should.exist(err);
err.errorType.should.be.equal('NotFoundError');
err.message.should.be.equal('Image not found.');
done();
});
});
it('[failure] handles invalid URL', function (done) {
const url = 'Not-a-valid-url';
imageSize.getImageSizeFromUrl(url)
.catch(function (err) {
should.exist(err);
err.errorType.should.be.equal('InternalServerError');
err.message.should.be.equal('URL empty or invalid.');
done();
});
});
it('[failure] will timeout', function (done) {
const url = 'https://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256';
const requestMock = nock('https://static.wixstatic.com')
.get('/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256')
2020-07-21 18:53:06 +01:00
.delayConnection(11)
.reply(408);
configUtils.set('times:getImageSizeTimeoutInMS', 10);
imageSize.getImageSizeFromUrl(url)
.catch(function (err) {
requestMock.isDone().should.be.true();
should.exist(err);
err.errorType.should.be.equal('InternalServerError');
err.message.should.be.equal('Request timed out.');
done();
});
});
it('[failure] returns error if \`probe-image-size`\ module throws error', function (done) {
const url = 'https://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg';
const probeSizeOfStub = sinon.stub();
probeSizeOfStub.throws({error: 'probe-image-size could not find dimensions'});
imageSize.__set__('probeSizeOf', probeSizeOfStub);
imageSize.getImageSizeFromUrl(url)
.then(() => {
true.should.be.false('succeeded when expecting failure');
})
.catch(function (err) {
should.exist(err);
err.errorType.should.be.equal('InternalServerError');
err.error.should.be.equal('probe-image-size could not find dimensions');
done();
});
});
it('[failure] returns error if \`image-size`\ module throws error', function (done) {
const url = 'https://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.ico';
const requestMock = nock('https://static.wixstatic.com')
.get('/media/355241_d31358572a2542c5a44738ddcb59e7ea.ico')
.reply(200, {
body: '<Buffer 2c be a4 40 f7 87 73 1e 57 2c c1 e4 0d 79 03 95 42 f0 42 2e 41 95 27 c9 5c 35 a7 71 2c 09 5a 57 d3 04 1e 83 03 28 07 96 b0 c8 88 65 07 7a d1 d6 63 50>'
});
const sizeOfStub = sinon.stub();
sizeOfStub.throws({error: 'image-size could not find dimensions'});
imageSize.__set__('sizeOf', sizeOfStub);
imageSize.getImageSizeFromUrl(url)
.then(() => {
true.should.be.false('succeeded when expecting failure');
})
.catch(function (err) {
requestMock.isDone().should.be.true();
should.exist(err);
err.errorType.should.be.equal('InternalServerError');
err.error.should.be.equal('image-size could not find dimensions');
done();
});
});
it('[failure] returns error if request errors', function (done) {
const url = 'https://notarealwebsite.com/images/notapicture.jpg';
const requestMock = nock('https://notarealwebsite.com')
.get('/images/notapicture.jpg')
.reply(500, {message: 'something awful happened', code: 'AWFUL_ERROR'});
imageSize.getImageSizeFromUrl(url)
.catch(function (err) {
requestMock.isDone().should.be.true();
should.exist(err);
err.errorType.should.be.equal('InternalServerError');
err.message.should.be.equal('Unknown Request error.');
done();
});
});
});
describe('getImageSizeFromStoragePath', function () {
it('[success] should return image dimensions for locally stored images', function (done) {
const url = '/content/images/ghost-logo.png';
const expectedImageObject = {
height: 257,
url: 'http://myblog.com/content/images/ghost-logo.png',
width: 800
};
storage.getStorage().storagePath = path.join(__dirname, '../../../../test/utils/fixtures/images/');
const urlForStub = sinon.stub(urlUtils, 'urlFor');
urlForStub.withArgs('image').returns('http://myblog.com/content/images/ghost-logo.png');
urlForStub.withArgs('home').returns('http://myblog.com/');
const urlGetSubdirStub = sinon.stub(urlUtils, 'getSubdir');
urlGetSubdirStub.returns('');
imageSize.getImageSizeFromStoragePath(url).then(function (res) {
should.exist(res);
should.exist(res.width);
res.width.should.be.equal(expectedImageObject.width);
should.exist(res.height);
res.height.should.be.equal(expectedImageObject.height);
should.exist(res.url);
res.url.should.be.equal(expectedImageObject.url);
done();
}).catch(done);
});
it('[success] should return image dimensions for locally stored images with subdirectory', function (done) {
const url = '/content/images/favicon_too_large.png';
const expectedImageObject = {
height: 1010,
url: 'http://myblog.com/blog/content/images/favicon_too_large.png',
width: 1010
};
storage.getStorage().storagePath = path.join(__dirname, '../../../../test/utils/fixtures/images/');
const urlForStub = sinon.stub(urlUtils, 'urlFor');
urlForStub.withArgs('image').returns('http://myblog.com/blog/content/images/favicon_too_large.png');
urlForStub.withArgs('home').returns('http://myblog.com/');
const urlGetSubdirStub = sinon.stub(urlUtils, 'getSubdir');
urlGetSubdirStub.returns('/blog');
imageSize.getImageSizeFromStoragePath(url).then(function (res) {
should.exist(res);
should.exist(res.width);
res.width.should.be.equal(expectedImageObject.width);
should.exist(res.height);
res.height.should.be.equal(expectedImageObject.height);
should.exist(res.url);
res.url.should.be.equal(expectedImageObject.url);
done();
}).catch(done);
});
it('[success] should return largest image dimensions for locally stored .ico image', function (done) {
const url = 'http://myblog.com/content/images/favicon_multi_sizes.ico';
const expectedImageObject = {
height: 64,
url: 'http://myblog.com/content/images/favicon_multi_sizes.ico',
width: 64
};
storage.getStorage().storagePath = path.join(__dirname, '../../../../test/utils/fixtures/images/');
const urlForStub = sinon.stub(urlUtils, 'urlFor');
urlForStub.withArgs('image').returns('http://myblog.com/content/images/favicon_multi_sizes.ico');
urlForStub.withArgs('home').returns('http://myblog.com/');
const urlGetSubdirStub = sinon.stub(urlUtils, 'getSubdir');
urlGetSubdirStub.returns('');
imageSize.getImageSizeFromStoragePath(url).then(function (res) {
should.exist(res);
should.exist(res.width);
res.width.should.be.equal(expectedImageObject.width);
should.exist(res.height);
res.height.should.be.equal(expectedImageObject.height);
should.exist(res.url);
res.url.should.be.equal(expectedImageObject.url);
done();
}).catch(done);
});
it('[failure] returns error if storage adapter errors', function (done) {
const url = '/content/images/not-existing-image.png';
storage.getStorage().storagePath = path.join(__dirname, '../../../../test/utils/fixtures/images/');
const urlForStub = sinon.stub(urlUtils, 'urlFor');
urlForStub.withArgs('image').returns('http://myblog.com/content/images/not-existing-image.png');
urlForStub.withArgs('home').returns('http://myblog.com/');
const urlGetSubdirStub = sinon.stub(urlUtils, 'getSubdir');
urlGetSubdirStub.returns('');
imageSize.getImageSizeFromStoragePath(url)
.catch(function (err) {
should.exist(err);
(err instanceof errors.NotFoundError).should.eql(true);
done();
});
});
it('[failure] returns error if \`image-size`\ module throws error', function (done) {
const url = '/content/images/ghost-logo.pngx';
const sizeOfStub = sinon.stub();
sizeOfStub.throws({error: 'image-size could not find dimensions'});
imageSize.__set__('sizeOf', sizeOfStub);
storage.getStorage().storagePath = path.join(__dirname, '../../../../test/utils/fixtures/images/');
const urlForStub = sinon.stub(urlUtils, 'urlFor');
urlForStub.withArgs('image').returns('http://myblog.com/content/images/ghost-logo.pngx');
urlForStub.withArgs('home').returns('http://myblog.com/');
const urlGetSubdirStub = sinon.stub(urlUtils, 'getSubdir');
urlGetSubdirStub.returns('');
imageSize.getImageSizeFromStoragePath(url)
.catch(function (err) {
should.exist(err);
err.error.should.be.equal('image-size could not find dimensions');
done();
});
});
});
});