@@ -286,4 +286,354 @@ mod tests {
286286 assert_eq ! ( deflated. min_width, 0.0 ) ;
287287 assert_eq ! ( deflated. max_width, 0.0 ) ;
288288 }
289+
290+ // =========================================================================
291+ // Clone and Copy Trait Tests
292+ // =========================================================================
293+
294+ #[ test]
295+ fn test_constraints_clone ( ) {
296+ let c = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
297+ let cloned = c;
298+ assert_eq ! ( c, cloned) ;
299+ }
300+
301+ #[ test]
302+ fn test_constraints_copy ( ) {
303+ let c = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
304+ let copied = c;
305+ // Both should be valid and equal
306+ assert_eq ! ( c. min_width, copied. min_width) ;
307+ assert_eq ! ( c. max_width, copied. max_width) ;
308+ }
309+
310+ // =========================================================================
311+ // Debug Trait Tests
312+ // =========================================================================
313+
314+ #[ test]
315+ fn test_constraints_debug ( ) {
316+ let c = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
317+ let debug = format ! ( "{:?}" , c) ;
318+ assert ! ( debug. contains( "Constraints" ) ) ;
319+ assert ! ( debug. contains( "min_width" ) ) ;
320+ assert ! ( debug. contains( "max_width" ) ) ;
321+ }
322+
323+ // =========================================================================
324+ // PartialEq Tests
325+ // =========================================================================
326+
327+ #[ test]
328+ fn test_constraints_equality ( ) {
329+ let c1 = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
330+ let c2 = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
331+ assert_eq ! ( c1, c2) ;
332+ }
333+
334+ #[ test]
335+ fn test_constraints_inequality_min_width ( ) {
336+ let c1 = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
337+ let c2 = Constraints :: new ( 15.0 , 100.0 , 20.0 , 200.0 ) ;
338+ assert_ne ! ( c1, c2) ;
339+ }
340+
341+ #[ test]
342+ fn test_constraints_inequality_max_width ( ) {
343+ let c1 = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
344+ let c2 = Constraints :: new ( 10.0 , 150.0 , 20.0 , 200.0 ) ;
345+ assert_ne ! ( c1, c2) ;
346+ }
347+
348+ #[ test]
349+ fn test_constraints_inequality_min_height ( ) {
350+ let c1 = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
351+ let c2 = Constraints :: new ( 10.0 , 100.0 , 25.0 , 200.0 ) ;
352+ assert_ne ! ( c1, c2) ;
353+ }
354+
355+ #[ test]
356+ fn test_constraints_inequality_max_height ( ) {
357+ let c1 = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
358+ let c2 = Constraints :: new ( 10.0 , 100.0 , 20.0 , 250.0 ) ;
359+ assert_ne ! ( c1, c2) ;
360+ }
361+
362+ // =========================================================================
363+ // Serialization Tests
364+ // =========================================================================
365+
366+ #[ test]
367+ fn test_constraints_serialize ( ) {
368+ let c = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
369+ let json = serde_json:: to_string ( & c) . unwrap ( ) ;
370+ assert ! ( json. contains( "min_width" ) ) ;
371+ assert ! ( json. contains( "10" ) ) ;
372+ }
373+
374+ #[ test]
375+ fn test_constraints_deserialize ( ) {
376+ let json = r#"{"min_width":10.0,"max_width":100.0,"min_height":20.0,"max_height":200.0}"# ;
377+ let c: Constraints = serde_json:: from_str ( json) . unwrap ( ) ;
378+ assert_eq ! ( c. min_width, 10.0 ) ;
379+ assert_eq ! ( c. max_width, 100.0 ) ;
380+ assert_eq ! ( c. min_height, 20.0 ) ;
381+ assert_eq ! ( c. max_height, 200.0 ) ;
382+ }
383+
384+ #[ test]
385+ fn test_constraints_roundtrip_serialization ( ) {
386+ let original = Constraints :: new ( 15.5 , 150.5 , 25.5 , 250.5 ) ;
387+ let json = serde_json:: to_string ( & original) . unwrap ( ) ;
388+ let deserialized: Constraints = serde_json:: from_str ( & json) . unwrap ( ) ;
389+ assert_eq ! ( original, deserialized) ;
390+ }
391+
392+ // =========================================================================
393+ // Constrain Edge Cases
394+ // =========================================================================
395+
396+ #[ test]
397+ fn test_constrain_at_minimum ( ) {
398+ let c = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
399+ let size = Size :: new ( 10.0 , 20.0 ) ;
400+ assert_eq ! ( c. constrain( size) , size) ;
401+ }
402+
403+ #[ test]
404+ fn test_constrain_at_maximum ( ) {
405+ let c = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
406+ let size = Size :: new ( 100.0 , 200.0 ) ;
407+ assert_eq ! ( c. constrain( size) , size) ;
408+ }
409+
410+ #[ test]
411+ fn test_constrain_zero_size ( ) {
412+ let c = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
413+ let size = Size :: new ( 0.0 , 0.0 ) ;
414+ assert_eq ! ( c. constrain( size) , Size :: new( 10.0 , 20.0 ) ) ;
415+ }
416+
417+ #[ test]
418+ fn test_constrain_negative_clamped ( ) {
419+ let c = Constraints :: new ( 0.0 , 100.0 , 0.0 , 100.0 ) ;
420+ let size = Size :: new ( -10.0 , -20.0 ) ;
421+ assert_eq ! ( c. constrain( size) , Size :: new( 0.0 , 0.0 ) ) ;
422+ }
423+
424+ #[ test]
425+ fn test_constrain_with_zero_constraints ( ) {
426+ let c = Constraints :: new ( 0.0 , 0.0 , 0.0 , 0.0 ) ;
427+ let size = Size :: new ( 100.0 , 100.0 ) ;
428+ assert_eq ! ( c. constrain( size) , Size :: new( 0.0 , 0.0 ) ) ;
429+ }
430+
431+ // =========================================================================
432+ // is_tight Edge Cases
433+ // =========================================================================
434+
435+ #[ test]
436+ fn test_is_tight_width_only ( ) {
437+ let c = Constraints :: new ( 50.0 , 50.0 , 0.0 , 100.0 ) ;
438+ assert ! ( !c. is_tight( ) ) ; // Height is not tight
439+ }
440+
441+ #[ test]
442+ fn test_is_tight_height_only ( ) {
443+ let c = Constraints :: new ( 0.0 , 100.0 , 50.0 , 50.0 ) ;
444+ assert ! ( !c. is_tight( ) ) ; // Width is not tight
445+ }
446+
447+ #[ test]
448+ fn test_is_tight_zero_size ( ) {
449+ let c = Constraints :: tight ( Size :: new ( 0.0 , 0.0 ) ) ;
450+ assert ! ( c. is_tight( ) ) ;
451+ }
452+
453+ // =========================================================================
454+ // Bounded Tests
455+ // =========================================================================
456+
457+ #[ test]
458+ fn test_has_bounded_height_only ( ) {
459+ let c = Constraints :: new ( 0.0 , f32:: INFINITY , 0.0 , 100.0 ) ;
460+ assert ! ( !c. has_bounded_width( ) ) ;
461+ assert ! ( c. has_bounded_height( ) ) ;
462+ assert ! ( !c. is_bounded( ) ) ;
463+ }
464+
465+ #[ test]
466+ fn test_has_bounded_width_only ( ) {
467+ let c = Constraints :: new ( 0.0 , 100.0 , 0.0 , f32:: INFINITY ) ;
468+ assert ! ( c. has_bounded_width( ) ) ;
469+ assert ! ( !c. has_bounded_height( ) ) ;
470+ assert ! ( !c. is_bounded( ) ) ;
471+ }
472+
473+ // =========================================================================
474+ // biggest() Edge Cases
475+ // =========================================================================
476+
477+ #[ test]
478+ fn test_biggest_with_infinity_width_only ( ) {
479+ let c = Constraints :: new ( 50.0 , f32:: INFINITY , 0.0 , 100.0 ) ;
480+ let biggest = c. biggest ( ) ;
481+ assert_eq ! ( biggest. width, 50.0 ) ; // Falls back to min
482+ assert_eq ! ( biggest. height, 100.0 ) ;
483+ }
484+
485+ #[ test]
486+ fn test_biggest_with_infinity_height_only ( ) {
487+ let c = Constraints :: new ( 0.0 , 100.0 , 50.0 , f32:: INFINITY ) ;
488+ let biggest = c. biggest ( ) ;
489+ assert_eq ! ( biggest. width, 100.0 ) ;
490+ assert_eq ! ( biggest. height, 50.0 ) ; // Falls back to min
491+ }
492+
493+ #[ test]
494+ fn test_biggest_tight_constraints ( ) {
495+ let c = Constraints :: tight ( Size :: new ( 42.0 , 24.0 ) ) ;
496+ assert_eq ! ( c. biggest( ) , Size :: new( 42.0 , 24.0 ) ) ;
497+ }
498+
499+ // =========================================================================
500+ // smallest() Tests
501+ // =========================================================================
502+
503+ #[ test]
504+ fn test_smallest_unbounded ( ) {
505+ let c = Constraints :: unbounded ( ) ;
506+ assert_eq ! ( c. smallest( ) , Size :: new( 0.0 , 0.0 ) ) ;
507+ }
508+
509+ #[ test]
510+ fn test_smallest_tight ( ) {
511+ let c = Constraints :: tight ( Size :: new ( 42.0 , 24.0 ) ) ;
512+ assert_eq ! ( c. smallest( ) , Size :: new( 42.0 , 24.0 ) ) ;
513+ }
514+
515+ #[ test]
516+ fn test_smallest_loose ( ) {
517+ let c = Constraints :: loose ( Size :: new ( 100.0 , 200.0 ) ) ;
518+ assert_eq ! ( c. smallest( ) , Size :: new( 0.0 , 0.0 ) ) ;
519+ }
520+
521+ // =========================================================================
522+ // with_* Methods Chain Tests
523+ // =========================================================================
524+
525+ #[ test]
526+ fn test_with_methods_chained ( ) {
527+ let c = Constraints :: unbounded ( )
528+ . with_min_width ( 10.0 )
529+ . with_max_width ( 100.0 )
530+ . with_min_height ( 20.0 )
531+ . with_max_height ( 200.0 ) ;
532+
533+ assert_eq ! ( c. min_width, 10.0 ) ;
534+ assert_eq ! ( c. max_width, 100.0 ) ;
535+ assert_eq ! ( c. min_height, 20.0 ) ;
536+ assert_eq ! ( c. max_height, 200.0 ) ;
537+ }
538+
539+ #[ test]
540+ fn test_with_methods_preserve_other_values ( ) {
541+ let c = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
542+
543+ let c2 = c. with_min_width ( 15.0 ) ;
544+ assert_eq ! ( c2. max_width, 100.0 ) ;
545+ assert_eq ! ( c2. min_height, 20.0 ) ;
546+ assert_eq ! ( c2. max_height, 200.0 ) ;
547+
548+ let c3 = c. with_max_width ( 150.0 ) ;
549+ assert_eq ! ( c3. min_width, 10.0 ) ;
550+ assert_eq ! ( c3. min_height, 20.0 ) ;
551+ assert_eq ! ( c3. max_height, 200.0 ) ;
552+ }
553+
554+ // =========================================================================
555+ // deflate() Edge Cases
556+ // =========================================================================
557+
558+ #[ test]
559+ fn test_deflate_asymmetric ( ) {
560+ let c = Constraints :: new ( 20.0 , 100.0 , 30.0 , 150.0 ) ;
561+ let deflated = c. deflate ( 10.0 , 20.0 ) ;
562+ assert_eq ! ( deflated. min_width, 10.0 ) ;
563+ assert_eq ! ( deflated. max_width, 90.0 ) ;
564+ assert_eq ! ( deflated. min_height, 10.0 ) ;
565+ assert_eq ! ( deflated. max_height, 130.0 ) ;
566+ }
567+
568+ #[ test]
569+ fn test_deflate_zero ( ) {
570+ let c = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
571+ let deflated = c. deflate ( 0.0 , 0.0 ) ;
572+ assert_eq ! ( c, deflated) ;
573+ }
574+
575+ #[ test]
576+ fn test_deflate_exact_match ( ) {
577+ let c = Constraints :: new ( 10.0 , 100.0 , 20.0 , 200.0 ) ;
578+ let deflated = c. deflate ( 10.0 , 20.0 ) ;
579+ assert_eq ! ( deflated. min_width, 0.0 ) ;
580+ assert_eq ! ( deflated. max_width, 90.0 ) ;
581+ assert_eq ! ( deflated. min_height, 0.0 ) ;
582+ assert_eq ! ( deflated. max_height, 180.0 ) ;
583+ }
584+
585+ #[ test]
586+ fn test_deflate_negative_becomes_zero ( ) {
587+ let c = Constraints :: new ( 5.0 , 10.0 , 5.0 , 10.0 ) ;
588+ let deflated = c. deflate ( 15.0 , 15.0 ) ;
589+ assert_eq ! ( deflated. min_width, 0.0 ) ;
590+ assert_eq ! ( deflated. max_width, 0.0 ) ;
591+ assert_eq ! ( deflated. min_height, 0.0 ) ;
592+ assert_eq ! ( deflated. max_height, 0.0 ) ;
593+ }
594+
595+ // =========================================================================
596+ // Constructor Edge Cases
597+ // =========================================================================
598+
599+ #[ test]
600+ fn test_new_with_zero_values ( ) {
601+ let c = Constraints :: new ( 0.0 , 0.0 , 0.0 , 0.0 ) ;
602+ assert_eq ! ( c. min_width, 0.0 ) ;
603+ assert_eq ! ( c. max_width, 0.0 ) ;
604+ assert ! ( c. is_tight( ) ) ;
605+ }
606+
607+ #[ test]
608+ fn test_tight_with_large_values ( ) {
609+ let c = Constraints :: tight ( Size :: new ( 10000.0 , 10000.0 ) ) ;
610+ assert ! ( c. is_tight( ) ) ;
611+ assert_eq ! ( c. biggest( ) , Size :: new( 10000.0 , 10000.0 ) ) ;
612+ }
613+
614+ #[ test]
615+ fn test_loose_with_zero ( ) {
616+ let c = Constraints :: loose ( Size :: new ( 0.0 , 0.0 ) ) ;
617+ assert ! ( c. is_tight( ) ) ; // min and max are both 0
618+ assert_eq ! ( c. biggest( ) , Size :: new( 0.0 , 0.0 ) ) ;
619+ }
620+
621+ // =========================================================================
622+ // Default Trait Tests
623+ // =========================================================================
624+
625+ #[ test]
626+ fn test_default_is_unbounded ( ) {
627+ let default = Constraints :: default ( ) ;
628+ let unbounded = Constraints :: unbounded ( ) ;
629+ assert_eq ! ( default , unbounded) ;
630+ }
631+
632+ #[ test]
633+ fn test_default_not_bounded ( ) {
634+ let c = Constraints :: default ( ) ;
635+ assert ! ( !c. is_bounded( ) ) ;
636+ assert ! ( !c. has_bounded_width( ) ) ;
637+ assert ! ( !c. has_bounded_height( ) ) ;
638+ }
289639}
0 commit comments