diff options
author | 2022-12-07 21:52:24 +0100 | |
---|---|---|
committer | 2022-12-07 21:52:24 +0100 | |
commit | 8476cf319b7ebae87c7928592604a54833ac56ef (patch) | |
tree | a13b04dc2ee1b56a183ae562050540cb17bd2334 /src | |
parent | 0ff853437bacc2e027a1606b84d7a6f361e818e6 (diff) | |
download | it-tools-8476cf319b7ebae87c7928592604a54833ac56ef.tar.gz it-tools-8476cf319b7ebae87c7928592604a54833ac56ef.tar.zst it-tools-8476cf319b7ebae87c7928592604a54833ac56ef.zip |
fix(integer-base-converter): handle non-decimal char and better error message
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/integer-base-converter/integer-base-converter.model.ts | 2 | ||||
-rw-r--r-- | src/tools/integer-base-converter/integer-base-converter.vue | 49 | ||||
-rw-r--r-- | src/utils/error.test.ts | 29 | ||||
-rw-r--r-- | src/utils/error.ts | 24 |
4 files changed, 93 insertions, 11 deletions
diff --git a/src/tools/integer-base-converter/integer-base-converter.model.ts b/src/tools/integer-base-converter/integer-base-converter.model.ts index c3ed66d..cfe15bd 100644 --- a/src/tools/integer-base-converter/integer-base-converter.model.ts +++ b/src/tools/integer-base-converter/integer-base-converter.model.ts @@ -7,7 +7,7 @@ export function convertBase({ value, fromBase, toBase }: { value: string; fromBa .reverse() .reduce((carry: number, digit: string, index: number) => { if (!fromRange.includes(digit)) { - throw new Error('Invalid digit `' + digit + '` for base ' + fromBase + '.'); + throw new Error('Invalid digit "' + digit + '" for base ' + fromBase + '.'); } return (carry += fromRange.indexOf(digit) * Math.pow(fromBase, index)); }, 0); diff --git a/src/tools/integer-base-converter/integer-base-converter.vue b/src/tools/integer-base-converter/integer-base-converter.vue index 04c4321..33b1dee 100644 --- a/src/tools/integer-base-converter/integer-base-converter.vue +++ b/src/tools/integer-base-converter/integer-base-converter.vue @@ -4,7 +4,7 @@ <div v-if="styleStore.isSmallScreen"> <n-input-group> <n-input-group-label style="flex: 0 0 120px"> Input number: </n-input-group-label> - <n-input-number v-model:value="inputNumber" min="0" style="width: 100%" /> + <n-input v-model:value="input" style="width: 100%" :status="error ? 'error' : undefined" /> </n-input-group> <n-input-group> <n-input-group-label style="flex: 0 0 120px"> Input base: </n-input-group-label> @@ -14,51 +14,65 @@ <n-input-group v-else> <n-input-group-label style="flex: 0 0 120px"> Input number: </n-input-group-label> - <n-input-number v-model:value="inputNumber" min="0" /> + <n-input v-model:value="input" :status="error ? 'error' : undefined" /> <n-input-group-label style="flex: 0 0 120px"> Input base: </n-input-group-label> <n-input-number v-model:value="inputBase" max="64" min="2" /> </n-input-group> + + <n-alert v-if="error" style="margin-top: 25px" type="error">{{ error }}</n-alert> <n-divider /> <n-input-group> <n-input-group-label style="flex: 0 0 170px"> Binary (2): </n-input-group-label> - <input-copyable :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 2 })" readonly /> + <input-copyable + :value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 2 })" + readonly + placeholder="Binary version will be here..." + /> </n-input-group> <n-input-group> <n-input-group-label style="flex: 0 0 170px"> Octal (8): </n-input-group-label> - <input-copyable :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 8 })" readonly /> + <input-copyable + :value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 8 })" + readonly + placeholder="Octal version will be here..." + /> </n-input-group> <n-input-group> <n-input-group-label style="flex: 0 0 170px"> Decimal (10): </n-input-group-label> <input-copyable - :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 10 })" + :value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 10 })" readonly + placeholder="Decimal version will be here..." /> </n-input-group> <n-input-group> <n-input-group-label style="flex: 0 0 170px"> Hexadecimal (16): </n-input-group-label> <input-copyable - :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 16 })" + :value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 16 })" readonly + placeholder="Decimal version will be here..." /> </n-input-group> <n-input-group> <n-input-group-label style="flex: 0 0 170px"> Base64 (64): </n-input-group-label> <input-copyable - :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 64 })" + :value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 64 })" readonly + placeholder="Base64 version will be here..." /> </n-input-group> <n-input-group> <n-input-group-label style="flex: 0 0 85px"> Custom: </n-input-group-label> <n-input-number v-model:value="outputBase" style="flex: 0 0 86px" max="64" min="2" /> <input-copyable - :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: outputBase })" + :value="errorlessConvert({ value: input, fromBase: inputBase, toBase: outputBase })" readonly + :placeholder="`Base ${outputBase} will be here...`" /> </n-input-group> </n-card> @@ -66,16 +80,31 @@ </template> <script setup lang="ts"> -import { ref } from 'vue'; +import { computed, ref } from 'vue'; import { useStyleStore } from '@/stores/style.store'; +import { getErrorMessageIfThrows } from '@/utils/error'; import { convertBase } from './integer-base-converter.model'; import InputCopyable from '../../components/InputCopyable.vue'; const styleStore = useStyleStore(); -const inputNumber = ref(42); +const input = ref('42'); const inputBase = ref(10); const outputBase = ref(42); + +function errorlessConvert(...args: Parameters<typeof convertBase>) { + try { + return convertBase(...args); + } catch (err) { + return ''; + } +} + +const error = computed(() => + getErrorMessageIfThrows(() => + convertBase({ value: input.value, fromBase: inputBase.value, toBase: outputBase.value }), + ), +); </script> <style lang="less" scoped> diff --git a/src/utils/error.test.ts b/src/utils/error.test.ts new file mode 100644 index 0000000..0272804 --- /dev/null +++ b/src/utils/error.test.ts @@ -0,0 +1,29 @@ +import { describe, expect, it } from 'vitest'; +import { getErrorMessageIfThrows } from './error'; + +describe('error util', () => { + describe('getErrorMessageIfThrows', () => { + it('get an error message if the callback throws, undefined instead', () => { + expect( + getErrorMessageIfThrows(() => { + throw 'message'; + }), + ).to.equal('message'); + + expect( + getErrorMessageIfThrows(() => { + throw new Error('message'); + }), + ).to.equal('message'); + + expect( + getErrorMessageIfThrows(() => { + throw { message: 'message' }; + }), + ).to.equal('message'); + + // eslint-disable-next-line @typescript-eslint/no-empty-function + expect(getErrorMessageIfThrows(() => {})).to.equal(undefined); + }); + }); +}); diff --git a/src/utils/error.ts b/src/utils/error.ts new file mode 100644 index 0000000..681db91 --- /dev/null +++ b/src/utils/error.ts @@ -0,0 +1,24 @@ +import _ from 'lodash'; + +export { getErrorMessageIfThrows }; + +function getErrorMessageIfThrows(cb: () => unknown) { + try { + cb(); + return undefined; + } catch (err) { + if (_.isString(err)) { + return err; + } + + if (_.isError(err)) { + return err.message; + } + + if (_.isObject(err) && _.has(err, 'message')) { + return (err as { message: string }).message; + } + + return 'An error as occurred.'; + } +} |