@pyreon/attrs 0.11.5 → 0.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,14 @@
1
- import attrsComponent from "../attrs"
2
- import attrs from "../init"
3
- import isAttrsComponent from "../isAttrsComponent"
1
+ import attrsComponent from '../attrs'
2
+ import attrs from '../init'
3
+ import isAttrsComponent from '../isAttrsComponent'
4
4
 
5
5
  /**
6
6
  * Simple base component for testing.
7
7
  * Returns a VNode-like object so we can inspect the final props.
8
8
  */
9
9
  const BaseComponent = (props: any) => ({
10
- type: "div",
11
- props: { ...props, "data-testid": "base" },
10
+ type: 'div',
11
+ props: { ...props, 'data-testid': 'base' },
12
12
  children: props.children ?? props.label ?? null,
13
13
  key: null,
14
14
  })
@@ -22,201 +22,201 @@ const renderProps = (Component: any, props: Record<string, any> = {}) => {
22
22
  // --------------------------------------------------------
23
23
  // attrs() initialization
24
24
  // --------------------------------------------------------
25
- describe("attrs initialization", () => {
26
- it("should create an attrs component from a base component", () => {
27
- const Component = attrs({ name: "TestComponent", component: BaseComponent })
25
+ describe('attrs initialization', () => {
26
+ it('should create an attrs component from a base component', () => {
27
+ const Component = attrs({ name: 'TestComponent', component: BaseComponent })
28
28
  expect(Component).toBeDefined()
29
29
  expect(Component.IS_ATTRS).toBe(true)
30
- expect(Component.displayName).toBe("TestComponent")
30
+ expect(Component.displayName).toBe('TestComponent')
31
31
  })
32
32
 
33
- it("should throw when component is missing (dev mode)", () => {
34
- expect(() => attrs({ name: "Test", component: undefined as any })).toThrow()
33
+ it('should throw when component is missing (dev mode)', () => {
34
+ expect(() => attrs({ name: 'Test', component: undefined as any })).toThrow()
35
35
  })
36
36
 
37
- it("should throw when name is missing (dev mode)", () => {
37
+ it('should throw when name is missing (dev mode)', () => {
38
38
  expect(() => attrs({ name: undefined as any, component: BaseComponent })).toThrow()
39
39
  })
40
40
 
41
- it("should render the wrapped component", () => {
42
- const Component = attrs({ name: "Test", component: BaseComponent })
43
- const result = renderProps(Component, { label: "Hello" })
44
- expect(result.label).toBe("Hello")
41
+ it('should render the wrapped component', () => {
42
+ const Component = attrs({ name: 'Test', component: BaseComponent })
43
+ const result = renderProps(Component, { label: 'Hello' })
44
+ expect(result.label).toBe('Hello')
45
45
  })
46
46
 
47
- it("should add data-attrs in development mode", () => {
48
- const Component = attrs({ name: "MyComponent", component: BaseComponent })
47
+ it('should add data-attrs in development mode', () => {
48
+ const Component = attrs({ name: 'MyComponent', component: BaseComponent })
49
49
  const result = renderProps(Component)
50
- expect(result["data-attrs"]).toBe("MyComponent")
50
+ expect(result['data-attrs']).toBe('MyComponent')
51
51
  })
52
52
  })
53
53
 
54
54
  // --------------------------------------------------------
55
55
  // .attrs() chaining
56
56
  // --------------------------------------------------------
57
- describe(".attrs() chaining", () => {
58
- it("should apply default attrs to the component", () => {
57
+ describe('.attrs() chaining', () => {
58
+ it('should apply default attrs to the component', () => {
59
59
  const Component = attrs({
60
- name: "Test",
60
+ name: 'Test',
61
61
  component: BaseComponent,
62
- }).attrs(() => ({ label: "Default Label" }))
62
+ }).attrs(() => ({ label: 'Default Label' }))
63
63
 
64
64
  const result = renderProps(Component)
65
- expect(result.label).toBe("Default Label")
65
+ expect(result.label).toBe('Default Label')
66
66
  })
67
67
 
68
- it("should allow props to override default attrs", () => {
68
+ it('should allow props to override default attrs', () => {
69
69
  const Component = attrs({
70
- name: "Test",
70
+ name: 'Test',
71
71
  component: BaseComponent,
72
- }).attrs(() => ({ label: "Default" }))
72
+ }).attrs(() => ({ label: 'Default' }))
73
73
 
74
- const result = renderProps(Component, { label: "Override" })
75
- expect(result.label).toBe("Override")
74
+ const result = renderProps(Component, { label: 'Override' })
75
+ expect(result.label).toBe('Override')
76
76
  })
77
77
 
78
- it("should support multiple .attrs() chains", () => {
78
+ it('should support multiple .attrs() chains', () => {
79
79
  const Component = attrs({
80
- name: "Test",
80
+ name: 'Test',
81
81
  component: BaseComponent,
82
82
  })
83
- .attrs(() => ({ "data-first": "yes" }))
84
- .attrs(() => ({ "data-second": "yes" }))
83
+ .attrs(() => ({ 'data-first': 'yes' }))
84
+ .attrs(() => ({ 'data-second': 'yes' }))
85
85
 
86
86
  const result = renderProps(Component)
87
- expect(result["data-first"]).toBe("yes")
88
- expect(result["data-second"]).toBe("yes")
87
+ expect(result['data-first']).toBe('yes')
88
+ expect(result['data-second']).toBe('yes')
89
89
  })
90
90
 
91
- it("should pass current props to attrs callback", () => {
91
+ it('should pass current props to attrs callback', () => {
92
92
  const Component = attrs({
93
- name: "Test",
93
+ name: 'Test',
94
94
  component: BaseComponent,
95
95
  }).attrs((props: any) => ({
96
- "data-variant": props.variant === "primary" ? "is-primary" : "is-default",
96
+ 'data-variant': props.variant === 'primary' ? 'is-primary' : 'is-default',
97
97
  }))
98
98
 
99
- const result = renderProps(Component, { variant: "primary" })
100
- expect(result["data-variant"]).toBe("is-primary")
99
+ const result = renderProps(Component, { variant: 'primary' })
100
+ expect(result['data-variant']).toBe('is-primary')
101
101
  })
102
102
 
103
- it("should support object-based attrs", () => {
103
+ it('should support object-based attrs', () => {
104
104
  const Component = attrs({
105
- name: "Test",
105
+ name: 'Test',
106
106
  component: BaseComponent,
107
- }).attrs({ label: "Static Label" })
107
+ }).attrs({ label: 'Static Label' })
108
108
 
109
109
  const result = renderProps(Component)
110
- expect(result.label).toBe("Static Label")
110
+ expect(result.label).toBe('Static Label')
111
111
  })
112
112
 
113
- it("should support priority attrs", () => {
113
+ it('should support priority attrs', () => {
114
114
  const Component = attrs({
115
- name: "Test",
115
+ name: 'Test',
116
116
  component: BaseComponent,
117
117
  })
118
- .attrs(() => ({ label: "Normal" }))
119
- .attrs(() => ({ label: "Priority" }), { priority: true })
118
+ .attrs(() => ({ label: 'Normal' }))
119
+ .attrs(() => ({ label: 'Priority' }), { priority: true })
120
120
 
121
121
  // Priority attrs have lower precedence than normal attrs
122
122
  const result = renderProps(Component)
123
- expect(result.label).toBe("Normal")
123
+ expect(result.label).toBe('Normal')
124
124
  })
125
125
 
126
- it("should support filter option to remove attrs from final props", () => {
126
+ it('should support filter option to remove attrs from final props', () => {
127
127
  const Component = attrs({
128
- name: "Test",
128
+ name: 'Test',
129
129
  component: BaseComponent,
130
- }).attrs(() => ({ label: "Visible" }), {
131
- filter: ["data-internal"],
130
+ }).attrs(() => ({ label: 'Visible' }), {
131
+ filter: ['data-internal'],
132
132
  })
133
133
 
134
134
  const result = renderProps(Component, {
135
- "data-internal": "secret",
136
- label: "test",
135
+ 'data-internal': 'secret',
136
+ label: 'test',
137
137
  })
138
- expect(result["data-internal"]).toBeUndefined()
138
+ expect(result['data-internal']).toBeUndefined()
139
139
  })
140
140
  })
141
141
 
142
142
  // --------------------------------------------------------
143
143
  // .config() chaining
144
144
  // --------------------------------------------------------
145
- describe(".config() chaining", () => {
146
- it("should return a new component instance", () => {
147
- const Original = attrs({ name: "Test", component: BaseComponent })
145
+ describe('.config() chaining', () => {
146
+ it('should return a new component instance', () => {
147
+ const Original = attrs({ name: 'Test', component: BaseComponent })
148
148
  const Configured = Original.config({})
149
149
  expect(Configured).not.toBe(Original)
150
150
  expect(Configured.IS_ATTRS).toBe(true)
151
151
  })
152
152
 
153
- it("should update displayName when name is changed", () => {
154
- const Original = attrs({ name: "Original", component: BaseComponent })
155
- const Renamed = Original.config({ name: "Renamed" })
156
- expect(Renamed.displayName).toBe("Renamed")
157
- expect(Original.displayName).toBe("Original")
153
+ it('should update displayName when name is changed', () => {
154
+ const Original = attrs({ name: 'Original', component: BaseComponent })
155
+ const Renamed = Original.config({ name: 'Renamed' })
156
+ expect(Renamed.displayName).toBe('Renamed')
157
+ expect(Original.displayName).toBe('Original')
158
158
  })
159
159
 
160
- it("should swap the rendered component", () => {
160
+ it('should swap the rendered component', () => {
161
161
  const AltComponent = (props: any) => ({
162
- type: "span",
163
- props: { ...props, "data-testid": "alt" },
162
+ type: 'span',
163
+ props: { ...props, 'data-testid': 'alt' },
164
164
  children: props.label,
165
165
  key: null,
166
166
  })
167
167
 
168
- const Original = attrs({ name: "Test", component: BaseComponent })
168
+ const Original = attrs({ name: 'Test', component: BaseComponent })
169
169
  const Swapped = Original.config({ component: AltComponent })
170
170
 
171
- const result = Swapped({ label: "swapped" }) as any
172
- expect(result.props["data-testid"]).toBe("alt")
173
- expect(result.children).toBe("swapped")
171
+ const result = Swapped({ label: 'swapped' }) as any
172
+ expect(result.props['data-testid']).toBe('alt')
173
+ expect(result.children).toBe('swapped')
174
174
  })
175
175
 
176
- it("should preserve attrs chain after config swap", () => {
176
+ it('should preserve attrs chain after config swap', () => {
177
177
  const AltComponent = (props: any) => ({
178
- type: "span",
179
- props: { ...props, "data-testid": "alt" },
178
+ type: 'span',
179
+ props: { ...props, 'data-testid': 'alt' },
180
180
  children: props.label,
181
181
  key: null,
182
182
  })
183
183
 
184
- const Component = attrs({ name: "Test", component: BaseComponent })
185
- .attrs(() => ({ label: "from-attrs" }))
184
+ const Component = attrs({ name: 'Test', component: BaseComponent })
185
+ .attrs(() => ({ label: 'from-attrs' }))
186
186
  .config({ component: AltComponent })
187
187
 
188
188
  const result = Component({}) as any
189
- expect(result.children).toBe("from-attrs")
189
+ expect(result.children).toBe('from-attrs')
190
190
  })
191
191
  })
192
192
 
193
193
  // --------------------------------------------------------
194
194
  // .statics() chaining
195
195
  // --------------------------------------------------------
196
- describe(".statics() chaining", () => {
197
- it("should assign statics to component meta", () => {
196
+ describe('.statics() chaining', () => {
197
+ it('should assign statics to component meta', () => {
198
198
  const Component = attrs({
199
- name: "Test",
199
+ name: 'Test',
200
200
  component: BaseComponent,
201
- }).statics({ theme: "dark", sizes: ["sm", "md", "lg"] })
201
+ }).statics({ theme: 'dark', sizes: ['sm', 'md', 'lg'] })
202
202
 
203
203
  expect(Component.meta).toEqual({
204
- theme: "dark",
205
- sizes: ["sm", "md", "lg"],
204
+ theme: 'dark',
205
+ sizes: ['sm', 'md', 'lg'],
206
206
  })
207
207
  })
208
208
 
209
- it("should merge statics across chains", () => {
209
+ it('should merge statics across chains', () => {
210
210
  const Component = attrs({
211
- name: "Test",
211
+ name: 'Test',
212
212
  component: BaseComponent,
213
213
  })
214
- .statics({ theme: "dark" })
215
- .statics({ variant: "primary" })
214
+ .statics({ theme: 'dark' })
215
+ .statics({ variant: 'primary' })
216
216
 
217
217
  expect(Component.meta).toEqual({
218
- theme: "dark",
219
- variant: "primary",
218
+ theme: 'dark',
219
+ variant: 'primary',
220
220
  })
221
221
  })
222
222
  })
@@ -224,132 +224,132 @@ describe(".statics() chaining", () => {
224
224
  // --------------------------------------------------------
225
225
  // .compose() chaining
226
226
  // --------------------------------------------------------
227
- describe(".compose() chaining", () => {
228
- it("should wrap component with a HOC", () => {
227
+ describe('.compose() chaining', () => {
228
+ it('should wrap component with a HOC', () => {
229
229
  const withWrapper = (WrappedComponent: any) => (props: any) => ({
230
- type: "div",
231
- props: { "data-testid": "hoc-wrapper" },
230
+ type: 'div',
231
+ props: { 'data-testid': 'hoc-wrapper' },
232
232
  children: WrappedComponent(props),
233
233
  key: null,
234
234
  })
235
235
 
236
236
  const Component = attrs({
237
- name: "Test",
237
+ name: 'Test',
238
238
  component: BaseComponent,
239
239
  }).compose({ withWrapper })
240
240
 
241
- const result = Component({ label: "composed" }) as any
242
- expect(result.props["data-testid"]).toBe("hoc-wrapper")
243
- expect(result.children.children).toBe("composed")
241
+ const result = Component({ label: 'composed' }) as any
242
+ expect(result.props['data-testid']).toBe('hoc-wrapper')
243
+ expect(result.children.children).toBe('composed')
244
244
  })
245
245
 
246
- it("should apply multiple HOCs in correct order", () => {
246
+ it('should apply multiple HOCs in correct order', () => {
247
247
  const order: string[] = []
248
248
 
249
249
  const withOuter = (Wrapped: any) => (props: any) => {
250
- order.push("outer")
250
+ order.push('outer')
251
251
  return Wrapped(props)
252
252
  }
253
253
 
254
254
  const withInner = (Wrapped: any) => (props: any) => {
255
- order.push("inner")
255
+ order.push('inner')
256
256
  return Wrapped(props)
257
257
  }
258
258
 
259
259
  const Component = attrs({
260
- name: "Test",
260
+ name: 'Test',
261
261
  component: BaseComponent,
262
262
  }).compose({ withOuter, withInner })
263
263
 
264
264
  Component({})
265
265
  // calculateHocsFuncs reverses the order: last-defined runs first
266
- expect(order).toEqual(["inner", "outer"])
266
+ expect(order).toEqual(['inner', 'outer'])
267
267
  })
268
268
 
269
- it("should remove a HOC by setting it to false", () => {
269
+ it('should remove a HOC by setting it to false', () => {
270
270
  const withWrapper = (WrappedComponent: any) => (props: any) => ({
271
- type: "div",
272
- props: { "data-testid": "hoc-wrapper" },
271
+ type: 'div',
272
+ props: { 'data-testid': 'hoc-wrapper' },
273
273
  children: WrappedComponent(props),
274
274
  key: null,
275
275
  })
276
276
 
277
277
  const WithHoc = attrs({
278
- name: "Test",
278
+ name: 'Test',
279
279
  component: BaseComponent,
280
280
  }).compose({ withWrapper })
281
281
 
282
282
  const WithoutHoc = WithHoc.compose({ withWrapper: false })
283
283
 
284
- const result = WithoutHoc({ label: "no-hoc" }) as any
284
+ const result = WithoutHoc({ label: 'no-hoc' }) as any
285
285
  // Should render base component directly, no wrapper
286
- expect(result.props["data-testid"]).toBe("base")
287
- expect(result.children).toBe("no-hoc")
286
+ expect(result.props['data-testid']).toBe('base')
287
+ expect(result.children).toBe('no-hoc')
288
288
  })
289
289
  })
290
290
 
291
291
  // --------------------------------------------------------
292
292
  // .getDefaultAttrs()
293
293
  // --------------------------------------------------------
294
- describe(".getDefaultAttrs()", () => {
295
- it("should return computed default attrs for given props", () => {
294
+ describe('.getDefaultAttrs()', () => {
295
+ it('should return computed default attrs for given props', () => {
296
296
  const Component = attrs({
297
- name: "Test",
297
+ name: 'Test',
298
298
  component: BaseComponent,
299
299
  }).attrs((props: any) => ({
300
- computed: props.variant === "primary" ? "blue" : "gray",
300
+ computed: props.variant === 'primary' ? 'blue' : 'gray',
301
301
  }))
302
302
 
303
- const defaults = Component.getDefaultAttrs({ variant: "primary" })
304
- expect(defaults).toEqual({ computed: "blue" })
303
+ const defaults = Component.getDefaultAttrs({ variant: 'primary' })
304
+ expect(defaults).toEqual({ computed: 'blue' })
305
305
  })
306
306
 
307
- it("should return empty object when no attrs defined", () => {
308
- const Component = attrs({ name: "Test", component: BaseComponent })
307
+ it('should return empty object when no attrs defined', () => {
308
+ const Component = attrs({ name: 'Test', component: BaseComponent })
309
309
  const defaults = Component.getDefaultAttrs({})
310
310
  expect(defaults).toEqual({})
311
311
  })
312
312
 
313
- it("should merge multiple attrs chains", () => {
313
+ it('should merge multiple attrs chains', () => {
314
314
  const Component = attrs({
315
- name: "Test",
315
+ name: 'Test',
316
316
  component: BaseComponent,
317
317
  })
318
- .attrs(() => ({ color: "blue" }))
319
- .attrs(() => ({ size: "lg" }))
318
+ .attrs(() => ({ color: 'blue' }))
319
+ .attrs(() => ({ size: 'lg' }))
320
320
 
321
321
  const defaults = Component.getDefaultAttrs({})
322
- expect(defaults).toEqual({ color: "blue", size: "lg" })
322
+ expect(defaults).toEqual({ color: 'blue', size: 'lg' })
323
323
  })
324
324
  })
325
325
 
326
326
  // --------------------------------------------------------
327
327
  // isAttrsComponent
328
328
  // --------------------------------------------------------
329
- describe("isAttrsComponent", () => {
330
- it("should return true for attrs components", () => {
331
- const Component = attrs({ name: "Test", component: BaseComponent })
329
+ describe('isAttrsComponent', () => {
330
+ it('should return true for attrs components', () => {
331
+ const Component = attrs({ name: 'Test', component: BaseComponent })
332
332
  expect(isAttrsComponent(Component)).toBe(true)
333
333
  })
334
334
 
335
- it("should return false for plain components", () => {
335
+ it('should return false for plain components', () => {
336
336
  expect(isAttrsComponent(BaseComponent)).toBe(false)
337
337
  })
338
338
 
339
- it("should return false for null", () => {
339
+ it('should return false for null', () => {
340
340
  expect(isAttrsComponent(null)).toBe(false)
341
341
  })
342
342
 
343
- it("should return false for undefined", () => {
343
+ it('should return false for undefined', () => {
344
344
  expect(isAttrsComponent(undefined)).toBe(false)
345
345
  })
346
346
 
347
- it("should return false for non-objects", () => {
348
- expect(isAttrsComponent("string")).toBe(false)
347
+ it('should return false for non-objects', () => {
348
+ expect(isAttrsComponent('string')).toBe(false)
349
349
  expect(isAttrsComponent(123)).toBe(false)
350
350
  })
351
351
 
352
- it("should return true for objects with IS_ATTRS property", () => {
352
+ it('should return true for objects with IS_ATTRS property', () => {
353
353
  expect(isAttrsComponent({ IS_ATTRS: true })).toBe(true)
354
354
  })
355
355
  })
@@ -357,15 +357,15 @@ describe("isAttrsComponent", () => {
357
357
  // --------------------------------------------------------
358
358
  // displayName fallback
359
359
  // --------------------------------------------------------
360
- describe("displayName resolution", () => {
361
- it("should fall back to component.displayName when name is not provided", () => {
360
+ describe('displayName resolution', () => {
361
+ it('should fall back to component.displayName when name is not provided', () => {
362
362
  const NamedComponent = (props: any) => ({
363
- type: "div",
363
+ type: 'div',
364
364
  props,
365
365
  children: props.children,
366
366
  key: null,
367
367
  })
368
- NamedComponent.displayName = "MyDisplayName"
368
+ NamedComponent.displayName = 'MyDisplayName'
369
369
 
370
370
  const Component = attrsComponent({
371
371
  name: undefined as any,
@@ -376,13 +376,13 @@ describe("displayName resolution", () => {
376
376
  compose: {},
377
377
  statics: {},
378
378
  })
379
- expect(Component.displayName).toBe("MyDisplayName")
379
+ expect(Component.displayName).toBe('MyDisplayName')
380
380
  })
381
381
 
382
- it("should fall back to component.name when name and displayName are not provided", () => {
382
+ it('should fall back to component.name when name and displayName are not provided', () => {
383
383
  function ExplicitNameComponent(props: any) {
384
384
  return {
385
- type: "div",
385
+ type: 'div',
386
386
  props,
387
387
  children: props.children,
388
388
  key: null,
@@ -398,16 +398,16 @@ describe("displayName resolution", () => {
398
398
  compose: {},
399
399
  statics: {},
400
400
  })
401
- expect(Component.displayName).toBe("ExplicitNameComponent")
401
+ expect(Component.displayName).toBe('ExplicitNameComponent')
402
402
  })
403
403
  })
404
404
 
405
405
  // --------------------------------------------------------
406
406
  // Ref as normal prop
407
407
  // --------------------------------------------------------
408
- describe("ref passthrough", () => {
409
- it("should pass ref as a normal prop through the chain", () => {
410
- const Component = attrs({ name: "Test", component: BaseComponent })
408
+ describe('ref passthrough', () => {
409
+ it('should pass ref as a normal prop through the chain', () => {
410
+ const Component = attrs({ name: 'Test', component: BaseComponent })
411
411
  const refObj = { current: null }
412
412
 
413
413
  const result = renderProps(Component, { ref: refObj })
@@ -418,10 +418,10 @@ describe("ref passthrough", () => {
418
418
  // --------------------------------------------------------
419
419
  // Immutability
420
420
  // --------------------------------------------------------
421
- describe("immutability", () => {
422
- it("should return new instances on each chain call", () => {
423
- const Base = attrs({ name: "Test", component: BaseComponent })
424
- const WithAttrs = Base.attrs(() => ({ label: "a" }))
421
+ describe('immutability', () => {
422
+ it('should return new instances on each chain call', () => {
423
+ const Base = attrs({ name: 'Test', component: BaseComponent })
424
+ const WithAttrs = Base.attrs(() => ({ label: 'a' }))
425
425
  const WithStatics = Base.statics({ x: 1 })
426
426
 
427
427
  expect(Base).not.toBe(WithAttrs)
@@ -429,60 +429,60 @@ describe("immutability", () => {
429
429
  expect(WithAttrs).not.toBe(WithStatics)
430
430
  })
431
431
 
432
- it("should not affect parent when child is modified", () => {
432
+ it('should not affect parent when child is modified', () => {
433
433
  const Parent = attrs({
434
- name: "Parent",
434
+ name: 'Parent',
435
435
  component: BaseComponent,
436
- }).attrs(() => ({ label: "Parent" }))
436
+ }).attrs(() => ({ label: 'Parent' }))
437
437
 
438
- const Child = Parent.attrs(() => ({ label: "Child" }))
438
+ const Child = Parent.attrs(() => ({ label: 'Child' }))
439
439
 
440
440
  const parentResult = renderProps(Parent)
441
- expect(parentResult.label).toBe("Parent")
441
+ expect(parentResult.label).toBe('Parent')
442
442
 
443
443
  const childResult = renderProps(Child)
444
- expect(childResult.label).toBe("Child")
444
+ expect(childResult.label).toBe('Child')
445
445
  })
446
446
  })
447
447
 
448
448
  // --------------------------------------------------------
449
449
  // Deep chaining
450
450
  // --------------------------------------------------------
451
- describe("deep chaining", () => {
452
- it("should accumulate attrs across 3+ levels", () => {
453
- const Component = attrs({ name: "Test", component: BaseComponent })
454
- .attrs(() => ({ "data-a": "1" }))
455
- .attrs(() => ({ "data-b": "2" }))
456
- .attrs(() => ({ "data-c": "3" }))
451
+ describe('deep chaining', () => {
452
+ it('should accumulate attrs across 3+ levels', () => {
453
+ const Component = attrs({ name: 'Test', component: BaseComponent })
454
+ .attrs(() => ({ 'data-a': '1' }))
455
+ .attrs(() => ({ 'data-b': '2' }))
456
+ .attrs(() => ({ 'data-c': '3' }))
457
457
 
458
458
  const result = renderProps(Component)
459
- expect(result["data-a"]).toBe("1")
460
- expect(result["data-b"]).toBe("2")
461
- expect(result["data-c"]).toBe("3")
459
+ expect(result['data-a']).toBe('1')
460
+ expect(result['data-b']).toBe('2')
461
+ expect(result['data-c']).toBe('3')
462
462
  })
463
463
 
464
- it("should combine attrs, statics, and config in a single chain", () => {
465
- const Component = attrs({ name: "Base", component: BaseComponent })
466
- .attrs(() => ({ label: "hello" }))
467
- .statics({ variant: "primary" })
468
- .config({ name: "FinalName" })
469
- .attrs(() => ({ "data-extra": "yes" }))
464
+ it('should combine attrs, statics, and config in a single chain', () => {
465
+ const Component = attrs({ name: 'Base', component: BaseComponent })
466
+ .attrs(() => ({ label: 'hello' }))
467
+ .statics({ variant: 'primary' })
468
+ .config({ name: 'FinalName' })
469
+ .attrs(() => ({ 'data-extra': 'yes' }))
470
470
 
471
- expect(Component.displayName).toBe("FinalName")
472
- expect(Component.meta).toEqual({ variant: "primary" })
471
+ expect(Component.displayName).toBe('FinalName')
472
+ expect(Component.meta).toEqual({ variant: 'primary' })
473
473
 
474
474
  const result = renderProps(Component)
475
- expect(result.label).toBe("hello")
476
- expect(result["data-extra"]).toBe("yes")
475
+ expect(result.label).toBe('hello')
476
+ expect(result['data-extra']).toBe('yes')
477
477
  })
478
478
 
479
- it("should allow later attrs to override earlier ones", () => {
480
- const Component = attrs({ name: "Test", component: BaseComponent })
481
- .attrs(() => ({ label: "first" }))
482
- .attrs(() => ({ label: "second" }))
483
- .attrs(() => ({ label: "third" }))
479
+ it('should allow later attrs to override earlier ones', () => {
480
+ const Component = attrs({ name: 'Test', component: BaseComponent })
481
+ .attrs(() => ({ label: 'first' }))
482
+ .attrs(() => ({ label: 'second' }))
483
+ .attrs(() => ({ label: 'third' }))
484
484
 
485
485
  const result = renderProps(Component)
486
- expect(result.label).toBe("third")
486
+ expect(result.label).toBe('third')
487
487
  })
488
488
  })