enhancement(media-library-uploadcare): update uploadcare plugin (#2029)

This commit is contained in:
Aleksandr Grenishin 2019-02-08 22:06:08 +03:00 committed by Shawn Erquhart
parent 15d221d4a4
commit ff73175244
5 changed files with 96 additions and 87 deletions

View File

@ -0,0 +1,26 @@
{
"name": "netlify-cms-media-library-uploadcare",
"version": "0.2.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"jquery": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
"integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg=="
},
"uploadcare-widget": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/uploadcare-widget/-/uploadcare-widget-3.6.2.tgz",
"integrity": "sha512-M/nIb88eGgvD5ua28TA9v8pI7922HucOIkLlu8kDcepbG9Psw0EEBQnOgn0eW4lHAMNH1Hs8vg0T33zgsiN4bg==",
"requires": {
"jquery": ">=1.10.2"
}
},
"uploadcare-widget-tab-effects": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/uploadcare-widget-tab-effects/-/uploadcare-widget-tab-effects-1.3.0.tgz",
"integrity": "sha512-6ZJm96K8/fKySU7NU8YNG0ZxyEeSToeTu4+2Iz7YFf6qZgLw3sECn/XudGxN8jJIsHpilhy040pqDzu6A78Mig=="
}
}
}

View File

@ -26,7 +26,8 @@
"webpack": "^4.16.1", "webpack": "^4.16.1",
"webpack-cli": "^3.1.0" "webpack-cli": "^3.1.0"
}, },
"peerDependencies": { "dependencies": {
"netlify-cms-lib-util": "^2.0.4" "uploadcare-widget": "^3.6.2",
"uploadcare-widget-tab-effects": "^1.3.0"
} }
} }

View File

@ -1,6 +1,7 @@
import { queryHelpers, waitForElement } from 'dom-testing-library';
import uuid from 'uuid/v4'; import uuid from 'uuid/v4';
import uploadcare from '../index'; import uploadcareMediaLibrary from '../index';
import uploadcare from 'uploadcare-widget';
import uploadcareTabEffects from 'uploadcare-widget-tab-effects';
function generateMockUrl({ count = 1, cdnUrl } = {}) { function generateMockUrl({ count = 1, cdnUrl } = {}) {
const baseUrl = 'https://ucarecdn.com'; const baseUrl = 'https://ucarecdn.com';
@ -13,38 +14,12 @@ function generateMockUrl({ count = 1, cdnUrl } = {}) {
return result; return result;
} }
describe('uploadcare media library', () => {
let handleInsert;
let simulateCloseDialog;
let uploadcareScripts = [];
const TEST_PUBLIC_KEY = 123;
const defaultConfig = {
imagesOnly: false,
multiple: false,
previewStep: true,
};
beforeEach(() => {
/**
* We load the Uploadcare library by injecting script tags to the page
* head. Initialization waits for the scripts to load, so here we fake it.
* This also tests that the expected scripts are added to the DOM.
*/
[/uploadcare\.full\.js$/, /uploadcare\.tab-effects\.js$/].forEach(pattern => {
waitForElement(() => {
return queryHelpers.queryByAttribute('src', document, pattern);
}).then(script => {
uploadcareScripts.push(script);
script.onreadystatechange();
});
});
let openDialogCallback; let openDialogCallback;
/** /**
* Mock of the uploadcare widget object itself. * Mock of the uploadcare widget object itself.
*/ */
window.uploadcare = { jest.mock('uploadcare-widget', () => ({
registerTab: jest.fn(), registerTab: jest.fn(),
openDialog: jest.fn(() => ({ openDialog: jest.fn(() => ({
done: jest.fn(cb => { done: jest.fn(cb => {
@ -59,8 +34,20 @@ describe('uploadcare media library', () => {
loadFileGroup: () => ({ loadFileGroup: () => ({
done: cb => cb(), done: cb => cb(),
}), }),
}));
describe('uploadcare media library', () => {
let handleInsert;
let simulateCloseDialog;
const TEST_PUBLIC_KEY = 123;
const defaultConfig = {
imagesOnly: false,
multiple: false,
previewStep: true,
integration: 'NetlifyCMS-Uploadcare-MediaLibrary',
}; };
beforeEach(() => {
/** /**
* Mock to manually call the close dialog registered callback. * Mock to manually call the close dialog registered callback.
*/ */
@ -75,17 +62,8 @@ describe('uploadcare media library', () => {
handleInsert = jest.fn(); handleInsert = jest.fn();
}); });
afterEach(() => {
/**
* Remove the script elements from the dom after each test.
*/
const { head } = document;
uploadcareScripts.forEach(script => head.contains(script) && head.removeChild(script));
uploadcareScripts = [];
});
it('exports an object with expected properties', () => { it('exports an object with expected properties', () => {
expect(uploadcare).toMatchInlineSnapshot(` expect(uploadcareMediaLibrary).toMatchInlineSnapshot(`
Object { Object {
"init": [Function], "init": [Function],
"name": "uploadcare", "name": "uploadcare",
@ -100,17 +78,15 @@ Object {
publicKey: TEST_PUBLIC_KEY, publicKey: TEST_PUBLIC_KEY,
}, },
}; };
await uploadcare.init({ options }); await uploadcareMediaLibrary.init({ options });
expect(window.UPLOADCARE_LIVE).toEqual(false); expect(window.UPLOADCARE_LIVE).toEqual(false);
expect(window.UPLOADCARE_MANUAL_START).toEqual(true); expect(window.UPLOADCARE_MANUAL_START).toEqual(true);
expect(window.UPLOADCARE_PUBLIC_KEY).toEqual(TEST_PUBLIC_KEY); expect(window.UPLOADCARE_PUBLIC_KEY).toEqual(TEST_PUBLIC_KEY);
}); });
it('registers the effects tab', async () => { it('registers the effects tab', async () => {
const mockEffectsTab = { mockEffectsTab: true }; await uploadcareMediaLibrary.init();
window.uploadcareTabEffects = mockEffectsTab; expect(uploadcare.registerTab).toHaveBeenCalledWith('preview', uploadcareTabEffects);
await uploadcare.init();
expect(window.uploadcare.registerTab).toHaveBeenCalledWith('preview', mockEffectsTab);
}); });
}); });
@ -122,9 +98,9 @@ Object {
}; };
it('has defaults', async () => { it('has defaults', async () => {
const integration = await uploadcare.init(); const integration = await uploadcareMediaLibrary.init();
await integration.show(); await integration.show();
expect(window.uploadcare.openDialog).toHaveBeenCalledWith(null, defaultConfig); expect(uploadcare.openDialog).toHaveBeenCalledWith(null, defaultConfig);
}); });
it('can be defined globally', async () => { it('can be defined globally', async () => {
@ -132,9 +108,9 @@ Object {
...defaultConfig, ...defaultConfig,
...options.config, ...options.config,
}; };
const integration = await uploadcare.init({ options }); const integration = await uploadcareMediaLibrary.init({ options });
await integration.show(); await integration.show();
expect(window.uploadcare.openDialog).toHaveBeenCalledWith(null, expectedConfig); expect(uploadcare.openDialog).toHaveBeenCalledWith(null, expectedConfig);
}); });
it('can be defined per field', async () => { it('can be defined per field', async () => {
@ -142,9 +118,9 @@ Object {
...defaultConfig, ...defaultConfig,
...options.config, ...options.config,
}; };
const integration = await uploadcare.init(); const integration = await uploadcareMediaLibrary.init();
await integration.show({ config: options.config }); await integration.show({ config: options.config });
expect(window.uploadcare.openDialog).toHaveBeenCalledWith(null, expectedConfig); expect(uploadcare.openDialog).toHaveBeenCalledWith(null, expectedConfig);
}); });
}); });
@ -161,9 +137,9 @@ Object {
...options.config, ...options.config,
imagesOnly: true, imagesOnly: true,
}; };
const integration = await uploadcare.init(); const integration = await uploadcareMediaLibrary.init();
await integration.show({ config: options.config, imagesOnly: true }); await integration.show({ config: options.config, imagesOnly: true });
expect(window.uploadcare.openDialog).toHaveBeenCalledWith(null, expectedConfig); expect(uploadcare.openDialog).toHaveBeenCalledWith(null, expectedConfig);
}); });
it('allows multiple selection if allowMultiple is not false', async () => { it('allows multiple selection if allowMultiple is not false', async () => {
@ -173,9 +149,9 @@ Object {
...options.config, ...options.config,
multiple: true, multiple: true,
}; };
const integration = await uploadcare.init({ options }); const integration = await uploadcareMediaLibrary.init({ options });
await integration.show({ config: options.config }); await integration.show({ config: options.config });
expect(window.uploadcare.openDialog).toHaveBeenCalledWith(null, expectedConfig); expect(uploadcare.openDialog).toHaveBeenCalledWith(null, expectedConfig);
}); });
it('disallows multiple selection if allowMultiple is false', async () => { it('disallows multiple selection if allowMultiple is false', async () => {
@ -185,15 +161,15 @@ Object {
...options.config, ...options.config,
multiple: false, multiple: false,
}; };
const integration = await uploadcare.init({ options }); const integration = await uploadcareMediaLibrary.init({ options });
await integration.show({ config: options.config, allowMultiple: false }); await integration.show({ config: options.config, allowMultiple: false });
expect(window.uploadcare.openDialog).toHaveBeenCalledWith(null, expectedConfig); expect(uploadcare.openDialog).toHaveBeenCalledWith(null, expectedConfig);
}); });
it('passes selected image url to handleInsert', async () => { it('passes selected image url to handleInsert', async () => {
const url = generateMockUrl(); const url = generateMockUrl();
const mockResult = { cdnUrl: url }; const mockResult = { cdnUrl: url };
const integration = await uploadcare.init({ handleInsert }); const integration = await uploadcareMediaLibrary.init({ handleInsert });
await integration.show(); await integration.show();
await simulateCloseDialog(mockResult); await simulateCloseDialog(mockResult);
expect(handleInsert).toHaveBeenCalledWith(url); expect(handleInsert).toHaveBeenCalledWith(url);
@ -203,7 +179,7 @@ Object {
options.config.multiple = true; options.config.multiple = true;
const { result, cdnUrl } = generateMockUrl({ count: 3, cdnUrl: true }); const { result, cdnUrl } = generateMockUrl({ count: 3, cdnUrl: true });
const mockDialogCloseResult = { cdnUrl, count: 3 }; const mockDialogCloseResult = { cdnUrl, count: 3 };
const integration = await uploadcare.init({ options, handleInsert }); const integration = await uploadcareMediaLibrary.init({ options, handleInsert });
await integration.show(); await integration.show();
await simulateCloseDialog(mockDialogCloseResult); await simulateCloseDialog(mockDialogCloseResult);
expect(handleInsert).toHaveBeenCalledWith(result); expect(handleInsert).toHaveBeenCalledWith(result);
@ -212,7 +188,7 @@ Object {
describe('enableStandalone method', () => { describe('enableStandalone method', () => {
it('returns false', async () => { it('returns false', async () => {
const integration = await uploadcare.init(); const integration = await uploadcareMediaLibrary.init();
expect(integration.enableStandalone()).toEqual(false); expect(integration.enableStandalone()).toEqual(false);
}); });
}); });

View File

@ -1,6 +1,8 @@
import { loadScript } from 'netlify-cms-lib-util'; import uploadcare from 'uploadcare-widget';
import uploadcareTabEffects from 'uploadcare-widget-tab-effects';
import { Iterable } from 'immutable'; import { Iterable } from 'immutable';
const USER_AGENT = 'NetlifyCMS-Uploadcare-MediaLibrary';
const CDN_BASE_URL = 'https://ucarecdn.com'; const CDN_BASE_URL = 'https://ucarecdn.com';
/** /**
@ -8,6 +10,7 @@ const CDN_BASE_URL = 'https://ucarecdn.com';
*/ */
const defaultConfig = { const defaultConfig = {
previewStep: true, previewStep: true,
integration: USER_AGENT,
}; };
/** /**
@ -36,9 +39,7 @@ function getFileGroup(files) {
* `fileFrom`, but requires the promise returned by `loadFileGroup` to provide * `fileFrom`, but requires the promise returned by `loadFileGroup` to provide
* the result of it's `done` method. * the result of it's `done` method.
*/ */
return new Promise(resolve => return new Promise(resolve => uploadcare.loadFileGroup(groupId).done(group => resolve(group)));
window.uploadcare.loadFileGroup(groupId).done(group => resolve(group)),
);
} }
/** /**
@ -62,7 +63,7 @@ function getFiles(value) {
function getFile(url) { function getFile(url) {
const groupPattern = /~\d+\/nth\/\d+\//; const groupPattern = /~\d+\/nth\/\d+\//;
const uploaded = url.startsWith(CDN_BASE_URL) && !groupPattern.test(url); const uploaded = url.startsWith(CDN_BASE_URL) && !groupPattern.test(url);
return window.uploadcare.fileFrom(uploaded ? 'uploaded' : 'url', url); return uploadcare.fileFrom(uploaded ? 'uploaded' : 'url', url);
} }
/** /**
@ -70,7 +71,7 @@ function getFile(url) {
* each use. * each use.
*/ */
function openDialog(files, config, handleInsert) { function openDialog(files, config, handleInsert) {
window.uploadcare.openDialog(files, config).done(({ promise }) => uploadcare.openDialog(files, config).done(({ promise }) =>
promise().then(({ cdnUrl, count }) => { promise().then(({ cdnUrl, count }) => {
if (config.multiple) { if (config.multiple) {
const urls = Array.from({ length: count }, (val, idx) => `${cdnUrl}nth/${idx}/`); const urls = Array.from({ length: count }, (val, idx) => `${cdnUrl}nth/${idx}/`);
@ -94,20 +95,11 @@ async function init({ options = { config: {} }, handleInsert } = {}) {
window.UPLOADCARE_MANUAL_START = true; window.UPLOADCARE_MANUAL_START = true;
window.UPLOADCARE_PUBLIC_KEY = publicKey; window.UPLOADCARE_PUBLIC_KEY = publicKey;
/**
* Loading scripts via url because the uploadcare widget includes
* non-strict-mode code that's incompatible with our build system
*/
await loadScript('https://unpkg.com/uploadcare-widget@^3.6.0/uploadcare.full.js');
await loadScript(
'https://unpkg.com/uploadcare-widget-tab-effects@^1.2.1/dist/uploadcare.tab-effects.js',
);
/** /**
* Register the effects tab by default because the effects tab is awesome. Can * Register the effects tab by default because the effects tab is awesome. Can
* be disabled via config. * be disabled via config.
*/ */
window.uploadcare.registerTab('preview', window.uploadcareTabEffects); uploadcare.registerTab('preview', uploadcareTabEffects);
return { return {
/** /**

View File

@ -7172,6 +7172,10 @@ joi@^9.2.0:
moment "2.x.x" moment "2.x.x"
topo "2.x.x" topo "2.x.x"
jquery@>=1.10.2:
version "3.3.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
js-base64@^2.1.9, js-base64@^2.4.8: js-base64@^2.1.9, js-base64@^2.4.8:
version "2.4.8" version "2.4.8"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.8.tgz#57a9b130888f956834aa40c5b165ba59c758f033" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.8.tgz#57a9b130888f956834aa40c5b165ba59c758f033"
@ -12374,6 +12378,16 @@ upath@^1.0.5:
resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd"
integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==
uploadcare-widget-tab-effects@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/uploadcare-widget-tab-effects/-/uploadcare-widget-tab-effects-1.3.0.tgz#13a7d58af0a38dca34dac03f90670d5103d17be7"
uploadcare-widget@^3.6.2:
version "3.6.2"
resolved "https://registry.yarnpkg.com/uploadcare-widget/-/uploadcare-widget-3.6.2.tgz#621bbef6d9a527a7fdcd6939e574819e6683e717"
dependencies:
jquery ">=1.10.2"
uri-js@^4.2.1: uri-js@^4.2.1:
version "4.2.2" version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"