wcb/test/utils/deserialize.test.mjs
Ayo 1b3e251a9d
Some checks are pending
Tests / Unit (push) Waiting to run
Tests / E2E (push) Waiting to run
feat!: reflect boolean props as bare attributes
Boolean props follow the HTML presence/absence semantics.
- We stick close to standard HTML behavior: flag="false" is treated as
true in most cases. Standard bare attributes disabled and required for
form fields are interpreted as true with non-existence as false.
- The use-cases for aria-*="false" and contenteditable="false" are also
supported by typing them in the JS class as string ("true" | "false").
This "true" | "false" opt-in is types-only. At runtime it's just a
string, and strings already serialize literally and are never removed —
so the enumerated/aria path needs no runtime code.
2026-07-20 19:57:23 +02:00

45 lines
1.6 KiB
JavaScript

import { describe, expect, test } from 'vitest'
import { serialize } from '../../src/utils/serialize.mjs'
import { deserialize } from '../../src/utils/deserialize.mjs'
describe('deserialize', () => {
test('parses number strings', () => {
expect(deserialize('3', 'number')).toBe(3)
expect(deserialize('-4.5', 'number')).toBe(-4.5)
})
test('treats any present boolean attribute value as true', () => {
// strict HTML semantics: presence wins, exactly like `disabled="false"`
expect(deserialize('', 'boolean')).toBe(true)
expect(deserialize('true', 'boolean')).toBe(true)
expect(deserialize('false', 'boolean')).toBe(true)
expect(deserialize('anything', 'boolean')).toBe(true)
})
test('parses object strings', () => {
expect(deserialize('{"hello":"world"}', 'object')).toEqual({
hello: 'world',
})
expect(deserialize('[1,2,3]', 'object')).toEqual([1, 2, 3])
expect(deserialize('null', 'object')).toBeNull()
})
test('passes strings through untouched', () => {
expect(deserialize('World', 'string')).toBe('World')
// an unknown/default type is treated as a plain string
expect(deserialize('World', 'symbol')).toBe('World')
})
test('round-trips values through serialize', () => {
// booleans are excluded: they no longer reflect through `serialize` at
// all — `false` is an *absent* attribute, which never reaches deserialize
const cases = [
[3, 'number'],
[{ a: 1, b: [2, 3] }, 'object'],
['hello', 'string'],
]
for (const [value, type] of cases) {
expect(deserialize(serialize(value), type)).toEqual(value)
}
})
})