Revert "Move Gerrit.* to a separate file."
This reverts commit 8a56045eba.
Reason for revert: This may break the plugin bundling somehow
Change-Id: Ie2d0be40dd1085b01e7ce396982ff40270d80a69
This commit is contained in:
@@ -1,95 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
const PRELOADED_PROTOCOL = 'preloaded:';
|
||||
|
||||
let _restAPI;
|
||||
|
||||
const getRestAPI = () => {
|
||||
if (!_restAPI) {
|
||||
_restAPI = document.createElement('gr-rest-api-interface');
|
||||
}
|
||||
return _restAPI;
|
||||
};
|
||||
|
||||
function getPluginNameFromUrl(url) {
|
||||
if (!(url instanceof URL)) {
|
||||
try {
|
||||
url = new URL(url);
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (url.protocol === PRELOADED_PROTOCOL) {
|
||||
return url.pathname;
|
||||
}
|
||||
const base = Gerrit.BaseUrlBehavior.getBaseUrl();
|
||||
const pathname = url.pathname.replace(base, '');
|
||||
// Site theme is server from predefined path.
|
||||
if (pathname === '/static/gerrit-theme.html') {
|
||||
return 'gerrit-theme';
|
||||
} else if (!pathname.startsWith('/plugins')) {
|
||||
console.warn('Plugin not being loaded from /plugins base path:',
|
||||
url.href, '— Unable to determine name.');
|
||||
return null;
|
||||
}
|
||||
// Pathname should normally look like this:
|
||||
// /plugins/PLUGINNAME/static/SCRIPTNAME.html
|
||||
// Or, for app/samples:
|
||||
// /plugins/PLUGINNAME.html
|
||||
return pathname.split('/')[2].split('.')[0];
|
||||
}
|
||||
|
||||
// TODO (viktard): deprecate in favor of GrPluginRestApi.
|
||||
function send(method, url, opt_callback, opt_payload) {
|
||||
return getRestAPI().send(method, url, opt_payload).then(response => {
|
||||
if (response.status < 200 || response.status >= 300) {
|
||||
return response.text().then(text => {
|
||||
if (text) {
|
||||
return Promise.reject(text);
|
||||
} else {
|
||||
return Promise.reject(response.status);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return getRestAPI().getResponseObject(response);
|
||||
}
|
||||
}).then(response => {
|
||||
if (opt_callback) {
|
||||
opt_callback(response);
|
||||
}
|
||||
return response;
|
||||
});
|
||||
}
|
||||
|
||||
function resetInternalState() {
|
||||
_restAPI = null;
|
||||
}
|
||||
|
||||
window._apiUtils = {
|
||||
getPluginNameFromUrl,
|
||||
send,
|
||||
getRestAPI,
|
||||
|
||||
// TEST only methods
|
||||
resetInternalState,
|
||||
};
|
||||
})(window);
|
||||
@@ -1,78 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
@license
|
||||
Copyright (C) 2019 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.
|
||||
-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>gr-api-interface</title>
|
||||
<script src="/test/common-test-setup.js"></script>
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<link rel="import" href="../../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="gr-js-api-interface.html">
|
||||
|
||||
<script>void(0);</script>
|
||||
|
||||
<script>
|
||||
|
||||
const PRELOADED_PROTOCOL = 'preloaded:';
|
||||
|
||||
suite('gr-api-utils tests', () => {
|
||||
suite('test getPluginNameFromUrl', () => {
|
||||
const {getPluginNameFromUrl} = window._apiUtils;
|
||||
|
||||
test('with empty string', () => {
|
||||
assert.equal(getPluginNameFromUrl(''), null);
|
||||
});
|
||||
|
||||
test('with invalid url', () => {
|
||||
assert.equal(getPluginNameFromUrl('test'), null);
|
||||
});
|
||||
|
||||
test('with random invalid url', () => {
|
||||
assert.equal(getPluginNameFromUrl('http://example.com'), null);
|
||||
assert.equal(
|
||||
getPluginNameFromUrl('http://example.com/static/a.html'),
|
||||
null
|
||||
);
|
||||
});
|
||||
|
||||
test('with valid urls', () => {
|
||||
assert.equal(
|
||||
getPluginNameFromUrl('http://example.com/plugins/a.html'),
|
||||
'a'
|
||||
);
|
||||
assert.equal(
|
||||
getPluginNameFromUrl('http://example.com/plugins/a/static/t.html'),
|
||||
'a'
|
||||
);
|
||||
});
|
||||
|
||||
test('with preloaded urls', () => {
|
||||
assert.equal(getPluginNameFromUrl(`${PRELOADED_PROTOCOL}a`), 'a');
|
||||
});
|
||||
|
||||
test('with gerrit-theme override', () => {
|
||||
assert.equal(
|
||||
getPluginNameFromUrl('http://example.com/static/gerrit-theme.html'),
|
||||
'gerrit-theme'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -1,280 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Hash of loaded and installed plugins, name to Plugin object.
|
||||
*/
|
||||
const _plugins = {};
|
||||
|
||||
/**
|
||||
* Array of plugin URLs to be loaded, name to url.
|
||||
*/
|
||||
let _pluginsPending = {};
|
||||
|
||||
let _pluginsInstalled = [];
|
||||
|
||||
let _pluginsPendingCount = -1;
|
||||
|
||||
const UNKNOWN_PLUGIN = 'unknown';
|
||||
const PRELOADED_PROTOCOL = 'preloaded:';
|
||||
|
||||
const PLUGIN_LOADING_TIMEOUT_MS = 10000;
|
||||
|
||||
let _reporting;
|
||||
const getReporting = () => {
|
||||
if (!_reporting) {
|
||||
_reporting = document.createElement('gr-reporting');
|
||||
}
|
||||
return _reporting;
|
||||
};
|
||||
|
||||
// Import utils methods
|
||||
const {
|
||||
getPluginNameFromUrl,
|
||||
send,
|
||||
getRestAPI,
|
||||
resetInternalState,
|
||||
} = window._apiUtils;
|
||||
|
||||
const API_VERSION = '0.1';
|
||||
|
||||
window.Gerrit = window.Gerrit || {};
|
||||
const Gerrit = window.Gerrit;
|
||||
|
||||
let _resolveAllPluginsLoaded = null;
|
||||
let _allPluginsPromise = null;
|
||||
|
||||
Gerrit._endpoints = new GrPluginEndpoints();
|
||||
|
||||
// Provide reset plugins function to clear installed plugins between tests.
|
||||
const app = document.querySelector('#app');
|
||||
if (!app) {
|
||||
// No gr-app found (running tests)
|
||||
Gerrit._installPreloadedPlugins = installPreloadedPlugins;
|
||||
Gerrit._flushPreinstalls = flushPreinstalls;
|
||||
Gerrit._resetPlugins = () => {
|
||||
_allPluginsPromise = null;
|
||||
_pluginsInstalled = [];
|
||||
_pluginsPending = {};
|
||||
_pluginsPendingCount = -1;
|
||||
_reporting = null;
|
||||
_resolveAllPluginsLoaded = null;
|
||||
resetInternalState();
|
||||
Gerrit._endpoints = new GrPluginEndpoints();
|
||||
for (const k of Object.keys(_plugins)) {
|
||||
delete _plugins[k];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use plugin.styles().css(rulesStr) instead. Please, consult
|
||||
* the documentation how to replace it accordingly.
|
||||
*/
|
||||
Gerrit.css = function(rulesStr) {
|
||||
console.warn('Gerrit.css(rulesStr) is deprecated!',
|
||||
'Use plugin.styles().css(rulesStr)');
|
||||
if (!Gerrit._customStyleSheet) {
|
||||
const styleEl = document.createElement('style');
|
||||
document.head.appendChild(styleEl);
|
||||
Gerrit._customStyleSheet = styleEl.sheet;
|
||||
}
|
||||
|
||||
const name = '__pg_js_api_class_' +
|
||||
Gerrit._customStyleSheet.cssRules.length;
|
||||
Gerrit._customStyleSheet.insertRule('.' + name + '{' + rulesStr + '}', 0);
|
||||
return name;
|
||||
};
|
||||
|
||||
Gerrit.install = function(callback, opt_version, opt_src) {
|
||||
// HTML import polyfill adds __importElement pointing to the import tag.
|
||||
const script = document.currentScript &&
|
||||
(document.currentScript.__importElement || document.currentScript);
|
||||
|
||||
let src = opt_src || (script && script.src);
|
||||
if (!src || src.startsWith('data:')) {
|
||||
src = script && script.baseURI;
|
||||
}
|
||||
const name = getPluginNameFromUrl(src);
|
||||
|
||||
if (opt_version && opt_version !== API_VERSION) {
|
||||
Gerrit._pluginInstallError(`Plugin ${name} install error: only version ` +
|
||||
API_VERSION + ' is supported in PolyGerrit. ' + opt_version +
|
||||
' was given.');
|
||||
return;
|
||||
}
|
||||
|
||||
const existingPlugin = _plugins[name];
|
||||
const plugin = existingPlugin || new Plugin(src);
|
||||
try {
|
||||
callback(plugin);
|
||||
if (name) {
|
||||
_plugins[name] = plugin;
|
||||
}
|
||||
if (!existingPlugin) {
|
||||
Gerrit._pluginInstalled(src);
|
||||
}
|
||||
} catch (e) {
|
||||
Gerrit._pluginInstallError(`${e.name}: ${e.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
Gerrit.getLoggedIn = function() {
|
||||
console.warn('Gerrit.getLoggedIn() is deprecated! ' +
|
||||
'Use plugin.restApi().getLoggedIn()');
|
||||
return document.createElement('gr-rest-api-interface').getLoggedIn();
|
||||
};
|
||||
|
||||
Gerrit.get = function(url, callback) {
|
||||
console.warn('.get() is deprecated! Use plugin.restApi().get()');
|
||||
send('GET', url, callback);
|
||||
};
|
||||
|
||||
Gerrit.post = function(url, payload, callback) {
|
||||
console.warn('.post() is deprecated! Use plugin.restApi().post()');
|
||||
send('POST', url, callback, payload);
|
||||
};
|
||||
|
||||
Gerrit.put = function(url, payload, callback) {
|
||||
console.warn('.put() is deprecated! Use plugin.restApi().put()');
|
||||
send('PUT', url, callback, payload);
|
||||
};
|
||||
|
||||
Gerrit.delete = function(url, opt_callback) {
|
||||
console.warn('.delete() is deprecated! Use plugin.restApi().delete()');
|
||||
return getRestAPI().send('DELETE', url).then(response => {
|
||||
if (response.status !== 204) {
|
||||
return response.text().then(text => {
|
||||
if (text) {
|
||||
return Promise.reject(text);
|
||||
} else {
|
||||
return Promise.reject(response.status);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (opt_callback) {
|
||||
opt_callback(response);
|
||||
}
|
||||
return response;
|
||||
});
|
||||
};
|
||||
|
||||
Gerrit.awaitPluginsLoaded = function() {
|
||||
if (!_allPluginsPromise) {
|
||||
if (Gerrit._arePluginsLoaded()) {
|
||||
_allPluginsPromise = Promise.resolve();
|
||||
} else {
|
||||
let timeoutId;
|
||||
_allPluginsPromise =
|
||||
Promise.race([
|
||||
new Promise(resolve => _resolveAllPluginsLoaded = resolve),
|
||||
new Promise(resolve => timeoutId = setTimeout(
|
||||
Gerrit._pluginLoadingTimeout, PLUGIN_LOADING_TIMEOUT_MS)),
|
||||
]).then(() => clearTimeout(timeoutId));
|
||||
}
|
||||
}
|
||||
return _allPluginsPromise;
|
||||
};
|
||||
|
||||
Gerrit._pluginLoadingTimeout = function() {
|
||||
console.error(`Failed to load plugins: ${Object.keys(_pluginsPending)}`);
|
||||
Gerrit._setPluginsPending([]);
|
||||
};
|
||||
|
||||
Gerrit._setPluginsPending = function(plugins) {
|
||||
_pluginsPending = plugins.reduce((o, url) => {
|
||||
// TODO(viktard): Remove guard (@see Issue 8962)
|
||||
o[getPluginNameFromUrl(url) || UNKNOWN_PLUGIN] = url;
|
||||
return o;
|
||||
}, {});
|
||||
Gerrit._setPluginsCount(Object.keys(_pluginsPending).length);
|
||||
};
|
||||
|
||||
Gerrit._setPluginsCount = function(count) {
|
||||
_pluginsPendingCount = count;
|
||||
if (Gerrit._arePluginsLoaded()) {
|
||||
getReporting().pluginsLoaded(_pluginsInstalled);
|
||||
if (_resolveAllPluginsLoaded) {
|
||||
_resolveAllPluginsLoaded();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Gerrit._pluginInstallError = function(message) {
|
||||
document.dispatchEvent(new CustomEvent('show-alert', {
|
||||
detail: {
|
||||
message: `Plugin install error: ${message}`,
|
||||
},
|
||||
}));
|
||||
console.info(`Plugin install error: ${message}`);
|
||||
Gerrit._setPluginsCount(_pluginsPendingCount - 1);
|
||||
};
|
||||
|
||||
Gerrit._pluginInstalled = function(url) {
|
||||
const name = getPluginNameFromUrl(url) || UNKNOWN_PLUGIN;
|
||||
if (!_pluginsPending[name]) {
|
||||
console.warn(`Unexpected plugin ${name} installed from ${url}.`);
|
||||
} else {
|
||||
delete _pluginsPending[name];
|
||||
_pluginsInstalled.push(name);
|
||||
Gerrit._setPluginsCount(_pluginsPendingCount - 1);
|
||||
getReporting().pluginLoaded(name);
|
||||
console.log(`Plugin ${name} installed.`);
|
||||
}
|
||||
};
|
||||
|
||||
Gerrit._arePluginsLoaded = function() {
|
||||
return _pluginsPendingCount === 0;
|
||||
};
|
||||
|
||||
Gerrit._getPluginScreenName = function(pluginName, screenName) {
|
||||
return `${pluginName}-screen-${screenName}`;
|
||||
};
|
||||
|
||||
Gerrit._isPluginPreloaded = function(url) {
|
||||
const name = getPluginNameFromUrl(url);
|
||||
if (name && Gerrit._preloadedPlugins) {
|
||||
return name in Gerrit._preloadedPlugins;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
function flushPreinstalls() {
|
||||
if (window.Gerrit.flushPreinstalls) {
|
||||
window.Gerrit.flushPreinstalls();
|
||||
}
|
||||
}
|
||||
|
||||
function installPreloadedPlugins() {
|
||||
if (!Gerrit._preloadedPlugins) { return; }
|
||||
for (const name in Gerrit._preloadedPlugins) {
|
||||
if (!Gerrit._preloadedPlugins.hasOwnProperty(name)) { continue; }
|
||||
const callback = Gerrit._preloadedPlugins[name];
|
||||
Gerrit.install(callback, API_VERSION, PRELOADED_PROTOCOL + name);
|
||||
}
|
||||
}
|
||||
|
||||
flushPreinstalls();
|
||||
|
||||
// Preloaded plugins should be installed after Gerrit.install() is set,
|
||||
// since plugin preloader substitutes Gerrit.install() temporarily.
|
||||
installPreloadedPlugins();
|
||||
})(window);
|
||||
@@ -1,188 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
@license
|
||||
Copyright (C) 2019 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.
|
||||
-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>gr-api-interface</title>
|
||||
<script src="/test/common-test-setup.js"></script>
|
||||
<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
|
||||
|
||||
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="/bower_components/web-component-tester/browser.js"></script>
|
||||
<link rel="import" href="../../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="gr-js-api-interface.html">
|
||||
|
||||
<script>void(0);</script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
<gr-js-api-interface></gr-js-api-interface>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-gerrit tests', () => {
|
||||
let element;
|
||||
let plugin;
|
||||
let sandbox;
|
||||
let sendStub;
|
||||
|
||||
setup(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
sendStub = sandbox.stub().returns(Promise.resolve({status: 200}));
|
||||
stub('gr-rest-api-interface', {
|
||||
getAccount() {
|
||||
return Promise.resolve({name: 'Judy Hopps'});
|
||||
},
|
||||
send(...args) {
|
||||
return sendStub(...args);
|
||||
},
|
||||
});
|
||||
element = fixture('basic');
|
||||
Gerrit.install(p => { plugin = p; }, '0.1',
|
||||
'http://test.com/plugins/testplugin/static/test.js');
|
||||
Gerrit._setPluginsPending([]);
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
element._removeEventCallbacks();
|
||||
plugin = null;
|
||||
});
|
||||
|
||||
test('reuse plugin for install calls', () => {
|
||||
let otherPlugin;
|
||||
Gerrit.install(p => { otherPlugin = p; }, '0.1',
|
||||
'http://test.com/plugins/testplugin/static/test.js');
|
||||
assert.strictEqual(plugin, otherPlugin);
|
||||
});
|
||||
|
||||
test('flushes preinstalls if provided', () => {
|
||||
assert.doesNotThrow(() => {
|
||||
Gerrit._flushPreinstalls();
|
||||
});
|
||||
window.Gerrit.flushPreinstalls = sandbox.stub();
|
||||
Gerrit._flushPreinstalls();
|
||||
assert.isTrue(window.Gerrit.flushPreinstalls.calledOnce);
|
||||
delete window.Gerrit.flushPreinstalls;
|
||||
});
|
||||
|
||||
test('versioning', () => {
|
||||
const callback = sandbox.spy();
|
||||
Gerrit.install(callback, '0.0pre-alpha');
|
||||
assert(callback.notCalled);
|
||||
});
|
||||
|
||||
test('_setPluginsCount', done => {
|
||||
stub('gr-reporting', {
|
||||
pluginsLoaded() {
|
||||
done();
|
||||
},
|
||||
});
|
||||
Gerrit._setPluginsCount(0);
|
||||
});
|
||||
|
||||
test('_arePluginsLoaded', () => {
|
||||
assert.isTrue(Gerrit._arePluginsLoaded());
|
||||
Gerrit._setPluginsCount(1);
|
||||
assert.isFalse(Gerrit._arePluginsLoaded());
|
||||
Gerrit._setPluginsCount(0);
|
||||
assert.isTrue(Gerrit._arePluginsLoaded());
|
||||
});
|
||||
|
||||
test('_pluginInstalled', () => {
|
||||
const pluginsLoadedStub = sandbox.stub();
|
||||
stub('gr-reporting', {
|
||||
pluginsLoaded: (...args) => pluginsLoadedStub(...args),
|
||||
});
|
||||
const plugins = [
|
||||
'http://test.com/plugins/foo/static/test.js',
|
||||
'http://test.com/plugins/bar/static/test.js',
|
||||
];
|
||||
Gerrit._setPluginsPending(plugins);
|
||||
Gerrit._pluginInstalled(plugins[0]);
|
||||
Gerrit._pluginInstalled(plugins[1]);
|
||||
assert.isTrue(pluginsLoadedStub.calledWithExactly(['foo', 'bar']));
|
||||
});
|
||||
|
||||
test('install calls _pluginInstalled', () => {
|
||||
sandbox.stub(Gerrit, '_pluginInstalled');
|
||||
Gerrit.install(p => { plugin = p; }, '0.1',
|
||||
'http://test.com/plugins/testplugin/static/test.js');
|
||||
|
||||
// testplugin has already been installed once (in setup).
|
||||
assert.isFalse(Gerrit._pluginInstalled.called);
|
||||
|
||||
// testplugin2 plugin has not yet been installed.
|
||||
Gerrit.install(p => { plugin = p; }, '0.1',
|
||||
'http://test.com/plugins/testplugin2/static/test.js');
|
||||
assert.isTrue(Gerrit._pluginInstalled.calledOnce);
|
||||
});
|
||||
|
||||
test('plugin install errors mark plugins as loaded', () => {
|
||||
Gerrit._setPluginsCount(1);
|
||||
Gerrit.install(() => {}, '0.0pre-alpha');
|
||||
return Gerrit.awaitPluginsLoaded();
|
||||
});
|
||||
|
||||
test('multiple ui plugins per java plugin', () => {
|
||||
const file1 = 'http://test.com/plugins/qaz/static/foo.nocache.js';
|
||||
const file2 = 'http://test.com/plugins/qaz/static/bar.js';
|
||||
Gerrit._setPluginsPending([file1, file2]);
|
||||
Gerrit.install(() => {}, '0.1', file1);
|
||||
Gerrit.install(() => {}, '0.1', file2);
|
||||
return Gerrit.awaitPluginsLoaded();
|
||||
});
|
||||
|
||||
test('plugin install errors shows toasts', () => {
|
||||
const alertStub = sandbox.stub();
|
||||
document.addEventListener('show-alert', alertStub);
|
||||
Gerrit._setPluginsCount(1);
|
||||
Gerrit.install(() => {}, '0.0pre-alpha');
|
||||
return Gerrit.awaitPluginsLoaded().then(() => {
|
||||
assert.isTrue(alertStub.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
test('Gerrit._isPluginPreloaded', () => {
|
||||
Gerrit._preloadedPlugins = {baz: ()=>{}};
|
||||
assert.isFalse(Gerrit._isPluginPreloaded('plugins/foo/bar'));
|
||||
assert.isFalse(Gerrit._isPluginPreloaded('http://a.com/42'));
|
||||
assert.isTrue(Gerrit._isPluginPreloaded('preloaded:baz'));
|
||||
Gerrit._preloadedPlugins = null;
|
||||
});
|
||||
|
||||
test('preloaded plugins are installed', () => {
|
||||
const installStub = sandbox.stub();
|
||||
Gerrit._preloadedPlugins = {foo: installStub};
|
||||
Gerrit._installPreloadedPlugins();
|
||||
assert.isTrue(installStub.called);
|
||||
const pluginApi = installStub.lastCall.args[0];
|
||||
assert.strictEqual(pluginApi.getPluginName(), 'foo');
|
||||
});
|
||||
|
||||
test('installing preloaded plugin', () => {
|
||||
let plugin;
|
||||
window.ASSETS_PATH = 'http://blips.com/chitz';
|
||||
Gerrit.install(p => { plugin = p; }, '0.1', 'preloaded:foo');
|
||||
assert.strictEqual(plugin.getPluginName(), 'foo');
|
||||
assert.strictEqual(plugin.url('/some/thing.html'),
|
||||
'http://blips.com/chitz/plugins/foo/some/thing.html');
|
||||
delete window.ASSETS_PATH;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -31,7 +31,6 @@ limitations under the License.
|
||||
<link rel="import" href="../gr-rest-api-interface/gr-rest-api-interface.html">
|
||||
|
||||
<dom-module id="gr-js-api-interface">
|
||||
<script src="gr-api-utils.js"></script>
|
||||
<script src="gr-annotation-actions-context.js"></script>
|
||||
<script src="gr-annotation-actions-js-api.js"></script>
|
||||
<script src="gr-change-actions-js-api.js"></script>
|
||||
@@ -41,5 +40,4 @@ limitations under the License.
|
||||
<script src="gr-plugin-action-context.js"></script>
|
||||
<script src="gr-plugin-rest-api.js"></script>
|
||||
<script src="gr-public-js-api.js"></script>
|
||||
<script src="gr-gerrit.js"></script>
|
||||
</dom-module>
|
||||
|
||||
@@ -73,6 +73,23 @@ limitations under the License.
|
||||
plugin = null;
|
||||
});
|
||||
|
||||
test('reuse plugin for install calls', () => {
|
||||
let otherPlugin;
|
||||
Gerrit.install(p => { otherPlugin = p; }, '0.1',
|
||||
'http://test.com/plugins/testplugin/static/test.js');
|
||||
assert.strictEqual(plugin, otherPlugin);
|
||||
});
|
||||
|
||||
test('flushes preinstalls if provided', () => {
|
||||
assert.doesNotThrow(() => {
|
||||
Gerrit._flushPreinstalls();
|
||||
});
|
||||
window.Gerrit.flushPreinstalls = sandbox.stub();
|
||||
Gerrit._flushPreinstalls();
|
||||
assert.isTrue(window.Gerrit.flushPreinstalls.calledOnce);
|
||||
delete window.Gerrit.flushPreinstalls;
|
||||
});
|
||||
|
||||
test('url', () => {
|
||||
assert.equal(plugin.url(), 'http://test.com/plugins/testplugin/');
|
||||
assert.equal(plugin.url('/static/test.js'),
|
||||
@@ -296,6 +313,12 @@ limitations under the License.
|
||||
element.handleEvent(element.EventType.HIGHLIGHTJS_LOADED, {hljs: testHljs});
|
||||
});
|
||||
|
||||
test('versioning', () => {
|
||||
const callback = sandbox.spy();
|
||||
Gerrit.install(callback, '0.0pre-alpha');
|
||||
assert(callback.notCalled);
|
||||
});
|
||||
|
||||
test('getAccount', done => {
|
||||
plugin.restApi().getLoggedIn().then(loggedIn => {
|
||||
assert.isTrue(loggedIn);
|
||||
@@ -303,6 +326,77 @@ limitations under the License.
|
||||
});
|
||||
});
|
||||
|
||||
test('_setPluginsCount', done => {
|
||||
stub('gr-reporting', {
|
||||
pluginsLoaded() {
|
||||
done();
|
||||
},
|
||||
});
|
||||
Gerrit._setPluginsCount(0);
|
||||
});
|
||||
|
||||
test('_arePluginsLoaded', () => {
|
||||
assert.isTrue(Gerrit._arePluginsLoaded());
|
||||
Gerrit._setPluginsCount(1);
|
||||
assert.isFalse(Gerrit._arePluginsLoaded());
|
||||
Gerrit._setPluginsCount(0);
|
||||
assert.isTrue(Gerrit._arePluginsLoaded());
|
||||
});
|
||||
|
||||
test('_pluginInstalled', () => {
|
||||
const pluginsLoadedStub = sandbox.stub();
|
||||
stub('gr-reporting', {
|
||||
pluginsLoaded: (...args) => pluginsLoadedStub(...args),
|
||||
});
|
||||
const plugins = [
|
||||
'http://test.com/plugins/foo/static/test.js',
|
||||
'http://test.com/plugins/bar/static/test.js',
|
||||
];
|
||||
Gerrit._setPluginsPending(plugins);
|
||||
Gerrit._pluginInstalled(plugins[0]);
|
||||
Gerrit._pluginInstalled(plugins[1]);
|
||||
assert.isTrue(pluginsLoadedStub.calledWithExactly(['foo', 'bar']));
|
||||
});
|
||||
|
||||
test('install calls _pluginInstalled', () => {
|
||||
sandbox.stub(Gerrit, '_pluginInstalled');
|
||||
Gerrit.install(p => { plugin = p; }, '0.1',
|
||||
'http://test.com/plugins/testplugin/static/test.js');
|
||||
|
||||
// testplugin has already been installed once (in setup).
|
||||
assert.isFalse(Gerrit._pluginInstalled.called);
|
||||
|
||||
// testplugin2 plugin has not yet been installed.
|
||||
Gerrit.install(p => { plugin = p; }, '0.1',
|
||||
'http://test.com/plugins/testplugin2/static/test.js');
|
||||
assert.isTrue(Gerrit._pluginInstalled.calledOnce);
|
||||
});
|
||||
|
||||
test('plugin install errors mark plugins as loaded', () => {
|
||||
Gerrit._setPluginsCount(1);
|
||||
Gerrit.install(() => {}, '0.0pre-alpha');
|
||||
return Gerrit.awaitPluginsLoaded();
|
||||
});
|
||||
|
||||
test('multiple ui plugins per java plugin', () => {
|
||||
const file1 = 'http://test.com/plugins/qaz/static/foo.nocache.js';
|
||||
const file2 = 'http://test.com/plugins/qaz/static/bar.js';
|
||||
Gerrit._setPluginsPending([file1, file2]);
|
||||
Gerrit.install(() => {}, '0.1', file1);
|
||||
Gerrit.install(() => {}, '0.1', file2);
|
||||
return Gerrit.awaitPluginsLoaded();
|
||||
});
|
||||
|
||||
test('plugin install errors shows toasts', () => {
|
||||
const alertStub = sandbox.stub();
|
||||
document.addEventListener('show-alert', alertStub);
|
||||
Gerrit._setPluginsCount(1);
|
||||
Gerrit.install(() => {}, '0.0pre-alpha');
|
||||
return Gerrit.awaitPluginsLoaded().then(() => {
|
||||
assert.isTrue(alertStub.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
test('attributeHelper', () => {
|
||||
assert.isOk(plugin.attributeHelper());
|
||||
});
|
||||
@@ -328,6 +422,33 @@ limitations under the License.
|
||||
element.EventType.ADMIN_MENU_LINKS);
|
||||
});
|
||||
|
||||
test('Gerrit._isPluginPreloaded', () => {
|
||||
Gerrit._preloadedPlugins = {baz: ()=>{}};
|
||||
assert.isFalse(Gerrit._isPluginPreloaded('plugins/foo/bar'));
|
||||
assert.isFalse(Gerrit._isPluginPreloaded('http://a.com/42'));
|
||||
assert.isTrue(Gerrit._isPluginPreloaded('preloaded:baz'));
|
||||
Gerrit._preloadedPlugins = null;
|
||||
});
|
||||
|
||||
test('preloaded plugins are installed', () => {
|
||||
const installStub = sandbox.stub();
|
||||
Gerrit._preloadedPlugins = {foo: installStub};
|
||||
Gerrit._installPreloadedPlugins();
|
||||
assert.isTrue(installStub.called);
|
||||
const pluginApi = installStub.lastCall.args[0];
|
||||
assert.strictEqual(pluginApi.getPluginName(), 'foo');
|
||||
});
|
||||
|
||||
test('installing preloaded plugin', () => {
|
||||
let plugin;
|
||||
window.ASSETS_PATH = 'http://blips.com/chitz';
|
||||
Gerrit.install(p => { plugin = p; }, '0.1', 'preloaded:foo');
|
||||
assert.strictEqual(plugin.getPluginName(), 'foo');
|
||||
assert.strictEqual(plugin.url('/some/thing.html'),
|
||||
'http://blips.com/chitz/plugins/foo/some/thing.html');
|
||||
delete window.ASSETS_PATH;
|
||||
});
|
||||
|
||||
suite('test plugin with base url', () => {
|
||||
let baseUrlPlugin;
|
||||
|
||||
|
||||
@@ -17,18 +17,71 @@
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Hash of loaded and installed plugins, name to Plugin object.
|
||||
*/
|
||||
const _plugins = {};
|
||||
|
||||
/**
|
||||
* Array of plugin URLs to be loaded, name to url.
|
||||
*/
|
||||
let _pluginsPending = {};
|
||||
|
||||
let _pluginsInstalled = [];
|
||||
|
||||
let _pluginsPendingCount = -1;
|
||||
|
||||
const PRELOADED_PROTOCOL = 'preloaded:';
|
||||
|
||||
const UNKNOWN_PLUGIN = 'unknown';
|
||||
|
||||
const PANEL_ENDPOINTS_MAPPING = {
|
||||
CHANGE_SCREEN_BELOW_COMMIT_INFO_BLOCK: 'change-view-integration',
|
||||
CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK: 'change-metadata-item',
|
||||
};
|
||||
|
||||
// Import utils methods
|
||||
const {
|
||||
getPluginNameFromUrl,
|
||||
send,
|
||||
} = window._apiUtils;
|
||||
const PLUGIN_LOADING_TIMEOUT_MS = 10000;
|
||||
|
||||
let _restAPI;
|
||||
|
||||
const getRestAPI = () => {
|
||||
if (!_restAPI) {
|
||||
_restAPI = document.createElement('gr-rest-api-interface');
|
||||
}
|
||||
return _restAPI;
|
||||
};
|
||||
|
||||
let _reporting;
|
||||
const getReporting = () => {
|
||||
if (!_reporting) {
|
||||
_reporting = document.createElement('gr-reporting');
|
||||
}
|
||||
return _reporting;
|
||||
};
|
||||
|
||||
// TODO (viktard): deprecate in favor of GrPluginRestApi.
|
||||
function send(method, url, opt_callback, opt_payload) {
|
||||
return getRestAPI().send(method, url, opt_payload).then(response => {
|
||||
if (response.status < 200 || response.status >= 300) {
|
||||
return response.text().then(text => {
|
||||
if (text) {
|
||||
return Promise.reject(text);
|
||||
} else {
|
||||
return Promise.reject(response.status);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return getRestAPI().getResponseObject(response);
|
||||
}
|
||||
}).then(response => {
|
||||
if (opt_callback) {
|
||||
opt_callback(response);
|
||||
}
|
||||
return response;
|
||||
});
|
||||
}
|
||||
|
||||
const API_VERSION = '0.1';
|
||||
|
||||
/**
|
||||
* Plugin-provided custom components can affect content in extension
|
||||
@@ -46,6 +99,50 @@
|
||||
STYLE: 'style',
|
||||
};
|
||||
|
||||
function flushPreinstalls() {
|
||||
if (window.Gerrit.flushPreinstalls) {
|
||||
window.Gerrit.flushPreinstalls();
|
||||
}
|
||||
}
|
||||
|
||||
function installPreloadedPlugins() {
|
||||
if (!Gerrit._preloadedPlugins) { return; }
|
||||
for (const name in Gerrit._preloadedPlugins) {
|
||||
if (!Gerrit._preloadedPlugins.hasOwnProperty(name)) { continue; }
|
||||
const callback = Gerrit._preloadedPlugins[name];
|
||||
Gerrit.install(callback, API_VERSION, PRELOADED_PROTOCOL + name);
|
||||
}
|
||||
}
|
||||
|
||||
function getPluginNameFromUrl(url) {
|
||||
if (!(url instanceof URL)) {
|
||||
try {
|
||||
url = new URL(url);
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (url.protocol === PRELOADED_PROTOCOL) {
|
||||
return url.pathname;
|
||||
}
|
||||
const base = Gerrit.BaseUrlBehavior.getBaseUrl();
|
||||
const pathname = url.pathname.replace(base, '');
|
||||
// Site theme is server from predefined path.
|
||||
if (pathname === '/static/gerrit-theme.html') {
|
||||
return 'gerrit-theme';
|
||||
} else if (!pathname.startsWith('/plugins')) {
|
||||
console.warn('Plugin not being loaded from /plugins base path:',
|
||||
url.href, '— Unable to determine name.');
|
||||
return;
|
||||
}
|
||||
// Pathname should normally look like this:
|
||||
// /plugins/PLUGINNAME/static/SCRIPTNAME.html
|
||||
// Or, for app/samples:
|
||||
// /plugins/PLUGINNAME.html
|
||||
return pathname.split('/')[2].split('.')[0];
|
||||
}
|
||||
|
||||
function Plugin(opt_url) {
|
||||
this._domHooks = new GrDomHooksManager(this);
|
||||
|
||||
@@ -378,5 +475,211 @@
|
||||
},
|
||||
};
|
||||
|
||||
window.Plugin = Plugin;
|
||||
flushPreinstalls();
|
||||
|
||||
window.Gerrit = window.Gerrit || {};
|
||||
const Gerrit = window.Gerrit;
|
||||
|
||||
let _resolveAllPluginsLoaded = null;
|
||||
let _allPluginsPromise = null;
|
||||
|
||||
Gerrit._endpoints = new GrPluginEndpoints();
|
||||
|
||||
// Provide reset plugins function to clear installed plugins between tests.
|
||||
const app = document.querySelector('#app');
|
||||
if (!app) {
|
||||
// No gr-app found (running tests)
|
||||
Gerrit._installPreloadedPlugins = installPreloadedPlugins;
|
||||
Gerrit._flushPreinstalls = flushPreinstalls;
|
||||
Gerrit._resetPlugins = () => {
|
||||
_allPluginsPromise = null;
|
||||
_pluginsInstalled = [];
|
||||
_pluginsPending = {};
|
||||
_pluginsPendingCount = -1;
|
||||
_reporting = null;
|
||||
_resolveAllPluginsLoaded = null;
|
||||
_restAPI = null;
|
||||
Gerrit._endpoints = new GrPluginEndpoints();
|
||||
for (const k of Object.keys(_plugins)) {
|
||||
delete _plugins[k];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use plugin.styles().css(rulesStr) instead. Please, consult
|
||||
* the documentation how to replace it accordingly.
|
||||
*/
|
||||
Gerrit.css = function(rulesStr) {
|
||||
console.warn('Gerrit.css(rulesStr) is deprecated!',
|
||||
'Use plugin.styles().css(rulesStr)');
|
||||
if (!Gerrit._customStyleSheet) {
|
||||
const styleEl = document.createElement('style');
|
||||
document.head.appendChild(styleEl);
|
||||
Gerrit._customStyleSheet = styleEl.sheet;
|
||||
}
|
||||
|
||||
const name = '__pg_js_api_class_' +
|
||||
Gerrit._customStyleSheet.cssRules.length;
|
||||
Gerrit._customStyleSheet.insertRule('.' + name + '{' + rulesStr + '}', 0);
|
||||
return name;
|
||||
};
|
||||
|
||||
Gerrit.install = function(callback, opt_version, opt_src) {
|
||||
// HTML import polyfill adds __importElement pointing to the import tag.
|
||||
const script = document.currentScript &&
|
||||
(document.currentScript.__importElement || document.currentScript);
|
||||
|
||||
let src = opt_src || (script && script.src);
|
||||
if (!src || src.startsWith('data:')) {
|
||||
src = script && script.baseURI;
|
||||
}
|
||||
const name = getPluginNameFromUrl(src);
|
||||
|
||||
if (opt_version && opt_version !== API_VERSION) {
|
||||
Gerrit._pluginInstallError(`Plugin ${name} install error: only version ` +
|
||||
API_VERSION + ' is supported in PolyGerrit. ' + opt_version +
|
||||
' was given.');
|
||||
return;
|
||||
}
|
||||
|
||||
const existingPlugin = _plugins[name];
|
||||
const plugin = existingPlugin || new Plugin(src);
|
||||
try {
|
||||
callback(plugin);
|
||||
if (name) {
|
||||
_plugins[name] = plugin;
|
||||
}
|
||||
if (!existingPlugin) {
|
||||
Gerrit._pluginInstalled(src);
|
||||
}
|
||||
} catch (e) {
|
||||
Gerrit._pluginInstallError(`${e.name}: ${e.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
Gerrit.getLoggedIn = function() {
|
||||
console.warn('Gerrit.getLoggedIn() is deprecated! ' +
|
||||
'Use plugin.restApi().getLoggedIn()');
|
||||
return document.createElement('gr-rest-api-interface').getLoggedIn();
|
||||
};
|
||||
|
||||
Gerrit.get = function(url, callback) {
|
||||
console.warn('.get() is deprecated! Use plugin.restApi().get()');
|
||||
send('GET', url, callback);
|
||||
};
|
||||
|
||||
Gerrit.post = function(url, payload, callback) {
|
||||
console.warn('.post() is deprecated! Use plugin.restApi().post()');
|
||||
send('POST', url, callback, payload);
|
||||
};
|
||||
|
||||
Gerrit.put = function(url, payload, callback) {
|
||||
console.warn('.put() is deprecated! Use plugin.restApi().put()');
|
||||
send('PUT', url, callback, payload);
|
||||
};
|
||||
|
||||
Gerrit.delete = function(url, opt_callback) {
|
||||
console.warn('.delete() is deprecated! Use plugin.restApi().delete()');
|
||||
return getRestAPI().send('DELETE', url).then(response => {
|
||||
if (response.status !== 204) {
|
||||
return response.text().then(text => {
|
||||
if (text) {
|
||||
return Promise.reject(text);
|
||||
} else {
|
||||
return Promise.reject(response.status);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (opt_callback) {
|
||||
opt_callback(response);
|
||||
}
|
||||
return response;
|
||||
});
|
||||
};
|
||||
|
||||
Gerrit.awaitPluginsLoaded = function() {
|
||||
if (!_allPluginsPromise) {
|
||||
if (Gerrit._arePluginsLoaded()) {
|
||||
_allPluginsPromise = Promise.resolve();
|
||||
} else {
|
||||
let timeoutId;
|
||||
_allPluginsPromise =
|
||||
Promise.race([
|
||||
new Promise(resolve => _resolveAllPluginsLoaded = resolve),
|
||||
new Promise(resolve => timeoutId = setTimeout(
|
||||
Gerrit._pluginLoadingTimeout, PLUGIN_LOADING_TIMEOUT_MS)),
|
||||
]).then(() => clearTimeout(timeoutId));
|
||||
}
|
||||
}
|
||||
return _allPluginsPromise;
|
||||
};
|
||||
|
||||
Gerrit._pluginLoadingTimeout = function() {
|
||||
console.error(`Failed to load plugins: ${Object.keys(_pluginsPending)}`);
|
||||
Gerrit._setPluginsPending([]);
|
||||
};
|
||||
|
||||
Gerrit._setPluginsPending = function(plugins) {
|
||||
_pluginsPending = plugins.reduce((o, url) => {
|
||||
// TODO(viktard): Remove guard (@see Issue 8962)
|
||||
o[getPluginNameFromUrl(url) || UNKNOWN_PLUGIN] = url;
|
||||
return o;
|
||||
}, {});
|
||||
Gerrit._setPluginsCount(Object.keys(_pluginsPending).length);
|
||||
};
|
||||
|
||||
Gerrit._setPluginsCount = function(count) {
|
||||
_pluginsPendingCount = count;
|
||||
if (Gerrit._arePluginsLoaded()) {
|
||||
getReporting().pluginsLoaded(_pluginsInstalled);
|
||||
if (_resolveAllPluginsLoaded) {
|
||||
_resolveAllPluginsLoaded();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Gerrit._pluginInstallError = function(message) {
|
||||
document.dispatchEvent(new CustomEvent('show-alert', {
|
||||
detail: {
|
||||
message: `Plugin install error: ${message}`,
|
||||
},
|
||||
}));
|
||||
console.info(`Plugin install error: ${message}`);
|
||||
Gerrit._setPluginsCount(_pluginsPendingCount - 1);
|
||||
};
|
||||
|
||||
Gerrit._pluginInstalled = function(url) {
|
||||
const name = getPluginNameFromUrl(url) || UNKNOWN_PLUGIN;
|
||||
if (!_pluginsPending[name]) {
|
||||
console.warn(`Unexpected plugin ${name} installed from ${url}.`);
|
||||
} else {
|
||||
delete _pluginsPending[name];
|
||||
_pluginsInstalled.push(name);
|
||||
Gerrit._setPluginsCount(_pluginsPendingCount - 1);
|
||||
getReporting().pluginLoaded(name);
|
||||
console.log(`Plugin ${name} installed.`);
|
||||
}
|
||||
};
|
||||
|
||||
Gerrit._arePluginsLoaded = function() {
|
||||
return _pluginsPendingCount === 0;
|
||||
};
|
||||
|
||||
Gerrit._getPluginScreenName = function(pluginName, screenName) {
|
||||
return `${pluginName}-screen-${screenName}`;
|
||||
};
|
||||
|
||||
Gerrit._isPluginPreloaded = function(url) {
|
||||
const name = getPluginNameFromUrl(url);
|
||||
if (name && Gerrit._preloadedPlugins) {
|
||||
return name in Gerrit._preloadedPlugins;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Preloaded plugins should be installed after Gerrit.install() is set,
|
||||
// since plugin preloader substitutes Gerrit.install() temporarily.
|
||||
installPreloadedPlugins();
|
||||
})(window);
|
||||
|
||||
Reference in New Issue
Block a user