ripple 0.3.61 → 0.3.63

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.
@@ -503,6 +503,108 @@ describe('tsx expression', () => {
503
503
  expect(button.querySelector('.btn-label').textContent).toBe('Save');
504
504
  });
505
505
 
506
+ it('renders deeply nested tsx and tsrx expression values', () => {
507
+ function makeFragment(label: string) {
508
+ return <tsrx>
509
+ <span class="label">{label}</span>
510
+ const test = <tsx>
511
+ {[1, 2, 3, 4].map(
512
+ (item) => <tsx>
513
+ {<tsrx>
514
+ <div class="helper-item">{item}</div>
515
+ </tsrx>}
516
+ </tsx>,
517
+ )}
518
+ </tsx>;
519
+ {test}
520
+ </tsrx>;
521
+ }
522
+
523
+ component App() {
524
+ {<tsx>{[1, 2, 3].map((item) => <div class="app-item">{item}</div>)}</tsx>}
525
+ {makeFragment('from helper')}
526
+ }
527
+
528
+ render(App);
529
+
530
+ expect(
531
+ Array.from(container.querySelectorAll('.app-item')).map((node) => node.textContent),
532
+ ).toEqual([
533
+ '1',
534
+ '2',
535
+ '3',
536
+ ]);
537
+ expect(container.querySelector('.label').textContent).toBe('from helper');
538
+ expect(
539
+ Array.from(container.querySelectorAll('.helper-item')).map((node) => node.textContent),
540
+ ).toEqual(['1', '2', '3', '4']);
541
+ });
542
+
543
+ it('renders tsrx nested directly inside a top-level tsx expression value', () => {
544
+ component App() {
545
+ const content = <tsx>
546
+ <section class="outer">
547
+ {<tsrx>
548
+ <div class="inner">{'from tsrx'}</div>
549
+ </tsrx>}
550
+ </section>
551
+ </tsx>;
552
+
553
+ {content}
554
+ }
555
+
556
+ render(App);
557
+
558
+ const outer = container.querySelector('.outer');
559
+ expect(outer).toBeTruthy();
560
+ expect(outer.querySelector('.inner').textContent).toBe('from tsrx');
561
+ });
562
+
563
+ it('renders nested elements from tsrx inside a top-level tsx value', () => {
564
+ component App() {
565
+ const content = <tsx>
566
+ <div class="wrapper">
567
+ {<tsrx>
568
+ <section class="native">
569
+ <span class="nested-tsrx">{'inside nested tsrx'}</span>
570
+ </section>
571
+ </tsrx>}
572
+ </div>
573
+ </tsx>;
574
+
575
+ {content}
576
+ }
577
+
578
+ render(App);
579
+
580
+ const native = container.querySelector('.native');
581
+ expect(native).toBeTruthy();
582
+ expect(native.querySelector('.nested-tsrx').textContent).toBe('inside nested tsrx');
583
+ });
584
+
585
+ it('renders tsx declared inside tsrx nested from a top-level tsx value', () => {
586
+ component App() {
587
+ const content = <tsx>
588
+ {<tsrx>
589
+ const nested = <tsx>
590
+ <span class="nested-tsx">
591
+ {'inside nested tsx'}
592
+ </span>
593
+ </tsx>;
594
+ <div class="native">{nested}</div>
595
+ </tsrx>}
596
+ </tsx>;
597
+
598
+ {content}
599
+ }
600
+
601
+ render(App);
602
+
603
+ const native = container.querySelector('.native');
604
+ expect(native).toBeTruthy();
605
+ expect(native.querySelector('.nested-tsx').textContent).toBe('inside nested tsx');
606
+ });
607
+
506
608
  it('renders tsx as prop with fallback in component', () => {
507
609
  component Alert(&{ icon, message }: { icon?: any; message: string }) {
508
610
  <div class="alert">
@@ -60,6 +60,133 @@ describe('hydration > basic', () => {
60
60
  expect(container.innerHTML).toBeHtml('<div>42</div><span>COMPUTED</span>');
61
61
  });
62
62
 
63
+ it('hydrates deeply nested tsx and tsrx expression values', async () => {
64
+ await hydrateComponent(
65
+ ServerComponents.NestedTsxTsrxExpressionValues,
66
+ ClientComponents.NestedTsxTsrxExpressionValues,
67
+ );
68
+
69
+ expect(
70
+ Array.from(container.querySelectorAll('.app-item')).map((node) => node.textContent),
71
+ ).toEqual(['1', '2', '3']);
72
+ expect(container.querySelector('.label')?.textContent).toBe('from helper');
73
+ expect(
74
+ Array.from(container.querySelectorAll('.helper-item')).map((node) => node.textContent),
75
+ ).toEqual(['1', '2', '3', '4']);
76
+ });
77
+
78
+ it('hydrates mixed tsrx collection text without duplicating server text', async () => {
79
+ await hydrateComponent(
80
+ ServerComponents.MixedTsrxCollectionText,
81
+ ClientComponents.MixedTsrxCollectionText,
82
+ );
83
+
84
+ const collection = container.querySelector('.mixed-collection');
85
+ expect(collection?.textContent).toBe('alpha beta gamma delta epsilon zeta');
86
+ expect(collection?.querySelector('.middle')?.textContent).toBe('beta');
87
+ expect(collection?.querySelector('.tail')?.textContent).toBe('epsilon');
88
+ });
89
+
90
+ it('hydrates split mixed collection text when the client updates a coalesced server text segment', async () => {
91
+ await hydrateComponent(
92
+ ServerComponents.MixedTsrxCollectionSplitServerText,
93
+ ClientComponents.MixedTsrxCollectionSplitClientText,
94
+ );
95
+
96
+ const collection = container.querySelector('.mixed-collection-split');
97
+ expect(collection?.textContent).toBe('alpha beta gamma changed epsilon zeta');
98
+ expect(collection?.querySelector('.middle')?.textContent).toBe('beta');
99
+ expect(collection?.querySelector('.tail')?.textContent).toBe('epsilon');
100
+ });
101
+
102
+ it('hydrates primitive mixed collection text with client/server text differences', async () => {
103
+ await hydrateComponent(
104
+ ServerComponents.MixedTsrxCollectionPrimitiveServerText,
105
+ ClientComponents.MixedTsrxCollectionPrimitiveClientText,
106
+ );
107
+
108
+ const collection = container.querySelector('.mixed-collection-primitive');
109
+ expect(collection?.textContent).toBe('count: 2 / false ok');
110
+ expect(collection?.querySelector('.primitive-tail')?.textContent).toBe(' ok');
111
+ });
112
+
113
+ it('hydrates dynamic array values returned from calls without comma stringification', async () => {
114
+ await hydrateComponent(
115
+ ServerComponents.DynamicArrayFromCall,
116
+ ClientComponents.DynamicArrayFromCall,
117
+ );
118
+
119
+ expect(container.querySelector('.dynamic-array-call')?.textContent).toBe(
120
+ 'start:one2truefalse:end',
121
+ );
122
+ });
123
+
124
+ it('hydrates dynamic array values from tracked state without comma stringification', async () => {
125
+ await hydrateComponent(
126
+ ServerComponents.DynamicArrayFromTrack,
127
+ ClientComponents.DynamicArrayFromTrack,
128
+ );
129
+
130
+ expect(container.querySelector('.dynamic-array-track')?.textContent).toBe(
131
+ 'start:one2truefalse:end',
132
+ );
133
+ });
134
+
135
+ it('hydrates dynamic array values from conditionals without comma stringification', async () => {
136
+ await hydrateComponent(
137
+ ServerComponents.DynamicArrayFromConditional,
138
+ ClientComponents.DynamicArrayFromConditional,
139
+ );
140
+
141
+ expect(container.querySelector('.dynamic-array-conditional')?.textContent).toBe(
142
+ 'start:one2truefalse:end',
143
+ );
144
+ });
145
+
146
+ it('hydrates dynamic array values from logical expressions without comma stringification', async () => {
147
+ await hydrateComponent(
148
+ ServerComponents.DynamicArrayFromLogical,
149
+ ClientComponents.DynamicArrayFromLogical,
150
+ );
151
+
152
+ expect(container.querySelector('.dynamic-array-logical')?.textContent).toBe(
153
+ 'start:one2truefalse:end',
154
+ );
155
+ });
156
+
157
+ it('hydrates tsrx nested directly inside a top-level tsx expression value', async () => {
158
+ await hydrateComponent(
159
+ ServerComponents.NestedTsrxInsideTopLevelTsxExpression,
160
+ ClientComponents.NestedTsrxInsideTopLevelTsxExpression,
161
+ );
162
+
163
+ const outer = container.querySelector('.outer');
164
+ expect(outer).toBeTruthy();
165
+ expect(outer?.querySelector('.inner')?.textContent).toBe('from tsrx');
166
+ });
167
+
168
+ it('hydrates nested elements from tsrx inside a top-level tsx value', async () => {
169
+ await hydrateComponent(
170
+ ServerComponents.NestedTsrxElementsInsideTopLevelTsxValue,
171
+ ClientComponents.NestedTsrxElementsInsideTopLevelTsxValue,
172
+ );
173
+
174
+ const native = container.querySelector('.native');
175
+ expect(native).toBeTruthy();
176
+ expect(native?.querySelector('.nested-tsrx')?.textContent).toBe('inside nested tsrx');
177
+ });
178
+
179
+ it('hydrates tsx declared inside tsrx nested from a top-level tsx value', async () => {
180
+ await hydrateComponent(
181
+ ServerComponents.TsxDeclaredInsideNestedTsrxFromTopLevelTsx,
182
+ ClientComponents.TsxDeclaredInsideNestedTsrxFromTopLevelTsx,
183
+ );
184
+
185
+ const native = container.querySelector('.native');
186
+ expect(native).toBeTruthy();
187
+ expect(native?.querySelector('.nested-tsx')?.textContent).toBe('inside nested tsx');
188
+ });
189
+
63
190
  it('restores text children after hydrating away initial server text', async () => {
64
191
  await hydrateComponent(
65
192
  ServerComponents.TextPropWithToggle,