diff --git a/packages/utils/__tests__/animation.vitest.ts b/packages/utils/__tests__/animation.vitest.ts new file mode 100644 index 0000000000..9615f5438b --- /dev/null +++ b/packages/utils/__tests__/animation.vitest.ts @@ -0,0 +1,16 @@ +import { describe, expect, it } from 'vitest' +import { cubic, easeInOutCubic } from '..' + +describe('animation', () => { + it('cubic should work', () => { + expect(cubic(1)).toMatchInlineSnapshot('1') + expect(cubic(5)).toMatchInlineSnapshot('125') + expect(cubic(10)).toMatchInlineSnapshot('1000') + }) + + it('easeInOutCubic should work', () => { + expect(easeInOutCubic(1)).toMatchInlineSnapshot('1') + expect(easeInOutCubic(0.8).toFixed(4)).toMatchInlineSnapshot('"0.9680"') + expect(easeInOutCubic(0.4).toFixed(4)).toMatchInlineSnapshot('"0.2560"') + }) +}) diff --git a/packages/utils/__tests__/arrays.vitest.ts b/packages/utils/__tests__/arrays.vitest.ts new file mode 100644 index 0000000000..e95f7f2649 --- /dev/null +++ b/packages/utils/__tests__/arrays.vitest.ts @@ -0,0 +1,20 @@ +import { describe, expect, it } from 'vitest' +import { castArray as lodashCastArray } from 'lodash-es' +import { castArray, ensureArray, unique } from '..' + +describe('arrays', () => { + it('unique should work', () => { + expect(unique([1, 2, 3, 1])).toEqual([1, 2, 3]) + expect(unique([1, 2, 3])).toEqual([1, 2, 3]) + }) + + it('castArray should work', () => { + expect(castArray([1, 2, 3])).toEqual([1, 2, 3]) + expect(castArray(0)).toEqual([0]) + expect(castArray(undefined)).toEqual([]) + }) + + it('re-export ensureArray', () => { + expect(ensureArray).toBe(lodashCastArray) + }) +}) diff --git a/packages/utils/__tests__/browser.vitest.ts b/packages/utils/__tests__/browser.vitest.ts new file mode 100644 index 0000000000..bc01383472 --- /dev/null +++ b/packages/utils/__tests__/browser.vitest.ts @@ -0,0 +1,28 @@ +import { describe, expect, it, vi } from 'vitest' +import { isFirefox } from '..' + +describe('browser', () => { + it('isFirefox should work', () => { + const userAgents = [ + [ + 'Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0', + true, + ], + ['Mozilla/5.0 (Android; Mobile; rv:40.0) Gecko/40.0 Firefox/40.0', true], + [ + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:99.0) Gecko/20100101 Firefox/99.0', + true, + ], + [ + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36', + false, + ], + ] as const + for (const [userAgent, value] of userAgents) { + vi.spyOn(navigator, 'userAgent', 'get').mockImplementation( + () => userAgent + ) + expect(isFirefox()).toBe(value) + } + }) +}) diff --git a/packages/utils/__tests__/error.vitest.ts b/packages/utils/__tests__/error.vitest.ts new file mode 100644 index 0000000000..c3c175d08b --- /dev/null +++ b/packages/utils/__tests__/error.vitest.ts @@ -0,0 +1,26 @@ +import { describe, expect, it, vi } from 'vitest' +import { debugWarn, throwError } from '..' + +describe('error', () => { + it('throwError should work', () => { + expect(() => + throwError('scope', 'message') + ).toThrowErrorMatchingInlineSnapshot('"[scope] message"') + }) + + it('debugWarn should work', () => { + const warnFn = vi.spyOn(console, 'warn').mockImplementation(() => vi.fn) + debugWarn('scope', 'message') + debugWarn(new SyntaxError('custom error')) + expect(warnFn.mock.calls).toMatchInlineSnapshot(` + [ + [ + [ElementPlusError: [scope] message], + ], + [ + [SyntaxError: custom error], + ], + ] + `) + }) +}) diff --git a/packages/utils/__tests__/i18n.vitest.ts b/packages/utils/__tests__/i18n.vitest.ts new file mode 100644 index 0000000000..422a10452e --- /dev/null +++ b/packages/utils/__tests__/i18n.vitest.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from 'vitest' +import { isKorean } from '..' + +describe('i18n', () => { + it('isKorean should work', () => { + expect(isKorean('한국어')).toBe(true) + expect(isKorean('한국어 korean')).toBe(true) + expect(isKorean('korean')).toBe(false) + expect(isKorean('中文')).toBe(false) + expect(isKorean('にほんご')).toBe(false) + }) +}) diff --git a/packages/utils/__tests__/objects.vitest.ts b/packages/utils/__tests__/objects.vitest.ts index 7a76613a2e..e569db6487 100644 --- a/packages/utils/__tests__/objects.vitest.ts +++ b/packages/utils/__tests__/objects.vitest.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { getProp } from '..' +import { entriesOf, getProp } from '..' const AXIOM = 'Rem is the best girl' @@ -31,4 +31,9 @@ describe('objects', () => { getProp(obj, 'a.b.c').value = AXIOM expect(obj.a.b.c).toBe(AXIOM) }) + + it('entriesOf should work', () => { + const obj = { key: 'value', foo: 'bar' } + expect(entriesOf(obj)).toEqual(Object.entries(obj)) + }) }) diff --git a/packages/utils/__tests__/raf.vitest.ts b/packages/utils/__tests__/raf.vitest.ts new file mode 100644 index 0000000000..4b35f40709 --- /dev/null +++ b/packages/utils/__tests__/raf.vitest.ts @@ -0,0 +1,94 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { cAF, rAF } from '..' + +describe('raf', () => { + beforeEach(() => { + vi.useFakeTimers() + }) + afterEach(() => { + vi.useRealTimers() + vi.restoreAllMocks() + }) + + it('CSR should work', () => { + const fn = vi.fn() + rAF(() => fn('first')) + vi.runAllTimers() + expect(fn.mock.calls).toMatchInlineSnapshot(` + [ + [ + "first", + ], + ] + `) + + rAF(() => fn('second')) + vi.runAllTimers() + expect(fn.mock.calls).toMatchInlineSnapshot(` + [ + [ + "first", + ], + [ + "second", + ], + ] + `) + + const handle = rAF(() => fn('cancel')) + cAF(handle) + vi.runAllTimers() + expect(fn.mock.calls).toMatchInlineSnapshot(` + [ + [ + "first", + ], + [ + "second", + ], + ] + `) + }) + + it('SSR should work', () => { + vi.mock('@vueuse/core', () => ({ isClient: false })) + + const fn = vi.fn() + rAF(() => fn('first')) + vi.runAllTimers() + expect(fn.mock.calls).toMatchInlineSnapshot(` + [ + [ + "first", + ], + ] + `) + + rAF(() => fn('second')) + vi.runAllTimers() + expect(fn.mock.calls).toMatchInlineSnapshot(` + [ + [ + "first", + ], + [ + "second", + ], + ] + `) + + const handle = rAF(() => fn('cancel')) + cAF(handle) + vi.runAllTimers() + expect(fn.mock.calls).toMatchInlineSnapshot(` + [ + [ + "first", + ], + [ + "second", + ], + ] + `) + }) +}) diff --git a/packages/utils/__tests__/rand.vitest.ts b/packages/utils/__tests__/rand.vitest.ts new file mode 100644 index 0000000000..b65705c376 --- /dev/null +++ b/packages/utils/__tests__/rand.vitest.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from 'vitest' +import { generateId, getRandomInt } from '..' + +describe('rand', () => { + it('generateId should work', () => { + expect(generateId()).to.be.a('number') + }) + + it('getRandomInt should work', () => { + expect(getRandomInt(1000)).lessThan(1000) + }) +}) diff --git a/packages/utils/__tests__/strings.vitest.ts b/packages/utils/__tests__/strings.vitest.ts new file mode 100644 index 0000000000..77929a7d2a --- /dev/null +++ b/packages/utils/__tests__/strings.vitest.ts @@ -0,0 +1,25 @@ +import * as vueShared from '@vue/shared' +import { describe, expect, it } from 'vitest' +import { + camelize, + capitalize, + escapeStringRegexp, + hyphenate, + kebabCase, +} from '..' + +describe('strings', () => { + it('escapeStringRegexp should work', () => { + expect(escapeStringRegexp('foo')).toMatchInlineSnapshot('"foo"') + expect(escapeStringRegexp('**\\//aa^~#$')).toMatchInlineSnapshot( + '"\\\\*\\\\*\\\\\\\\//aa\\\\^~#\\\\$"' + ) + }) + + it('re-export from @vue/shared', () => { + expect(camelize).toBe(vueShared.camelize) + expect(capitalize).toBe(vueShared.capitalize) + expect(hyphenate).toBe(vueShared.hyphenate) + expect(kebabCase).toBe(vueShared.hyphenate) + }) +}) diff --git a/packages/utils/__tests__/types.vitest.ts b/packages/utils/__tests__/types.vitest.ts new file mode 100644 index 0000000000..e89c2533ee --- /dev/null +++ b/packages/utils/__tests__/types.vitest.ts @@ -0,0 +1,81 @@ +import * as vue from 'vue' +import * as vueShared from '@vue/shared' +import * as vueuse from '@vueuse/core' +import { describe, expect, it } from 'vitest' +import { + isArray, + isBoolean, + isDate, + isElement, + isEmpty, + isFunction, + isNumber, + isObject, + isPromise, + isPropAbsent, + isString, + isSymbol, + isUndefined, + isVNode, +} from '..' + +describe('types', () => { + it('re-export from @vue/shared', () => { + expect(isArray).toBe(vueShared.isArray) + expect(isDate).toBe(vueShared.isDate) + expect(isFunction).toBe(vueShared.isFunction) + expect(isObject).toBe(vueShared.isObject) + expect(isPromise).toBe(vueShared.isPromise) + expect(isString).toBe(vueShared.isString) + expect(isSymbol).toBe(vueShared.isSymbol) + }) + + it('re-export from vueuse', () => { + expect(isBoolean).toBe(vueuse.isBoolean) + expect(isNumber).toBe(vueuse.isNumber) + }) + + it('re-export from vue', () => { + expect(isVNode).toBe(vue.isVNode) + }) + + it('isUndefined should work', () => { + expect(isUndefined(undefined)).toBe(true) + expect(isUndefined(null)).toBe(false) + expect(isUndefined('null')).toBe(false) + }) + + it('isEmpty should work', () => { + expect(isEmpty(undefined)).toBe(true) + expect(isEmpty([])).toBe(true) + expect(isEmpty({})).toBe(true) + expect(isEmpty('hello')).toBe(false) + expect(isEmpty(0)).toBe(false) + expect(isEmpty(false)).toBe(true) + }) + + it('isElement should work', () => { + expect(isElement(document.createElement('div'))).toBe(true) + expect(isElement(document.createElement('span'))).toBe(true) + expect(isElement(document.createElement('h1'))).toBe(true) + expect(isElement({})).toBe(false) + expect(isElement('element')).toBe(false) + }) + + it('isElement should return false when Element is not exists', () => { + const _Element = window.Element + + window.Element = undefined as any + expect(isElement(document.createElement('div'))).toBe(false) + + window.Element = _Element + expect(isElement(document.createElement('div'))).toBe(true) + }) + + it('isPropAbsent should work', () => { + expect(isPropAbsent(null)).toBe(true) + expect(isPropAbsent(undefined)).toBe(true) + expect(isPropAbsent(123)).toBe(false) + expect(isPropAbsent({})).toBe(false) + }) +}) diff --git a/packages/utils/__tests__/typescript.vitest.ts b/packages/utils/__tests__/typescript.vitest.ts new file mode 100644 index 0000000000..71cfbc99e9 --- /dev/null +++ b/packages/utils/__tests__/typescript.vitest.ts @@ -0,0 +1,9 @@ +import { describe, expect, it } from 'vitest' +import { mutable } from '..' + +describe('typescript', () => { + it('mutable should work', () => { + const obj = { key: 'value', foo: 'bar' } + expect(mutable(obj)).toBe(obj) + }) +}) diff --git a/packages/utils/animation.ts b/packages/utils/animation.ts index d4ec00ff88..5ae42039c3 100644 --- a/packages/utils/animation.ts +++ b/packages/utils/animation.ts @@ -1,4 +1,6 @@ -export const cubic = (value: number): number => value ** 3 +export const cubic = (value: number): number => { + return value ** 3 +} export const easeInOutCubic = (value: number): number => value < 0.5 ? cubic(value * 2) / 2 : 1 - cubic((1 - value) * 2) / 2