forked from bgd-labs/aave-proposals-v3
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: better number formatting (bgd-labs#25)
* fix: better number formatting * fix: improve generator * fix: uncomment test * Update src/20231029_AaveV3Ethereum_ACIPhaseII/ACIPhaseII_20231029.s.sol * fix: add advanced input * fix: add correct error
- Loading branch information
1 parent
c223665
commit 2ff5ecc
Showing
8 changed files
with
253 additions
and
34 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
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,80 @@ | ||
import {expect, describe, it} from 'vitest'; | ||
import {render} from '@inquirer/testing'; | ||
import { | ||
numberInput, | ||
percentInput, | ||
transformNumberToHumanReadable, | ||
transformNumberToPercent, | ||
translateJsNumberToSol, | ||
translateJsPercentToSol, | ||
} from './prompts'; | ||
|
||
describe('prompts', () => { | ||
describe('numberInput', () => { | ||
it('handles "yes"', async () => { | ||
const {answer, events, getScreen} = await render(numberInput, { | ||
message: 'Enter number?', | ||
}); | ||
|
||
expect(getScreen()).toMatchInlineSnapshot('"? Enter number? (KEEP_CURRENT)"'); | ||
|
||
events.type('yes112.3'); | ||
expect(getScreen()).toMatchInlineSnapshot('"? Enter number? 1,123"'); | ||
|
||
events.keypress('enter'); | ||
await expect(answer).resolves.toEqual('1_123'); | ||
}); | ||
}); | ||
|
||
describe('percentInput', () => { | ||
it('handles "yes"', async () => { | ||
const {answer, events, getScreen} = await render(percentInput, { | ||
message: 'Enter number?', | ||
}); | ||
|
||
expect(getScreen()).toMatchInlineSnapshot('"? Enter number? (KEEP_CURRENT)"'); | ||
|
||
events.type('yes12.3'); | ||
expect(getScreen()).toMatchInlineSnapshot('"? Enter number? 12.3 %"'); | ||
|
||
events.keypress('enter'); | ||
await expect(answer).resolves.toEqual('12_30'); | ||
}); | ||
}); | ||
/** | ||
* Transformers are here to format the input based on a users input | ||
* They do not change the users input value though, the effect is purely visual | ||
*/ | ||
describe('transforms', () => { | ||
it('transformNumberToHumanReadable: should return a human readable full number', () => { | ||
expect(transformNumberToHumanReadable('1000')).toBe('1,000'); | ||
expect(transformNumberToHumanReadable('1000000')).toBe('1,000,000'); | ||
}); | ||
|
||
it('transformNumberToPercent: should return a human readable % number', () => { | ||
expect(transformNumberToPercent('100')).toBe('100 %'); | ||
expect(transformNumberToPercent('3333.33')).toBe('3,333.33 %'); | ||
expect(transformNumberToPercent('0.33')).toBe('0.33 %'); | ||
expect(transformNumberToPercent('0.3')).toBe('0.3 %'); | ||
}); | ||
}); | ||
|
||
/** | ||
* Translates, translate the js input value to solidity | ||
*/ | ||
describe('translate', () => { | ||
it('translateJsNumberToSol: should properly translate values', () => { | ||
expect(translateJsNumberToSol('0')).toBe('0'); | ||
expect(translateJsNumberToSol('1000')).toBe('1_000'); | ||
expect(translateJsNumberToSol('1000000')).toBe('1_000_000'); | ||
}); | ||
|
||
it('translateJsPercentToSol: should properly translate % values', () => { | ||
expect(translateJsPercentToSol('0')).toBe('0'); | ||
expect(translateJsPercentToSol('100')).toBe('100_00'); | ||
expect(translateJsPercentToSol('3333.33')).toBe('3_333_33'); | ||
expect(translateJsPercentToSol('0.33')).toBe('33'); | ||
expect(translateJsPercentToSol('0.3')).toBe('30'); | ||
}); | ||
}); | ||
}); |
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,96 @@ | ||
import { | ||
createPrompt, | ||
useState, | ||
useKeypress, | ||
usePrefix, | ||
isEnterKey, | ||
isBackspaceKey, | ||
type PromptConfig, | ||
} from '@inquirer/core'; | ||
import type {} from '@inquirer/type'; | ||
import chalk from 'chalk'; | ||
|
||
type InputConfig = PromptConfig<{ | ||
default?: string; | ||
transformer?: (value: string, {isFinal}: {isFinal: boolean}) => string; | ||
validate?: (value: string) => boolean | string | Promise<string | boolean>; | ||
pattern?: RegExp; | ||
patternError?: string; | ||
}>; | ||
|
||
/** | ||
* It's a modified input prompt allowing to specify a pattern | ||
* The input will simply discard any non conform input and show an error | ||
*/ | ||
export const advancedInput = createPrompt<string, InputConfig>((config, done) => { | ||
const {validate = () => true, pattern, patternError} = config; | ||
const [status, setStatus] = useState<string>('pending'); | ||
const [defaultValue = '', setDefaultValue] = useState<string | undefined>(config.default); | ||
const [errorMsg, setError] = useState<string | undefined>(undefined); | ||
const [value, setValue] = useState<string>(''); | ||
|
||
const isLoading = status === 'loading'; | ||
const prefix = usePrefix(isLoading); | ||
|
||
useKeypress(async (key, rl) => { | ||
// Ignore keypress while our prompt is doing other processing. | ||
if (status !== 'pending') { | ||
return; | ||
} | ||
|
||
if (!pattern || pattern?.test(rl.line)) { | ||
if (isEnterKey(key)) { | ||
const answer = value || defaultValue; | ||
setStatus('loading'); | ||
const isValid = await validate(answer); | ||
if (isValid === true) { | ||
setValue(answer); | ||
setStatus('done'); | ||
done(answer); | ||
} else { | ||
// Reset the readline line value to the previous value. On line event, the value | ||
// get cleared, forcing the user to re-enter the value instead of fixing it. | ||
rl.write(value); | ||
setError(isValid || 'You must provide a valid value'); | ||
setStatus('pending'); | ||
} | ||
} else if (isBackspaceKey(key) && !value) { | ||
setDefaultValue(undefined); | ||
} else if (key.name === 'tab' && !value) { | ||
setDefaultValue(undefined); | ||
rl.clearLine(0); // Remove the tab character. | ||
rl.write(defaultValue); | ||
setValue(defaultValue); | ||
} else { | ||
setValue(rl.line); | ||
setError(undefined); | ||
} | ||
} else { | ||
const line = rl.line; | ||
rl.clearLine(0); | ||
rl.write(line.slice(0, -1)); | ||
setError(patternError); | ||
} | ||
}); | ||
|
||
const message = chalk.bold(config.message); | ||
let formattedValue = value; | ||
if (typeof config.transformer === 'function') { | ||
formattedValue = config.transformer(value, {isFinal: status === 'done'}); | ||
} | ||
if (status === 'done') { | ||
formattedValue = chalk.cyan(formattedValue); | ||
} | ||
|
||
let defaultStr = ''; | ||
if (defaultValue && status !== 'done' && !value) { | ||
defaultStr = chalk.dim(` (${defaultValue})`); | ||
} | ||
|
||
let error = ''; | ||
if (errorMsg) { | ||
error = chalk.red(`> ${errorMsg}`); | ||
} | ||
|
||
return [`${prefix} ${message}${defaultStr} ${formattedValue}`, error]; | ||
}); |
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
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