-
Notifications
You must be signed in to change notification settings - Fork 108
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'mock-api' of https://github.com/Mist3rBru/clack into mo…
…ck-api
- Loading branch information
Showing
73 changed files
with
6,236 additions
and
1,936 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
{ | ||
"typescript.tsdk": "node_modules/typescript/lib" | ||
"typescript.tsdk": "node_modules/typescript/lib", | ||
"editor.defaultFormatter": "biomejs.biome" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** @type {import('jest').Config} */ | ||
export default { | ||
bail: true, | ||
clearMocks: true, | ||
testEnvironment: 'node', | ||
transform: { | ||
'^.+\\.ts$': '@swc/jest', | ||
}, | ||
moduleNameMapper: { | ||
'^(\\.{1,2}/.*)\\.js$': '$1', | ||
}, | ||
testRegex: ['__tests__/.+(spec|test).ts$'], | ||
setupFiles: ['<rootDir>/setup.tests.ts'], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { readdirSync } from 'node:fs'; | ||
import { join } from 'node:path'; | ||
import * as packageExports from '../src/index'; | ||
|
||
describe('Package', () => { | ||
const exportedKeys = Object.keys(packageExports); | ||
|
||
it('should export all prompts', async () => { | ||
const promptsPath = join(__dirname, '../src/prompts'); | ||
const promptFiles = readdirSync(promptsPath); | ||
|
||
for (const file of promptFiles) { | ||
const prompt = await import(join(promptsPath, file)); | ||
expect(exportedKeys).toContain(prompt.default.name); | ||
} | ||
}); | ||
|
||
it('should export selected utils', async () => { | ||
const utils: string[] = ['block', 'isCancel', 'mockPrompt', 'setGlobalAliases']; | ||
|
||
for (const util of utils) { | ||
expect(exportedKeys).toContain(util); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './mock-readable.js'; | ||
export * from './mock-writable.js'; |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import { ConfirmPrompt, mockPrompt, setGlobalAliases } from '../../src'; | ||
import type { ConfirmOptions } from '../../src/prompts/confirm'; | ||
|
||
const makeSut = (opts?: Partial<ConfirmOptions>) => { | ||
return new ConfirmPrompt({ | ||
render() { | ||
return this.value; | ||
}, | ||
active: 'yes', | ||
inactive: 'no', | ||
...opts, | ||
}).prompt(); | ||
}; | ||
|
||
describe('ConfirmPrompt', () => { | ||
const mock = mockPrompt<ConfirmPrompt>(); | ||
|
||
afterEach(() => { | ||
mock.close(); | ||
}); | ||
|
||
it('should set a boolean value', () => { | ||
makeSut({ | ||
// @ts-expect-error | ||
initialValue: ' ', | ||
}); | ||
expect(mock.value).toBe(true); | ||
mock.close(); | ||
|
||
makeSut({ | ||
// @ts-expect-error | ||
initialValue: '', | ||
}); | ||
expect(mock.state).toBe('initial'); | ||
expect(mock.value).toBe(false); | ||
}); | ||
|
||
it('should change value when cursor changes', () => { | ||
makeSut(); | ||
|
||
expect(mock.value).toBe(false); | ||
mock.pressKey('up', { name: 'up' }); | ||
expect(mock.cursor).toBe(0); | ||
expect(mock.value).toBe(true); | ||
mock.pressKey('right', { name: 'right' }); | ||
expect(mock.cursor).toBe(1); | ||
expect(mock.value).toBe(false); | ||
mock.pressKey('left', { name: 'left' }); | ||
expect(mock.cursor).toBe(0); | ||
expect(mock.value).toBe(true); | ||
}); | ||
|
||
it('should change value on cursor alias', () => { | ||
setGlobalAliases([['u', 'up']]); | ||
makeSut(); | ||
|
||
expect(mock.value).toBe(false); | ||
mock.pressKey('u', { name: 'u' }); | ||
expect(mock.value).toBe(true); | ||
}); | ||
|
||
it('should not change value on type', () => { | ||
makeSut(); | ||
|
||
expect(mock.value).toBe(false); | ||
mock.pressKey('t', { name: 't' }); | ||
expect(mock.value).toBe(false); | ||
mock.pressKey('e', { name: 'e' }); | ||
expect(mock.value).toBe(false); | ||
}); | ||
|
||
it('should submit value', () => { | ||
makeSut(); | ||
|
||
mock.submit(); | ||
|
||
expect(mock.state).toBe('submit'); | ||
expect(mock.value).toBe(false); | ||
}); | ||
|
||
it('should submit value on confirm alias', () => { | ||
const aliases = [ | ||
['y', true], | ||
['n', false], | ||
] as const; | ||
|
||
for (const [alias, expected] of aliases) { | ||
makeSut(); | ||
expect(mock.state).not.toBe('submit'); | ||
mock.pressKey(alias, { name: alias }); | ||
expect(mock.state).toBe('submit'); | ||
expect(mock.value).toBe(expected); | ||
mock.close(); | ||
} | ||
}); | ||
}); |
177 changes: 177 additions & 0 deletions
177
packages/core/__tests__/prompts/group-multiselect.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
import { GroupMultiSelectPrompt, mockPrompt, setGlobalAliases } from '../../src'; | ||
import type { GroupMultiSelectOptions } from '../../src/prompts/group-multiselect'; | ||
|
||
const makeSut = (opts?: Partial<GroupMultiSelectOptions<{ value: string }>>) => { | ||
return new GroupMultiSelectPrompt<any>({ | ||
render() { | ||
return this.value; | ||
}, | ||
options: { | ||
'changed packages': [{ value: '@scope/a' }, { value: '@scope/b' }, { value: '@scope/c' }], | ||
'unchanged packages': [{ value: '@scope/x' }, { value: '@scope/y' }, { value: '@scope/z' }], | ||
}, | ||
...opts, | ||
}).prompt(); | ||
}; | ||
|
||
describe('GroupMultiSelectPrompt', () => { | ||
const mock = mockPrompt<GroupMultiSelectPrompt<{ value: string }>>(); | ||
|
||
afterEach(() => { | ||
mock.close(); | ||
}); | ||
|
||
it('should set options', () => { | ||
makeSut(); | ||
|
||
expect(mock.options).toStrictEqual([ | ||
{ label: 'changed packages', value: 'changed packages', group: true }, | ||
{ value: '@scope/a', group: 'changed packages' }, | ||
{ value: '@scope/b', group: 'changed packages' }, | ||
{ value: '@scope/c', group: 'changed packages' }, | ||
{ label: 'unchanged packages', value: 'unchanged packages', group: true }, | ||
{ value: '@scope/x', group: 'unchanged packages' }, | ||
{ value: '@scope/y', group: 'unchanged packages' }, | ||
{ value: '@scope/z', group: 'unchanged packages' }, | ||
]); | ||
}); | ||
|
||
it('should set initialValues', () => { | ||
makeSut({ | ||
initialValues: ['@scope/a', 'unchanged packages'], | ||
}); | ||
|
||
expect(mock.value).toStrictEqual(['@scope/a', '@scope/x', '@scope/y', '@scope/z']); | ||
}); | ||
|
||
it('should set initial cursor position', () => { | ||
makeSut({ | ||
cursorAt: '@scope/b', | ||
}); | ||
|
||
expect(mock.cursor).toBe(2); | ||
}); | ||
|
||
it('should set default cursor position', () => { | ||
makeSut(); | ||
|
||
expect(mock.cursor).toBe(0); | ||
}); | ||
|
||
it('should change cursor position on cursor', () => { | ||
makeSut({ | ||
options: { | ||
groupA: [{ value: '1' }], | ||
groupB: [{ value: '1' }], | ||
}, | ||
}); | ||
const moves = [ | ||
['down', 1], | ||
['right', 2], | ||
['down', 3], | ||
['right', 0], | ||
['left', 3], | ||
['up', 2], | ||
] as const; | ||
|
||
for (const [cursor, index] of moves) { | ||
mock.emit('cursor', cursor); | ||
expect(mock.cursor).toBe(index); | ||
} | ||
}); | ||
|
||
it('should change cursor position on cursor alias', () => { | ||
setGlobalAliases([ | ||
['d', 'down'], | ||
['u', 'up'], | ||
]); | ||
makeSut(); | ||
const moves = [ | ||
['d', 1], | ||
['u', 0], | ||
] as const; | ||
|
||
for (const [cursor, index] of moves) { | ||
mock.pressKey(cursor, { name: cursor }); | ||
expect(mock.cursor).toBe(index); | ||
} | ||
}); | ||
|
||
it('should toggle option', () => { | ||
makeSut(); | ||
|
||
mock.emit('cursor', 'down'); | ||
mock.emit('cursor', 'space'); | ||
|
||
expect(mock.value).toStrictEqual(['@scope/a']); | ||
}); | ||
|
||
it('should toggle multiple options', () => { | ||
makeSut(); | ||
|
||
mock.emit('cursor', 'down'); | ||
mock.emit('cursor', 'space'); | ||
mock.emit('cursor', 'down'); | ||
mock.emit('cursor', 'space'); | ||
|
||
expect(mock.value).toStrictEqual(['@scope/a', '@scope/b']); | ||
}); | ||
|
||
it('should untoggle option', () => { | ||
makeSut(); | ||
|
||
mock.emit('cursor', 'down'); | ||
mock.emit('cursor', 'space'); | ||
mock.emit('cursor', 'space'); | ||
|
||
expect(mock.value).toStrictEqual([]); | ||
}); | ||
|
||
it('should toggle group', () => { | ||
makeSut(); | ||
|
||
mock.emit('cursor', 'space'); | ||
|
||
expect(mock.value).toStrictEqual(['@scope/a', '@scope/b', '@scope/c']); | ||
}); | ||
|
||
it('should toggle multiple groups', () => { | ||
makeSut(); | ||
|
||
mock.emit('cursor', 'space'); | ||
mock.emit('cursor', 'down'); | ||
mock.emit('cursor', 'down'); | ||
mock.emit('cursor', 'down'); | ||
mock.emit('cursor', 'down'); | ||
mock.emit('cursor', 'space'); | ||
|
||
expect(mock.value).toStrictEqual([ | ||
'@scope/a', | ||
'@scope/b', | ||
'@scope/c', | ||
'@scope/x', | ||
'@scope/y', | ||
'@scope/z', | ||
]); | ||
}); | ||
|
||
it('should untoggle group', () => { | ||
makeSut(); | ||
|
||
mock.emit('cursor', 'space'); | ||
mock.emit('cursor', 'space'); | ||
|
||
expect(mock.value).toStrictEqual([]); | ||
}); | ||
|
||
it('should submit value', () => { | ||
makeSut({ | ||
initialValues: ['changed packages'], | ||
}); | ||
|
||
mock.submit(); | ||
|
||
expect(mock.state).toBe('submit'); | ||
expect(mock.value).toStrictEqual(['@scope/a', '@scope/b', '@scope/c']); | ||
}); | ||
}); |
Oops, something went wrong.