summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/js-tests/ui/editCommands/editCommandsTests.js183
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/js-tests/ui/editCommands/frame.html44
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/js-tests/ui/uiTests.html1
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/orion/editorCommands.js104
4 files changed, 293 insertions, 39 deletions
diff --git a/bundles/org.eclipse.orion.client.ui/web/js-tests/ui/editCommands/editCommandsTests.js b/bundles/org.eclipse.orion.client.ui/web/js-tests/ui/editCommands/editCommandsTests.js
new file mode 100644
index 0000000..d2eb6ee
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.ui/web/js-tests/ui/editCommands/editCommandsTests.js
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * @license
+ * Copyright (c) 2014 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html).
+ *
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+/*eslint-env browser, amd, mocha */
+/*eslint no-unused-vars:0 */
+/*global URL*/
+
+/**
+ * Tests the orion.edit.command extensions.
+ */
+define([
+ "chai/chai",
+ "js-tests/editor/mockEditor",
+ "orion/contentTypes",
+ "orion/Deferred",
+ "orion/editorCommands",
+ "orion/inputManager",
+ "orion/progress",
+ "orion/serviceregistry",
+ "orion/URL-shim", // no exports
+], function(chai, MockEditor, mContentTypes, Deferred, mEditorCommands, mInputManager, mProgress, mServiceRegistry) {
+ var EDITOR_COMMAND = "orion.edit.command",
+ FRAME_URL = "/abcdefghi", //"http://example.org/foo";
+ assert = chai.assert;
+
+ // Test variables
+ var serviceRegistry, contentTypeRegistry, progress, editorCommandFactory, inputManager, mockEditor,
+ initialFrames;
+
+ function setup() {
+ serviceRegistry = new mServiceRegistry.ServiceRegistry();
+ contentTypeRegistry = new mContentTypes.ContentTypeRegistry(serviceRegistry);
+ progress = new mProgress.ProgressService(serviceRegistry);
+ inputManager = new mInputManager.InputManager({
+ serviceRegistry: serviceRegistry,
+ });
+ editorCommandFactory = new mEditorCommands.EditorCommandFactory({
+ inputManager: inputManager,
+ serviceRegistry: serviceRegistry
+ });
+ mockEditor = new MockEditor({});
+ mockEditor.installTextView();
+ initialFrames = Array.prototype.map.call(document.getElementsByTagName("iframe"), function(iframe) {
+ return iframe.src;
+ });
+ }
+
+ function teardown() {
+ serviceRegistry = contentTypeRegistry = editorCommandFactory = inputManager = mockEditor = null;
+ // Remove any iframes created during the test
+ Array.prototype.forEach.call(document.getElementsByTagName("iframe"), function(iframe) {
+ if (initialFrames.indexOf(iframe.src) === -1)
+ iframe.parentNode.removeChild(iframe);
+ });
+ }
+
+ function registerMessageService(impl) {
+ if (!(serviceRegistry.getService("orion.page.message"))) {
+ impl = impl || {};
+ impl.setProgressMessage = impl.setProgressMessage || Function.prototype; // noop
+ impl.setProgressResult = impl.setProgressResult || Function.prototype; // noop
+ serviceRegistry.registerService("orion.page.message", impl);
+ }
+ }
+
+ function registerEditorCommand(impl) {
+ serviceRegistry.registerService(EDITOR_COMMAND, impl, {
+ id: "example",
+ name: "Example Command",
+ });
+ }
+
+ function executeCommand() {
+ // Due to the service dependency editorCommands -> orion.page.progress -> orion.page.message,
+ // a message service must be registered before we invoke an editor command, else it will throw.
+ registerMessageService();
+
+ return editorCommandFactory._createEditCommands(mockEditor).then(function(commandObjects) {
+ commandObjects.some(function(obj) {
+ if (obj.info.id === "example") {
+ // Execute command programatically
+ obj.command.callback(/* .. */);
+ return true;
+ }
+ });
+ });
+ }
+
+ function assertFrameExists(url) {
+ var found = Array.prototype.slice.call(document.getElementsByTagName("iframe")).some(function(frame) {
+ return new URL(frame.src).pathname.indexOf(url) === 0;
+ });
+ assert.equal(found, true, "Found the iframe " + url + " in the page");
+ }
+
+ describe("orion.edit.command", function() {
+ beforeEach(setup);
+ afterEach(teardown);
+
+ it("should set status for return value with 'status'", function() {
+ // TODO
+ assert.ok(false);
+ });
+ it("should set editor text for return value with 'text'", function() {
+ // TODO
+ assert.ok(false);
+ });
+ it("should set editor text for return value with 'selection'", function() {
+ // TODO
+ assert.ok(false);
+ });
+
+ describe("delegated UI", function() {
+ describe("legacy", function() {
+ it("should open frame for return value with 'uriTemplate'", function() {
+ registerEditorCommand({
+ run: function() {
+ return {
+ uriTemplate: FRAME_URL
+ };
+ }
+ });
+ var promise = new Deferred();
+ executeCommand();
+ setTimeout(function() {
+ // Ensure the frame was opened
+ assertFrameExists(FRAME_URL);
+ promise.resolve();
+ });
+ return promise;
+ });
+ });
+ describe("callback-based", function() {
+ it("#openDelegatedUI() should open frame", function() {
+ var promise = new Deferred();
+ registerEditorCommand({
+ execute: function(callbacks/*, options*/) {
+ var c = callbacks.openDelegatedUI({
+ id: "example.delegated",
+ uriTemplate: FRAME_URL,
+ });
+ // FIXME #openDelegatedUI returns undefined?
+ setTimeout(function() {
+ assertFrameExists(FRAME_URL);
+ promise.resolve();
+ }, 0);
+ }
+ });
+ executeCommand();
+ return promise;
+ });
+ it("should be able to set status from frame", function() {
+ registerEditorCommand({
+ execute: function(callbacks/*, options*/) {
+ callbacks.openDelegatedUI({
+ id: "example",
+ uriTemplate: "./editCommands/frame.html?source=example&action=status&message=howdy", // relative to uiTests.html
+ });
+ }
+ });
+
+ var promise = new Deferred();
+ registerMessageService({
+ setProgressResult: function(status) {
+ // Ensure the message service was invoked with the status sent by the the frame
+ assert.equal(status.Message, "howdy");
+ promise.resolve();
+ }
+ });
+ executeCommand();
+ return promise;
+ });
+ });
+ });
+ });
+}); \ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.ui/web/js-tests/ui/editCommands/frame.html b/bundles/org.eclipse.orion.client.ui/web/js-tests/ui/editCommands/frame.html
new file mode 100644
index 0000000..cf04250
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.ui/web/js-tests/ui/editCommands/frame.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Delegated UI test fame</title>
+</head>
+<body>
+<script>
+ /*eslint-env browser*/
+ /*global console */
+
+ function parseQuery() {
+ var query = window.location.search.substr(1).split("&");
+ var params = Object.create(null);
+ for (var i=0; i < query.length; i++) {
+ var name = query[i], match = /(.*)=(.*)$/.exec(name);
+ if (match) {
+ params[match[1]] = match[2];
+ } else {
+ params[name] = null;
+ }
+ }
+ return params;
+ }
+
+ var params = parseQuery();
+ var action = params.action, source = params.source;
+ if (action === "status") {
+ window.parent.postMessage(JSON.stringify({
+ pageService: "orion.page.delegatedUI",
+ source: source,
+ Status: {
+ Message: params.message
+ }
+ }), "*");
+ } else if (action === "close") {
+ window.parent.postMessage(JSON.stringify({
+ pageService: "orion.page.delegatedUI",
+ source: source,
+ cancelled: true
+ }), "*");
+ }
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.ui/web/js-tests/ui/uiTests.html b/bundles/org.eclipse.orion.client.ui/web/js-tests/ui/uiTests.html
index e18189b..5867041 100644
--- a/bundles/org.eclipse.orion.client.ui/web/js-tests/ui/uiTests.html
+++ b/bundles/org.eclipse.orion.client.ui/web/js-tests/ui/uiTests.html
@@ -24,6 +24,7 @@
"js-tests/ui/compare/compareTests",
"js-tests/ui/contentTypes/contentTypesTests",
"js-tests/ui/dispatcher/editDispatcherTests",
+ "js-tests/ui/editCommands/editCommandsTests",
"js-tests/ui/encoding/encodingTests",
"js-tests/ui/extensionParsing/extensionParsingTests",
"js-tests/ui/fileapi/fileapiTests",
diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/editorCommands.js b/bundles/org.eclipse.orion.client.ui/web/orion/editorCommands.js
index a4bf90e..c6c1e44 100644
--- a/bundles/org.eclipse.orion.client.ui/web/orion/editorCommands.js
+++ b/bundles/org.eclipse.orion.client.ui/web/orion/editorCommands.js
@@ -122,6 +122,10 @@ define([
}
}
+ function errorTransformer(error) {
+ return {_error: error};
+ }
+
function EditorCommandFactory (options) {
this.serviceRegistry = options.serviceRegistry;
this.commandService = options.commandRegistry;
@@ -474,12 +478,18 @@ define([
this.commandService.addCommand(blameCommand);
this.commandService.registerCommandContribution(this.toolbarId , "orion.edit.blame", 1, "orion.menuBarToolsGroup", false, new mKeyBinding.KeyBinding('b', true, true), new mCommandRegistry.URLBinding("blame", "blame")); //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
},
-
- _generateEditCommands: function(editor) {
+
+ /**
+ * Helper for {@link #_generateEditCommands}. Creates and returns the Command objects and the service info
+ * that derived them. Does not render commands.
+ * @returns {orion.Promise} A promise resolving to an array of Objects having 2 properties:
+ * <p><tt>info: Object</tt><br>
+ * <tt>command: {@link orion.edit.Command}</tt>
+ * </p>
+ */
+ _createEditCommands: function(editor) {
var self = this;
- var toolbarId = this.toolbarId;
-
function getContentTypes(serviceRegistry) {
if (contentTypesCache) {
return contentTypesCache;
@@ -496,14 +506,6 @@ define([
});
}
- // KB exists so that we can pass an array (from info.key) rather than actual arguments
- function createKeyBinding(args) {
- if (!args) { return null; }
- var keyBinding = new mKeyBinding.KeyBinding();
- mKeyBinding.KeyBinding.apply(keyBinding, args);
- return keyBinding;
- }
-
// add the commands generated by plug-ins who implement the "orion.edit.command" extension.
//
// Note that the shape of the "orion.edit.command" extension is not in any shape or form that could be considered final.
@@ -519,7 +521,7 @@ define([
var makeCommand = function(info, service, options) {
var commandVisibleWhen = options.visibleWhen;
options.visibleWhen = function(item) {
- if (!editor.installed || self.inputManager.getReadOnly()) {
+ if (!editor.installed || inputManager.getReadOnly()) {
return false;
}
return !commandVisibleWhen || commandVisibleWhen(item);
@@ -602,9 +604,9 @@ define([
options.callback = options.callback.bind(editor);
return new mCommands.Command(options);
};
- Deferred.when(getContentTypes(this.serviceRegistry), function() {
- var deferreds = [];
- var position = 100;
+ return Deferred.when(getContentTypes(this.serviceRegistry), function() {
+ // Create Commands
+ var createdCommands = [];
actionReferences.forEach(function(serviceReference) {
var id = serviceReference.getProperty("editor"); //$NON-NLS-0$
//TODO should this filtering be done in extension commands
@@ -622,32 +624,56 @@ define([
var deferred = mExtensionCommands._createCommandOptions(info, serviceReference, self.serviceRegistry, contentTypesCache, false, function(items) {
// items is the editor and we care about the file metadata for validation
return inputManager.getFileMetadata();
+ }).then(function(commandOptions){
+ return {
+ info: info,
+ command: makeCommand(info, service, commandOptions)
+ };
});
- deferreds.push(deferred);
- deferred.then(function(commandOptions){
- var command = makeCommand(info, service, commandOptions);
- self.commandService.addCommand(command);
- self.commandService.registerCommandContribution(self.toolbarId, command.id, position, "orion.menuBarToolsGroup", info.bindingOnly, createKeyBinding(info.key)); //$NON-NLS-0$
- });
- position++;
+ createdCommands.push(deferred);
});
- Deferred.all(deferreds, function(error) {return {_error: error}; }).then(function(promises) {
- // In the editor, we generate page level commands to the banner. Don't bother if we don't know the input
- // metadata, because we'll generate again once we know.
- var metadata;
- if ((metadata = inputManager.getFileMetadata())) {
- var toolbar = lib.node(toolbarId); //$NON-NLS-0$
- if (toolbar) {
- self.commandService.destroy(toolbar);
- self.commandService.renderCommands(toolbar.id, toolbar, metadata, editor, "button"); //$NON-NLS-0$
- }
- toolbar = lib.node("pageNavigationActions"); //$NON-NLS-0$
- if (toolbar) {
- self.commandService.destroy(toolbar);
- self.commandService.renderCommands(toolbar.id, toolbar, editor, editor, "button"); //$NON-NLS-0$
- }
+ return Deferred.all(createdCommands);
+ });
+ },
+
+ /**
+ * Creates and renders commands.
+ * @returns {orion.Promise}
+ */
+ _generateEditCommands: function(editor) {
+ // KB exists so that we can pass an array (from info.key) rather than actual arguments
+ function createKeyBinding(args) {
+ if (!args) { return null; }
+ var keyBinding = new mKeyBinding.KeyBinding();
+ mKeyBinding.KeyBinding.apply(keyBinding, args);
+ return keyBinding;
+ }
+
+ var toolbarId = this.toolbarId, commandService = this.commandService, inputManager = this.inputManager;
+ return this._createEditCommands(editor).then(function(commandObjects) {
+ // Add and register commands.
+ for (var i = 0, position = 100; i < commandObjects.length; i++, position++) {
+ var command = commandObjects[i].command, info = commandObjects[i].info;
+ commandService.addCommand(command);
+ commandService.registerCommandContribution(toolbarId, command.id, position, "orion.menuBarToolsGroup", info.bindingOnly, createKeyBinding(info.key)); //$NON-NLS-0$
+ }
+
+ // Render commands.
+ // In the editor, we generate page level commands to the banner. Don't bother if we don't know the input
+ // metadata, because we'll generate again once we know.
+ var metadata;
+ if ((metadata = inputManager.getFileMetadata())) {
+ var toolbar = lib.node(toolbarId); //$NON-NLS-0$
+ if (toolbar) {
+ commandService.destroy(toolbar);
+ commandService.renderCommands(toolbar.id, toolbar, metadata, editor, "button"); //$NON-NLS-0$
}
- });
+ toolbar = lib.node("pageNavigationActions"); //$NON-NLS-0$
+ if (toolbar) {
+ commandService.destroy(toolbar);
+ commandService.renderCommands(toolbar.id, toolbar, editor, editor, "button"); //$NON-NLS-0$
+ }
+ }
});
}
};