summaryrefslogtreecommitdiffstats
path: root/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.ts')
-rw-r--r--polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.ts428
1 files changed, 428 insertions, 0 deletions
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.ts
new file mode 100644
index 0000000000..4bfa0eb3bd
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.ts
@@ -0,0 +1,428 @@
+/**
+ * @license
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import '../../../test/common-test-setup-karma';
+import {PLUGIN_LOADING_TIMEOUT_MS} from './gr-api-utils';
+import {PluginLoader, _testOnly_resetPluginLoader} from './gr-plugin-loader';
+import {resetPlugins, stubBaseUrl} from '../../../test/test-utils';
+import {addListenerForTest, stubRestApi} from '../../../test/test-utils';
+import {PluginApi} from '../../../api/plugin';
+import {SinonFakeTimers} from 'sinon';
+import {Timestamp} from '../../../api/rest-api';
+
+suite('gr-plugin-loader tests', () => {
+ let plugin: PluginApi;
+
+ let url: string;
+ let pluginLoader: PluginLoader;
+ let clock: SinonFakeTimers;
+ let bodyStub: sinon.SinonStub;
+
+ setup(() => {
+ clock = sinon.useFakeTimers();
+
+ stubRestApi('getAccount').returns(
+ Promise.resolve({name: 'Judy Hopps', registered_on: '' as Timestamp})
+ );
+ stubRestApi('send').returns(
+ Promise.resolve({...new Response(), status: 200})
+ );
+ pluginLoader = _testOnly_resetPluginLoader();
+ bodyStub = sinon.stub(document.body, 'appendChild');
+ url = window.location.origin;
+ });
+
+ teardown(() => {
+ clock.restore();
+ resetPlugins();
+ });
+
+ test('reuse plugin for install calls', () => {
+ window.Gerrit.install(
+ p => {
+ plugin = p;
+ },
+ '0.1',
+ 'http://test.com/plugins/testplugin/static/test.js'
+ );
+
+ let otherPlugin;
+ window.Gerrit.install(
+ p => {
+ otherPlugin = p;
+ },
+ '0.1',
+ 'http://test.com/plugins/testplugin/static/test.js'
+ );
+ assert.strictEqual(plugin, otherPlugin);
+ });
+
+ test('versioning', () => {
+ const callback = sinon.spy();
+ window.Gerrit.install(callback, '0.0pre-alpha');
+ assert(callback.notCalled);
+ });
+
+ test('report pluginsLoaded', async () => {
+ const pluginsLoadedStub = sinon.stub(
+ pluginLoader._getReporting(),
+ 'pluginsLoaded'
+ );
+ pluginsLoadedStub.reset();
+ (window.Gerrit as any)._loadPlugins([]);
+ await flush();
+ assert.isTrue(pluginsLoadedStub.called);
+ });
+
+ test('arePluginsLoaded', () => {
+ assert.isFalse(pluginLoader.arePluginsLoaded());
+ const plugins = [
+ 'http://test.com/plugins/foo/static/test.js',
+ 'http://test.com/plugins/bar/static/test.js',
+ ];
+
+ pluginLoader.loadPlugins(plugins);
+ assert.isFalse(pluginLoader.arePluginsLoaded());
+ // Timeout on loading plugins
+ clock.tick(PLUGIN_LOADING_TIMEOUT_MS * 2);
+
+ flush();
+ assert.isTrue(pluginLoader.arePluginsLoaded());
+ });
+
+ test('plugins installed successfully', async () => {
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake(url => {
+ window.Gerrit.install(() => void 0, undefined, url);
+ });
+ const pluginsLoadedStub = sinon.stub(
+ pluginLoader._getReporting(),
+ 'pluginsLoaded'
+ );
+
+ const plugins = [
+ 'http://test.com/plugins/foo/static/test.js',
+ 'http://test.com/plugins/bar/static/test.js',
+ ];
+ pluginLoader.loadPlugins(plugins);
+
+ await flush();
+ assert.isTrue(pluginsLoadedStub.calledWithExactly(['foo', 'bar']));
+ assert.isTrue(pluginLoader.arePluginsLoaded());
+ });
+
+ test('isPluginEnabled and isPluginLoaded', () => {
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake(url => {
+ window.Gerrit.install(() => void 0, undefined, url);
+ });
+
+ const plugins = [
+ 'http://test.com/plugins/foo/static/test.js',
+ 'http://test.com/plugins/bar/static/test.js',
+ 'bar/static/test.js',
+ ];
+ pluginLoader.loadPlugins(plugins);
+ assert.isTrue(
+ plugins.every(plugin => pluginLoader.isPluginEnabled(plugin))
+ );
+
+ flush();
+ assert.isTrue(pluginLoader.arePluginsLoaded());
+ assert.isTrue(plugins.every(plugin => pluginLoader.isPluginLoaded(plugin)));
+ });
+
+ test('plugins installed mixed result, 1 fail 1 succeed', async () => {
+ const plugins = [
+ 'http://test.com/plugins/foo/static/test.js',
+ 'http://test.com/plugins/bar/static/test.js',
+ ];
+
+ const alertStub = sinon.stub();
+ addListenerForTest(document, 'show-alert', alertStub);
+
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake(url => {
+ window.Gerrit.install(
+ () => {
+ if (url === plugins[0]) {
+ throw new Error('failed');
+ }
+ },
+ undefined,
+ url
+ );
+ });
+
+ const pluginsLoadedStub = sinon.stub(
+ pluginLoader._getReporting(),
+ 'pluginsLoaded'
+ );
+
+ pluginLoader.loadPlugins(plugins);
+
+ await flush();
+ assert.isTrue(pluginsLoadedStub.calledWithExactly(['bar']));
+ assert.isTrue(pluginLoader.arePluginsLoaded());
+ assert.isTrue(alertStub.calledOnce);
+ });
+
+ test('isPluginEnabled and isPluginLoaded for mixed results', async () => {
+ const plugins = [
+ 'http://test.com/plugins/foo/static/test.js',
+ 'http://test.com/plugins/bar/static/test.js',
+ ];
+
+ const alertStub = sinon.stub();
+ addListenerForTest(document, 'show-alert', alertStub);
+
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake(url => {
+ window.Gerrit.install(
+ () => {
+ if (url === plugins[0]) {
+ throw new Error('failed');
+ }
+ },
+ undefined,
+ url
+ );
+ });
+
+ const pluginsLoadedStub = sinon.stub(
+ pluginLoader._getReporting(),
+ 'pluginsLoaded'
+ );
+
+ pluginLoader.loadPlugins(plugins);
+ assert.isTrue(
+ plugins.every(plugin => pluginLoader.isPluginEnabled(plugin))
+ );
+
+ await flush();
+ assert.isTrue(pluginsLoadedStub.calledWithExactly(['bar']));
+ assert.isTrue(pluginLoader.arePluginsLoaded());
+ assert.isTrue(alertStub.calledOnce);
+ assert.isTrue(pluginLoader.isPluginLoaded(plugins[1]));
+ assert.isFalse(pluginLoader.isPluginLoaded(plugins[0]));
+ });
+
+ test('plugins installed all failed', async () => {
+ const plugins = [
+ 'http://test.com/plugins/foo/static/test.js',
+ 'http://test.com/plugins/bar/static/test.js',
+ ];
+
+ const alertStub = sinon.stub();
+ addListenerForTest(document, 'show-alert', alertStub);
+
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake(url => {
+ window.Gerrit.install(
+ () => {
+ throw new Error('failed');
+ },
+ undefined,
+ url
+ );
+ });
+
+ const pluginsLoadedStub = sinon.stub(
+ pluginLoader._getReporting(),
+ 'pluginsLoaded'
+ );
+
+ pluginLoader.loadPlugins(plugins);
+
+ await flush();
+ assert.isTrue(pluginsLoadedStub.calledWithExactly([]));
+ assert.isTrue(pluginLoader.arePluginsLoaded());
+ assert.isTrue(alertStub.calledTwice);
+ });
+
+ test('plugins installed failed because of wrong version', async () => {
+ const plugins = [
+ 'http://test.com/plugins/foo/static/test.js',
+ 'http://test.com/plugins/bar/static/test.js',
+ ];
+
+ const alertStub = sinon.stub();
+ addListenerForTest(document, 'show-alert', alertStub);
+
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake(url => {
+ window.Gerrit.install(() => {}, url === plugins[0] ? '' : 'alpha', url);
+ });
+
+ const pluginsLoadedStub = sinon.stub(
+ pluginLoader._getReporting(),
+ 'pluginsLoaded'
+ );
+
+ pluginLoader.loadPlugins(plugins);
+
+ await flush();
+ assert.isTrue(pluginsLoadedStub.calledWithExactly(['foo']));
+ assert.isTrue(pluginLoader.arePluginsLoaded());
+ assert.isTrue(alertStub.calledOnce);
+ });
+
+ test('multiple assets for same plugin installed successfully', async () => {
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake(url => {
+ window.Gerrit.install(() => void 0, undefined, url);
+ });
+ const pluginsLoadedStub = sinon.stub(
+ pluginLoader._getReporting(),
+ 'pluginsLoaded'
+ );
+
+ const plugins = [
+ 'http://test.com/plugins/foo/static/test.js',
+ 'http://test.com/plugins/foo/static/test2.js',
+ 'http://test.com/plugins/bar/static/test.js',
+ ];
+ pluginLoader.loadPlugins(plugins);
+
+ await flush();
+ assert.isTrue(pluginsLoadedStub.calledWithExactly(['foo', 'bar']));
+ assert.isTrue(pluginLoader.arePluginsLoaded());
+ });
+
+ suite('plugin path and url', () => {
+ let loadJsPluginStub: sinon.SinonStub;
+ setup(() => {
+ loadJsPluginStub = sinon.stub();
+ sinon
+ .stub(pluginLoader, '_createScriptTag')
+ .callsFake((url: string, _onerror?: OnErrorEventHandler | undefined) =>
+ loadJsPluginStub(url)
+ );
+ });
+
+ test('invalid plugin path', () => {
+ const failToLoadStub = sinon.stub();
+ sinon.stub(pluginLoader, '_failToLoad').callsFake((...args) => {
+ failToLoadStub(...args);
+ });
+
+ pluginLoader.loadPlugins(['foo/bar']);
+
+ assert.isTrue(failToLoadStub.calledOnce);
+ assert.isTrue(
+ failToLoadStub.calledWithExactly(
+ 'Unrecognized plugin path foo/bar',
+ 'foo/bar'
+ )
+ );
+ });
+
+ test('relative path for plugins', () => {
+ pluginLoader.loadPlugins(['foo/bar.js']);
+
+ assert.isTrue(loadJsPluginStub.calledOnce);
+ assert.isTrue(loadJsPluginStub.calledWithExactly(`${url}/foo/bar.js`));
+ });
+
+ test('relative path should honor getBaseUrl', () => {
+ const testUrl = '/test';
+ stubBaseUrl(testUrl);
+
+ pluginLoader.loadPlugins(['foo/bar.js']);
+
+ assert.isTrue(loadJsPluginStub.calledOnce);
+ assert.isTrue(
+ loadJsPluginStub.calledWithExactly(`${url}${testUrl}/foo/bar.js`)
+ );
+ });
+
+ test('absolute path for plugins', () => {
+ pluginLoader.loadPlugins(['http://e.com/foo/bar.js']);
+
+ assert.isTrue(loadJsPluginStub.calledOnce);
+ assert.isTrue(
+ loadJsPluginStub.calledWithExactly('http://e.com/foo/bar.js')
+ );
+ });
+ });
+
+ suite('With ASSETS_PATH', () => {
+ let loadJsPluginStub: sinon.SinonStub;
+ setup(() => {
+ window.ASSETS_PATH = 'https://cdn.com';
+ loadJsPluginStub = sinon.stub();
+ sinon
+ .stub(pluginLoader, '_createScriptTag')
+ .callsFake((url: string, _onerror?: OnErrorEventHandler | undefined) =>
+ loadJsPluginStub(url)
+ );
+ });
+
+ teardown(() => {
+ window.ASSETS_PATH = '';
+ });
+
+ test('Should try load plugins from assets path instead', () => {
+ pluginLoader.loadPlugins(['foo/bar.js']);
+
+ assert.isTrue(loadJsPluginStub.calledOnce);
+ assert.isTrue(
+ loadJsPluginStub.calledWithExactly('https://cdn.com/foo/bar.js')
+ );
+ });
+
+ test('Should honor original path if exists', () => {
+ pluginLoader.loadPlugins(['http://e.com/foo/bar.js']);
+
+ assert.isTrue(loadJsPluginStub.calledOnce);
+ assert.isTrue(
+ loadJsPluginStub.calledWithExactly('http://e.com/foo/bar.js')
+ );
+ });
+
+ test('Should try replace current host with assetsPath', () => {
+ const host = window.location.origin;
+ pluginLoader.loadPlugins([`${host}/foo/bar.js`]);
+
+ assert.isTrue(loadJsPluginStub.calledOnce);
+ assert.isTrue(
+ loadJsPluginStub.calledWithExactly('https://cdn.com/foo/bar.js')
+ );
+ });
+ });
+
+ test('adds js plugins will call the body', () => {
+ pluginLoader.loadPlugins([
+ 'http://e.com/foo/bar.js',
+ 'http://e.com/bar/foo.js',
+ ]);
+ assert.isTrue(bodyStub.calledTwice);
+ });
+
+ test('can call awaitPluginsLoaded multiple times', async () => {
+ const plugins = ['http://e.com/foo/bar.js', 'http://e.com/bar/foo.js'];
+
+ let installed = false;
+ function pluginCallback(url: string) {
+ if (url === plugins[1]) {
+ installed = true;
+ }
+ }
+ sinon.stub(pluginLoader, '_loadJsPlugin').callsFake(url => {
+ window.Gerrit.install(() => pluginCallback(url), undefined, url);
+ });
+
+ pluginLoader.loadPlugins(plugins);
+
+ await pluginLoader.awaitPluginsLoaded();
+ assert.isTrue(installed);
+ await pluginLoader.awaitPluginsLoaded();
+ });
+});