@@ -3,6 +3,8 @@ import { h, render } from "preact";
33import { useMemo } from "preact/hooks" ;
44import { setupRerender } from "preact/test-utils" ;
55
6+ const sleep = ( ms ?: number ) => new Promise ( r => setTimeout ( r , ms ) ) ;
7+
68describe ( "@preact/signals" , ( ) => {
79 let scratch : HTMLDivElement ;
810 let rerender : ( ) => void ;
@@ -146,4 +148,85 @@ describe("@preact/signals", () => {
146148 expect ( scratch . textContent ) . to . equal ( "bar" ) ;
147149 } ) ;
148150 } ) ;
151+
152+ describe ( "prop bindings" , ( ) => {
153+ it ( "should set the initial value of the checked property" , ( ) => {
154+ const s = signal ( true ) ;
155+ // @ts -ignore
156+ render ( h ( "input" , { checked : s } ) , scratch ) ;
157+
158+ expect ( scratch . firstChild ) . to . have . property ( "checked" , true ) ;
159+ expect ( s . value ) . to . equal ( true ) ;
160+ } ) ;
161+
162+ it ( "should update the checked property on change" , ( ) => {
163+ const s = signal ( true ) ;
164+ // @ts -ignore
165+ render ( h ( "input" , { checked : s } ) , scratch ) ;
166+
167+ expect ( scratch . firstChild ) . to . have . property ( "checked" , true ) ;
168+
169+ s . value = false ;
170+
171+ expect ( scratch . firstChild ) . to . have . property ( "checked" , false ) ;
172+ } ) ;
173+
174+ it ( "should update props without re-rendering" , async ( ) => {
175+ const s = signal ( "initial" ) ;
176+ const spy = sinon . spy ( ) ;
177+ function Wrap ( ) {
178+ spy ( ) ;
179+ // @ts -ignore
180+ return h ( "input" , { value : s } ) ;
181+ }
182+ render ( h ( Wrap , { } ) , scratch ) ;
183+ spy . resetHistory ( ) ;
184+
185+ expect ( scratch . firstChild ) . to . have . property ( "value" , "initial" ) ;
186+
187+ s . value = "updated" ;
188+
189+ expect ( scratch . firstChild ) . to . have . property ( "value" , "updated" ) ;
190+
191+ // ensure the component was never re-rendered: (even after a tick)
192+ await sleep ( ) ;
193+ expect ( spy ) . not . to . have . been . called ;
194+
195+ s . value = "second update" ;
196+
197+ expect ( scratch . firstChild ) . to . have . property ( "value" , "second update" ) ;
198+
199+ // ensure the component was never re-rendered: (even after a tick)
200+ await sleep ( ) ;
201+ expect ( spy ) . not . to . have . been . called ;
202+ } ) ;
203+
204+ it ( "should set and update string style property" , async ( ) => {
205+ const style = signal ( "left: 10px" ) ;
206+ const spy = sinon . spy ( ) ;
207+ function Wrap ( ) {
208+ spy ( ) ;
209+ // @ts -ignore
210+ return h ( "div" , { style } ) ;
211+ }
212+ render ( h ( Wrap , { } ) , scratch ) ;
213+ spy . resetHistory ( ) ;
214+
215+ const div = scratch . firstChild as HTMLDivElement ;
216+
217+ expect ( div . style ) . to . have . property ( "left" , "10px" ) ;
218+
219+ // ensure the component was never re-rendered: (even after a tick)
220+ await sleep ( ) ;
221+ expect ( spy ) . not . to . have . been . called ;
222+
223+ style . value = "left: 20px;" ;
224+
225+ expect ( div . style ) . to . have . property ( "left" , "20px" ) ;
226+
227+ // ensure the component was never re-rendered: (even after a tick)
228+ await sleep ( ) ;
229+ expect ( spy ) . not . to . have . been . called ;
230+ } ) ;
231+ } ) ;
149232} ) ;
0 commit comments