2
0
mirror of https://github.com/tenrok/maska.git synced 2026-05-15 11:59:38 +03:00

refactor: move to single package

This commit is contained in:
Alexander Shabunevich
2024-06-02 14:32:46 +03:00
parent 548d4e224b
commit 9b454e996a
80 changed files with 893 additions and 1423 deletions
+149
View File
@@ -0,0 +1,149 @@
import { describe, expect, test } from 'vitest'
import userEvent from '@testing-library/user-event'
import Alpine from 'alpinejs'
import { nextTick } from 'alpinejs/src/nextTick'
import { xMaska } from '../src/alpine'
Alpine.plugin(xMaska)
Alpine.start()
let input: HTMLInputElement
const user = userEvent.setup()
const prepareInput = async (markup: string) => {
document.body.innerHTML = markup
await nextTick()
return <HTMLInputElement>document.querySelector('input')
}
describe('init', () => {
test('with data attr', async () => {
input = await prepareInput(`<input x-maska data-maska="#-#" value="123">`)
expect(input).toHaveValue('1-2')
})
test('with wrapper', async () => {
input = await prepareInput(
`<div x-maska><input data-maska="#-#" value="123"></div>`
)
expect(input).toHaveValue('1-2')
})
test('with expression', async () => {
input = await prepareInput(
`<input x-maska="{ mask: '#-#', eager: true }" value="1">`
)
expect(input).toHaveValue('1-')
await user.type(input, '23')
expect(input).toHaveValue('1-2')
})
test('bind x-model', async () => {
input = await prepareInput(
`<div x-data="{ val: '1', options: { mask: '#-#', eager: true }}">
<input x-maska="options" x-model="val">
<span x-text="val"></span>
<input type="checkbox" x-model="options.eager" />
</div>`
)
const span = <HTMLSpanElement>document.querySelector('span')
const checkbox = <HTMLInputElement>(
document.querySelector('input[type="checkbox"]')
)
expect(input).toHaveValue('1-')
expect(span).toHaveTextContent('1-')
await user.type(input, '23')
expect(input).toHaveValue('1-2')
expect(span).toHaveTextContent('1-2')
await user.click(checkbox)
await user.clear(input)
await user.type(input, '1')
expect(input).toHaveValue('1')
expect(span).toHaveTextContent('1')
await user.click(checkbox)
expect(input).toHaveValue('1-')
expect(span).toHaveTextContent('1-')
})
})
describe('bindings', () => {
test('bind masked', async () => {
input = await prepareInput(
`<div x-data="{ maskedvalue: '' }">
<input x-maska:maskedvalue data-maska="#-#">
<span x-text="maskedvalue"></span>
</div>`
)
const span = <HTMLSpanElement>document.querySelector('span')
await user.type(input, '123')
expect(input).toHaveValue('1-2')
expect(span).toHaveTextContent('1-2')
})
test('bind unmasked', async () => {
input = await prepareInput(
`<div x-data="{ unmaskedvalue: '' }">
<input x-maska:unmaskedvalue.unmasked data-maska="#-#">
<span x-text="unmaskedvalue"></span>
</div>`
)
const span = <HTMLSpanElement>document.querySelector('span')
await user.type(input, '123')
expect(input).toHaveValue('1-2')
expect(span).toHaveTextContent('12')
})
test('bind completed', async () => {
input = await prepareInput(
`<div x-data="{ iscompleted: false }">
<input x-maska:iscompleted.completed data-maska="#-#">
<span x-show="iscompleted"></span>
</div>`
)
const span = <HTMLSpanElement>document.querySelector('span')
await user.type(input, '1')
expect(input).toHaveValue('1')
expect(span).not.toBeVisible()
await user.type(input, '2')
expect(input).toHaveValue('1-2')
expect(span).toBeVisible()
})
test('bind masked with onMask', async () => {
input = await prepareInput(
`<div x-data="{ maskedvalue: '', options: { onMaska: () => null }}">
<input x-maska:maskedvalue="options" data-maska="#-#">
<span x-text="maskedvalue"></span>
</div>`
)
const span = <HTMLSpanElement>document.querySelector('span')
await user.type(input, '123')
expect(input).toHaveValue('1-2')
expect(span).toHaveTextContent('1-2')
})
})
+2164
View File
File diff suppressed because it is too large Load Diff
+819
View File
@@ -0,0 +1,819 @@
import { expect, test } from 'vitest'
import { Mask } from '../src/mask'
test('null mask', () => {
const mask = new Mask({ mask: null })
expect(mask.masked('1a')).toBe('1a')
})
test('empty string mask', () => {
const mask = new Mask({ mask: '' })
expect(mask.masked('1a')).toBe('1a')
})
test('undefined mask', () => {
const mask = new Mask({ mask: undefined })
expect(mask.masked('1a')).toBe('1a')
})
test('@ @ mask', () => {
const mask = new Mask({ mask: '@ @' })
expect(mask.masked('1')).toBe('')
expect(mask.masked('a')).toBe('a')
expect(mask.masked('ab')).toBe('a b')
expect(mask.masked('abc')).toBe('a b')
expect(mask.masked('1abc')).toBe('a b')
expect(mask.unmasked('1abc')).toBe('ab')
expect(mask.completed('a')).toBe(false)
expect(mask.completed('ab')).toBe(true)
})
test('@ @ eager mask', () => {
const mask = new Mask({ mask: '@ @', eager: true })
expect(mask.masked('1')).toBe('')
expect(mask.masked('a')).toBe('a ')
expect(mask.masked('ab')).toBe('a b')
expect(mask.masked('abc')).toBe('a b')
expect(mask.masked('1abc')).toBe('a b')
expect(mask.unmasked('1abc')).toBe('ab')
})
test('#.# mask', () => {
const mask = new Mask({ mask: '#.#' })
expect(mask.masked('1')).toBe('1')
expect(mask.masked('1.')).toBe('1.')
expect(mask.masked('12')).toBe('1.2')
expect(mask.masked('123')).toBe('1.2')
expect(mask.masked('a123')).toBe('1.2')
expect(mask.unmasked('a123')).toBe('12')
})
test('#.# eager mask', () => {
const mask = new Mask({ mask: '#.#', eager: true })
expect(mask.masked('1')).toBe('1.')
expect(mask.masked('1.')).toBe('1.')
expect(mask.masked('1 ')).toBe('1.')
expect(mask.masked('12')).toBe('1.2')
expect(mask.masked('123')).toBe('1.2')
expect(mask.masked('a123')).toBe('1.2')
expect(mask.unmasked('a123')).toBe('12')
})
test('@@-## mask', () => {
const mask = new Mask({ mask: '@@-##' })
expect(mask.masked('12')).toBe('')
expect(mask.masked('ab')).toBe('ab')
expect(mask.masked('ab12')).toBe('ab-12')
expect(mask.masked('ab-12')).toBe('ab-12')
expect(mask.masked('abc123')).toBe('ab-12')
expect(mask.masked('a1b2a1b2')).toBe('ab-21')
expect(mask.unmasked('a1b2a1b2')).toBe('ab21')
})
test('@@-## eager mask', () => {
const mask = new Mask({ mask: '@@-##', eager: true })
expect(mask.masked('12')).toBe('')
expect(mask.masked('ab')).toBe('ab-')
expect(mask.masked('ab12')).toBe('ab-12')
expect(mask.masked('ab-12')).toBe('ab-12')
expect(mask.masked('abc123')).toBe('ab-12')
expect(mask.masked('a1b2a1b2')).toBe('ab-21')
expect(mask.unmasked('a1b2a1b2')).toBe('ab21')
})
test('(#) mask', () => {
const mask = new Mask({ mask: '(#)' })
expect(mask.masked('1')).toBe('(1')
expect(mask.masked('(1')).toBe('(1')
expect(mask.masked('1 ')).toBe('(1)')
expect(mask.masked('12')).toBe('(1)')
expect(mask.masked('a12')).toBe('(1)')
expect(mask.unmasked('a123')).toBe('1')
})
test('(#) eager mask', () => {
const mask = new Mask({ mask: '(#)', eager: true })
expect(mask.masked('1')).toBe('(1)')
expect(mask.masked('(1')).toBe('(1)')
expect(mask.masked('12')).toBe('(1)')
expect(mask.masked('a12')).toBe('(1)')
expect(mask.unmasked('a123')).toBe('1')
})
test('#-#--# mask', () => {
const mask = new Mask({ mask: '#-#--#' })
expect(mask.masked('1')).toBe('1')
expect(mask.masked('12')).toBe('1-2')
expect(mask.masked('123')).toBe('1-2--3')
expect(mask.masked('a1234')).toBe('1-2--3')
expect(mask.unmasked('a1234')).toBe('123')
})
test('#-#--# eager mask', () => {
const mask = new Mask({ mask: '#-#--#', eager: true })
expect(mask.masked('1')).toBe('1-')
expect(mask.masked('12')).toBe('1-2--')
expect(mask.masked('123')).toBe('1-2--3')
expect(mask.masked('a1234')).toBe('1-2--3')
expect(mask.unmasked('a1234')).toBe('123')
})
test('!##.# mask', () => {
const mask = new Mask({ mask: '!##.#' })
expect(mask.masked('1')).toBe('#1')
expect(mask.masked('#1')).toBe('#1')
expect(mask.masked('12')).toBe('#1.2')
expect(mask.masked('1.2')).toBe('#1.2')
expect(mask.masked('#1.2')).toBe('#1.2')
expect(mask.masked('123')).toBe('#1.2')
expect(mask.masked('a123')).toBe('#1.2')
expect(mask.unmasked('a123')).toBe('12')
})
test('!##.# eager mask', () => {
const mask = new Mask({ mask: '!##.#', eager: true })
expect(mask.masked('1')).toBe('#1.')
expect(mask.masked('#1')).toBe('#1.')
expect(mask.masked('12')).toBe('#1.2')
expect(mask.masked('1.2')).toBe('#1.2')
expect(mask.masked('#1.2')).toBe('#1.2')
expect(mask.masked('123')).toBe('#1.2')
expect(mask.masked('a123')).toBe('#1.2')
expect(mask.unmasked('a123')).toBe('12')
})
test('0#.# mask', () => {
const mask = new Mask({ mask: '0#.#' })
expect(mask.masked('1')).toBe('01')
expect(mask.masked('0')).toBe('0')
expect(mask.masked('01')).toBe('01')
expect(mask.masked('01.')).toBe('01.')
expect(mask.masked('12')).toBe('01.2')
expect(mask.masked('1.2')).toBe('01.2')
expect(mask.masked('01.2')).toBe('01.2')
expect(mask.masked('123')).toBe('01.2')
expect(mask.masked('a123')).toBe('01.2')
expect(mask.unmasked('a123')).toBe('12')
})
test('0#.# eager mask', () => {
const mask = new Mask({ mask: '0#.#', eager: true })
expect(mask.masked('1')).toBe('01.')
expect(mask.masked('0')).toBe('0')
expect(mask.masked('01')).toBe('01.')
expect(mask.masked('01.')).toBe('01.')
expect(mask.masked('12')).toBe('01.2')
expect(mask.masked('1.2')).toBe('01.2')
expect(mask.masked('01.2')).toBe('01.2')
expect(mask.masked('123')).toBe('01.2')
expect(mask.masked('a123')).toBe('01.2')
expect(mask.unmasked('a123')).toBe('12')
})
test('#.#!* mask', () => {
const mask = new Mask({ mask: '#.#!*' })
expect(mask.masked('1')).toBe('1')
expect(mask.masked('12')).toBe('1.2')
expect(mask.masked('1.2')).toBe('1.2')
expect(mask.masked('12*')).toBe('1.2*')
expect(mask.masked('1.2*')).toBe('1.2*')
expect(mask.masked('1.2 ')).toBe('1.2*')
expect(mask.masked('123')).toBe('1.2*')
expect(mask.masked('a123')).toBe('1.2*')
expect(mask.unmasked('a123')).toBe('12')
})
test('#.#!* eager mask', () => {
const mask = new Mask({ mask: '#.#!*', eager: true })
expect(mask.masked('1')).toBe('1.')
expect(mask.masked('12')).toBe('1.2*')
expect(mask.masked('1.2')).toBe('1.2*')
expect(mask.masked('12*')).toBe('1.2*')
expect(mask.masked('1.2*')).toBe('1.2*')
expect(mask.masked('123')).toBe('1.2*')
expect(mask.masked('a123')).toBe('1.2*')
expect(mask.unmasked('a123')).toBe('12')
})
test('#.#!** mask', () => {
const mask = new Mask({ mask: '#.#!**' })
expect(mask.masked('1')).toBe('1')
expect(mask.masked('12')).toBe('1.2')
expect(mask.masked('1.2')).toBe('1.2')
expect(mask.masked('12*')).toBe('1.2*')
expect(mask.masked('1.2*')).toBe('1.2*')
expect(mask.masked('1.2 ')).toBe('1.2*')
expect(mask.masked('123')).toBe('1.2*3')
expect(mask.masked('12*3')).toBe('1.2*3')
expect(mask.masked('a123')).toBe('1.2*3')
expect(mask.unmasked('a123')).toBe('123')
})
test('#.#!** eager mask', () => {
const mask = new Mask({ mask: '#.#!**', eager: true })
expect(mask.masked('1')).toBe('1.')
expect(mask.masked('12')).toBe('1.2*')
expect(mask.masked('1.2')).toBe('1.2*')
expect(mask.masked('12*')).toBe('1.2*')
expect(mask.masked('1.2*')).toBe('1.2*')
expect(mask.masked('1.2*3')).toBe('1.2*3')
expect(mask.masked('123')).toBe('1.2*3')
expect(mask.masked('a123')).toBe('1.2*3')
expect(mask.unmasked('a123')).toBe('123')
})
test('0#!-# mask', () => {
const mask = new Mask({ mask: '0#!-#' })
expect(mask.masked('a')).toBe('0')
expect(mask.masked('0')).toBe('0')
expect(mask.masked('01')).toBe('01')
expect(mask.masked('1')).toBe('01')
expect(mask.masked('12')).toBe('01-2')
expect(mask.masked('01-2')).toBe('01-2')
expect(mask.masked('123')).toBe('01-2')
expect(mask.masked('a123')).toBe('01-2')
expect(mask.unmasked('a123')).toBe('12')
})
test('!0#!-# eager mask', () => {
const mask = new Mask({ mask: '!0#!-#', eager: true })
expect(mask.masked('a')).toBe('0')
expect(mask.masked('0')).toBe('0')
expect(mask.masked('01')).toBe('01-')
expect(mask.masked('1')).toBe('01-')
expect(mask.masked('12')).toBe('01-2')
expect(mask.masked('01-2')).toBe('01-2')
expect(mask.masked('123')).toBe('01-2')
expect(mask.masked('a123')).toBe('01-2')
expect(mask.unmasked('a123')).toBe('12')
})
test('#2 ## mask', () => {
const mask = new Mask({ mask: '#2 ##' })
expect(mask.masked('1')).toBe('1')
expect(mask.masked('12')).toBe('12')
expect(mask.masked('12 ')).toBe('12 ')
expect(mask.masked('13')).toBe('12 3')
expect(mask.masked('123')).toBe('12 3')
expect(mask.masked('134')).toBe('12 34')
expect(mask.masked('1234')).toBe('12 34')
expect(mask.masked('1345')).toBe('12 34')
expect(mask.masked('12345')).toBe('12 34')
expect(mask.masked('a1')).toBe('1')
expect(mask.masked('a13')).toBe('12 3')
expect(mask.unmasked('12345')).toBe('134')
})
test('#2 ## eager mask', () => {
const mask = new Mask({ mask: '#2 ##', eager: true })
expect(mask.masked('1')).toBe('12 ')
expect(mask.masked('12')).toBe('12 ')
expect(mask.masked('12 ')).toBe('12 ')
expect(mask.masked('13')).toBe('12 3')
expect(mask.masked('123')).toBe('12 3')
expect(mask.masked('134')).toBe('12 34')
expect(mask.masked('1234')).toBe('12 34')
expect(mask.masked('1345')).toBe('12 34')
expect(mask.masked('12345')).toBe('12 34')
expect(mask.masked('a1')).toBe('12 ')
expect(mask.masked('a13')).toBe('12 3')
expect(mask.unmasked('12345')).toBe('134')
})
test('(#) 3## mask', () => {
const mask = new Mask({ mask: '(#) 3##' })
expect(mask.masked('1')).toBe('(1')
expect(mask.masked('12')).toBe('(1) 32')
expect(mask.masked('123')).toBe('(1) 323')
expect(mask.masked('1234')).toBe('(1) 323')
expect(mask.masked('13')).toBe('(1) 3')
expect(mask.masked('134')).toBe('(1) 34')
expect(mask.masked('(1) 23')).toBe('(1) 323')
expect(mask.masked('(1) 34')).toBe('(1) 34')
expect(mask.unmasked('1')).toBe('1')
expect(mask.unmasked('1234')).toBe('123')
expect(mask.unmasked('(1) 3')).toBe('1')
expect(mask.unmasked('(1) 32')).toBe('12')
})
test('(#) 3## eager mask', () => {
const mask = new Mask({ mask: '(#) 3##', eager: true })
expect(mask.masked('1')).toBe('(1) 3')
expect(mask.masked('1 ')).toBe('(1) 3')
expect(mask.masked('12')).toBe('(1) 32')
expect(mask.masked('1 2')).toBe('(1) 32')
expect(mask.masked('123')).toBe('(1) 323')
expect(mask.masked('1234')).toBe('(1) 323')
expect(mask.masked('13')).toBe('(1) 3')
expect(mask.masked('1 3')).toBe('(1) 3')
expect(mask.masked('134')).toBe('(1) 34')
expect(mask.masked('(1) 23')).toBe('(1) 323')
expect(mask.masked('(1) 34')).toBe('(1) 34')
expect(mask.unmasked('1')).toBe('1')
expect(mask.unmasked('1234')).toBe('123')
expect(mask.unmasked('(1) 3')).toBe('1')
expect(mask.unmasked('(1) 32')).toBe('12')
})
test('(1) 2# mask', () => {
const mask = new Mask({ mask: '(1) 2#' })
expect(mask.masked(' ')).toBe('(1) ')
expect(mask.masked('.')).toBe('(1) 2')
expect(mask.masked('1')).toBe('(1')
expect(mask.masked('12')).toBe('(1) 2')
expect(mask.masked('123')).toBe('(1) 23')
expect(mask.masked('1234')).toBe('(1) 23')
expect(mask.masked('13')).toBe('(1) 23')
expect(mask.masked('(1) 23')).toBe('(1) 23')
expect(mask.masked('(1) 34')).toBe('(1) 23')
expect(mask.masked('2')).toBe('(1) 2')
expect(mask.masked('23')).toBe('(1) 23')
expect(mask.masked('3')).toBe('(1) 23')
expect(mask.masked('4')).toBe('(1) 24')
expect(mask.unmasked('1')).toBe('')
expect(mask.unmasked('12')).toBe('')
expect(mask.unmasked('123')).toBe('3')
expect(mask.unmasked('(1) 23')).toBe('3')
})
test('(1) 2## eager mask', () => {
const mask = new Mask({ mask: '(1) 2##', eager: true })
expect(mask.masked(' ')).toBe('(1) 2')
expect(mask.masked('.')).toBe('(1) 2')
expect(mask.masked('1')).toBe('(1) 2')
expect(mask.masked('1 ')).toBe('(1) 2')
expect(mask.masked('12')).toBe('(1) 2')
expect(mask.masked('1 2')).toBe('(1) 2')
expect(mask.masked('123')).toBe('(1) 23')
expect(mask.masked('1 23')).toBe('(1) 23')
expect(mask.masked('12 3')).toBe('(1) 23')
expect(mask.masked('13')).toBe('(1) 23')
expect(mask.masked('134')).toBe('(1) 234')
expect(mask.masked('(1) 23')).toBe('(1) 23')
expect(mask.masked('(1) 34')).toBe('(1) 234')
expect(mask.masked('2')).toBe('(1) 2')
expect(mask.masked('23')).toBe('(1) 23')
expect(mask.masked('3')).toBe('(1) 23')
expect(mask.masked('34')).toBe('(1) 234')
expect(mask.unmasked('1')).toBe('')
expect(mask.unmasked('12')).toBe('')
expect(mask.unmasked('123')).toBe('3')
expect(mask.unmasked('(1) 23')).toBe('3')
})
test('12## mask', () => {
const mask = new Mask({ mask: '12##' })
expect(mask.masked('.')).toBe('12')
expect(mask.masked('1')).toBe('1')
expect(mask.masked('1 ')).toBe('12')
expect(mask.masked('2')).toBe('12')
expect(mask.masked('3')).toBe('123')
expect(mask.masked('12')).toBe('12')
expect(mask.masked('12 ')).toBe('12')
expect(mask.masked('123')).toBe('123')
expect(mask.masked('13')).toBe('123')
expect(mask.masked('134')).toBe('1234')
expect(mask.unmasked('1')).toBe('')
expect(mask.unmasked('12')).toBe('')
expect(mask.unmasked('123')).toBe('3')
expect(mask.unmasked('3')).toBe('3')
expect(mask.unmasked('(1) 23')).toBe('12')
})
test('12## eager mask', () => {
const mask = new Mask({ mask: '12##', eager: true })
expect(mask.masked(' ')).toBe('12')
expect(mask.masked('.')).toBe('12')
expect(mask.masked('1')).toBe('12')
expect(mask.masked('1 ')).toBe('12')
expect(mask.masked('2')).toBe('12')
expect(mask.masked('3')).toBe('123')
expect(mask.masked('12')).toBe('12')
expect(mask.masked('123')).toBe('123')
expect(mask.masked('13')).toBe('123')
expect(mask.masked('134')).toBe('1234')
expect(mask.masked('34')).toBe('1234')
expect(mask.unmasked('1')).toBe('')
expect(mask.unmasked('12')).toBe('')
expect(mask.unmasked('123')).toBe('3')
expect(mask.unmasked('3')).toBe('3')
expect(mask.unmasked('(1) 23')).toBe('12')
})
test('#!!# mask', () => {
const mask = new Mask({ mask: '#!!#' })
expect(mask.masked('1')).toBe('1')
expect(mask.masked('12')).toBe('1!2')
expect(mask.masked('1!2')).toBe('1!2')
expect(mask.masked('123')).toBe('1!2')
expect(mask.masked('a123')).toBe('1!2')
expect(mask.unmasked('a123')).toBe('12')
})
test('#!!# eager mask', () => {
const mask = new Mask({ mask: '#!!#', eager: true })
expect(mask.masked('1')).toBe('1!')
expect(mask.masked('12')).toBe('1!2')
expect(mask.masked('1!2')).toBe('1!2')
expect(mask.masked('123')).toBe('1!2')
expect(mask.masked('a123')).toBe('1!2')
expect(mask.unmasked('a123')).toBe('12')
})
test('+1 (###) ###-##-## mask', () => {
const mask = new Mask({ mask: '+1 (###) ###-##-##' })
expect(mask.masked('999')).toBe('+1 (999')
expect(mask.masked('999123')).toBe('+1 (999) 123')
expect(mask.masked('19991234567')).toBe('+1 (999) 123-45-67')
expect(mask.masked('+19991234567')).toBe('+1 (999) 123-45-67')
expect(mask.masked('9991234567')).toBe('+1 (999) 123-45-67')
expect(mask.masked('a9991234567')).toBe('+1 (999) 123-45-67')
expect(mask.unmasked('+19991234567')).toBe('9991234567')
})
test('+1 (###) ###-##-## eager mask', () => {
const mask = new Mask({ mask: '+1 (###) ###-##-##', eager: true })
expect(mask.masked('.')).toBe('+1 (')
expect(mask.masked(' ')).toBe('+1 (')
expect(mask.masked('+')).toBe('+1 (')
expect(mask.masked('99')).toBe('+1 (99')
expect(mask.masked('999')).toBe('+1 (999) ')
expect(mask.masked('99912')).toBe('+1 (999) 12')
expect(mask.masked('999123')).toBe('+1 (999) 123-')
expect(mask.masked('19')).toBe('+1 (9')
expect(mask.masked('19991234567')).toBe('+1 (999) 123-45-67')
expect(mask.masked('+19991234567')).toBe('+1 (999) 123-45-67')
expect(mask.masked('9991234567')).toBe('+1 (999) 123-45-67')
expect(mask.masked('a9991234567')).toBe('+1 (999) 123-45-67')
expect(mask.unmasked('+19991234567')).toBe('9991234567')
})
test('1 (###) ###-##-## eager mask', () => {
const mask = new Mask({ mask: '1 (###) ###-##-##', eager: true })
expect(mask.masked('+')).toBe('1 (')
expect(mask.masked('+19991234567')).toBe('1 (199) 912-34-56')
expect(mask.masked('19991234567')).toBe('1 (999) 123-45-67')
expect(mask.masked('9991234567')).toBe('1 (999) 123-45-67')
expect(mask.masked('a9991234567')).toBe('1 (999) 123-45-67')
expect(mask.unmasked('19991234567')).toBe('9991234567')
expect(mask.unmasked('+19991234567')).toBe('1999123456')
})
test('transform mask', () => {
const mask = new Mask({
mask: 'ZZzz',
tokens: {
Z: { pattern: /[a-zA-Z]/, transform: (char) => char.toUpperCase() },
z: { pattern: /[a-zA-Z]/, transform: (char) => char.toLowerCase() }
}
})
expect(mask.masked('abcd')).toBe('ABcd')
expect(mask.masked('ABCD')).toBe('ABcd')
expect(mask.masked('1AB2CD')).toBe('ABcd')
expect(mask.unmasked('1AB2CD')).toBe('ABcd')
})
test('transform strict mask', () => {
const mask = new Mask({
mask: 'ZZzz',
tokens: {
Z: { pattern: /[A-Z]/, transform: (char) => char.toUpperCase() },
z: { pattern: /[a-z]/, transform: (char) => char.toLowerCase() }
}
})
expect(mask.masked('abcd')).toBe('ABcd')
expect(mask.masked('ABCD')).toBe('ABcd')
expect(mask.masked('1AB2CD')).toBe('ABcd')
expect(mask.unmasked('1AB2CD')).toBe('ABcd')
})
test('IP mask', () => {
const mask = new Mask({
mask: '#00.#00.#00.#00',
tokens: {
0: { pattern: /[\d]/, optional: true }
}
})
expect(mask.masked('127.0.0.1')).toBe('127.0.0.1')
expect(mask.masked('254254254254')).toBe('254.254.254.254')
expect(mask.masked('1.23.456.7890')).toBe('1.23.456.789')
expect(mask.masked('a1.23.456.7890')).toBe('1.23.456.789')
expect(mask.unmasked('a254.254.254.254')).toBe('254254254254')
})
test('repeated simple mask', () => {
const mask = new Mask({
mask: '9',
tokens: {
9: { pattern: /[\d]/, repeated: true }
}
})
expect(mask.masked('1')).toBe('1')
expect(mask.masked('12')).toBe('12')
expect(mask.masked('12 ')).toBe('12')
expect(mask.unmasked('a12')).toBe('12')
})
test('repeated 99.9 mask', () => {
const mask = new Mask({
mask: '99.9',
tokens: {
9: { pattern: /[\d]/, repeated: true }
}
})
expect(mask.masked('12')).toBe('12')
expect(mask.masked('123')).toBe('12.3')
expect(mask.masked('1234')).toBe('12.34')
expect(mask.masked('12345')).toBe('12.345')
expect(mask.masked('123456')).toBe('12.345.6')
expect(mask.masked('1234567')).toBe('12.345.67')
expect(mask.masked('12345678')).toBe('12.345.678')
expect(mask.masked('123456789')).toBe('12.345.678.9')
expect(mask.masked('a123456789')).toBe('12.345.678.9')
expect(mask.unmasked('a123456789')).toBe('123456789')
})
test('repeated 99.9 eager mask', () => {
const mask = new Mask({
mask: '99.9',
eager: true,
tokens: {
9: { pattern: /[\d]/, repeated: true }
}
})
expect(mask.masked('12')).toBe('12.')
expect(mask.masked('123')).toBe('12.3')
expect(mask.masked('1234')).toBe('12.34')
expect(mask.masked('12345')).toBe('12.345.')
expect(mask.masked('123456')).toBe('12.345.6')
expect(mask.masked('1234567')).toBe('12.345.67')
expect(mask.masked('12345678')).toBe('12.345.678.')
expect(mask.masked('123456789')).toBe('12.345.678.9')
expect(mask.unmasked('123456789')).toBe('123456789')
})
test('#-## reversed mask', () => {
const mask = new Mask({ mask: '#-##', reversed: true })
expect(mask.masked('1')).toBe('1')
expect(mask.masked('12')).toBe('12')
expect(mask.masked('123')).toBe('1-23')
expect(mask.masked('1234')).toBe('2-34')
expect(mask.masked('a1234')).toBe('2-34')
expect(mask.unmasked('a1234')).toBe('234')
})
test('#-## reversed eager mask', () => {
const mask = new Mask({ mask: '#-##', reversed: true, eager: true })
expect(mask.masked('1')).toBe('1')
expect(mask.masked('12')).toBe('-12')
expect(mask.masked('123')).toBe('1-23')
expect(mask.masked('1234')).toBe('2-34')
expect(mask.masked('a1234')).toBe('2-34')
expect(mask.unmasked('a1234')).toBe('234')
})
test('repeated reversed mask', () => {
const mask = new Mask({
mask: '9 99#,##',
reversed: true,
tokens: {
9: { pattern: /[\d]/, repeated: true }
}
})
expect(mask.masked('12')).toBe('12')
expect(mask.masked('123')).toBe('1,23')
expect(mask.masked('1234')).toBe('12,34')
expect(mask.masked('12345')).toBe('123,45')
expect(mask.masked('123456')).toBe('1 234,56')
expect(mask.masked('1234567')).toBe('12 345,67')
expect(mask.masked('12345678')).toBe('123 456,78')
expect(mask.masked('123456789')).toBe('1 234 567,89')
expect(mask.unmasked('123456789')).toBe('123456789')
})
test('repeated reversed eager mask', () => {
const mask = new Mask({
mask: '9 99#,##',
reversed: true,
eager: true,
tokens: {
9: { pattern: /[\d]/, repeated: true }
}
})
expect(mask.masked('1')).toBe('1')
expect(mask.masked('12')).toBe(',12')
expect(mask.masked('123')).toBe('1,23')
expect(mask.masked('1234')).toBe('12,34')
expect(mask.masked('12345')).toBe(' 123,45')
expect(mask.masked('123456')).toBe('1 234,56')
expect(mask.masked('1234567')).toBe('12 345,67')
expect(mask.masked('12345678')).toBe(' 123 456,78')
expect(mask.masked('123456789')).toBe('1 234 567,89')
expect(mask.unmasked('123456789')).toBe('123456789')
})
test('multiple numbers mask', () => {
const mask = new Mask({
mask: '+ +',
tokens: { '+': { pattern: /\d/, multiple: true } }
})
expect(mask.masked('1')).toBe('1')
expect(mask.masked('1 2')).toBe('1 2')
expect(mask.masked('1 2 3')).toBe('1 2')
expect(mask.masked('12')).toBe('12')
expect(mask.masked('12 ')).toBe('12 ')
expect(mask.masked('12 3')).toBe('12 3')
expect(mask.masked('12 34')).toBe('12 34')
expect(mask.masked('12 34 ')).toBe('12 34')
expect(mask.masked('12 34 5')).toBe('12 34')
expect(mask.masked('a12 34 5')).toBe('12 34')
expect(mask.masked('12.34.5')).toBe('12 34')
expect(mask.unmasked('a1 2 3')).toBe('12')
expect(mask.unmasked('12 3')).toBe('123')
expect(mask.unmasked('12 34 5')).toBe('1234')
})
test('multiple letters mask', () => {
const mask = new Mask({
mask: '+ +',
tokens: { '+': { pattern: /[a-zA-Z]/, multiple: true } }
})
expect(mask.masked('a')).toBe('a')
expect(mask.masked('ab')).toBe('ab')
expect(mask.masked('a b')).toBe('a b')
expect(mask.masked('a b с')).toBe('a b')
expect(mask.masked('ab ')).toBe('ab ')
expect(mask.masked('ab c')).toBe('ab c')
expect(mask.masked('ab cd')).toBe('ab cd')
expect(mask.masked('ab cd ')).toBe('ab cd')
expect(mask.masked('ab cd e')).toBe('ab cd')
expect(mask.masked('1ab cd e')).toBe('ab cd')
expect(mask.masked('ab.cd.e')).toBe('ab cd')
expect(mask.unmasked('1a b c')).toBe('ab')
expect(mask.unmasked('ab c')).toBe('abc')
expect(mask.unmasked('ab cd e')).toBe('abcd')
})
test('dynamic empty mask', () => {
const mask = new Mask({ mask: [] })
expect(mask.masked('1')).toBe('1')
})
test('dynamic single mask', () => {
const mask = new Mask({ mask: ['#-#'] })
expect(mask.masked('123')).toBe('1-2')
expect(mask.unmasked('123')).toBe('12')
})
test('dynamic mask', () => {
const mask = new Mask({ mask: ['###.###.###-##', '##.###.###/####-##'] })
expect(mask.masked('12345678901')).toBe('123.456.789-01')
expect(mask.masked('123456789012')).toBe('12.345.678/9012')
expect(mask.masked('12345678901234')).toBe('12.345.678/9012-34')
expect(mask.masked('a123456789012345')).toBe('12.345.678/9012-34')
expect(mask.unmasked('a123456789012345')).toBe('12345678901234')
expect(mask.completed('12345678901')).toBe(false)
expect(mask.completed('12345678901234')).toBe(true)
})
test('dynamic function mask', () => {
const mask = new Mask({
mask: (value) => (value.startsWith('1') ? '#-#--#' : '## ##')
})
expect(mask.masked('12')).toBe('1-2')
expect(mask.masked('1234')).toBe('1-2--3')
expect(mask.masked('23')).toBe('23')
expect(mask.masked('23456')).toBe('23 45')
expect(mask.masked('a23456')).toBe('23 45')
expect(mask.unmasked('a123')).toBe('123')
expect(mask.unmasked('a2345')).toBe('2345')
expect(mask.completed('12')).toBe(false)
expect(mask.completed('123')).toBe(true)
expect(mask.completed('234')).toBe(false)
expect(mask.completed('2345')).toBe(true)
})
test('dynamic escaped mask', () => {
const mask = new Mask({ mask: ['!###', '!###-##', '!###.##.##'] })
expect(mask.masked('12')).toBe('#12')
expect(mask.masked('1234')).toBe('#12-34')
expect(mask.masked('12345')).toBe('#12.34.5')
expect(mask.masked('1234567')).toBe('#12.34.56')
})
test('tokens replaced', () => {
const mask = new Mask({
mask: 'Z-#',
tokens: { Z: { pattern: /[0-9]/ } },
tokensReplace: true
})
expect(mask.masked('1')).toBe('1')
expect(mask.masked('12')).toBe('1-#')
expect(mask.masked('123')).toBe('1-#')
expect(mask.masked('1-#')).toBe('1-#')
expect(mask.unmasked('12')).toBe('1')
})
+159
View File
@@ -0,0 +1,159 @@
import { expect, test } from 'vitest'
import { Mask } from '../src/mask'
test('default number settings', () => {
const mask = new Mask({ number: {} })
expect(mask.masked('0')).toBe('0')
expect(mask.masked('00')).toBe('0')
expect(mask.masked('01')).toBe('1')
expect(mask.masked('1a')).toBe('1')
expect(mask.masked('12')).toBe('12')
expect(mask.masked('123')).toBe('123')
expect(mask.masked('1234')).toBe('1,234')
expect(mask.masked('12345')).toBe('12,345')
expect(mask.masked('123456')).toBe('123,456')
expect(mask.masked('1234567')).toBe('1,234,567')
expect(mask.masked('1234567.')).toBe('1,234,567')
expect(mask.masked('1234567.1')).toBe('1,234,567')
expect(mask.masked('-1234')).toBe('-1,234')
expect(mask.masked('--1234')).toBe('-1,234')
})
test('default number unmasked', () => {
const mask = new Mask({ number: {} })
expect(mask.unmasked('0')).toBe('0')
expect(mask.unmasked('00')).toBe('0')
expect(mask.unmasked('01')).toBe('1')
expect(mask.unmasked('1a')).toBe('1')
expect(mask.unmasked('12')).toBe('12')
expect(mask.unmasked('123')).toBe('123')
expect(mask.unmasked('1234')).toBe('1234')
expect(mask.unmasked('12345')).toBe('12345')
expect(mask.unmasked('123456')).toBe('123456')
expect(mask.unmasked('1234567')).toBe('1234567')
expect(mask.unmasked('1234567.')).toBe('1234567')
expect(mask.unmasked('1234567.1')).toBe('1234567')
expect(mask.unmasked('-1234')).toBe('-1234')
expect(mask.unmasked('--1234')).toBe('-1234')
})
test('fraction number', () => {
const mask = new Mask({ number: { fraction: 2 } })
expect(mask.masked('0')).toBe('0')
expect(mask.masked('1a')).toBe('1')
expect(mask.masked('12')).toBe('12')
expect(mask.masked('123')).toBe('123')
expect(mask.masked('1234')).toBe('1,234')
expect(mask.masked('1234567.')).toBe('1,234,567.')
expect(mask.masked('1234567..')).toBe('1,234,567.')
expect(mask.masked('1234567.1')).toBe('1,234,567.1')
expect(mask.masked('1234567.10')).toBe('1,234,567.10')
expect(mask.masked('1234567.109')).toBe('1,234,567.10')
expect(mask.masked('1234567.0')).toBe('1,234,567.0')
expect(mask.masked('1234567.01')).toBe('1,234,567.01')
expect(mask.masked('1234567.019')).toBe('1,234,567.01')
expect(mask.masked('1234567.1.')).toBe('1,234,567.1')
expect(mask.masked('1234567.1.2')).toBe('1,234,567.1')
})
test('fraction number unmasked', () => {
const mask = new Mask({ number: { fraction: 2 } })
expect(mask.unmasked('0')).toBe('0')
expect(mask.unmasked('1a')).toBe('1')
expect(mask.unmasked('12')).toBe('12')
expect(mask.unmasked('123')).toBe('123')
expect(mask.unmasked('1234')).toBe('1234')
expect(mask.unmasked('1234567.')).toBe('1234567')
expect(mask.unmasked('1234567..')).toBe('1234567')
expect(mask.unmasked('1234567.1')).toBe('1234567.1')
expect(mask.unmasked('1234567.10')).toBe('1234567.10')
expect(mask.unmasked('1234567.109')).toBe('1234567.10')
expect(mask.unmasked('1234567.0')).toBe('1234567.0')
expect(mask.unmasked('1234567.01')).toBe('1234567.01')
expect(mask.unmasked('1234567.019')).toBe('1234567.01')
expect(mask.unmasked('1234567.1.')).toBe('1234567.1')
expect(mask.unmasked('1234567.1.2')).toBe('1234567.1')
})
test('unsigned number', () => {
const mask = new Mask({ number: { unsigned: true } })
expect(mask.masked('1')).toBe('1')
expect(mask.masked('-1')).toBe('1')
expect(mask.masked('--1')).toBe('1')
})
test('russian number', () => {
const mask = new Mask({ number: { locale: 'ru', fraction: 2 } })
expect(mask.masked('1a')).toBe('1')
expect(mask.masked('12')).toBe('12')
expect(mask.masked('123')).toBe('123')
expect(mask.masked('1234')).toBe('1 234')
expect(mask.masked('12345')).toBe('12 345')
expect(mask.masked('123456')).toBe('123 456')
expect(mask.masked('1234567')).toBe('1 234 567')
expect(mask.masked('1234567.')).toBe('1 234 567,')
expect(mask.masked('1234567..')).toBe('1 234 567,')
expect(mask.masked('1234567.1')).toBe('1 234 567,1')
expect(mask.masked('1234567.10')).toBe('1 234 567,10')
expect(mask.masked('1234567.109')).toBe('1 234 567,10')
expect(mask.masked('1234567.0')).toBe('1 234 567,0')
expect(mask.masked('1234567.01')).toBe('1 234 567,01')
expect(mask.masked('1234567.019')).toBe('1 234 567,01')
expect(mask.masked('1234567.1.')).toBe('1 234 567,1')
expect(mask.masked('1234567.1.2')).toBe('1 234 567,1')
expect(mask.masked('-1234')).toBe('-1 234')
expect(mask.masked('--1234')).toBe('-1 234')
})
test('russian unmasked number', () => {
const mask = new Mask({ number: { locale: 'ru', fraction: 2 } })
expect(mask.unmasked('1a')).toBe('1')
expect(mask.unmasked('12')).toBe('12')
expect(mask.unmasked('123')).toBe('123')
expect(mask.unmasked('1234')).toBe('1234')
expect(mask.unmasked('12345')).toBe('12345')
expect(mask.unmasked('123456')).toBe('123456')
expect(mask.unmasked('1234567')).toBe('1234567')
expect(mask.unmasked('1234567.')).toBe('1234567')
expect(mask.unmasked('1234567..')).toBe('1234567')
expect(mask.unmasked('1234567.1')).toBe('1234567.1')
expect(mask.unmasked('1234567.10')).toBe('1234567.10')
expect(mask.unmasked('1234567.109')).toBe('1234567.10')
expect(mask.unmasked('1234567.0')).toBe('1234567.0')
expect(mask.unmasked('1234567.01')).toBe('1234567.01')
expect(mask.unmasked('1234567.019')).toBe('1234567.01')
expect(mask.unmasked('1234567.1.')).toBe('1234567.1')
expect(mask.unmasked('1234567.1.2')).toBe('1234567.1')
expect(mask.unmasked('-1234')).toBe('-1234')
expect(mask.unmasked('--1234')).toBe('-1234')
})
test('initial number', () => {
const mask = new Mask({ number: { fraction: 2 } })
expect(mask.masked('1234.56')).toBe('1,234.56')
expect(mask.masked('1234,56')).toBe('123,456')
expect(mask.masked('1,234.56')).toBe('1,234.56')
expect(mask.masked('1 234,56')).toBe('123,456')
expect(mask.masked('1 234.56')).toBe('1,234.56')
expect(mask.masked('1 234.56')).toBe('1,234.56')
})
test('initial russian number', () => {
const mask = new Mask({ number: { locale: 'ru', fraction: 2 } })
expect(mask.masked('1234.56')).toBe('1 234,56')
expect(mask.masked('1234,56')).toBe('1 234,56')
expect(mask.masked('1,234.56')).toBe('1,23')
expect(mask.masked('1 234,56')).toBe('1 234,56')
expect(mask.masked('1 234.56')).toBe('1 234,56')
expect(mask.masked('1 234.56')).toBe('1 234,56')
})
+1
View File
@@ -0,0 +1 @@
import '@testing-library/jest-dom/vitest'
+52
View File
@@ -0,0 +1,52 @@
import { expect, test } from 'vitest'
import { tick } from 'svelte'
import { render } from '@testing-library/svelte'
import userEvent from '@testing-library/user-event'
import BindValue from './svelte/BindValue.svelte'
import InitialValue from './svelte/InitialValue.svelte'
import Options from './svelte/Options.svelte'
import Simple from './svelte/Simple.svelte'
const user = userEvent.setup()
test('simple directive', async () => {
const { container } = render(Simple as any)
const input = container.querySelector('input')!
await user.type(input, '123')
expect(input).toHaveValue('1-2')
})
test('initial value', async () => {
const { container } = render(InitialValue as any)
const input = container.querySelector('input')!
await tick()
expect(input).toHaveValue('1-2')
})
test('bind value', async () => {
const { container } = render(BindValue as any)
const input = container.querySelector('input')!
await tick()
expect(input).toHaveValue('1-2')
})
test('options', async () => {
const { container } = render(Options as any)
const input = container.querySelector('input[type="text"]')!
const checkbox = container.querySelector('input[type="checkbox"]')!
await user.type(input, '1')
expect(input).toHaveValue('1')
await user.click(checkbox)
expect(input).toHaveValue('1-')
await user.type(input, '23')
expect(input).toHaveValue('1-2')
})
+9
View File
@@ -0,0 +1,9 @@
<script lang="ts">
import { maska } from '../../src/svelte'
let value = '123'
</script>
<main>
<input use:maska data-maska="#-#" bind:value />
</main>
+33
View File
@@ -0,0 +1,33 @@
<script lang="ts">
import BindValue from './BindValue.svelte'
import Event from './Event.svelte'
import InitialValue from './InitialValue.svelte'
import Number from './Number.svelte'
import Options from './Options.svelte'
import Simple from './Simple.svelte'
let component = Simple
</script>
<main>
<select bind:value={component}>
<option value={BindValue}>BindValue</option>
<option value={Event}>Event</option>
<option value={InitialValue}>InitialValue</option>
<option value={Number}>Number</option>
<option value={Options}>Options</option>
<option value={Simple}>Simple</option>
</select>
<div class="comp">
<svelte:component this={component} />
</div>
</main>
<style>
.comp {
margin-top: 1em;
padding: 1em;
border: 1px solid #ccc;
}
</style>
+10
View File
@@ -0,0 +1,10 @@
<script lang="ts">
import type { MaskaDetail } from '../../src'
import { maska } from '../../src/svelte'
const onMaska = (e: CustomEvent<MaskaDetail>) => console.log(e.detail.masked)
</script>
<main>
<input use:maska data-maska="#-#" on:maska={onMaska} />
</main>
+7
View File
@@ -0,0 +1,7 @@
<script lang="ts">
import { maska } from '../../src/svelte'
</script>
<main>
<input use:maska data-maska="#-#" value="123" />
</main>
+13
View File
@@ -0,0 +1,13 @@
<script lang="ts">
import { maska } from '../../src/svelte'
const options = {
number: {}
}
</script>
<main>
<input use:maska={options} />
<input use:maska data-maska-number />
<input use:maska data-maska-number-locale="ru" />
</main>
+13
View File
@@ -0,0 +1,13 @@
<script lang="ts">
import { maska } from '../../src/svelte'
const options = {
mask: '#-#',
eager: false
}
</script>
<main>
<input type="checkbox" bind:checked={options.eager} />
<input type="text" use:maska={options} />
</main>
+7
View File
@@ -0,0 +1,7 @@
<script lang="ts">
import { maska } from '../../src/svelte'
</script>
<main>
<input use:maska data-maska="#-#" />
</main>
+309
View File
@@ -0,0 +1,309 @@
import { nextTick } from 'vue'
import { expect, test } from 'vitest'
import { mount } from '@vue/test-utils'
import BindCompleted from './vue/BindCompleted.vue'
import BindMasked from './vue/BindMasked.vue'
import BindModel from './vue/BindModel.vue'
import BindUnmasked from './vue/BindUnmasked.vue'
import Callbacks from './vue/Callbacks.vue'
import ChangeValue from './vue/ChangeValue.vue'
import Config from './vue/Config.vue'
import Custom from './vue/Custom.vue'
import DataAttr from './vue/DataAttr.vue'
import Dynamic from './vue/Dynamic.vue'
import Events from './vue/Events.vue'
import Hooks from './vue/Hooks.vue'
import Initial from './vue/Initial.vue'
import Model from './vue/Model.vue'
import Multiple from './vue/Multiple.vue'
import Options from './vue/Options.vue'
import Parent from './vue/Parent.vue'
import Simple from './vue/Simple.vue'
test('simple directive', async () => {
const wrapper = mount(Simple)
expect(wrapper.exists).toBeTruthy()
const input = wrapper.get('input')
await input.setValue('123')
expect(input.element.value).toBe('1-2')
})
test('data-attr', async () => {
const wrapper = mount(DataAttr)
const input = wrapper.get('input')
await input.setValue('1')
expect(input.element.value).toBe('1-')
await input.setValue('123')
expect(input.element.value).toBe('1-2')
})
test('parent element', async () => {
const wrapper = mount(Parent)
const input = wrapper.get('input')
await input.setValue('1')
expect(input.element.value).toBe('1-')
await input.setValue('123')
expect(input.element.value).toBe('1-2')
})
test('dynamic mask', async () => {
const wrapper = mount(Dynamic)
const input = wrapper.get('input')
await input.setValue('12')
expect(input.element.value).toBe('1--2')
await input.setValue('123')
expect(input.element.value).toBe('1-2--3')
})
test('initial value', async () => {
const wrapper = mount(Initial)
const input1 = wrapper.get<HTMLInputElement>('#input1')
const input2 = wrapper.get<HTMLInputElement>('#input2')
await nextTick()
expect(input1.element.value).toBe('1-2')
expect(input2.element.value).toBe('3-4')
})
test('bind masked', async () => {
const wrapper = mount(BindMasked)
const input = wrapper.get('input')
await input.setValue('123')
expect(input.element.value).toBe('1-2')
expect(wrapper.get('div').element.textContent).toBe('1-2')
})
test('bind unmasked', async () => {
const wrapper = mount(BindUnmasked)
const input = wrapper.get('input')
await input.setValue('123')
expect(input.element.value).toBe('1-2')
expect(wrapper.get('div').element.textContent).toBe('12')
})
test('bind completed', async () => {
const wrapper = mount(BindCompleted)
const input = wrapper.get('input')
await input.setValue('12')
expect(input.element.value).toBe('1-2')
expect(wrapper.get('div').element.textContent).toBe('Uncompleted')
await input.setValue('123')
expect(input.element.value).toBe('1-2-3')
expect(wrapper.get('div').element.textContent).toBe('Completed')
})
test('bind v-model', async () => {
const wrapper = mount(BindModel)
const input = wrapper.get('input')
await new Promise((r) => setTimeout(r))
expect(input.element.value).toBe('1-2')
expect(wrapper.get('#value1').element.textContent).toBe('1-2')
expect(wrapper.get('#value2').element.textContent).toBe('12')
await input.setValue('345')
expect(input.element.value).toBe('3-4')
expect(wrapper.get('#value1').element.textContent).toBe('3-4')
expect(wrapper.get('#value2').element.textContent).toBe('34')
})
test('v-model', async () => {
const wrapper = mount(Model)
const input = wrapper.get('input')
await new Promise((r) => setTimeout(r))
expect(input.element.value).toBe('1-2')
expect(wrapper.get('div').element.textContent).toBe('1-2')
await input.setValue('1')
expect(input.element.value).toBe('1-')
expect(wrapper.get('div').element.textContent).toBe('1-')
await input.setValue('123')
expect(input.element.value).toBe('1-2')
expect(wrapper.get('div').element.textContent).toBe('1-2')
})
test('custom component', async () => {
const wrapper = mount(Custom)
const input = wrapper.get('input')
await input.setValue('1')
expect(input.element.value).toBe('1-')
expect(wrapper.get('div').element.textContent).toBe('1-')
await input.setValue('123')
expect(input.element.value).toBe('1-2')
expect(wrapper.get('div').element.textContent).toBe('1-2')
})
// TODO: find a way to test keyboard input, like backspace after input '567'
test('change value', async () => {
const wrapper = mount(ChangeValue)
const input = wrapper.get('input')
await nextTick()
expect(input.element.value).toBe('12-3')
await wrapper.get('button').trigger('click')
expect(input.element.value).toBe('56-7')
})
test('multiple inputs', async () => {
const wrapper = mount(Multiple)
const input = wrapper.get<HTMLInputElement>('#input1')
const checkbox = wrapper.get<HTMLInputElement>('#checkbox')
await new Promise((r) => setTimeout(r))
expect(wrapper.get('#value1').element.textContent).toBe('1-2')
expect(wrapper.get('#value2').element.textContent).toBe('3-2')
expect(wrapper.emitted()).toHaveProperty('mask1')
expect(wrapper.emitted()).toHaveProperty('mask2')
expect(wrapper.emitted('mask1')).toHaveLength(1)
expect(wrapper.emitted('mask2')).toHaveLength(1)
await input.setValue('1')
expect(input.element.value).toBe('1')
expect(wrapper.get('#value1').element.textContent).toBe('1')
expect(wrapper.emitted()).toHaveProperty('mask1')
expect(wrapper.emitted('mask1')).toHaveLength(2)
expect(wrapper.emitted('mask2')).toHaveLength(1)
await checkbox.setValue()
expect(checkbox.element).toBeChecked()
expect(input.element.value).toBe('1-')
expect(wrapper.emitted('mask1')).toHaveLength(3)
expect(wrapper.emitted('mask2')).toHaveLength(1)
})
test('config and bind', async () => {
const wrapper = mount(Config)
const input = wrapper.get('input')
await input.setValue('1')
expect(input.element.value).toBe('')
expect(wrapper.get('div').element.textContent).toBe('')
await input.setValue('ab')
expect(input.element.value).toBe('AB')
expect(wrapper.get('div').element.textContent).toBe('AB')
await input.setValue('ab cd ')
expect(input.element.value).toBe('AB CD')
expect(wrapper.get('div').element.textContent).toBe('AB CD')
await input.setValue('ab cd1')
expect(input.element.value).toBe('AB CD')
expect(wrapper.get('div').element.textContent).toBe('AB CD')
})
test('hooks', async () => {
const wrapper = mount(Hooks)
const input = wrapper.get('input')
await input.setValue('1')
expect(input.element.value).toBe('')
await input.setValue('ab')
expect(input.element.value).toBe('AB')
await input.setValue('ab cd ')
expect(input.element.value).toBe('AB CD')
await input.setValue('ab cd1')
expect(input.element.value).toBe('AB CD')
})
test('events', async () => {
const wrapper = mount(Events)
const input = wrapper.get('input')
await input.setValue('1')
expect(wrapper.emitted()).toHaveProperty('mask')
expect(wrapper.emitted('mask')).toHaveLength(1)
expect(wrapper.emitted('mask')[0][0]).toHaveProperty('completed', false)
await input.setValue('12')
expect(wrapper.emitted('mask')).toHaveLength(2)
expect(wrapper.emitted('mask')[1][0]).toHaveProperty('completed', true)
})
test('callbacks', async () => {
const wrapper = mount(Callbacks)
const input1 = wrapper.get('#input1')
const input2 = wrapper.get('#input2')
await input1.setValue('1')
expect(wrapper.emitted()).toHaveProperty('mask1')
expect(wrapper.emitted('mask1')).toHaveLength(1)
expect(wrapper.emitted('mask1')[0][0]).toHaveProperty('completed', false)
await input1.setValue('12')
expect(wrapper.emitted('mask1')).toHaveLength(2)
expect(wrapper.emitted('mask1')[1][0]).toHaveProperty('completed', true)
await input2.setValue('3')
expect(wrapper.emitted()).toHaveProperty('mask2')
expect(wrapper.emitted()).toHaveProperty('mask3')
expect(wrapper.emitted('mask2')).toHaveLength(1)
expect(wrapper.emitted('mask3')).toHaveLength(1)
expect(wrapper.emitted('mask2')[0][0]).toHaveProperty('completed', false)
expect(wrapper.emitted('mask3')[0][0]).toHaveProperty('completed', false)
await input2.setValue('34')
expect(wrapper.emitted('mask2')).toHaveLength(2)
expect(wrapper.emitted('mask3')).toHaveLength(2)
expect(wrapper.emitted('mask2')[1][0]).toHaveProperty('completed', true)
expect(wrapper.emitted('mask3')[1][0]).toHaveProperty('completed', true)
expect(wrapper.get('.bound1').element.textContent).toBe('1-2')
expect(wrapper.get('.bound2').element.textContent).toBe('3-4')
})
test('options api component', async () => {
const wrapper = mount(Options)
const input = wrapper.get('input')
await input.setValue('123')
expect(input.element.value).toBe('1-2')
expect(wrapper.get('div').element.textContent).toBe('1-2')
})
+12
View File
@@ -0,0 +1,12 @@
<script setup lang="ts">
import { ref } from 'vue'
import { vMaska } from '../../src/vue'
const bound = ref(false)
</script>
<template>
<input v-maska:bound.completed data-maska="#-#-#" />
<div v-if="bound === true">Completed</div>
<div v-else>Uncompleted</div>
</template>
+11
View File
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { ref } from 'vue'
import { vMaska } from '../../src/vue'
const bound = ref('')
</script>
<template>
<input v-maska:bound.masked data-maska="#-#" />
<div>{{ bound }}</div>
</template>
+13
View File
@@ -0,0 +1,13 @@
<script setup lang="ts">
import { ref } from 'vue'
import { vMaska } from '../../src/vue'
const value = ref('123')
const bound = ref('')
</script>
<template>
<input v-maska:bound.unmasked data-maska="#-#" data-maska-eager v-model="value" />
<div id="value1">{{ value }}</div>
<div id="value2">{{ bound }}</div>
</template>
+11
View File
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { ref } from 'vue'
import { vMaska } from '../../src/vue'
const bound = ref('')
</script>
<template>
<input v-maska:bound.unmasked data-maska="#-#" />
<div>{{ bound }}</div>
</template>
+27
View File
@@ -0,0 +1,27 @@
<script setup lang="ts">
import { ref } from 'vue';
import { MaskInputOptions } from '../../src'
import { vMaska } from '../../src/vue'
const emit = defineEmits(['mask1', 'mask2', 'mask3'])
const bound1 = ref('')
const bound2 = ref('')
const options1 = <MaskInputOptions>{
onMaska: (detail) => emit('mask1', detail)
}
const options2 = <MaskInputOptions>{
onMaska: [
(detail) => emit('mask2', detail),
(detail) => emit('mask3', detail),
]
}
</script>
<template>
<input id="input1" v-maska:bound1="options1" data-maska="#-#" />
<input id="input2" v-maska:bound2="options2" data-maska="#-#" />
<div class="bound1">{{ bound1 }}</div>
<div class="bound2">{{ bound2 }}</div>
</template>
+11
View File
@@ -0,0 +1,11 @@
<script setup>
import { ref } from 'vue'
import { vMaska } from '../../src/vue'
const data = ref('1234')
</script>
<template>
<input v-maska data-maska="##-#" v-model="data" data-maska-eager />
<button @click="data = '5678'">Set</button>
</template>
+22
View File
@@ -0,0 +1,22 @@
<script setup lang="ts">
import { ref } from 'vue'
import { MaskInputOptions } from '../../src'
import { vMaska } from '../../src/vue'
const bound = ref('')
const config = <MaskInputOptions>{
mask: 'A A',
tokens: {
A: {
pattern: /[A-Z]/,
multiple: true,
transform: (chr) => chr.toUpperCase()
}
}
}
</script>
<template>
<input v-maska:bound="config" />
<div>{{ bound }}</div>
</template>
+13
View File
@@ -0,0 +1,13 @@
<script setup lang="ts">
import { ref } from 'vue'
import { vMaska } from '../../src/vue'
import CustomInput from './CustomInput.vue'
const value = ref('')
</script>
<template>
<CustomInput v-maska data-maska="#-#" data-maska-eager v-model="value" />
<div>{{ value }}</div>
</template>
+11
View File
@@ -0,0 +1,11 @@
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
+7
View File
@@ -0,0 +1,7 @@
<script setup lang="ts">
import { vMaska } from '../../src/vue'
</script>
<template>
<input v-maska data-maska="#-#" data-maska-eager />
</template>
+61
View File
@@ -0,0 +1,61 @@
<script setup>
import { shallowRef } from 'vue'
import Sink from './Sink.vue'
import BindCompleted from './BindCompleted.vue'
import BindMasked from './BindMasked.vue'
import BindModel from './BindModel.vue'
import BindUnmasked from './BindUnmasked.vue'
import Callbacks from './Callbacks.vue'
import ChangeValue from './ChangeValue.vue'
import Config from './Config.vue'
import Custom from './Custom.vue'
import DataAttr from './DataAttr.vue'
import Dynamic from './Dynamic.vue'
import Events from './Events.vue'
import Hooks from './Hooks.vue'
import Initial from './Initial.vue'
import Model from './Model.vue'
import Multiple from './Multiple.vue'
import Options from './Options.vue'
import Parent from './Parent.vue'
import Simple from './Simple.vue'
const component = shallowRef(Sink)
</script>
<template>
<select v-model="component">
<option :value="Sink">Kitchen sink</option>
<option :value="BindCompleted">BindCompleted</option>
<option :value="BindMasked">BindMasked</option>
<option :value="BindModel">BindModel</option>
<option :value="BindUnmasked">BindUnmasked</option>
<option :value="Callbacks">Callbacks</option>
<option :value="ChangeValue">ChangeValue</option>
<option :value="Config">Config</option>
<option :value="Custom">Custom</option>
<option :value="DataAttr">DataAttr</option>
<option :value="Dynamic">Dynamic</option>
<option :value="Events">Events</option>
<option :value="Hooks">Hooks</option>
<option :value="Initial">Initial</option>
<option :value="Model">Model</option>
<option :value="Multiple">Multiple</option>
<option :value="Options">Options</option>
<option :value="Parent">Parent</option>
<option :value="Simple">Simple</option>
</select>
<div class="comp">
<component :is="component"></component>
</div>
</template>
<style scoped>
.comp {
margin-top: 1em;
padding: 1em;
border: 1px solid #ccc;
}
</style>
+10
View File
@@ -0,0 +1,10 @@
<script setup lang="ts">
import { ref } from 'vue'
import { vMaska } from '../../src/vue'
const mask = ref('["#--#", "#-#--#"]')
</script>
<template>
<input v-maska :data-maska="mask" />
</template>
+14
View File
@@ -0,0 +1,14 @@
<script setup lang="ts">
import { MaskaDetail } from '../../src'
import { vMaska } from '../../src/vue'
const emit = defineEmits(['mask'])
const onMaska = (e: CustomEvent<MaskaDetail>) => {
emit('mask', e.detail)
}
</script>
<template>
<input v-maska data-maska="#-#" @maska="onMaska" />
</template>
+12
View File
@@ -0,0 +1,12 @@
<script setup lang="ts">
import { MaskInputOptions } from '../../src'
import { vMaska } from '../../src/vue'
const config = <MaskInputOptions>{
preProcess: (val) => val.toUpperCase()
}
</script>
<template>
<input v-maska="config" data-maska="A A" data-maska-tokens="A:[A-Z]:multiple" />
</template>
+11
View File
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { ref } from 'vue'
import { vMaska } from '../../src/vue'
const initial = ref('345')
</script>
<template>
<input v-maska data-maska="#-#" id="input1" value="123" />
<input v-maska data-maska="#-#" id="input2" v-model="initial" />
</template>
+11
View File
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { ref } from 'vue'
import { vMaska } from '../../src/vue'
const value = ref('123')
</script>
<template>
<input v-maska data-maska="#-#" data-maska-eager v-model="value" />
<div>{{ value }}</div>
</template>
+44
View File
@@ -0,0 +1,44 @@
<script setup lang="ts">
import { reactive, ref } from 'vue'
import { vMaska } from '../../src/vue'
const emit = defineEmits(['mask1', 'mask2'])
const isEager = ref(false)
const value1 = ref('123')
const value2 = ref('321')
const options = reactive({
eager: isEager,
onMaska: () => null
})
const onMaska1 = () => {
emit('mask1')
}
const onMaska2 = () => {
emit('mask2')
}
</script>
<template>
<input id="checkbox" type="checkbox" v-model="isEager" />
<input
id="input1"
v-maska="options"
data-maska="#-#"
v-model="value1"
@maska="onMaska1"
/>
<input
id="input2"
v-maska
data-maska="#-#"
v-model="value2"
@maska="onMaska2"
/>
<div id="value1">{{ value1 }}</div>
<div id="value2">{{ value2 }}</div>
</template>
+19
View File
@@ -0,0 +1,19 @@
<script lang="ts">
import { vMaska } from '../../src/vue'
export default {
data() {
return {
bound: ''
}
},
directives: {
maska: vMaska
}
}
</script>
<template>
<input v-maska:bound data-maska="#-#" />
<div>{{ bound }}</div>
</template>
+13
View File
@@ -0,0 +1,13 @@
<script setup lang="ts">
import { vMaska } from '../../src/vue'
</script>
<template>
<div v-maska>
<input data-maska="#-#" data-maska-eager />
</div>
<div v-maska>
<!-- no input here -->
</div>
</template>
+7
View File
@@ -0,0 +1,7 @@
<script setup lang="ts">
import { vMaska } from '../../src/vue'
</script>
<template>
<input v-maska data-maska="#-#" />
</template>
+60
View File
@@ -0,0 +1,60 @@
<script setup>
import { reactive, ref } from 'vue'
import { vMaska } from '../../src/vue'
const mask = ref('+1 (###) ###-####')
const show = ref(true)
const eager = ref(true)
const valueMasked = ref('1234567')
const valueunmasked = ref('1')
const onMaska = (e) => console.log(e.detail)
const options = reactive({
mask,
eager
})
const options2 = {
preProcess: val => val.replace(/[$,]/g, ''),
postProcess: val => {
if (!val) return ''
const sub = 3 - (val.includes('.') ? val.length - val.indexOf('.') : 0)
return Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(val)
.slice(0, sub ? -sub : undefined)
}
}
</script>
<template>
<div class="row">
<div>
show: <input type="checkbox" v-model="show">
eager: <input type="checkbox" v-model="eager">
</div>
<div><input v-model="mask"></div>
<div v-if="show">
<input v-maska:valueunmasked.unmasked="options" v-model="valueMasked" @maska="onMaska">
<div>Masked: {{ valueMasked }}</div>
<div>Unmasked: {{ valueunmasked }}</div>
</div>
</div>
<div class="row"><input type="email" v-maska data-maska="##-##" data-maska-eager value="12"></div>
<div class="row"><input v-maska data-maska="####" value="1234"></div>
<div><input v-maska="options2" value="1234567" data-maska="0.99" data-maska-tokens="0:\d:multiple|9:\d:optional"></div>
</template>
<style scoped>
.row {
margin-bottom: 1em;
}
</style>