From 06d23e172b2aa36929083333da5f90509a3f580e Mon Sep 17 00:00:00 2001 From: anubra266 Date: Sun, 24 Nov 2024 15:57:33 -0800 Subject: [PATCH] chore: add tests for svelte merge-props --- packages/frameworks/svelte/src/merge-props.ts | 16 ++-- .../frameworks/svelte/src/normalize-props.ts | 2 +- .../svelte/tests/merge-props.test.ts | 89 +++++++++++++++++++ 3 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 packages/frameworks/svelte/tests/merge-props.test.ts diff --git a/packages/frameworks/svelte/src/merge-props.ts b/packages/frameworks/svelte/src/merge-props.ts index 97e1a20c0e..d9f4da9b22 100644 --- a/packages/frameworks/svelte/src/merge-props.ts +++ b/packages/frameworks/svelte/src/merge-props.ts @@ -1,4 +1,5 @@ import { mergeProps as zagMergeProps } from "@zag-js/core" +import { toStyleString } from "./normalize-props" const CSS_REGEX = /((?:--)?(?:\w+-?)+)\s*:\s*([^;]*)/g @@ -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[]) { 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 diff --git a/packages/frameworks/svelte/src/normalize-props.ts b/packages/frameworks/svelte/src/normalize-props.ts index fb01d4a334..371660ed45 100644 --- a/packages/frameworks/svelte/src/normalize-props.ts +++ b/packages/frameworks/svelte/src/normalize-props.ts @@ -19,7 +19,7 @@ export type PropTypes = SvelteHTMLElements & { style?: HTMLAttributes["style"] } -function toStyleString(style: Record) { +export function toStyleString(style: Record) { let string = "" for (let key in style) { diff --git a/packages/frameworks/svelte/tests/merge-props.test.ts b/packages/frameworks/svelte/tests/merge-props.test.ts new file mode 100644 index 0000000000..b65e20904b --- /dev/null +++ b/packages/frameworks/svelte/tests/merge-props.test.ts @@ -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") + }) +})