Example #1
0
 it('should be a new array', () => {
   registry.addCommand('test0', NULL_COMMAND);
   registry.addCommand('test1', NULL_COMMAND);
   let cmds = registry.listCommands();
   cmds.push('test2');
   expect(registry.listCommands()).to.deep.equal(['test0', 'test1']);
 });
Example #2
0
      it('should update the node content on command change event', async () => {
        const id = 'to-be-removed';
        let iconClassValue: string | null = null;
        const cmd = commands.addCommand(id, {
          execute: () => {
            /* no op */
          },
          label: 'Label-only button',
          iconClass: () => iconClassValue
        });
        const button = new CommandToolbarButton({
          commands,
          id
        });
        await render(button);
        const buttonNode = button.node.firstChild as HTMLButtonElement;
        expect(buttonNode.textContent).to.equal('Label-only button');
        expect(buttonNode.classList.contains(iconClassValue)).to.equal(false);

        iconClassValue = 'updated-icon-class';
        commands.notifyCommandChanged(id);
        await render(button);
        const wrapperNode = buttonNode.firstChild as HTMLElement;
        const iconNode = wrapperNode.firstChild as HTMLElement;
        expect(iconNode.classList.contains(iconClassValue)).to.equal(true);

        cmd.dispose();
      });
      it('should restore the widgets in a tracker', done => {
        let tracker = new InstanceTracker<Widget>({
          namespace: 'foo-widget',
          shell: new ApplicationShell()
        });
        let registry = new CommandRegistry();
        let state = new StateDB({ namespace: NAMESPACE });
        let ready = new PromiseDelegate<void>();
        let restorer = new LayoutRestorer({
          first: ready.promise, registry, state
        });
        let called = false;
        let key = `${tracker.namespace}:${tracker.namespace}`;

        registry.addCommand(tracker.namespace, {
          execute: () => { called = true; }
        });
        state.save(key, { data: null }).then(() => {
          return restorer.restore(tracker, {
            args: () => null,
            name: () => tracker.namespace,
            command: tracker.namespace
          });
        }).catch(done);
        ready.resolve(void 0);
        restorer.restored.then(() => { expect(called).to.be(true); })
          .then(() => state.remove(key))
          .then(() => { done(); })
          .catch(done);
      });
      it('should connect a node to a command', () => {
        let called = false;
        const command = 'commandlinker:connect-node';
        const commands = new CommandRegistry();
        const linker = new CommandLinker({ commands });
        let node: HTMLElement;
        let vnode: VirtualNode;
        const disposable = commands.addCommand(command, {
          execute: () => {
            called = true;
          }
        });

        vnode = h.div({ dataset: linker.populateVNodeDataset(command, null) });
        node = VirtualDOM.realize(vnode);
        document.body.appendChild(node);

        expect(called).to.equal(false);
        simulate(node, 'click');
        expect(called).to.equal(true);

        document.body.removeChild(node);
        linker.dispose();
        disposable.dispose();
      });
Example #5
0
      it('should stop routing if returned by a routed command', done => {
        const wanted = ['a', 'b'];
        const recorded: string[] = [];

        commands.addCommand('a', {
          execute: () => {
            recorded.push('a');
          }
        });
        commands.addCommand('b', {
          execute: () => {
            recorded.push('b');
          }
        });
        commands.addCommand('c', { execute: () => router.stop });
        commands.addCommand('d', {
          execute: () => {
            recorded.push('d');
          }
        });

        router.register({ command: 'a', pattern: /.*/, rank: 10 });
        router.register({ command: 'b', pattern: /.*/, rank: 20 });
        router.register({ command: 'c', pattern: /.*/, rank: 30 });
        router.register({ command: 'd', pattern: /.*/, rank: 40 });

        router.routed.connect(() => {
          expect(recorded).to.deep.equal(wanted);
          done();
        });
        router.route();
      });
Example #6
0
 it('should register partial and exact matches', () => {
   let count1 = 0;
   let count2 = 0;
   registry.addCommand('test1', {
     execute: () => { count1++; }
   });
   registry.addCommand('test2', {
     execute: () => { count2++; }
   });
   registry.addKeyBinding({
     keys: ['Ctrl S'],
     selector: `#${elem.id}`,
     command: 'test1'
   });
   registry.addKeyBinding({
     keys: ['Ctrl S', 'Ctrl D'],
     selector: `#${elem.id}`,
     command: 'test2'
   });
   let event1 = generate('keydown', { keyCode: 83, ctrlKey: true });
   let event2 = generate('keydown', { keyCode: 68, ctrlKey: true });
   expect(count1).to.equal(0);
   expect(count2).to.equal(0);
   elem.dispatchEvent(event1);
   expect(count1).to.equal(0);
   expect(count2).to.equal(0);
   elem.dispatchEvent(event2);
   expect(count1).to.equal(0);
   expect(count2).to.equal(1);
 });
Example #7
0
 it('should pick the selector with greater specificity', () => {
   elem.classList.add('test');
   let called1 = false;
   let called2 = false;
   registry.addCommand('test1', {
     execute: () => { called1 = true; }
   });
   registry.addCommand('test2', {
     execute: () => { called2 = true; }
   });
   registry.addKeyBinding({
     keys: ['Ctrl ;'],
     selector: '.test',
     command: 'test1'
   });
   registry.addKeyBinding({
     keys: ['Ctrl ;'],
     selector: `#${elem.id}`,
     command: 'test2'
   });
   let event = generate('keydown', { keyCode: 59, ctrlKey: true });
   elem.dispatchEvent(event);
   expect(called1).to.equal(false);
   expect(called2).to.equal(true);
 });
Example #8
0
      it('should disconnect a node from a command', () => {
        let called = false;
        let command = 'commandlinker:disconnect-node';
        let commands =new CommandRegistry();
        let linker = new CommandLinker({ commands });
        let node = document.createElement('div');
        let disposable = commands.addCommand(command, {
          execute: () => { called = true; }
        });

        document.body.appendChild(node);
        linker.connectNode(node, command, null);

        // Make sure connection is working.
        expect(called).to.be(false);
        simulate(node, 'click');
        expect(called).to.be(true);

        // Reset flag.
        called = false;

        // Make sure disconnection is working.
        linker.disconnectNode(node);
        expect(called).to.be(false);
        simulate(node, 'click');
        expect(called).to.be(false);

        document.body.removeChild(node);
        linker.dispose();
        disposable.dispose();
      });
Example #9
0
  before(() => {
    commands = new CommandRegistry();
    bkoMenu = new BkoMenu({ commands });

    commands.addCommand('test', { execute: () => {} });
    bkoMenu.addItem({command: 'test', submenu: bkoMenu, type: 'submenu'});
  });
Example #10
0
      it('should restore the widgets in a tracker', async () => {
        const tracker = new InstanceTracker<Widget>({
          namespace: 'foo-widget'
        });
        const registry = new CommandRegistry();
        const state = new StateDB({ namespace: NAMESPACE });
        const ready = new PromiseDelegate<void>();
        const restorer = new LayoutRestorer({
          first: ready.promise,
          registry,
          state
        });
        let called = false;
        const key = `${tracker.namespace}:${tracker.namespace}`;

        registry.addCommand(tracker.namespace, {
          execute: () => {
            called = true;
          }
        });
        await state.save(key, { data: null });
        ready.resolve(undefined);
        await restorer.restore(tracker, {
          args: () => null,
          name: () => tracker.namespace,
          command: tracker.namespace
        });
        await restorer.restored;
        expect(called).to.equal(true);
      });
Example #11
0
 it('should resolve an exact match of partial match time out', (done) => {
   let called1 = false;
   let called2 = false;
   registry.addCommand('test1', {
     execute: () => { called1 = true; }
   });
   registry.addCommand('test2', {
     execute: () => { called2 = true; }
   });
   registry.addKeyBinding({
     keys: ['D', 'D'],
     selector: `#${elem.id}`,
     command: 'test1'
   });
   registry.addKeyBinding({
     keys: ['D'],
     selector: `#${elem.id}`,
     command: 'test2'
   });
   let event = generate('keydown', { keyCode: 68 });
   elem.dispatchEvent(event);
   expect(called1).to.equal(false);
   expect(called2).to.equal(false);
   setTimeout(() => {
     expect(called1).to.equal(false);
     expect(called2).to.equal(true);
     done();
   }, 1300);
 });
Example #12
0
      it('should stop routing if returned by a routed command', async () => {
        const wanted = ['a', 'b'];
        const recorded: string[] = [];

        commands.addCommand('a', {
          execute: () => {
            recorded.push('a');
          }
        });
        commands.addCommand('b', {
          execute: () => {
            recorded.push('b');
          }
        });
        commands.addCommand('c', { execute: () => router.stop });
        commands.addCommand('d', {
          execute: () => {
            recorded.push('d');
          }
        });

        router.register({ command: 'a', pattern: /.*/, rank: 10 });
        router.register({ command: 'b', pattern: /.*/, rank: 20 });
        router.register({ command: 'c', pattern: /.*/, rank: 30 });
        router.register({ command: 'd', pattern: /.*/, rank: 40 });

        let promise = signalToPromise(router.routed);
        await router.route();
        await promise;
        expect(recorded).to.deep.equal(wanted);
      });
Example #13
0
 it('should get the display label for a specific command', () => {
   let cmd = {
     execute: (args: JSONObject) => { return args; },
     label: 'foo'
   };
   registry.addCommand('test', cmd);
   expect(registry.label('test')).to.equal('foo');
 });
Example #14
0
 it('should give the appropriate mnemonic given arguments', () => {
   let cmd = {
     execute: (args: JSONObject) => { return args; },
     mnemonic: (args: JSONObject) => { return JSON.stringify(args).length; }
   };
   registry.addCommand('test', cmd);
   expect(registry.mnemonic('test', {})).to.equal(2);
 });
Example #15
0
 it('should give the appropriate class name given arguments', () => {
   let cmd = {
     execute: (args: JSONObject) => { return args; },
     className: (args: JSONObject) => { return JSON.stringify(args); }
   };
   registry.addCommand('test', cmd);
   expect(registry.className('test', {})).to.equal('{}');
 });
Example #16
0
 it('should get the extra class name for a specific command', () => {
   let cmd = {
     execute: (args: JSONObject) => { return args; },
     className: 'foo'
   };
   registry.addCommand('test', cmd);
   expect(registry.className('test')).to.equal('foo');
 });
Example #17
0
 it('should get the usage text for a specific command', () => {
   let cmd = {
     execute: (args: JSONObject) => { return args; },
     usage: 'foo'
   };
   registry.addCommand('test', cmd);
   expect(registry.usage('test')).to.equal('foo');
 });
Example #18
0
 it('should get the mnemonic index for a specific command', () => {
   let cmd = {
     execute: (args: JSONObject) => { return args; },
     mnemonic: 1
   };
   registry.addCommand('test', cmd);
   expect(registry.mnemonic('test')).to.equal(1);
 });
Example #19
0
 it('should execute a specific command', () => {
   let called = false;
   let cmd = {
     execute: (args: JSONObject) => { called = true; },
   };
   registry.addCommand('test', cmd);
   registry.execute('test');
   expect(called).to.equal(true);
 });
Example #20
0
 it('should test whether a specific command is visible', () => {
   let cmd = {
     execute: (args: JSONObject) => { return args; },
     isVisible: (args: JSONObject) => { return args.visible as boolean; }
   };
   registry.addCommand('test', cmd);
   expect(registry.isVisible('test', { visible: true })).to.equal(true);
   expect(registry.isVisible('test', { visible: false })).to.equal(false);
 });
Example #21
0
 it('should test whether a specific command is toggled', () => {
   let cmd = {
     execute: (args: JSONObject) => { return args; },
     isToggled: (args: JSONObject) => { return args.toggled as boolean; }
   };
   registry.addCommand('test', cmd);
   expect(registry.isToggled('test', { toggled: true })).to.equal(true);
   expect(registry.isToggled('test', { toggled: false })).to.equal(false);
 });
Example #22
0
 it('should reject if the command throws an error', (done) => {
   let cmd = {
     execute: (args: JSONObject) => { throw new Error(''); },
   };
   registry.addCommand('test', cmd);
   registry.execute('test').catch(() => {
     done();
   });
 });
Example #23
0
 it('should clone the `cmd` before adding it to the registry', () => {
   let cmd = {
     execute: (args: JSONObject) => { return args; },
     label: 'foo'
   };
   registry.addCommand('test', cmd);
   cmd.label = 'bar';
   expect(registry.label('test')).to.equal('foo');
 });
Example #24
0
  function createFromCommand(commands: CommandRegistry, id: string): ToolbarButton | null {
    if (!commands.hasCommand(id)) {
      return null;
    }

    const button = new ToolbarButton({
      onClick: () => {
        commands.execute(id);
        button.node.blur();
      },
      className: Private.commandClassName(commands, id),
      tooltip: Private.commandTooltip(commands, id)
    });
    let oldClasses = Private.commandClassName(commands, id).split(/\s/);

    (button.node as HTMLButtonElement).disabled = !commands.isEnabled(id);
    Private.setNodeContentFromCommand(button.node, commands, id);

    // Ensure that we pick up relevant changes to the command:
    function onChange(sender: CommandRegistry, args: CommandRegistry.ICommandChangedArgs) {
      if (args.id !== id) {
        return;  // Not our command
      }

      if (args.type === 'removed') {
        // Dispose of button
        button.dispose();
        return;
      }

      if (args.type !== 'changed') {
        return;
      }

      // Update all fields (onClick is already indirected)
      const newClasses = Private.commandClassName(sender, id).split(/\s/);

      for (let cls of oldClasses) {
        if (cls && newClasses.indexOf(cls) === -1) {
          button.removeClass(cls);
        }
      }
      for (let cls of newClasses) {
        if (cls && oldClasses.indexOf(cls) === -1) {
          button.addClass(cls);
        }
      }
      oldClasses = newClasses;
      button.node.title = Private.commandTooltip(sender, id);
      Private.setNodeContentFromCommand(button.node, sender, id);
      (button.node as HTMLButtonElement).disabled = !sender.isEnabled(id);
    }
    commands.commandChanged.connect(onChange, button);

    return button;
  }
Example #25
0
 it('should resolve with the result of the command', (done) => {
   let cmd = {
     execute: (args: JSONObject) => { return args; },
   };
   registry.addCommand('test', cmd);
   registry.execute('test', { foo: 12 }).then(result => {
     expect(result).to.deep.equal({ foo: 12 });
     done();
   });
 });
Example #26
0
 it('should be the keybindings in the palette', () => {
   registry.addCommand('test', { execute: () => { } });
   registry.addKeyBinding({
     keys: ['Ctrl ;'],
     selector: `body`,
     command: 'test'
   });
   expect(registry.keyBindings.length).to.equal(1);
   expect(registry.keyBindings[0].command).to.equal('test');
 });
Example #27
0
 function commandClassName(commands: CommandRegistry, id: string): string {
   let name = commands.className(id);
   // Add the boolean state classes.
   if (commands.isToggled(id)) {
     name += ' p-mod-toggled';
   }
   if (!commands.isVisible(id)) {
     name += ' p-mod-hidden';
   }
   return name;
 }
Example #28
0
 it('should be emitted when a command is changed', () => {
   let called = false;
   registry.addCommand('test', NULL_COMMAND);
   registry.commandChanged.connect((reg, args) => {
     expect(reg).to.equal(registry);
     expect(args.id).to.equal('test');
     expect(args.type).to.equal('changed');
     called = true;
   });
   registry.notifyCommandChanged('test');
   expect(called).to.equal(true);
 });
Example #29
0
function addDefaultCommands(tracker: ITerminalTracker, commands: CommandRegistry) {

  /**
   * Whether there is an active terminal.
   */
  function hasWidget(): boolean {
    return tracker.currentWidget !== null;
  }

  commands.addCommand('terminal:increase-font', {
    label: 'Increase Terminal Font Size',
    execute: () => {
      let options = TerminalWidget.defaultOptions;
      if (options.fontSize < 72) {
        options.fontSize++;
        tracker.forEach(widget => { widget.fontSize = options.fontSize; });
      }
    },
    isEnabled: hasWidget
  });

  commands.addCommand('terminal:decrease-font', {
    label: 'Decrease Terminal Font Size',
    execute: () => {
      let options = TerminalWidget.defaultOptions;
      if (options.fontSize > 9) {
        options.fontSize--;
        tracker.forEach(widget => { widget.fontSize = options.fontSize; });
      }
    },
    isEnabled: hasWidget
  });

  commands.addCommand('terminal:toggle-theme', {
    label: 'Toggle Terminal Theme',
    caption: 'Switch Terminal Background and Font Colors',
    execute: () => {
      let options = TerminalWidget.defaultOptions;
      if (options.background === 'black') {
        options.background = 'white';
        options.color = 'black';
      } else {
        options.background = 'black';
        options.color = 'white';
      }
      tracker.forEach(widget => {
        widget.background = options.background;
        widget.color = options.color;
      });
    },
    isEnabled: hasWidget
  });
}
Example #30
0
  function setNodeContentFromCommand(node: HTMLElement, commands: CommandRegistry, id: string): void {
    const iconClass = commands.iconClass(id);
    const iconLabel = commands.iconLabel(id);
    const label = commands.label(id);

    node.innerHTML = '';
    if (iconClass) {
      node.className += ` ${iconClass}`;
      node.setAttribute('title', iconLabel || label);
    } else {
      node.innerText = label;
    }
  }