@@ -128,6 +128,57 @@ test.describe('live templates', () => {
128128 await expect . poll ( ( ) => find ( '[data-live-template] span' ) . textContent ( ) ) . toBe ( 'from script' )
129129 } )
130130
131+ test ( 'loop variables are captured and available in _= handlers' , async ( { html, find, page, run} ) => {
132+ await run ( "set $captureItems to [{name:'Alice'},{name:'Bob'},{name:'Charlie'}]" )
133+ await html ( `
134+ <script type="text/hypertemplate" live>
135+ <ul>
136+ #for item in $captureItems index i
137+ <li _="on click put item.name into me">${ "\x24" } {item.name}</li>
138+ #end
139+ </ul>
140+ </script>
141+ ` )
142+ await expect . poll ( ( ) => find ( '[data-live-template] li' ) . count ( ) ) . toBe ( 3 )
143+ await find ( '[data-live-template] li' ) . nth ( 1 ) . click ( )
144+ await expect ( find ( '[data-live-template] li' ) . nth ( 1 ) ) . toHaveText ( 'Bob' )
145+ } )
146+
147+ test ( 'loop index variable is captured alongside loop variable' , async ( { html, find, run} ) => {
148+ await run ( "set $idxItems to ['A','B','C']" )
149+ await html ( `
150+ <script type="text/hypertemplate" live>
151+ <ul>
152+ #for item in $idxItems index i
153+ <li _="on click put i + ':' + item into me">${ "\x24" } {item}</li>
154+ #end
155+ </ul>
156+ </script>
157+ ` )
158+ await expect . poll ( ( ) => find ( '[data-live-template] li' ) . count ( ) ) . toBe ( 3 )
159+ await find ( '[data-live-template] li' ) . nth ( 1 ) . click ( )
160+ await expect ( find ( '[data-live-template] li' ) . nth ( 1 ) ) . toHaveText ( '1:B' )
161+ } )
162+
163+ test ( 'loop variable capture works with remove for live list' , async ( { html, find, page, run} ) => {
164+ await run ( "set $removeItems to [{name:'A'},{name:'B'},{name:'C'}]" )
165+ await html ( `
166+ <script type="text/hypertemplate" live>
167+ <ul>
168+ #for item in $removeItems
169+ <li><span>${ "\x24" } {item.name}</span><button _="on click remove item from $removeItems">x</button></li>
170+ #end
171+ </ul>
172+ </script>
173+ ` )
174+ await expect . poll ( ( ) => find ( '[data-live-template] li' ) . count ( ) ) . toBe ( 3 )
175+ // Remove the middle item "B"
176+ await find ( '[data-live-template] li' ) . nth ( 1 ) . locator ( 'button' ) . click ( )
177+ await expect . poll ( ( ) => find ( '[data-live-template] li' ) . count ( ) ) . toBe ( 2 )
178+ await expect ( find ( '[data-live-template] li' ) . first ( ) . locator ( 'span' ) ) . toHaveText ( 'A' )
179+ await expect ( find ( '[data-live-template] li' ) . last ( ) . locator ( 'span' ) ) . toHaveText ( 'C' )
180+ } )
181+
131182 test ( 'script-based live template preserves ${} in bare attribute position' , async ( { html, find, page} ) => {
132183 await html ( `
133184 <script type="text/hypertemplate" live _="init set ^items to [{text:'A', done:true},{text:'B', done:false}]">
@@ -143,10 +194,10 @@ test.describe('live templates', () => {
143194 ` )
144195 await expect . poll ( ( ) => find ( '[data-live-template] li' ) . count ( ) ) . toBe ( 2 )
145196 var firstChecked = await page . evaluate ( ( ) =>
146- document . querySelector ( '[data-live-template] li:nth-child(1) input' ) . checked )
197+ document . querySelector ( '[data-live-template] li:first-of-type input' ) . checked )
147198 expect ( firstChecked ) . toBe ( true )
148199 var secondChecked = await page . evaluate ( ( ) =>
149- document . querySelector ( '[data-live-template] li:nth-child(2) input' ) . checked )
200+ document . querySelector ( '[data-live-template] li:last-of-type input' ) . checked )
150201 expect ( secondChecked ) . toBe ( false )
151202 await expect ( find ( '[data-live-template] li' ) . first ( ) ) . toHaveClass ( / d o n e / )
152203 await expect ( find ( '[data-live-template] li' ) . last ( ) ) . not . toHaveClass ( / d o n e / )
0 commit comments