From 50dab7256da12ac2e1bf032579c21f42d52ec696 Mon Sep 17 00:00:00 2001 From: Aleksandr Grenishin Date: Wed, 13 Feb 2019 18:19:33 +0300 Subject: [PATCH] enhancement(uploadcare): load uploadcare as module (#2091) --- .../package.json | 5 +- .../src/__tests__/index.spec.js | 114 +++++++----------- .../src/index.js | 29 ++--- yarn.lock | 14 +++ 4 files changed, 73 insertions(+), 89 deletions(-) diff --git a/packages/netlify-cms-media-library-uploadcare/package.json b/packages/netlify-cms-media-library-uploadcare/package.json index 05705bde..e8652f23 100644 --- a/packages/netlify-cms-media-library-uploadcare/package.json +++ b/packages/netlify-cms-media-library-uploadcare/package.json @@ -26,7 +26,8 @@ "webpack": "^4.16.1", "webpack-cli": "^3.1.0" }, - "peerDependencies": { - "netlify-cms-lib-util": "^2.0.4" + "dependencies": { + "uploadcare-widget": "^3.6.2", + "uploadcare-widget-tab-effects": "^1.3.0" } } diff --git a/packages/netlify-cms-media-library-uploadcare/src/__tests__/index.spec.js b/packages/netlify-cms-media-library-uploadcare/src/__tests__/index.spec.js index 0d2b19f4..28cd20f1 100644 --- a/packages/netlify-cms-media-library-uploadcare/src/__tests__/index.spec.js +++ b/packages/netlify-cms-media-library-uploadcare/src/__tests__/index.spec.js @@ -1,6 +1,7 @@ -import { queryHelpers, waitForElement } from 'dom-testing-library'; 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 } = {}) { const baseUrl = 'https://ucarecdn.com'; @@ -13,54 +14,40 @@ function generateMockUrl({ count = 1, cdnUrl } = {}) { return result; } +let openDialogCallback; + +/** + * Mock of the uploadcare widget object itself. + */ +jest.mock('uploadcare-widget', () => ({ + registerTab: jest.fn(), + openDialog: jest.fn(() => ({ + done: jest.fn(cb => { + openDialogCallback = cb; + }), + })), + fileFrom: jest.fn((type, url) => + Promise.resolve({ + testFileUrl: url, + }), + ), + loadFileGroup: () => ({ + done: cb => cb(), + }), +})); + describe('uploadcare media library', () => { let handleInsert; let simulateCloseDialog; - let uploadcareScripts = []; const TEST_PUBLIC_KEY = 123; const defaultConfig = { imagesOnly: false, multiple: false, previewStep: true, + integration: 'NetlifyCMS-Uploadcare-MediaLibrary', }; 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; - - /** - * Mock of the uploadcare widget object itself. - */ - window.uploadcare = { - registerTab: jest.fn(), - openDialog: jest.fn(() => ({ - done: jest.fn(cb => { - openDialogCallback = cb; - }), - })), - fileFrom: jest.fn((type, url) => - Promise.resolve({ - testFileUrl: url, - }), - ), - loadFileGroup: () => ({ - done: cb => cb(), - }), - }; - /** * Mock to manually call the close dialog registered callback. */ @@ -75,17 +62,8 @@ describe('uploadcare media library', () => { 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', () => { - expect(uploadcare).toMatchInlineSnapshot(` + expect(uploadcareMediaLibrary).toMatchInlineSnapshot(` Object { "init": [Function], "name": "uploadcare", @@ -100,17 +78,15 @@ Object { publicKey: TEST_PUBLIC_KEY, }, }; - await uploadcare.init({ options }); + await uploadcareMediaLibrary.init({ options }); expect(window.UPLOADCARE_LIVE).toEqual(false); expect(window.UPLOADCARE_MANUAL_START).toEqual(true); expect(window.UPLOADCARE_PUBLIC_KEY).toEqual(TEST_PUBLIC_KEY); }); it('registers the effects tab', async () => { - const mockEffectsTab = { mockEffectsTab: true }; - window.uploadcareTabEffects = mockEffectsTab; - await uploadcare.init(); - expect(window.uploadcare.registerTab).toHaveBeenCalledWith('preview', mockEffectsTab); + await uploadcareMediaLibrary.init(); + expect(uploadcare.registerTab).toHaveBeenCalledWith('preview', uploadcareTabEffects); }); }); @@ -122,9 +98,9 @@ Object { }; it('has defaults', async () => { - const integration = await uploadcare.init(); + const integration = await uploadcareMediaLibrary.init(); await integration.show(); - expect(window.uploadcare.openDialog).toHaveBeenCalledWith(null, defaultConfig); + expect(uploadcare.openDialog).toHaveBeenCalledWith(null, defaultConfig); }); it('can be defined globally', async () => { @@ -132,9 +108,9 @@ Object { ...defaultConfig, ...options.config, }; - const integration = await uploadcare.init({ options }); + const integration = await uploadcareMediaLibrary.init({ options }); await integration.show(); - expect(window.uploadcare.openDialog).toHaveBeenCalledWith(null, expectedConfig); + expect(uploadcare.openDialog).toHaveBeenCalledWith(null, expectedConfig); }); it('can be defined per field', async () => { @@ -142,9 +118,9 @@ Object { ...defaultConfig, ...options.config, }; - const integration = await uploadcare.init(); + const integration = await uploadcareMediaLibrary.init(); 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, imagesOnly: true, }; - const integration = await uploadcare.init(); + const integration = await uploadcareMediaLibrary.init(); 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 () => { @@ -173,9 +149,9 @@ Object { ...options.config, multiple: true, }; - const integration = await uploadcare.init({ options }); + const integration = await uploadcareMediaLibrary.init({ options }); 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 () => { @@ -185,15 +161,15 @@ Object { ...options.config, multiple: false, }; - const integration = await uploadcare.init({ options }); + const integration = await uploadcareMediaLibrary.init({ options }); 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 () => { const url = generateMockUrl(); const mockResult = { cdnUrl: url }; - const integration = await uploadcare.init({ handleInsert }); + const integration = await uploadcareMediaLibrary.init({ handleInsert }); await integration.show(); await simulateCloseDialog(mockResult); expect(handleInsert).toHaveBeenCalledWith(url); @@ -203,7 +179,7 @@ Object { options.config.multiple = true; const { result, cdnUrl } = generateMockUrl({ count: 3, cdnUrl: true }); const mockDialogCloseResult = { cdnUrl, count: 3 }; - const integration = await uploadcare.init({ options, handleInsert }); + const integration = await uploadcareMediaLibrary.init({ options, handleInsert }); await integration.show(); await simulateCloseDialog(mockDialogCloseResult); expect(handleInsert).toHaveBeenCalledWith(result); @@ -212,7 +188,7 @@ Object { describe('enableStandalone method', () => { it('returns false', async () => { - const integration = await uploadcare.init(); + const integration = await uploadcareMediaLibrary.init(); expect(integration.enableStandalone()).toEqual(false); }); }); diff --git a/packages/netlify-cms-media-library-uploadcare/src/index.js b/packages/netlify-cms-media-library-uploadcare/src/index.js index 7be26884..479f1c22 100644 --- a/packages/netlify-cms-media-library-uploadcare/src/index.js +++ b/packages/netlify-cms-media-library-uploadcare/src/index.js @@ -1,6 +1,11 @@ -import { loadScript } from 'netlify-cms-lib-util'; +import uploadcare from 'uploadcare-widget'; +import uploadcareTabEffects from 'uploadcare-widget-tab-effects'; import { Iterable } from 'immutable'; +window.UPLOADCARE_LIVE = false; +window.UPLOADCARE_MANUAL_START = true; + +const USER_AGENT = 'NetlifyCMS-Uploadcare-MediaLibrary'; const CDN_BASE_URL = 'https://ucarecdn.com'; /** @@ -8,6 +13,7 @@ const CDN_BASE_URL = 'https://ucarecdn.com'; */ const defaultConfig = { previewStep: true, + integration: USER_AGENT, }; /** @@ -36,9 +42,7 @@ function getFileGroup(files) { * `fileFrom`, but requires the promise returned by `loadFileGroup` to provide * the result of it's `done` method. */ - return new Promise(resolve => - window.uploadcare.loadFileGroup(groupId).done(group => resolve(group)), - ); + return new Promise(resolve => uploadcare.loadFileGroup(groupId).done(group => resolve(group))); } /** @@ -62,7 +66,7 @@ function getFiles(value) { function getFile(url) { const groupPattern = /~\d+\/nth\/\d+\//; 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 +74,7 @@ function getFile(url) { * each use. */ function openDialog(files, config, handleInsert) { - window.uploadcare.openDialog(files, config).done(({ promise }) => + uploadcare.openDialog(files, config).done(({ promise }) => promise().then(({ cdnUrl, count }) => { if (config.multiple) { const urls = Array.from({ length: count }, (val, idx) => `${cdnUrl}nth/${idx}/`); @@ -90,24 +94,13 @@ async function init({ options = { config: {} }, handleInsert } = {}) { const { publicKey, ...globalConfig } = options.config; const baseConfig = { ...defaultConfig, ...globalConfig }; - window.UPLOADCARE_LIVE = false; - window.UPLOADCARE_MANUAL_START = true; 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 * be disabled via config. */ - window.uploadcare.registerTab('preview', window.uploadcareTabEffects); + uploadcare.registerTab('preview', uploadcareTabEffects); return { /** diff --git a/yarn.lock b/yarn.lock index a1c86537..4daa1faa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7165,6 +7165,10 @@ joi@^9.2.0: moment "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: version "2.4.8" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.8.tgz#57a9b130888f956834aa40c5b165ba59c758f033" @@ -12367,6 +12371,16 @@ upath@^1.0.5: resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" 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: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"