@@ -4,20 +4,26 @@ import 'package:fl_chart/fl_chart.dart';
44import  'package:fl_chart/src/chart/line_chart/line_chart_curve.dart' ;
55import  'package:flutter_test/flutter_test.dart' ;
66
7- void  expectLikeStraightLine (
8-   LineChartCurve  curve, {
9-   Offset  point0 =  Offset .zero,
10-   Offset  point1 =  const  Offset (10 , 10 ),
11- }) {
12-   final  path =  Path ()..moveTo (point0.dx, point0.dy);
13-   curve.appendToPath (path, point0, point1, null );
14- 
15-   final  metrics =  path.computeMetrics ().toList ();
16-   expect (metrics.length, 1 );
17-   expect (metrics.single.length, closeTo (point1.distanceTo (point0), 0.001 ));
18- }
7+ const  samplePoints1 =  [
8+   Offset (10 , 10 ),
9+   Offset (20 , 20 ),
10+   Offset (30 , 40 ),
11+   Offset (40 , 10 ),
12+ ];
1913
2014void  main () {
15+   test ('static constructor' , () {
16+     expect (LineChartCurve .noCurve, equals (const  LineChartNoCurve ()));
17+     expect (
18+       LineChartCurve .cubicTension (),
19+       equals (const  LineChartCubicTensionCurve ()),
20+     );
21+     expect (
22+       LineChartCurve .cubicMonotone (),
23+       equals (const  LineChartCubicMonotoneCurve ()),
24+     );
25+   });
26+ 
2127  group ('LineChartNoCurve' , () {
2228    test ('equality check' , () {
2329      const  a =  LineChartNoCurve ();
@@ -51,26 +57,59 @@ void main() {
5157      expect (a.hashCode, equals (b.hashCode));
5258    });
5359
54-     test ('no curve case ' , () {
55-       const  curve =  LineChartCubicTensionCurve ();
60+     test ('lerp  no curve' , () {
61+       const  curve =  LineChartCubicTensionCurve (smoothness :   0.8 );
5662
5763      expect (
58-         curve.noCurveCase,
59-         equals (
60-           LineChartCubicTensionCurve (
61-             smoothness:  0 ,
62-             preventCurveOverShooting:  curve.preventCurveOverShooting,
63-             preventCurveOvershootingThreshold: 
64-                 curve.preventCurveOvershootingThreshold,
65-           ),
66-         ),
64+         lerpCurve (curve, const  LineChartNoCurve (), 0.5 ),
65+         equals (const  LineChartCubicTensionCurve (smoothness:  0.4 )),
6766      );
6867    });
6968
7069    test ('CubicTensionCurve with smoothness = 0 behaves like straight line' ,
7170        () {
7271      expectLikeStraightLine (const  LineChartCubicTensionCurve (smoothness:  0 ));
7372    });
73+ 
74+     test (
75+         'prevents overshoot when dy difference is below threshold in y direction' ,
76+         () {
77+       const  curve =  LineChartCubicTensionCurve (
78+         preventCurveOverShooting:  true ,
79+       );
80+ 
81+       // Create points where dy difference is below threshold (5 < 10) 
82+       final  points =  [
83+         Offset .zero,
84+         const  Offset (20 , 5 ), // dy = 5 
85+         const  Offset (40 , 8 ), // dy = 3 
86+       ];
87+ 
88+       final  path =  _buildPathWithCurve (points, curve);
89+ 
90+       final  metrics =  path.computeMetrics ().toList ();
91+       expect (metrics.length, 1 );
92+     });
93+ 
94+     test (
95+         'prevents overshoot when dx difference is below threshold in x direction' ,
96+         () {
97+       const  curve =  LineChartCubicTensionCurve (
98+         preventCurveOverShooting:  true ,
99+       );
100+ 
101+       // Create points where dx difference is below threshold (5 < 10) 
102+       final  points =  [
103+         Offset .zero,
104+         const  Offset (5 , 20 ), // dx = 5 
105+         const  Offset (8 , 40 ), // dx = 3 
106+       ];
107+ 
108+       final  path =  _buildPathWithCurve (points, curve);
109+ 
110+       final  metrics =  path.computeMetrics ().toList ();
111+       expect (metrics.length, 1 );
112+     });
74113  });
75114
76115  group ('LineChartCubicMonotoneCurve' , () {
@@ -82,122 +121,98 @@ void main() {
82121      expect (a.hashCode, equals (b.hashCode));
83122    });
84123
85-     test ('no curve case ' , () {
86-       const  curve =  LineChartCubicMonotoneCurve ();
124+     test ('lerp  no curve' , () {
125+       const  curve =  LineChartCubicMonotoneCurve (smooth :   0.8 );
87126
88127      expect (
89-         curve.noCurveCase,
90-         equals (
91-           LineChartCubicMonotoneCurve (
92-             smooth:  0 ,
93-             monotone:  curve.monotone,
94-             tinyThresholdSquared:  curve.tinyThresholdSquared,
95-           ),
96-         ),
128+         lerpCurve (const  LineChartNoCurve (), curve, 0.5 ),
129+         equals (const  LineChartCubicMonotoneCurve (smooth:  0.4 )),
97130      );
98131    });
99132
100-     group ('smooth parameter behavior' , () {
101-       test ('smooth = 0 produces straight line' , () {
102-         expectLikeStraightLine (
103-           const  LineChartCubicMonotoneCurve (smooth:  0 ),
104-         );
105-       });
106- 
107-       test ('smooth = 0.3 produces curved line shorter than smooth = 0.7' , () {
108-         final  points =  [
109-           Offset .zero,
110-           const  Offset (10 , 10 ),
111-           const  Offset (20 , 5 ),
112-           const  Offset (30 , 15 ),
113-         ];
114- 
115-         final  path1 =  _buildPathWithCurve (
116-           points,
117-           const  LineChartCubicMonotoneCurve (smooth:  0.3 ),
118-         );
119-         final  path2 =  _buildPathWithCurve (
120-           points,
121-           const  LineChartCubicMonotoneCurve (smooth:  0.7 ),
122-         );
123- 
124-         final  metrics1 =  path1.computeMetrics ().toList ();
125-         final  metrics2 =  path2.computeMetrics ().toList ();
133+     test ('draw straight line if just two points' , () {
134+       expectLikeStraightLine (
135+         const  LineChartCubicMonotoneCurve (tinyThresholdSquared:  0 ),
136+         points:  [Offset .zero, const  Offset (10 , 10 )],
137+       );
138+     });
126139
127-         expect (metrics1.length, 1 );
128-         expect (metrics2.length, 1 );
140+     test ('draw straight line if smooth = 0' , () {
141+       expectLikeStraightLine (
142+         const  LineChartCubicMonotoneCurve (
143+           smooth:  0 ,
144+           tinyThresholdSquared:  double .infinity,
145+         ),
146+       );
147+     });
129148
130-         // Higher smooth value should produce longer curved path 
131-         expect (
132-           metrics2.single.length,
133-           greaterThan (metrics1.single.length),
149+     group ('tinyThreshold parameter behavior' , () {
150+       test ('draw straight line if distance < tinyThreshold' , () {
151+         expectLikeStraightLine (
152+           const  LineChartCubicMonotoneCurve (
153+             tinyThresholdSquared:  double .infinity,
154+           ),
134155        );
135156      });
136157
137-       test ('smooth = 1.0 produces maximum smoothness' , () {
138-         final  points =  [
139-           Offset .zero,
140-           const  Offset (10 , 10 ),
141-           const  Offset (20 , 5 ),
142-         ];
143- 
158+       test ('draw curved line if distance > tinyThreshold' , () {
144159        final  path =  _buildPathWithCurve (
145-           points ,
146-           const  LineChartCubicMonotoneCurve (smooth :   1 ),
160+           samplePoints1 ,
161+           const  LineChartCubicMonotoneCurve (tinyThresholdSquared :   0 ),
147162        );
148163
149164        final  metrics =  path.computeMetrics ().toList ();
150-         expect (metrics.length, 1 );
151-         // Curved path should be longer than straight line 
165+ 
152166        expect (
153167          metrics.single.length,
154-           greaterThan (
155-             points[0 ].distanceTo (points[1 ]) +  points[1 ].distanceTo (points[2 ]),
156-           ),
168+           greaterThan (samplePoints1.straightDistance),
157169        );
158170      });
159171    });
160172
161-     group ('state management (_flag)' , () {
162-       test ('flag resets after last point' , () {
163-         final  points =  [
164-           Offset .zero,
165-           const  Offset (10 , 10 ),
166-           const  Offset (20 , 5 ),
167-         ];
168- 
169-         // First path 
170-         final  path1 =  _buildPathWithCurve (
171-           points,
172-           const  LineChartCubicMonotoneCurve (),
173-         );
174- 
175-         // Second path should not be affected by first path's flag 
176-         final  path2 =  _buildPathWithCurve (
177-           points,
178-           const  LineChartCubicMonotoneCurve (),
179-         );
180- 
181-         final  metrics1 =  path1.computeMetrics ().toList ();
182-         final  metrics2 =  path2.computeMetrics ().toList ();
183- 
184-         // Both paths should have identical length 
185-         expect (
186-           metrics1.single.length,
187-           closeTo (metrics2.single.length, 0.001 ),
188-         );
173+     group ('smooth parameter behavior' , () {
174+       test ('the effect of smooth increases monotonically' , () {
175+         var  smoothCount =  1 ;
176+         var  lastCurveLength =  samplePoints1.straightDistance;
177+ 
178+         while  (smoothCount <  11 ) {
179+           final  smooth =  0.1  *  smoothCount;
180+ 
181+           final  path =  _buildPathWithCurve (
182+             samplePoints1,
183+             LineChartCubicMonotoneCurve (
184+               smooth:  smooth,
185+               tinyThresholdSquared:  0 ,
186+             ),
187+           );
188+           final  curveLength =  path.computeMetrics ().single.length;
189+           expect (curveLength, greaterThanOrEqualTo (lastCurveLength));
190+           lastCurveLength =  curveLength;
191+           smoothCount++ ;
192+         }
189193      });
190194    });
191195  });
192196}
193197
198+ void  expectLikeStraightLine (
199+   LineChartCurve  curve, {
200+   List <Offset > points =  samplePoints1,
201+ }) {
202+   final  path =  _buildPathWithCurve (points, curve);
203+ 
204+   final  metrics =  path.computeMetrics ().toList ();
205+   expect (metrics.single.length, closeTo (points.straightDistance, 0.001 ));
206+ }
207+ 
194208/// Helper function to build a complete path with the given curve 
195209Path  _buildPathWithCurve (List <Offset > points, LineChartCurve  curve) {
210+   final  path =  Path ();
196211  if  (points.isEmpty) {
197-     return  Path () ;
212+     return  path ;
198213  }
199214
200-   final   path  =   Path (). .moveTo (points[0 ].dx, points[0 ].dy);
215+   path.moveTo (points[0 ].dx, points[0 ].dy);
201216
202217  for  (var  i =  1 ; i <  points.length; i++ ) {
203218    final  previous =  points[i -  1 ];
@@ -213,3 +228,13 @@ Path _buildPathWithCurve(List<Offset> points, LineChartCurve curve) {
213228extension  on  Offset  {
214229  double  distanceTo (Offset  other) =>  (this  -  other).distance;
215230}
231+ 
232+ extension  on  List <Offset > {
233+   double  get  straightDistance {
234+     double  distance =  0 ;
235+     for  (var  i =  1 ; i <  length; i++ ) {
236+       distance +=  this [i].distanceTo (this [i -  1 ]);
237+     }
238+     return  distance;
239+   }
240+ }
0 commit comments