Skip to content

Commit aee5d07

Browse files
committed
wip
1 parent 921c67a commit aee5d07

File tree

4 files changed

+459
-206
lines changed

4 files changed

+459
-206
lines changed
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
import { parseElement } from '../element-parser'
2+
3+
describe(parseElement, () => {
4+
test('parses a generic HTML element', () => {
5+
const element = document.createElement('div')
6+
element.id = 'test-id'
7+
element.classList.add('test-class')
8+
element.setAttribute('title', 'Test Title')
9+
element.textContent = 'Test Content'
10+
11+
const parsed = parseElement(element)
12+
13+
expect(parsed).toMatchInlineSnapshot(`
14+
{
15+
"attributes": {
16+
"class": "test-class",
17+
"id": "test-id",
18+
"title": "Test Title",
19+
},
20+
"classList": [
21+
"test-class",
22+
],
23+
"describedBy": undefined,
24+
"id": "test-id",
25+
"innerText": undefined,
26+
"label": undefined,
27+
"labels": [],
28+
"name": undefined,
29+
"nodeName": "DIV",
30+
"tagName": "DIV",
31+
"textContent": "Test Content",
32+
"title": "Test Title",
33+
"type": undefined,
34+
"value": undefined,
35+
}
36+
`)
37+
})
38+
39+
test('parses an HTMLSelectElement', () => {
40+
const select = document.createElement('select')
41+
select.id = 'select-id'
42+
select.classList.add('select-class')
43+
select.setAttribute('title', 'Select Title')
44+
select.selectedIndex = 1
45+
46+
const option1 = document.createElement('option')
47+
option1.value = 'value1'
48+
option1.label = 'label1'
49+
select.appendChild(option1)
50+
51+
const option2 = document.createElement('option')
52+
option2.value = 'value2'
53+
option2.label = 'label2'
54+
select.appendChild(option2)
55+
56+
select.selectedIndex = 1
57+
58+
const parsed = parseElement(select)
59+
60+
expect(parsed).toMatchInlineSnapshot(`
61+
{
62+
"attributes": {
63+
"class": "select-class",
64+
"id": "select-id",
65+
"title": "Select Title",
66+
},
67+
"classList": [
68+
"select-class",
69+
],
70+
"describedBy": undefined,
71+
"id": "select-id",
72+
"innerText": undefined,
73+
"label": undefined,
74+
"labels": [],
75+
"name": "",
76+
"nodeName": "SELECT",
77+
"selectedIndex": 1,
78+
"selectedOptions": [
79+
{
80+
"label": "label2",
81+
"value": "value2",
82+
},
83+
],
84+
"tagName": "SELECT",
85+
"textContent": "",
86+
"title": "Select Title",
87+
"type": "select-one",
88+
"value": "value2",
89+
}
90+
`)
91+
})
92+
93+
test('parses an HTMLInputElement', () => {
94+
const input = document.createElement('input')
95+
input.id = 'input-id'
96+
input.classList.add('input-class')
97+
input.setAttribute('title', 'Input Title')
98+
input.type = 'checkbox'
99+
input.checked = true
100+
101+
const parsed = parseElement(input)
102+
103+
expect(parsed).toMatchInlineSnapshot(`
104+
{
105+
"attributes": {
106+
"class": "input-class",
107+
"id": "input-id",
108+
"title": "Input Title",
109+
"type": "checkbox",
110+
},
111+
"checked": true,
112+
"classList": [
113+
"input-class",
114+
],
115+
"describedBy": undefined,
116+
"id": "input-id",
117+
"innerText": undefined,
118+
"label": undefined,
119+
"labels": [],
120+
"name": "",
121+
"nodeName": "INPUT",
122+
"tagName": "INPUT",
123+
"textContent": "",
124+
"title": "Input Title",
125+
"type": "checkbox",
126+
"value": "on",
127+
}
128+
`)
129+
})
130+
131+
test('parses an HTMLMediaElement', () => {
132+
const video = document.createElement('video')
133+
video.id = 'video-id'
134+
video.classList.add('video-class')
135+
video.setAttribute('title', 'Video Title')
136+
video.src = 'video.mp4'
137+
video.currentTime = 10
138+
139+
// Mock the duration property
140+
Object.defineProperty(video, 'duration', {
141+
value: 120,
142+
writable: true,
143+
})
144+
145+
Object.defineProperty(video, 'paused', {
146+
value: false,
147+
writable: true,
148+
})
149+
150+
Object.defineProperty(video, 'readyState', {
151+
value: 4,
152+
writable: true,
153+
})
154+
155+
video.muted = true
156+
video.playbackRate = 1.5
157+
video.volume = 0.8
158+
159+
const parsed = parseElement(video)
160+
161+
expect(parsed).toMatchInlineSnapshot(`
162+
{
163+
"attributes": {
164+
"class": "video-class",
165+
"id": "video-id",
166+
"src": "video.mp4",
167+
"title": "Video Title",
168+
},
169+
"classList": [
170+
"video-class",
171+
],
172+
"currentSrc": "",
173+
"currentTime": 10,
174+
"describedBy": undefined,
175+
"duration": 120,
176+
"ended": false,
177+
"id": "video-id",
178+
"innerText": undefined,
179+
"label": undefined,
180+
"labels": [],
181+
"muted": true,
182+
"name": undefined,
183+
"nodeName": "VIDEO",
184+
"paused": false,
185+
"playbackRate": 1.5,
186+
"readyState": 4,
187+
"src": "http://localhost/video.mp4",
188+
"tagName": "VIDEO",
189+
"textContent": "",
190+
"title": "Video Title",
191+
"type": undefined,
192+
"value": undefined,
193+
"volume": 0.8,
194+
}
195+
`)
196+
})
197+
198+
test('parses an HTMLFormElement', () => {
199+
const form = document.createElement('input')
200+
form.id = 'form-id'
201+
form.classList.add('form-class')
202+
form.setAttribute('title', 'Form Title')
203+
204+
const input = document.createElement('input')
205+
input.name = 'input-name'
206+
input.value = 'input-value'
207+
form.appendChild(input)
208+
209+
const parsed = parseElement(form)
210+
211+
expect(parsed).toMatchInlineSnapshot(`
212+
{
213+
"attributes": {
214+
"class": "form-class",
215+
"id": "form-id",
216+
"title": "Form Title",
217+
},
218+
"checked": false,
219+
"classList": [
220+
"form-class",
221+
],
222+
"describedBy": undefined,
223+
"id": "form-id",
224+
"innerText": undefined,
225+
"label": undefined,
226+
"labels": [],
227+
"name": "",
228+
"nodeName": "INPUT",
229+
"tagName": "INPUT",
230+
"textContent": "",
231+
"title": "Form Title",
232+
"type": "text",
233+
"value": "",
234+
}
235+
`)
236+
})
237+
test.only('handles scenarios where name is an object', () => {
238+
const form = document.createElement('form')
239+
form.id = 'form-id'
240+
form.classList.add('form-class')
241+
form.setAttribute('title', 'Form Title')
242+
243+
Object.defineProperty(form, 'name', {
244+
// this can happen in some weird cases?. just in case
245+
value: {
246+
hello: 'world',
247+
},
248+
writable: true,
249+
})
250+
251+
const parsed = parseElement(form)
252+
253+
expect(parsed).toMatchInlineSnapshot(`
254+
{
255+
"attributes": {
256+
"class": "form-class",
257+
"id": "form-id",
258+
"title": "Form Title",
259+
},
260+
"classList": [
261+
"form-class",
262+
],
263+
"describedBy": undefined,
264+
"formData": {},
265+
"id": "form-id",
266+
"innerText": undefined,
267+
"label": undefined,
268+
"labels": [],
269+
"name": undefined,
270+
"nodeName": "FORM",
271+
"tagName": "FORM",
272+
"textContent": undefined,
273+
"title": "Form Title",
274+
"type": undefined,
275+
"value": undefined,
276+
}
277+
`)
278+
})
279+
})

packages/signals/signals/src/core/signal-generators/dom-gen/change-gen.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { createInteractionSignal } from '../../../types/factories'
33
import { SignalEmitter } from '../../emitter'
44
import { SignalGlobalSettings } from '../../signals'
55
import { SignalGenerator } from '../types'
6-
import { shouldIgnoreElement, parseElement } from './dom-gen'
6+
import { shouldIgnoreElement } from './dom-gen'
7+
import { parseElement } from './element-parser'
78
import {
89
MutationObservable,
910
AttributeChangedEvent,

0 commit comments

Comments
 (0)