Skip to content

Commit b238e04

Browse files
committed
Add test for multipick prompoter
1 parent 1a26e58 commit b238e04

File tree

3 files changed

+146
-7
lines changed

3 files changed

+146
-7
lines changed

packages/core/src/shared/ui/pickerPrompter.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,10 @@ export function createLabelQuickPick<T extends string>(
241241

242242
function acceptItems<T>(picker: DataQuickPick<T>, resolve: (items: DataQuickPickItem<T>[]) => void): void {
243243
if (picker.selectedItems.length === 0) {
244+
if (picker.canSelectMany) {
245+
// Allow empty choice in multipick
246+
resolve(Array.from(picker.selectedItems))
247+
}
244248
return
245249
}
246250

@@ -559,16 +563,18 @@ export class QuickPickPrompter<T> extends Prompter<T> {
559563
return choices
560564
}
561565

562-
this._lastPicked = choices[0]
563-
const result = choices[0].data
564-
565566
if (this.quickPick.canSelectMany) {
566567
// return if control signal
567-
if (isWizardControl(result)) {
568-
return result
568+
if (choices.length !== 0 && isWizardControl(choices[0].data)) {
569+
return choices[0].data
569570
}
570571
// reset before setting recent again
571-
this.quickPick.items.map((item) => (item.recentlyUsed = false))
572+
this.quickPick.items.map((item) => {
573+
;(item.recentlyUsed = false),
574+
// picked will only work on the first choice. Once choosen, remove the picked flag.
575+
(item.picked = false)
576+
})
577+
// note this can be empty
572578
return JSON.stringify(
573579
await Promise.all(
574580
choices.map(async (choice) => {
@@ -578,6 +584,9 @@ export class QuickPickPrompter<T> extends Prompter<T> {
578584
)
579585
) as T
580586
}
587+
// else single pick
588+
this._lastPicked = choices[0]
589+
const result = choices[0].data
581590

582591
return result instanceof Function ? await result() : result
583592
}

packages/core/src/test/shared/ui/pickerPrompter.test.ts

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ import {
1414
defaultQuickpickOptions,
1515
QuickPickPrompter,
1616
customUserInput,
17+
createMultiPick,
1718
} from '../../../shared/ui/pickerPrompter'
1819
import { hasKey, isNonNullable } from '../../../shared/utilities/tsUtils'
19-
import { WIZARD_BACK } from '../../../shared/wizards/wizard'
20+
import { WIZARD_BACK, WIZARD_EXIT } from '../../../shared/wizards/wizard'
2021
import { getTestWindow } from '../../shared/vscode/window'
2122
import { TestQuickPick } from '../vscode/quickInput'
2223

@@ -396,3 +397,123 @@ describe('FilterBoxQuickPickPrompter', function () {
396397
assert.strictEqual(await loadAndPrompt(), testItems[0].data)
397398
})
398399
})
400+
401+
describe('MultiPick', function () {
402+
const items: DataQuickPickItem<string>[] = [
403+
{ label: 'item1', data: 'yes', picked: true },
404+
{ label: 'item2', data: 'no' },
405+
]
406+
const itemsNoPicked: DataQuickPickItem<string>[] = [
407+
{ label: 'item1', data: 'yes' },
408+
{ label: 'item2', data: 'no' },
409+
]
410+
let picker: TestQuickPick<DataQuickPickItem<string>>
411+
let testPrompter: QuickPickPrompter<string>
412+
413+
it('can handle back button', async function () {
414+
picker = getTestWindow().createQuickPick() as typeof picker
415+
picker.canSelectMany = true
416+
testPrompter = new QuickPickPrompter(picker)
417+
testPrompter.loadItems(items)
418+
testPrompter.onDidShow(() => picker.pressButton(createBackButton()))
419+
assert.strictEqual(await testPrompter.prompt(), WIZARD_BACK)
420+
})
421+
422+
it('can handle exit button', async function () {
423+
picker = getTestWindow().createQuickPick() as typeof picker
424+
picker.canSelectMany = true
425+
testPrompter = new QuickPickPrompter(picker)
426+
testPrompter.loadItems(items)
427+
testPrompter.onDidShow(() => picker.dispose())
428+
assert.strictEqual(await testPrompter.prompt(), WIZARD_EXIT)
429+
})
430+
431+
it('applies picked options', async function () {
432+
picker = getTestWindow().createQuickPick() as typeof picker
433+
picker.canSelectMany = true
434+
testPrompter = new QuickPickPrompter(picker)
435+
testPrompter.loadItems(items)
436+
437+
picker.onDidShow(async () => {
438+
picker.acceptDefault()
439+
})
440+
441+
picker.onDidChangeActive(async (items) => {
442+
assert.strictEqual(items[0].picked, true)
443+
assert.strictEqual(items[1].picked, false)
444+
assert.strictEqual(items[0].data, 'yes')
445+
assert.strictEqual(items[1].data, 'no')
446+
})
447+
448+
const result = await testPrompter.prompt()
449+
assert.deepStrictEqual(result, '["yes"]')
450+
})
451+
452+
it('pick non should return empty array', async function () {
453+
picker = getTestWindow().createQuickPick() as typeof picker
454+
picker.canSelectMany = true
455+
testPrompter = new QuickPickPrompter(picker)
456+
testPrompter.loadItems(itemsNoPicked)
457+
458+
picker.onDidShow(async () => {
459+
picker.acceptDefault()
460+
})
461+
462+
picker.onDidChangeActive(async (items) => {
463+
assert.strictEqual(items[0].picked, false)
464+
assert.strictEqual(items[1].picked, false)
465+
assert.strictEqual(items[0].data, 'yes')
466+
assert.strictEqual(items[1].data, 'no')
467+
})
468+
469+
const result = await testPrompter.prompt()
470+
assert.deepStrictEqual(result, '[]')
471+
})
472+
473+
it('creates a new prompter with options', async function () {
474+
const prompter = createMultiPick(items, { title: 'test' })
475+
assert.strictEqual(prompter.quickPick.title, 'test')
476+
})
477+
478+
it('creates a new prompter when given a promise for items', async function () {
479+
let resolveItems!: (items: DataQuickPickItem<string>[]) => void
480+
const itemsPromise = new Promise<DataQuickPickItem<string>[]>((resolve) => (resolveItems = resolve))
481+
const prompter = createMultiPick(itemsPromise)
482+
void prompter.prompt()
483+
assert.strictEqual(prompter.quickPick.busy, true)
484+
485+
resolveItems(items)
486+
await itemsPromise
487+
488+
assert.strictEqual(prompter.quickPick.busy, false)
489+
assert.deepStrictEqual(prompter.quickPick.items, items)
490+
})
491+
492+
it('creates a new prompter when given an AsyncIterable', async function () {
493+
let r1!: (v?: any) => void
494+
let r2!: (v?: any) => void
495+
const p1 = new Promise((r) => (r1 = r))
496+
const p2 = new Promise((r) => (r2 = r))
497+
498+
async function* generator() {
499+
for (const item of items) {
500+
if (item === items[0]) {
501+
await p1
502+
} else {
503+
await p2
504+
}
505+
yield [item]
506+
}
507+
}
508+
509+
const prompter = createMultiPick(generator())
510+
r1()
511+
await new Promise((r) => setImmediate(r))
512+
assert.deepStrictEqual(prompter.quickPick.items, [items[0]])
513+
assert.strictEqual(prompter.quickPick.busy, true)
514+
r2()
515+
await new Promise((r) => setImmediate(r))
516+
assert.deepStrictEqual(prompter.quickPick.items, items)
517+
assert.strictEqual(prompter.quickPick.busy, false)
518+
})
519+
})

packages/core/src/test/shared/vscode/quickInput.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,15 @@ export class PickerTester<T extends vscode.QuickPickItem> {
225225
this.triggers.onDidAccept.fire()
226226
}
227227

228+
/**
229+
* Attempts to accept the default state. Used to test Multipick
230+
*
231+
* See {@link acceptItem}.
232+
*/
233+
public acceptDefault(): void {
234+
this.triggers.onDidAccept.fire()
235+
}
236+
228237
/**
229238
* Asserts that the given items are loaded in the QuickPick, in the given order.
230239
*

0 commit comments

Comments
 (0)