diff options
author | Mark Macdonald <mamacdon@gmail.com> | 2014-10-04 17:48:38 -0400 |
---|---|---|
committer | Mark Macdonald <mamacdon@gmail.com> | 2014-10-06 11:15:46 -0400 |
commit | 23d42be47d9a33ac8fc7626e8677c9351ff1dcbb (patch) | |
tree | d51bc2919a5e80bdc395befb87fbbc78f67afe5b | |
parent | a2f3ecd73c21997379e4f6e0e9b2366a1fe5cae0 (diff) | |
download | org.eclipse.orion.client-origin/editorCommands_tests.zip org.eclipse.orion.client-origin/editorCommands_tests.tar.gz org.eclipse.orion.client-origin/editorCommands_tests.tar.bz2 |
Bug 419764 - add tests for orion.edit.command APIorigin/editorCommands_tests
* Make EditorCommandsFactory#_generateEditCommands() testable
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$ + } + } }); } }; |