Skip to content

Commit

Permalink
chore: add tests for svelte merge-props
Browse files Browse the repository at this point in the history
  • Loading branch information
anubra266 committed Nov 24, 2024
1 parent bbdb449 commit 06d23e1
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 12 deletions.
16 changes: 5 additions & 11 deletions packages/frameworks/svelte/src/merge-props.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { mergeProps as zagMergeProps } from "@zag-js/core"
import { toStyleString } from "./normalize-props"

const CSS_REGEX = /((?:--)?(?:\w+-?)+)\s*:\s*([^;]*)/g

Expand All @@ -13,21 +14,14 @@ const serialize = (style: string): CSSObject => {
return res
}

const css = (style: CSSObject | string | undefined): string => {
if (typeof style === "string") style = serialize(style)

const mergedString = Object.entries(style as CSSObject)
.map(([key, value]) => `${key}: ${value}`)
.join("; ")

return mergedString
}

export function mergeProps(...args: Record<string, any>[]) {
const merged = zagMergeProps(...args)

if ("style" in merged) {
merged.style = css(merged.style)
if (typeof merged.style === "string") {
merged.style = serialize(merged.style)
}
merged.style = toStyleString(merged.style)
}

return merged
Expand Down
2 changes: 1 addition & 1 deletion packages/frameworks/svelte/src/normalize-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export type PropTypes = SvelteHTMLElements & {
style?: HTMLAttributes<HTMLElement>["style"]
}

function toStyleString(style: Record<string, number | string>) {
export function toStyleString(style: Record<string, number | string>) {
let string = ""

for (let key in style) {
Expand Down
89 changes: 89 additions & 0 deletions packages/frameworks/svelte/tests/merge-props.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { describe, it, expect, vi } from "vitest"
import { mergeProps } from "../src"

describe("mergeProps for Svelte", () => {
it("handles one argument", () => {
const onClick = () => {}
const className = "primary"
const id = "test_id"

const props = mergeProps({ onClick, className, id })

expect(props.onClick).toBe(onClick)
expect(props.className).toBe(className)
expect(props.id).toBe(id)
})

it("combines handlers", () => {
let count = 0
const mockFn = vi.fn(() => {
count++
})

const props = mergeProps({ onClick: mockFn }, { onClick: mockFn }, { onClick: mockFn })

props.onClick()
expect(mockFn).toHaveBeenCalledTimes(3)
expect(count).toBe(3)
})

it("combines css classes", () => {
const className1 = "primary"
const className2 = "hover"
const className3 = "focus"

const props = mergeProps({ class: className1 }, { class: className2 }, { class: className3 })
expect(props.class).toBe("primary hover focus")

const props2 = mergeProps({ className: className1 }, { className: className2 }, { className: className3 })
expect(props2.className).toBe("primary hover focus")
})

it("combines styles", () => {
const apiStyles =
'margin:24px;padding:2;background-image:url("http://example.com/image.png");border:1px solid #123456;--x:123;'

const objStyles = {
margin: "10px",
fontSize: "2rem",
}
const stringStyles = "margin:10px;font-size:2rem;"

const propsFromObj = mergeProps({ style: apiStyles }, { style: objStyles })
const propsFromString = mergeProps({ style: apiStyles }, { style: stringStyles })

const result =
'margin:10px;padding:2;background-image:url("http://example.com/image.png");border:1px solid #123456;--x:123;font-size:2rem;'

expect(propsFromObj.style).toBe(result)
expect(propsFromString.style).toBe(result)
})

it("last value overwrites the event listeners", () => {
const mockFn = vi.fn()
const message1 = "click1"
const message2 = "click2"

const props = mergeProps(
{ onEvent: () => mockFn(message1) },
{ onEvent: () => mockFn(message2) },
{ onEvent: "overwrites" },
)

expect(props.onEvent).toBe("overwrites")
})

it("works with Svelte-specific props", () => {
const cb1 = vi.fn()
const cb2 = vi.fn()

const combined = mergeProps({ onClick: cb1 }, { onClick: cb2 })

combined.onClick("foo")

expect(cb1).toHaveBeenCalledTimes(1)
expect(cb1).toHaveBeenCalledWith("foo")
expect(cb2).toHaveBeenCalledTimes(1)
expect(cb2).toHaveBeenCalledWith("foo")
})
})

0 comments on commit 06d23e1

Please sign in to comment.