Skip to content

Commit

Permalink
test: update test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
haoziqaq committed Oct 28, 2024
1 parent c4a6395 commit 623e020
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 11 deletions.
16 changes: 6 additions & 10 deletions src/collection.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
import { isArray } from './general'
import { hasOwn, isArray, isObject } from './general'

export function mergeWith<TObject extends Record<string, any>, TSource extends Record<string, any>>(
object: TObject,
source: TSource,
callback: (
callback?: (
objValue: any,
srcValue: any,
key: string | number | symbol,
object?: TObject,
source?: TSource,
) => any | void,
): TObject & TSource {
type AnyObject = Record<string | number | symbol, any>

const isObject = (obj: any): obj is AnyObject => obj !== null && typeof obj === 'object'

function baseMerge(target: AnyObject, src: AnyObject): AnyObject {
function baseMerge(target: any, src: any): any {
// eslint-disable-next-line no-restricted-syntax
for (const key in src) {
if (Object.prototype.hasOwnProperty.call(src, key)) {
if (hasOwn(src, key)) {
const srcValue = src[key]
const targetValue = target[key]

const customResult = callback(targetValue, srcValue, key, object, source)
const customResult = callback?.(targetValue, srcValue, key, object, source)

if (customResult !== undefined) {
target[key] = customResult
Expand All @@ -40,5 +36,5 @@ export function mergeWith<TObject extends Record<string, any>, TSource extends R
return target
}

return baseMerge(object as AnyObject, source as AnyObject) as TObject & TSource
return baseMerge(object as any, source as any) as TObject & TSource
}
58 changes: 58 additions & 0 deletions tests/collection.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { describe, it, expect } from 'vitest'
import { mergeWith } from '../src'

describe('mergeWith', () => {
it('should merge two objects', () => {
const object = { a: 1, b: { c: 2 } }
const source = { b: { d: 3 }, e: 4 }
const result = mergeWith(object, source)

expect(result).toEqual({ a: 1, b: { c: 2, d: 3 }, e: 4 })
})

it('should use the callback to override values', () => {
const object = { a: 1, b: 2 }
const source = { a: 3, b: 4 }
const result = mergeWith(object, source, (objValue, srcValue) => objValue + srcValue)

expect(result).toEqual({ a: 4, b: 6 })
})

it('should handle nested merges', () => {
const object = { a: { b: 1 } }
const source = { a: { c: 2 } }
const result = mergeWith(object, source)

expect(result).toEqual({ a: { b: 1, c: 2 } })

const object2 = { a: 1 }
const source2 = { b: { c: 1 } }
const result2 = mergeWith(object2, source2)

expect(result2).toEqual({ a: 1, b: { c: 1 } })
})

it('should create new properties if they don’t exist in the target', () => {
const object = { a: 1 }
const source = { b: 2 }
const result = mergeWith(object, source)

expect(result).toEqual({ a: 1, b: 2 })
})

it('should handle array merging correctly', () => {
const object = { a: [1, 2] }
const source = { a: [3, 4] }
const result = mergeWith(object, source)

expect(result).toEqual({ a: [3, 4] })
})

it('should use callback for array merging', () => {
const object = { a: [1, 2] }
const source = { a: [3, 4] }
const result = mergeWith(object, source, (objValue, srcValue) => [...objValue, ...srcValue])

expect(result).toEqual({ a: [1, 2, 3, 4] })
})
})
165 changes: 165 additions & 0 deletions tests/element.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { it, expect, vi } from 'vitest'
import {
requestAnimationFrame,
cancelAnimationFrame,
raf,
doubleRaf,
getStyle,
getRect,
inViewport,
getParentScroller,
getAllParentScroller,
preventDefault,
getScrollTop,
getScrollLeft,
classes,
createNamespaceFn,
} from '../src'
import { describe } from 'node:test'

it('requestAnimationFrame', () => {
const fn = vi.fn()
const originFn = globalThis.requestAnimationFrame
globalThis.requestAnimationFrame = fn

requestAnimationFrame(fn)
expect(fn).toHaveBeenCalled()

globalThis.requestAnimationFrame = originFn
})

it('cancelAnimationFrame', () => {
const fn = vi.fn()
const originFn = globalThis.cancelAnimationFrame
globalThis.cancelAnimationFrame = fn

cancelAnimationFrame(1)
expect(fn).toHaveBeenCalledWith(1)

globalThis.cancelAnimationFrame = originFn
})

it('raf & doubleRaf', async () => {
const fn = vi.fn((resolve) => resolve())
const originFn = globalThis.requestAnimationFrame
globalThis.requestAnimationFrame = fn

await raf()
expect(fn).toHaveBeenCalled()

await doubleRaf()
expect(fn).toHaveBeenCalledTimes(3)

globalThis.requestAnimationFrame = originFn
})

it('getStyle', () => {
const element = document.createElement('div')
document.body.appendChild(element)
const style = getStyle(element)
expect(style).toBeInstanceOf(CSSStyleDeclaration)
document.body.removeChild(element)
})

it('getRect', () => {
const element = document.createElement('div')
document.body.appendChild(element)
const rect = getRect(element)
expect(rect).toHaveProperty('width')
document.body.removeChild(element)

const windowRect = getRect(window)
expect(windowRect).toHaveProperty('width', window.innerWidth)
expect(JSON.stringify(windowRect)).toBe(
JSON.stringify({
x: 0,
y: 0,
top: 0,
left: 0,
right: window.innerWidth,
bottom: window.innerHeight,
width: window.innerWidth,
height: window.innerHeight,
}),
)
})

it('inViewport should return true if element is in viewport', () => {
const element = document.createElement('div')
document.body.appendChild(element)
Object.assign(element.style, { position: 'fixed', top: '0', left: '0' })

expect(inViewport(element)).toBe(true)
document.body.removeChild(element)
})

describe('getParentScroller', () => {
it('found', () => {
const parent = document.createElement('div')
parent.style.overflowY = 'scroll'
document.body.appendChild(parent)

const child = document.createElement('div')
parent.appendChild(child)

expect(getParentScroller(child)).toBe(parent)
document.body.removeChild(parent)
})

it('not found', () => {
const child = document.createElement('div')
expect(getParentScroller(child)).toBe(window)
})
})

it('getAllParentScroller', () => {
const parent1 = document.createElement('div')
parent1.style.overflowY = 'scroll'
const parent2 = document.createElement('div')
document.body.appendChild(parent1)
parent1.appendChild(parent2)

const child = document.createElement('div')
parent2.appendChild(child)

expect(getAllParentScroller(child)).toEqual([parent1, window])
document.body.removeChild(parent1)
})

describe('preventDefault', () => {
it('cancelable', () => {
const event = { preventDefault: vi.fn(), cancelable: true } as unknown as Event
preventDefault(event)
expect(event.preventDefault).toHaveBeenCalled()
})

it('not cancelable', () => {
const event = { preventDefault: vi.fn(), cancelable: false } as unknown as Event
preventDefault(event)
expect(event.preventDefault).not.toHaveBeenCalled()
})
})

it('getScrollTop', () => {
document.body.scrollTop = 100
expect(getScrollTop(document.body)).toBe(100)
})

it('getScrollLeft', () => {
document.body.scrollLeft = 50
expect(getScrollLeft(document.body)).toBe(50)
})

it('classes should return an array of classes based on conditions', () => {
expect(classes('class1', [true, 'class2'], [false, 'class3', 'class4'])).toEqual(['class1', 'class2', 'class4'])
})

it('createNamespaceFn should create a BEM namespace function', () => {
const createNamespace = createNamespaceFn('var')
const { n } = createNamespace('button')

expect(n()).toBe('var-button')
expect(n('element')).toBe('var-button__element')
expect(n('--modifier')).toBe('var-button--modifier')
expect(n('$-box')).toBe('var-box')
})
24 changes: 23 additions & 1 deletion tests/general.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { it, expect } from 'vitest'
import { it, expect, beforeEach } from 'vitest'
import {
isNonEmptyArray,
isString,
Expand All @@ -22,6 +22,10 @@ import {
isTruthy,
toRawType,
hasOwn,
supportTouch,
inBrowser,
inMobile,
getGlobalThis,
} from '../src'

it('isNonEmptyArray', () => {
Expand Down Expand Up @@ -211,3 +215,21 @@ it('hasOwn', () => {
expect(hasOwn({ foo: 1 }, 'bar')).toBe(false)
expect(hasOwn(Object.create({ foo: 1 }), 'foo')).toBe(false)
})

it('supportTouch', () => {
expect(supportTouch()).toBe(true)
})

it('inBrowser', () => {
expect(inBrowser()).toBe(true)
})

it('inMobile', () => {
expect(inMobile()).toBe(false)
})

it('getGlobalThis', () => {
expect(getGlobalThis()).toBe(global)
expect(getGlobalThis()).toBe(window)
expect(getGlobalThis()).toBe(self)
})
1 change: 1 addition & 0 deletions tests/json.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ describe('JSON utility functions', () => {
expect(prettyString).toBe('{\n "key": "value",\n "number": 42\n}')
})
})

0 comments on commit 623e020

Please sign in to comment.