Merge branch 'main' into main
This commit is contained in:
commit
f83b5b082c
@ -11,7 +11,8 @@
|
||||
"scripts": {
|
||||
"build": "concurrently \"vite build\" \"tsc -p tsconfig.declaration.json\"",
|
||||
"prepare": "yarn build",
|
||||
"test": "yarn test:types",
|
||||
"test": "yarn test:unit && yarn test:types",
|
||||
"test:unit": "yarn nx build && vitest run",
|
||||
"test:types": "tsc --noEmit",
|
||||
"lint:code": "eslint --ext .js,.ts,.cjs,.tsx src/ --cache",
|
||||
"lint": "yarn lint:code && yarn lint:test",
|
||||
@ -36,6 +37,7 @@
|
||||
"@storybook/react-vite": "7.6.4",
|
||||
"@storybook/testing-library": "0.2.2",
|
||||
"@testing-library/react": "14.1.0",
|
||||
"@testing-library/react-hooks" : "8.0.1",
|
||||
"@vitejs/plugin-react": "4.2.1",
|
||||
"c8": "8.0.1",
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
@ -43,6 +45,7 @@
|
||||
"eslint-plugin-tailwindcss": "3.13.0",
|
||||
"jsdom": "24.1.0",
|
||||
"mocha": "10.2.0",
|
||||
"chai": "4.3.8",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"rollup-plugin-node-builtins": "2.1.2",
|
||||
|
@ -3,6 +3,6 @@ import assert from 'assert/strict';
|
||||
describe('Hello world', function () {
|
||||
it('Runs a test', function () {
|
||||
// TODO: Write me!
|
||||
assert.ok(require('../'));
|
||||
assert.equal(1, 1);
|
||||
});
|
||||
});
|
116
apps/admin-x-design-system/test/unit/hooks/usePagination.test.ts
Normal file
116
apps/admin-x-design-system/test/unit/hooks/usePagination.test.ts
Normal file
@ -0,0 +1,116 @@
|
||||
import {expect} from 'chai';
|
||||
import {renderHook, act} from '@testing-library/react-hooks';
|
||||
import {usePagination, PaginationMeta, PaginationData} from '../../../src/hooks/usePagination';
|
||||
|
||||
describe('usePagination', function () {
|
||||
const initialMeta: PaginationMeta = {
|
||||
limit: 10,
|
||||
pages: 5,
|
||||
total: 50,
|
||||
next: null,
|
||||
prev: null
|
||||
};
|
||||
|
||||
it('should initialize with the given meta and page', function () {
|
||||
const {result} = renderHook(() => usePagination({
|
||||
meta: initialMeta,
|
||||
limit: 10,
|
||||
page: 1,
|
||||
setPage: () => {}
|
||||
})
|
||||
);
|
||||
|
||||
const expectedData: PaginationData = {
|
||||
page: 1,
|
||||
pages: initialMeta.pages,
|
||||
total: initialMeta.total,
|
||||
limit: initialMeta.limit,
|
||||
setPage: result.current.setPage,
|
||||
nextPage: result.current.nextPage,
|
||||
prevPage: result.current.prevPage
|
||||
};
|
||||
|
||||
expect(result.current).to.deep.equal(expectedData);
|
||||
});
|
||||
|
||||
it('should update page correctly when nextPage and prevPage are called', function () {
|
||||
let currentPage = 1;
|
||||
const setPage = (newPage: number) => {
|
||||
currentPage = newPage;
|
||||
};
|
||||
|
||||
const {result} = renderHook(() => usePagination({
|
||||
meta: initialMeta,
|
||||
limit: 10,
|
||||
page: currentPage,
|
||||
setPage
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.nextPage();
|
||||
});
|
||||
|
||||
expect(currentPage).to.equal(2);
|
||||
|
||||
act(() => {
|
||||
result.current.prevPage();
|
||||
});
|
||||
|
||||
expect(currentPage).to.equal(1);
|
||||
});
|
||||
|
||||
it('should update page correctly when setPage is called', function () {
|
||||
let currentPage = 3;
|
||||
const setPage = (newPage: number) => {
|
||||
currentPage = newPage;
|
||||
};
|
||||
|
||||
const {result} = renderHook(() => usePagination({
|
||||
meta: initialMeta,
|
||||
limit: 10,
|
||||
page: currentPage,
|
||||
setPage
|
||||
})
|
||||
);
|
||||
|
||||
const newPage = 5;
|
||||
|
||||
act(() => {
|
||||
result.current.setPage(newPage);
|
||||
});
|
||||
|
||||
expect(currentPage).to.equal(newPage);
|
||||
});
|
||||
|
||||
it('should handle edge cases where meta.pages < page when setting meta', function () {
|
||||
let currentPage = 5;
|
||||
const setPage = (newPage: number) => {
|
||||
currentPage = newPage;
|
||||
};
|
||||
|
||||
const {rerender} = renderHook(
|
||||
({meta}) => usePagination({
|
||||
meta,
|
||||
limit: 10,
|
||||
page: currentPage,
|
||||
setPage
|
||||
}),
|
||||
{initialProps: {meta: initialMeta}}
|
||||
);
|
||||
|
||||
const updatedMeta: PaginationMeta = {
|
||||
limit: 10,
|
||||
pages: 4,
|
||||
total: 40,
|
||||
next: null,
|
||||
prev: null
|
||||
};
|
||||
|
||||
act(() => {
|
||||
rerender({meta: updatedMeta});
|
||||
});
|
||||
|
||||
expect(currentPage).to.equal(4);
|
||||
});
|
||||
});
|
@ -0,0 +1,150 @@
|
||||
import {expect} from 'chai';
|
||||
import {renderHook, act} from '@testing-library/react-hooks';
|
||||
import useSortableIndexedList from '../../../src/hooks/useSortableIndexedList';
|
||||
import sinon from 'sinon';
|
||||
|
||||
describe('useSortableIndexedList', function () {
|
||||
// Mock initial items and blank item
|
||||
const initialItems = [{name: 'Item 1'}, {name: 'Item 2'}];
|
||||
const blankItem = {name: ''};
|
||||
|
||||
// Mock canAddNewItem function
|
||||
const canAddNewItem = (item: { name: string }) => !!item.name;
|
||||
|
||||
it('should initialize with the given items', function () {
|
||||
const setItems = sinon.spy();
|
||||
|
||||
const {result} = renderHook(() => useSortableIndexedList({
|
||||
items: initialItems,
|
||||
setItems,
|
||||
blank: blankItem,
|
||||
canAddNewItem
|
||||
})
|
||||
);
|
||||
|
||||
// Assert initial items setup correctly
|
||||
expect(result.current.items).to.deep.equal(initialItems.map((item, index) => ({item, id: index.toString()})));
|
||||
});
|
||||
|
||||
it('should add a new item', function () {
|
||||
let items = initialItems;
|
||||
const setItems = (newItems: any[]) => {
|
||||
items = newItems;
|
||||
};
|
||||
|
||||
const {result} = renderHook(() => useSortableIndexedList({
|
||||
items,
|
||||
setItems,
|
||||
blank: blankItem,
|
||||
canAddNewItem
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.setNewItem({name: 'New Item'});
|
||||
result.current.addItem();
|
||||
});
|
||||
|
||||
// Assert items updated correctly after adding new item
|
||||
expect(items).to.deep.equal([...initialItems, {name: 'New Item'}]);
|
||||
});
|
||||
|
||||
it('should update an item', function () {
|
||||
let items = initialItems;
|
||||
const setItems = (newItems: any[]) => {
|
||||
items = newItems;
|
||||
};
|
||||
|
||||
const {result} = renderHook(() => useSortableIndexedList({
|
||||
items,
|
||||
setItems,
|
||||
blank: blankItem,
|
||||
canAddNewItem
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.updateItem('0', {name: 'Updated Item 1'});
|
||||
});
|
||||
|
||||
// Assert item updated correctly
|
||||
expect(items[0]).to.deep.equal({name: 'Updated Item 1'});
|
||||
});
|
||||
|
||||
it('should remove an item', function () {
|
||||
let items = initialItems;
|
||||
const setItems = (newItems: any[]) => {
|
||||
items = newItems;
|
||||
};
|
||||
|
||||
const {result} = renderHook(() => useSortableIndexedList({
|
||||
items,
|
||||
setItems,
|
||||
blank: blankItem,
|
||||
canAddNewItem
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.removeItem('0');
|
||||
});
|
||||
|
||||
// Assert item removed correctly
|
||||
expect(items).to.deep.equal([initialItems[1]]);
|
||||
});
|
||||
|
||||
it('should move an item', function () {
|
||||
let items = initialItems;
|
||||
const setItems = (newItems: any[]) => {
|
||||
items = newItems;
|
||||
};
|
||||
|
||||
const {result} = renderHook(() => useSortableIndexedList({
|
||||
items,
|
||||
setItems,
|
||||
blank: blankItem,
|
||||
canAddNewItem
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.moveItem('0', '1');
|
||||
});
|
||||
|
||||
// Assert item moved correctly
|
||||
expect(items).to.deep.equal([initialItems[1], initialItems[0]]);
|
||||
});
|
||||
|
||||
it('should not setItems for deeply equal items regardless of property order', function () {
|
||||
const setItems = sinon.spy();
|
||||
const initialItem = [{name: 'Item 1', url: 'http://example.com'}];
|
||||
const blankItem1 = {name: '', url: ''};
|
||||
|
||||
const {rerender} = renderHook(
|
||||
// eslint-disable-next-line
|
||||
({items, setItems}) => useSortableIndexedList({
|
||||
items,
|
||||
setItems,
|
||||
blank: blankItem1,
|
||||
canAddNewItem
|
||||
}),
|
||||
{
|
||||
initialProps: {
|
||||
items: initialItem,
|
||||
setItems
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
expect(setItems.callCount).to.equal(0);
|
||||
|
||||
// Re-render with items in different order but same content
|
||||
rerender({
|
||||
items: [{url: 'http://example.com', name: 'Item 1'}],
|
||||
setItems
|
||||
});
|
||||
|
||||
// Expect no additional calls because the items are deeply equal
|
||||
expect(setItems.callCount).to.equal(0);
|
||||
});
|
||||
});
|
@ -142,7 +142,7 @@ const Sidebar: React.FC = () => {
|
||||
unstyled
|
||||
onChange={updateSearch}
|
||||
/>
|
||||
{filter ? <Button className='absolute right-3 top-3 p-1' icon='close' iconColorClass='text-grey-700 !w-[10px] !h-[10px]' size='sm' unstyled onClick={() => {
|
||||
{filter ? <Button className='absolute top-3 p-1 sm:right-14 tablet:right-3' icon='close' iconColorClass='text-grey-700 !w-[10px] !h-[10px]' size='sm' unstyled onClick={() => {
|
||||
setFilter('');
|
||||
searchInputRef.current?.focus();
|
||||
}} /> : <div className='absolute -right-1/2 top-[9px] hidden rounded border border-grey-400 bg-white px-1.5 py-0.5 text-2xs font-semibold uppercase tracking-wider text-grey-600 shadow-[0px_1px_#CED4D9] dark:border-grey-800 dark:bg-grey-900 dark:text-grey-500 dark:shadow-[0px_1px_#626D79] tablet:!visible tablet:right-3 tablet:!block'>/</div>}
|
||||
|
@ -129,8 +129,8 @@ const Sidebar: React.FC<{
|
||||
NiceModal.show(ConfirmationModal, {
|
||||
title: 'Archive newsletter',
|
||||
prompt: <>
|
||||
<p>Your newsletter <strong>{newsletter.name}</strong> will no longer be visible to members or available as an option when publishing new posts.</p>
|
||||
<p>Existing posts previously sent as this newsletter will remain unchanged.</p>
|
||||
<div className="mb-6">Your newsletter <strong>{newsletter.name}</strong> will no longer be visible to members or available as an option when publishing new posts.</div>
|
||||
<div>Existing posts previously sent as this newsletter will remain unchanged.</div>
|
||||
</>,
|
||||
okLabel: 'Archive',
|
||||
okColor: 'red',
|
||||
|
@ -865,6 +865,7 @@
|
||||
.gh-post-analytics-resource h3 {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
.gh-post-analytics-box h4.gh-main-section-header.small {
|
||||
|
@ -1,6 +1,6 @@
|
||||
const debug = require('@tryghost/debug')('utils:image-size');
|
||||
const sizeOf = require('image-size');
|
||||
const probeSizeOf = require('probe-image-size');
|
||||
|
||||
const url = require('url');
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
@ -17,13 +17,14 @@ const FETCH_ONLY_FORMATS = [
|
||||
];
|
||||
|
||||
class ImageSize {
|
||||
constructor({config, storage, storageUtils, validator, urlUtils, request}) {
|
||||
constructor({config, storage, storageUtils, validator, urlUtils, request, probe}) {
|
||||
this.config = config;
|
||||
this.storage = storage;
|
||||
this.storageUtils = storageUtils;
|
||||
this.validator = validator;
|
||||
this.urlUtils = urlUtils;
|
||||
this.request = request;
|
||||
this.probe = probe;
|
||||
|
||||
this.REQUEST_OPTIONS = {
|
||||
// we need the user-agent, otherwise some https request may fail (e.g. cloudfare)
|
||||
@ -82,7 +83,18 @@ class ImageSize {
|
||||
}));
|
||||
}
|
||||
|
||||
return probeSizeOf(imageUrl, this.NEEDLE_OPTIONS);
|
||||
// wrap probe-image-size in a promise in case it is unresponsive/the timeout itself doesn't work
|
||||
return (Promise.race([
|
||||
this.probe(imageUrl, this.NEEDLE_OPTIONS),
|
||||
new Promise((res, rej) => {
|
||||
setTimeout(() => {
|
||||
rej(new errors.InternalServerError({
|
||||
message: 'Probe unresponsive.',
|
||||
code: 'IMAGE_SIZE_URL'
|
||||
}));
|
||||
}, this.NEEDLE_OPTIONS.response_timeout);
|
||||
})
|
||||
]));
|
||||
}
|
||||
|
||||
// download full image then use image-size to get it's dimensions
|
||||
|
@ -2,11 +2,12 @@ const BlogIcon = require('./BlogIcon');
|
||||
const CachedImageSizeFromUrl = require('./CachedImageSizeFromUrl');
|
||||
const Gravatar = require('./Gravatar');
|
||||
const ImageSize = require('./ImageSize');
|
||||
const probe = require('probe-image-size');
|
||||
|
||||
class ImageUtils {
|
||||
constructor({config, urlUtils, settingsCache, storageUtils, storage, validator, request, cacheStore}) {
|
||||
this.blogIcon = new BlogIcon({config, urlUtils, settingsCache, storageUtils});
|
||||
this.imageSize = new ImageSize({config, storage, storageUtils, validator, urlUtils, request});
|
||||
this.imageSize = new ImageSize({config, storage, storageUtils, validator, urlUtils, request, probe});
|
||||
this.cachedImageSizeFromUrl = new CachedImageSizeFromUrl({
|
||||
getImageSizeFromUrl: this.imageSize.getImageSizeFromUrl.bind(this.imageSize),
|
||||
cache: cacheStore
|
||||
|
@ -5,6 +5,7 @@ const path = require('path');
|
||||
const errors = require('@tryghost/errors');
|
||||
const fs = require('fs');
|
||||
const ImageSize = require('../../../../../core/server/lib/image/ImageSize');
|
||||
const probe = require('probe-image-size');
|
||||
|
||||
describe('lib/image: image size', function () {
|
||||
// use a 1x1 gif in nock responses because it's really small and easy to work with
|
||||
@ -18,7 +19,7 @@ describe('lib/image: image size', function () {
|
||||
it('[success] should have an image size function', function () {
|
||||
const imageSize = new ImageSize({config: {
|
||||
get: () => {}
|
||||
}, tpl: {}, storage: {}, storageUtils: {}, validator: {}, urlUtils: {}, request: {}});
|
||||
}, tpl: {}, storage: {}, storageUtils: {}, validator: {}, urlUtils: {}, request: {}, probe});
|
||||
should.exist(imageSize.getImageSizeFromUrl);
|
||||
should.exist(imageSize.getImageSizeFromStoragePath);
|
||||
});
|
||||
@ -42,7 +43,7 @@ describe('lib/image: image size', function () {
|
||||
isLocalImage: () => false
|
||||
}, validator: {
|
||||
isURL: () => true
|
||||
}, urlUtils: {}, request: {}});
|
||||
}, urlUtils: {}, request: {}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url).then(function (res) {
|
||||
requestMock.isDone().should.be.true();
|
||||
@ -77,7 +78,7 @@ describe('lib/image: image size', function () {
|
||||
});
|
||||
}
|
||||
return Promise.reject();
|
||||
}});
|
||||
}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url).then(function (res) {
|
||||
requestMock.isDone().should.be.false();
|
||||
@ -107,7 +108,7 @@ describe('lib/image: image size', function () {
|
||||
isLocalImage: () => false
|
||||
}, validator: {
|
||||
isURL: () => true
|
||||
}, urlUtils: {}, request: {}});
|
||||
}, urlUtils: {}, request: {}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url).then(function (res) {
|
||||
requestMock.isDone().should.be.true();
|
||||
@ -138,7 +139,7 @@ describe('lib/image: image size', function () {
|
||||
isLocalImage: () => false
|
||||
}, validator: {
|
||||
isURL: () => true
|
||||
}, urlUtils: {}, request: {}});
|
||||
}, urlUtils: {}, request: {}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url).then(function (res) {
|
||||
requestMockNotFound.isDone().should.be.false();
|
||||
@ -188,7 +189,7 @@ describe('lib/image: image size', function () {
|
||||
});
|
||||
}
|
||||
return Promise.reject();
|
||||
}});
|
||||
}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url).then(function (res) {
|
||||
requestMock.isDone().should.be.true();
|
||||
@ -218,7 +219,7 @@ describe('lib/image: image size', function () {
|
||||
isLocalImage: () => false
|
||||
}, validator: {
|
||||
isURL: () => true
|
||||
}, urlUtils: {}, request: {}});
|
||||
}, urlUtils: {}, request: {}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url).then(function (res) {
|
||||
requestMock.isDone().should.be.true();
|
||||
@ -254,7 +255,7 @@ describe('lib/image: image size', function () {
|
||||
isLocalImage: () => false
|
||||
}, validator: {
|
||||
isURL: () => true
|
||||
}, urlUtils: {}, request: {}});
|
||||
}, urlUtils: {}, request: {}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url).then(function (res) {
|
||||
requestMock.isDone().should.be.true();
|
||||
@ -300,7 +301,7 @@ describe('lib/image: image size', function () {
|
||||
}, validator: {}, urlUtils: {
|
||||
urlFor: urlForStub,
|
||||
getSubdir: urlGetSubdirStub
|
||||
}, request: {}});
|
||||
}, request: {}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url).then(function (res) {
|
||||
requestMock.isDone().should.be.false();
|
||||
@ -328,7 +329,7 @@ describe('lib/image: image size', function () {
|
||||
isLocalImage: () => false
|
||||
}, validator: {
|
||||
isURL: () => true
|
||||
}, urlUtils: {}, request: {}});
|
||||
}, urlUtils: {}, request: {}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url)
|
||||
.catch(function (err) {
|
||||
@ -366,7 +367,7 @@ describe('lib/image: image size', function () {
|
||||
return Promise.reject(new NotFound());
|
||||
}
|
||||
return Promise.reject();
|
||||
}});
|
||||
}}, probe);
|
||||
|
||||
imageSize.getImageSizeFromUrl(url)
|
||||
.catch(function (err) {
|
||||
@ -387,7 +388,7 @@ describe('lib/image: image size', function () {
|
||||
isLocalImage: () => false
|
||||
}, validator: {
|
||||
isURL: () => false
|
||||
}, urlUtils: {}, request: {}});
|
||||
}, urlUtils: {}, request: {}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url)
|
||||
.catch(function (err) {
|
||||
@ -398,7 +399,7 @@ describe('lib/image: image size', function () {
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('[failure] will timeout', function (done) {
|
||||
it('[failure] will handle responses timing out', function (done) {
|
||||
const url = 'https://static.wixstatic.com/media/355241_d31358572a2542c5a44738ddcb59e7ea.jpg_256';
|
||||
|
||||
const requestMock = nock('https://static.wixstatic.com')
|
||||
@ -409,14 +410,18 @@ describe('lib/image: image size', function () {
|
||||
const imageSize = new ImageSize({config: {
|
||||
get: (key) => {
|
||||
if (key === 'times:getImageSizeTimeoutInMS') {
|
||||
return 1;
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
}, tpl: {}, storage: {}, storageUtils: {
|
||||
isLocalImage: () => false
|
||||
}, validator: {
|
||||
isURL: () => true
|
||||
}, urlUtils: {}, request: {}});
|
||||
}, urlUtils: {}, request: {},
|
||||
probe(reqUrl, options) {
|
||||
// simulate probe the request timing out by probe's option
|
||||
return probe(reqUrl, {...options, response_timeout: 1});
|
||||
}});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url)
|
||||
.catch(function (err) {
|
||||
@ -441,7 +446,7 @@ describe('lib/image: image size', function () {
|
||||
isLocalImage: () => false
|
||||
}, validator: {
|
||||
isURL: () => true
|
||||
}, urlUtils: {}, request: {}});
|
||||
}, urlUtils: {}, request: {}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url)
|
||||
.then(() => {
|
||||
@ -475,7 +480,7 @@ describe('lib/image: image size', function () {
|
||||
});
|
||||
}
|
||||
return Promise.reject();
|
||||
}});
|
||||
}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url)
|
||||
.then(() => {
|
||||
@ -500,7 +505,7 @@ describe('lib/image: image size', function () {
|
||||
isURL: () => true
|
||||
}, urlUtils: {}, request: () => {
|
||||
return Promise.reject({});
|
||||
}});
|
||||
}, probe});
|
||||
|
||||
imageSize.getImageSizeFromUrl(url)
|
||||
.catch(function (err) {
|
||||
@ -510,6 +515,38 @@ describe('lib/image: image size', function () {
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('[failure] handles probe being unresponsive', function (done) {
|
||||
const url = 'http://img.stockfresh.com/files/f/feedough/x/11/1540353_20925115.jpg';
|
||||
const requestMock = nock('http://img.stockfresh.com')
|
||||
.get('/files/f/feedough/x/11/1540353_20925115.jpg')
|
||||
.reply(200, GIF1x1);
|
||||
|
||||
const imageSize = new ImageSize({config: {
|
||||
get: (key) => {
|
||||
if (key === 'times:getImageSizeTimeoutInMS') {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}, tpl: {}, storage: {}, storageUtils: {
|
||||
isLocalImage: () => false
|
||||
}, validator: {
|
||||
isURL: () => true
|
||||
}, urlUtils: {}, request: {},
|
||||
probe(reqUrl, options) {
|
||||
// simulate probe being unresponsive by making the timeout longer than the request
|
||||
return probe(reqUrl, {...options, response_timeout: 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('Probe unresponsive.');
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getImageSizeFromStoragePath', function () {
|
||||
@ -542,7 +579,7 @@ describe('lib/image: image size', function () {
|
||||
getSubdir: urlGetSubdirStub
|
||||
}, request: () => {
|
||||
return Promise.reject({});
|
||||
}});
|
||||
}, probe});
|
||||
|
||||
imageSize.getImageSizeFromStoragePath(url).then(function (res) {
|
||||
should.exist(res);
|
||||
@ -585,7 +622,7 @@ describe('lib/image: image size', function () {
|
||||
getSubdir: urlGetSubdirStub
|
||||
}, request: () => {
|
||||
return Promise.reject({});
|
||||
}});
|
||||
}, probe});
|
||||
|
||||
imageSize.getImageSizeFromStoragePath(url).then(function (res) {
|
||||
should.exist(res);
|
||||
@ -628,7 +665,7 @@ describe('lib/image: image size', function () {
|
||||
getSubdir: urlGetSubdirStub
|
||||
}, request: () => {
|
||||
return Promise.reject({});
|
||||
}});
|
||||
}, probe});
|
||||
|
||||
imageSize.getImageSizeFromStoragePath(url).then(function (res) {
|
||||
should.exist(res);
|
||||
@ -671,7 +708,7 @@ describe('lib/image: image size', function () {
|
||||
getSubdir: urlGetSubdirStub
|
||||
}, request: () => {
|
||||
return Promise.reject({});
|
||||
}});
|
||||
}, probe});
|
||||
|
||||
imageSize.getImageSizeFromStoragePath(url).then(function (res) {
|
||||
should.exist(res);
|
||||
@ -711,7 +748,7 @@ describe('lib/image: image size', function () {
|
||||
getSubdir: urlGetSubdirStub
|
||||
}, request: () => {
|
||||
return Promise.reject({});
|
||||
}});
|
||||
}, probe});
|
||||
|
||||
imageSize.getImageSizeFromStoragePath(url)
|
||||
.catch(function (err) {
|
||||
@ -746,7 +783,7 @@ describe('lib/image: image size', function () {
|
||||
getSubdir: urlGetSubdirStub
|
||||
}, request: () => {
|
||||
return Promise.reject({});
|
||||
}});
|
||||
}, probe});
|
||||
|
||||
imageSize.getImageSizeFromStoragePath(url)
|
||||
.catch(function (err) {
|
||||
|
15
yarn.lock
15
yarn.lock
@ -7810,6 +7810,14 @@
|
||||
lodash "^4.17.15"
|
||||
redent "^3.0.0"
|
||||
|
||||
"@testing-library/react-hooks@8.0.1":
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz#0924bbd5b55e0c0c0502d1754657ada66947ca12"
|
||||
integrity sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
react-error-boundary "^3.1.0"
|
||||
|
||||
"@testing-library/react@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.5.tgz#bb248f72f02a5ac9d949dea07279095fa577963b"
|
||||
@ -27785,6 +27793,13 @@ react-element-to-jsx-string@^15.0.0:
|
||||
is-plain-object "5.0.0"
|
||||
react-is "18.1.0"
|
||||
|
||||
react-error-boundary@^3.1.0:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.4.tgz#255db92b23197108757a888b01e5b729919abde0"
|
||||
integrity sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
|
||||
react-hot-toast@2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.4.1.tgz#df04295eda8a7b12c4f968e54a61c8d36f4c0994"
|
||||
|
Loading…
Reference in New Issue
Block a user