From d8ede7246c061db9066b268f5bd12a71dd6bdeed Mon Sep 17 00:00:00 2001 From: Jason Weill Date: Wed, 29 May 2024 16:35:14 -0700 Subject: [PATCH 1/5] Allows interleaving of search results --- packages/widgets/src/commandpalette.ts | 41 +++++--------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/packages/widgets/src/commandpalette.ts b/packages/widgets/src/commandpalette.ts index 4e2d7ef73..3f7e51e6a 100644 --- a/packages/widgets/src/commandpalette.ts +++ b/packages/widgets/src/commandpalette.ts @@ -1374,50 +1374,25 @@ namespace Private { * Create the results from an array of sorted scores. */ function createResults(scores: IScore[]): SearchResult[] { - // Set up an array to track which scores have been visited. - let visited = new Array(scores.length); - ArrayExt.fill(visited, false); - // Set up the search results array. let results: SearchResult[] = []; // Iterate over each score in the array. for (let i = 0, n = scores.length; i < n; ++i) { - // Ignore a score which has already been processed. - if (visited[i]) { - continue; - } - // Extract the current item and indices. - let { item, categoryIndices } = scores[i]; + let { item, categoryIndices, labelIndices } = scores[i]; // Extract the category for the current item. let category = item.category; - // Add the header result for the category. - results.push({ type: 'header', category, indices: categoryIndices }); - - // Find the rest of the scores with the same category. - for (let j = i; j < n; ++j) { - // Ignore a score which has already been processed. - if (visited[j]) { - continue; - } - - // Extract the data for the current score. - let { item, labelIndices } = scores[j]; - - // Ignore an item with a different category. - if (item.category !== category) { - continue; - } - - // Create the item result for the score. - results.push({ type: 'item', item, indices: labelIndices }); - - // Mark the score as processed. - visited[j] = true; + // Is this the same category as the preceding result? + if (i === 0 || category !== scores[i-1].item.category) { + // Add the header result for the category. + results.push({ type: 'header', category, indices: categoryIndices }); } + + // Create the item result for the score. + results.push({ type: 'item', item, indices: labelIndices }); } // Return the final results. From 92518935d4c81077ed1079757b0cc4643a5e6eb6 Mon Sep 17 00:00:00 2001 From: Jason Weill Date: Thu, 30 May 2024 10:42:00 -0700 Subject: [PATCH 2/5] Lint fix --- packages/widgets/src/commandpalette.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/widgets/src/commandpalette.ts b/packages/widgets/src/commandpalette.ts index 3f7e51e6a..087d05d40 100644 --- a/packages/widgets/src/commandpalette.ts +++ b/packages/widgets/src/commandpalette.ts @@ -1386,7 +1386,7 @@ namespace Private { let category = item.category; // Is this the same category as the preceding result? - if (i === 0 || category !== scores[i-1].item.category) { + if (i === 0 || category !== scores[i - 1].item.category) { // Add the header result for the category. results.push({ type: 'header', category, indices: categoryIndices }); } From cbb51e7e88ef6e3a42ee4d3b19a201cb028ee742 Mon Sep 17 00:00:00 2001 From: Jason Weill Date: Thu, 30 May 2024 16:02:55 -0700 Subject: [PATCH 3/5] Adds test case for search --- .../widgets/tests/src/commandpalette.spec.ts | 225 ++++++++++++++++++ 1 file changed, 225 insertions(+) diff --git a/packages/widgets/tests/src/commandpalette.spec.ts b/packages/widgets/tests/src/commandpalette.spec.ts index c57f8205e..496c8a7e6 100644 --- a/packages/widgets/tests/src/commandpalette.spec.ts +++ b/packages/widgets/tests/src/commandpalette.spec.ts @@ -114,6 +114,231 @@ describe('@lumino/widgets', () => { }); }); + describe('#search()', () => { + it('should search a list of commands', () => { + // Add several commands to the command registry and the palette + commands.addCommand('example:cut', { + label: 'Cut', + mnemonic: 1, + iconClass: 'fa fa-cut', + execute: () => { + console.log('Cut'); + } + }); + + commands.addCommand('example:copy', { + label: 'Copy File', + mnemonic: 0, + iconClass: 'fa fa-copy', + execute: () => { + console.log('Copy'); + } + }); + + commands.addCommand('example:paste', { + label: 'Paste', + mnemonic: 0, + iconClass: 'fa fa-paste', + execute: () => { + console.log('Paste'); + } + }); + + commands.addCommand('example:new-tab', { + label: 'New Tab', + mnemonic: 0, + caption: 'Open a new tab', + execute: () => { + console.log('New Tab'); + } + }); + + commands.addCommand('example:close-tab', { + label: 'Close Tab', + mnemonic: 2, + caption: 'Close the current tab', + execute: () => { + console.log('Close Tab'); + } + }); + + commands.addCommand('example:save-on-exit', { + label: 'Save on Exit', + mnemonic: 0, + caption: 'Toggle the save on exit flag', + execute: () => { + console.log('Save on Exit'); + } + }); + + commands.addCommand('example:open-task-manager', { + label: 'Task Manager', + mnemonic: 5, + isEnabled: () => false, + execute: () => {} + }); + + commands.addCommand('example:close', { + label: 'Close', + mnemonic: 0, + iconClass: 'fa fa-close', + execute: () => { + console.log('Close'); + } + }); + + commands.addCommand('example:one', { + label: 'One', + execute: () => { + console.log('One'); + } + }); + + commands.addCommand('example:two', { + label: 'Two', + execute: () => { + console.log('Two'); + } + }); + + commands.addCommand('example:three', { + label: 'Three', + execute: () => { + console.log('Three'); + } + }); + + commands.addCommand('example:four', { + label: 'Four', + execute: () => { + console.log('Four'); + } + }); + + commands.addCommand('example:black', { + label: 'Black', + execute: () => { + console.log('Black'); + } + }); + + commands.addCommand('example:clear-cell', { + label: 'Clear Cell', + execute: () => { + console.log('Clear Cell'); + } + }); + + commands.addCommand('example:cut-cells', { + label: 'Cut Cell(s)', + execute: () => { + console.log('Cut Cell(s)'); + } + }); + + commands.addCommand('example:run-cell', { + label: 'Run Cell', + execute: () => { + console.log('Run Cell'); + } + }); + + commands.addCommand('example:cell-test', { + label: 'Cell Test', + execute: () => { + console.log('Cell Test'); + } + }); + + commands.addCommand('notebook:new', { + label: 'New Notebook', + execute: () => { + console.log('New Notebook'); + } + }); + + commands.addKeyBinding({ + keys: ['Accel X'], + selector: 'body', + command: 'example:cut' + }); + + commands.addKeyBinding({ + keys: ['Accel C'], + selector: 'body', + command: 'example:copy' + }); + + commands.addKeyBinding({ + keys: ['Accel V'], + selector: 'body', + command: 'example:paste' + }); + + commands.addKeyBinding({ + keys: ['Accel J', 'Accel J'], + selector: 'body', + command: 'example:new-tab' + }); + + commands.addKeyBinding({ + keys: ['Accel M'], + selector: 'body', + command: 'example:open-task-manager' + }); + + let palette = new CommandPalette({ commands }); + palette.addItem({ command: 'example:cut', category: 'Edit' }); + palette.addItem({ command: 'example:copy', category: 'Edit' }); + palette.addItem({ command: 'example:paste', category: 'Edit' }); + palette.addItem({ command: 'example:one', category: 'Number' }); + palette.addItem({ command: 'example:two', category: 'Number' }); + palette.addItem({ command: 'example:three', category: 'Number' }); + palette.addItem({ command: 'example:four', category: 'Number' }); + palette.addItem({ command: 'example:black', category: 'Number' }); + palette.addItem({ command: 'example:new-tab', category: 'File' }); + palette.addItem({ command: 'example:close-tab', category: 'File' }); + palette.addItem({ command: 'example:save-on-exit', category: 'File' }); + palette.addItem({ command: 'example:open-task-manager', category: 'File' }); + palette.addItem({ command: 'example:close', category: 'File' }); + palette.addItem({ + command: 'example:clear-cell', + category: 'Notebook Cell Operations' + }); + palette.addItem({ + command: 'example:cut-cells', + category: 'Notebook Cell Operations' + }); + palette.addItem({ + command: 'example:run-cell', + category: 'Notebook Cell Operations' + }); + palette.addItem({ command: 'example:cell-test', category: 'Console' }); + palette.addItem({ command: 'notebook:new', category: 'Notebook' }); + palette.id = 'palette'; + + // Search the command palette: update the inputNode, then force a refresh + palette.inputNode.value = 'clea'; + palette.refresh(); + MessageLoop.flush(); + + // Expect that headers and items appear in descending score order, + // even if the same header occurs multiple times. + const children = palette.contentNode.children; + expect(children.length).to.equal(7); + expect(children[0].textContent).to.equal('Notebook Cell Operations'); + expect(children[1].getAttribute('data-command')).to.equal('example:clear-cell'); + // The next match should be from a different category + expect(children[2].textContent).to.equal('File'); + expect(children[3].getAttribute('data-command')).to.equal('example:close-tab'); + // The next match should be the same as in a previous category + expect(children[4].textContent).to.equal('Notebook Cell Operations'); + expect(children[5].getAttribute('data-command')).to.equal('example:cut-cells'); + // The next match has the same category as the previous one did, so the header is not repeated + expect(children[6].getAttribute('data-command')).to.equal('example:run-cell'); + }); + }); + describe('#addItems()', () => { it('should add items to a command palette using options', () => { const item = { From 82c2f32be42bd084c46d749ad9851d283c36ff95 Mon Sep 17 00:00:00 2001 From: Jason Weill Date: Thu, 30 May 2024 16:06:34 -0700 Subject: [PATCH 4/5] Lint fixes --- .../widgets/tests/src/commandpalette.spec.ts | 67 +++++++++++-------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/packages/widgets/tests/src/commandpalette.spec.ts b/packages/widgets/tests/src/commandpalette.spec.ts index 496c8a7e6..6f6a316e8 100644 --- a/packages/widgets/tests/src/commandpalette.spec.ts +++ b/packages/widgets/tests/src/commandpalette.spec.ts @@ -125,7 +125,7 @@ describe('@lumino/widgets', () => { console.log('Cut'); } }); - + commands.addCommand('example:copy', { label: 'Copy File', mnemonic: 0, @@ -134,7 +134,7 @@ describe('@lumino/widgets', () => { console.log('Copy'); } }); - + commands.addCommand('example:paste', { label: 'Paste', mnemonic: 0, @@ -143,7 +143,7 @@ describe('@lumino/widgets', () => { console.log('Paste'); } }); - + commands.addCommand('example:new-tab', { label: 'New Tab', mnemonic: 0, @@ -152,7 +152,7 @@ describe('@lumino/widgets', () => { console.log('New Tab'); } }); - + commands.addCommand('example:close-tab', { label: 'Close Tab', mnemonic: 2, @@ -161,7 +161,7 @@ describe('@lumino/widgets', () => { console.log('Close Tab'); } }); - + commands.addCommand('example:save-on-exit', { label: 'Save on Exit', mnemonic: 0, @@ -170,14 +170,14 @@ describe('@lumino/widgets', () => { console.log('Save on Exit'); } }); - + commands.addCommand('example:open-task-manager', { label: 'Task Manager', mnemonic: 5, isEnabled: () => false, execute: () => {} }); - + commands.addCommand('example:close', { label: 'Close', mnemonic: 0, @@ -186,107 +186,107 @@ describe('@lumino/widgets', () => { console.log('Close'); } }); - + commands.addCommand('example:one', { label: 'One', execute: () => { console.log('One'); } }); - + commands.addCommand('example:two', { label: 'Two', execute: () => { console.log('Two'); } }); - + commands.addCommand('example:three', { label: 'Three', execute: () => { console.log('Three'); } }); - + commands.addCommand('example:four', { label: 'Four', execute: () => { console.log('Four'); } }); - + commands.addCommand('example:black', { label: 'Black', execute: () => { console.log('Black'); } }); - + commands.addCommand('example:clear-cell', { label: 'Clear Cell', execute: () => { console.log('Clear Cell'); } }); - + commands.addCommand('example:cut-cells', { label: 'Cut Cell(s)', execute: () => { console.log('Cut Cell(s)'); } }); - + commands.addCommand('example:run-cell', { label: 'Run Cell', execute: () => { console.log('Run Cell'); } }); - + commands.addCommand('example:cell-test', { label: 'Cell Test', execute: () => { console.log('Cell Test'); } }); - + commands.addCommand('notebook:new', { label: 'New Notebook', execute: () => { console.log('New Notebook'); } }); - + commands.addKeyBinding({ keys: ['Accel X'], selector: 'body', command: 'example:cut' }); - + commands.addKeyBinding({ keys: ['Accel C'], selector: 'body', command: 'example:copy' }); - + commands.addKeyBinding({ keys: ['Accel V'], selector: 'body', command: 'example:paste' }); - + commands.addKeyBinding({ keys: ['Accel J', 'Accel J'], selector: 'body', command: 'example:new-tab' }); - + commands.addKeyBinding({ keys: ['Accel M'], selector: 'body', command: 'example:open-task-manager' }); - + let palette = new CommandPalette({ commands }); palette.addItem({ command: 'example:cut', category: 'Edit' }); palette.addItem({ command: 'example:copy', category: 'Edit' }); @@ -299,7 +299,10 @@ describe('@lumino/widgets', () => { palette.addItem({ command: 'example:new-tab', category: 'File' }); palette.addItem({ command: 'example:close-tab', category: 'File' }); palette.addItem({ command: 'example:save-on-exit', category: 'File' }); - palette.addItem({ command: 'example:open-task-manager', category: 'File' }); + palette.addItem({ + command: 'example:open-task-manager', + category: 'File' + }); palette.addItem({ command: 'example:close', category: 'File' }); palette.addItem({ command: 'example:clear-cell', @@ -327,15 +330,23 @@ describe('@lumino/widgets', () => { const children = palette.contentNode.children; expect(children.length).to.equal(7); expect(children[0].textContent).to.equal('Notebook Cell Operations'); - expect(children[1].getAttribute('data-command')).to.equal('example:clear-cell'); + expect(children[1].getAttribute('data-command')).to.equal( + 'example:clear-cell' + ); // The next match should be from a different category expect(children[2].textContent).to.equal('File'); - expect(children[3].getAttribute('data-command')).to.equal('example:close-tab'); + expect(children[3].getAttribute('data-command')).to.equal( + 'example:close-tab' + ); // The next match should be the same as in a previous category expect(children[4].textContent).to.equal('Notebook Cell Operations'); - expect(children[5].getAttribute('data-command')).to.equal('example:cut-cells'); + expect(children[5].getAttribute('data-command')).to.equal( + 'example:cut-cells' + ); // The next match has the same category as the previous one did, so the header is not repeated - expect(children[6].getAttribute('data-command')).to.equal('example:run-cell'); + expect(children[6].getAttribute('data-command')).to.equal( + 'example:run-cell' + ); }); }); From 102122f03726bc52117d1e2bd4f551c976567342 Mon Sep 17 00:00:00 2001 From: Jason Weill Date: Thu, 30 May 2024 17:07:09 -0700 Subject: [PATCH 5/5] Moves search unit test to 'refresh', the public function it tests --- .../widgets/tests/src/commandpalette.spec.ts | 414 +++++++++--------- 1 file changed, 206 insertions(+), 208 deletions(-) diff --git a/packages/widgets/tests/src/commandpalette.spec.ts b/packages/widgets/tests/src/commandpalette.spec.ts index 6f6a316e8..53f7c34ff 100644 --- a/packages/widgets/tests/src/commandpalette.spec.ts +++ b/packages/widgets/tests/src/commandpalette.spec.ts @@ -114,7 +114,212 @@ describe('@lumino/widgets', () => { }); }); - describe('#search()', () => { + describe('#addItems()', () => { + it('should add items to a command palette using options', () => { + const item = { + command: 'test2', + category: 'Test Category', + args: { foo: 'bar' }, + rank: 100 + }; + + expect(palette.items.length).to.equal(0); + palette.addItems([defaultOptions, item]); + expect(palette.items.length).to.equal(2); + expect(palette.items[0].command).to.equal('test'); + expect(palette.items[1].command).to.equal('test2'); + }); + }); + + describe('#addItem()', () => { + it('should add an item to a command palette using options', () => { + expect(palette.items.length).to.equal(0); + palette.addItem(defaultOptions); + expect(palette.items.length).to.equal(1); + expect(palette.items[0].command).to.equal('test'); + }); + + context('CommandPalette.IItem', () => { + describe('#command', () => { + it('should return the command name of a command item', () => { + let item = palette.addItem(defaultOptions); + expect(item.command).to.equal('test'); + }); + }); + + describe('#args', () => { + it('should return the args of a command item', () => { + let item = palette.addItem(defaultOptions); + expect(item.args).to.deep.equal(defaultOptions.args); + }); + + it('should default to an empty object', () => { + let item = palette.addItem({ command: 'test', category: 'test' }); + expect(item.args).to.deep.equal({}); + }); + }); + + describe('#category', () => { + it('should return the category of a command item', () => { + let item = palette.addItem(defaultOptions); + expect(item.category).to.equal(defaultOptions.category); + }); + }); + + describe('#rank', () => { + it('should return the rank of a command item', () => { + let item = palette.addItem(defaultOptions); + expect(item.rank).to.deep.equal(defaultOptions.rank); + }); + + it('should default to `Infinity`', () => { + let item = palette.addItem({ command: 'test', category: 'test' }); + expect(item.rank).to.equal(Infinity); + }); + }); + + describe('#label', () => { + it('should return the label of a command item', () => { + let label = 'test label'; + commands.addCommand('test', { execute: () => {}, label }); + let item = palette.addItem(defaultOptions); + expect(item.label).to.equal(label); + }); + }); + + describe('#caption', () => { + it('should return the caption of a command item', () => { + let caption = 'test caption'; + commands.addCommand('test', { execute: () => {}, caption }); + let item = palette.addItem(defaultOptions); + expect(item.caption).to.equal(caption); + }); + }); + + describe('#className', () => { + it('should return the class name of a command item', () => { + let className = 'testClass'; + commands.addCommand('test', { execute: () => {}, className }); + let item = palette.addItem(defaultOptions); + expect(item.className).to.equal(className); + }); + }); + + describe('#isEnabled', () => { + it('should return whether a command item is enabled', () => { + let called = false; + commands.addCommand('test', { + execute: () => {}, + isEnabled: () => { + called = true; + return false; + } + }); + let item = palette.addItem(defaultOptions); + expect(called).to.equal(false); + expect(item.isEnabled).to.equal(false); + expect(called).to.equal(true); + }); + }); + + describe('#isToggled', () => { + it('should return whether a command item is toggled', () => { + let called = false; + commands.addCommand('test', { + execute: () => {}, + isToggled: () => { + called = true; + return true; + } + }); + let item = palette.addItem(defaultOptions); + expect(called).to.equal(false); + expect(item.isToggled).to.equal(true); + expect(called).to.equal(true); + }); + }); + + describe('#isVisible', () => { + it('should return whether a command item is visible', () => { + let called = false; + commands.addCommand('test', { + execute: () => {}, + isVisible: () => { + called = true; + return false; + } + }); + let item = palette.addItem(defaultOptions); + expect(called).to.equal(false); + expect(item.isVisible).to.equal(false); + expect(called).to.equal(true); + }); + }); + + describe('#keyBinding', () => { + it('should return the key binding of a command item', () => { + commands.addKeyBinding({ + keys: ['Ctrl A'], + selector: 'body', + command: 'test', + args: defaultOptions.args + }); + let item = palette.addItem(defaultOptions); + expect(item.keyBinding!.keys).to.deep.equal(['Ctrl A']); + }); + }); + }); + }); + + describe('#removeItem()', () => { + it('should remove an item from a command palette by item', () => { + expect(palette.items.length).to.equal(0); + let item = palette.addItem(defaultOptions); + expect(palette.items.length).to.equal(1); + palette.removeItem(item); + expect(palette.items.length).to.equal(0); + }); + }); + + describe('#removeItemAt()', () => { + it('should remove an item from a command palette by index', () => { + expect(palette.items.length).to.equal(0); + palette.addItem(defaultOptions); + expect(palette.items.length).to.equal(1); + palette.removeItemAt(0); + expect(palette.items.length).to.equal(0); + }); + }); + + describe('#clearItems()', () => { + it('should remove all items from a command palette', () => { + expect(palette.items.length).to.equal(0); + palette.addItem({ command: 'test', category: 'one' }); + palette.addItem({ command: 'test', category: 'two' }); + expect(palette.items.length).to.equal(2); + palette.clearItems(); + expect(palette.items.length).to.equal(0); + }); + }); + + describe('#refresh()', () => { + it('should schedule a refresh of the search items', () => { + commands.addCommand('test', { execute: () => {}, label: 'test' }); + palette.addItem(defaultOptions); + + MessageLoop.flush(); + + let content = palette.contentNode; + let itemClass = '.lm-CommandPalette-item'; + let items = () => content.querySelectorAll(itemClass); + + expect(items()).to.have.length(1); + palette.inputNode.value = 'x'; + palette.refresh(); + MessageLoop.flush(); + expect(items()).to.have.length(0); + }); + it('should search a list of commands', () => { // Add several commands to the command registry and the palette commands.addCommand('example:cut', { @@ -350,213 +555,6 @@ describe('@lumino/widgets', () => { }); }); - describe('#addItems()', () => { - it('should add items to a command palette using options', () => { - const item = { - command: 'test2', - category: 'Test Category', - args: { foo: 'bar' }, - rank: 100 - }; - - expect(palette.items.length).to.equal(0); - palette.addItems([defaultOptions, item]); - expect(palette.items.length).to.equal(2); - expect(palette.items[0].command).to.equal('test'); - expect(palette.items[1].command).to.equal('test2'); - }); - }); - - describe('#addItem()', () => { - it('should add an item to a command palette using options', () => { - expect(palette.items.length).to.equal(0); - palette.addItem(defaultOptions); - expect(palette.items.length).to.equal(1); - expect(palette.items[0].command).to.equal('test'); - }); - - context('CommandPalette.IItem', () => { - describe('#command', () => { - it('should return the command name of a command item', () => { - let item = palette.addItem(defaultOptions); - expect(item.command).to.equal('test'); - }); - }); - - describe('#args', () => { - it('should return the args of a command item', () => { - let item = palette.addItem(defaultOptions); - expect(item.args).to.deep.equal(defaultOptions.args); - }); - - it('should default to an empty object', () => { - let item = palette.addItem({ command: 'test', category: 'test' }); - expect(item.args).to.deep.equal({}); - }); - }); - - describe('#category', () => { - it('should return the category of a command item', () => { - let item = palette.addItem(defaultOptions); - expect(item.category).to.equal(defaultOptions.category); - }); - }); - - describe('#rank', () => { - it('should return the rank of a command item', () => { - let item = palette.addItem(defaultOptions); - expect(item.rank).to.deep.equal(defaultOptions.rank); - }); - - it('should default to `Infinity`', () => { - let item = palette.addItem({ command: 'test', category: 'test' }); - expect(item.rank).to.equal(Infinity); - }); - }); - - describe('#label', () => { - it('should return the label of a command item', () => { - let label = 'test label'; - commands.addCommand('test', { execute: () => {}, label }); - let item = palette.addItem(defaultOptions); - expect(item.label).to.equal(label); - }); - }); - - describe('#caption', () => { - it('should return the caption of a command item', () => { - let caption = 'test caption'; - commands.addCommand('test', { execute: () => {}, caption }); - let item = palette.addItem(defaultOptions); - expect(item.caption).to.equal(caption); - }); - }); - - describe('#className', () => { - it('should return the class name of a command item', () => { - let className = 'testClass'; - commands.addCommand('test', { execute: () => {}, className }); - let item = palette.addItem(defaultOptions); - expect(item.className).to.equal(className); - }); - }); - - describe('#isEnabled', () => { - it('should return whether a command item is enabled', () => { - let called = false; - commands.addCommand('test', { - execute: () => {}, - isEnabled: () => { - called = true; - return false; - } - }); - let item = palette.addItem(defaultOptions); - expect(called).to.equal(false); - expect(item.isEnabled).to.equal(false); - expect(called).to.equal(true); - }); - }); - - describe('#isToggled', () => { - it('should return whether a command item is toggled', () => { - let called = false; - commands.addCommand('test', { - execute: () => {}, - isToggled: () => { - called = true; - return true; - } - }); - let item = palette.addItem(defaultOptions); - expect(called).to.equal(false); - expect(item.isToggled).to.equal(true); - expect(called).to.equal(true); - }); - }); - - describe('#isVisible', () => { - it('should return whether a command item is visible', () => { - let called = false; - commands.addCommand('test', { - execute: () => {}, - isVisible: () => { - called = true; - return false; - } - }); - let item = palette.addItem(defaultOptions); - expect(called).to.equal(false); - expect(item.isVisible).to.equal(false); - expect(called).to.equal(true); - }); - }); - - describe('#keyBinding', () => { - it('should return the key binding of a command item', () => { - commands.addKeyBinding({ - keys: ['Ctrl A'], - selector: 'body', - command: 'test', - args: defaultOptions.args - }); - let item = palette.addItem(defaultOptions); - expect(item.keyBinding!.keys).to.deep.equal(['Ctrl A']); - }); - }); - }); - }); - - describe('#removeItem()', () => { - it('should remove an item from a command palette by item', () => { - expect(palette.items.length).to.equal(0); - let item = palette.addItem(defaultOptions); - expect(palette.items.length).to.equal(1); - palette.removeItem(item); - expect(palette.items.length).to.equal(0); - }); - }); - - describe('#removeItemAt()', () => { - it('should remove an item from a command palette by index', () => { - expect(palette.items.length).to.equal(0); - palette.addItem(defaultOptions); - expect(palette.items.length).to.equal(1); - palette.removeItemAt(0); - expect(palette.items.length).to.equal(0); - }); - }); - - describe('#clearItems()', () => { - it('should remove all items from a command palette', () => { - expect(palette.items.length).to.equal(0); - palette.addItem({ command: 'test', category: 'one' }); - palette.addItem({ command: 'test', category: 'two' }); - expect(palette.items.length).to.equal(2); - palette.clearItems(); - expect(palette.items.length).to.equal(0); - }); - }); - - describe('#refresh()', () => { - it('should schedule a refresh of the search items', () => { - commands.addCommand('test', { execute: () => {}, label: 'test' }); - palette.addItem(defaultOptions); - - MessageLoop.flush(); - - let content = palette.contentNode; - let itemClass = '.lm-CommandPalette-item'; - let items = () => content.querySelectorAll(itemClass); - - expect(items()).to.have.length(1); - palette.inputNode.value = 'x'; - palette.refresh(); - MessageLoop.flush(); - expect(items()).to.have.length(0); - }); - }); - describe('#handleEvent()', () => { it('should handle click, keydown, and input events', () => { let palette = new LogPalette({ commands });