import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:ocideck/models/chart.dart'; import 'package:ocideck/models/slide.dart'; import 'package:ocideck/widgets/editors/chart_editor.dart'; Widget _host( Slide slide, ValueChanged onUpdate, { ValueChanged>? onAddVariants, }) { return MaterialApp( home: Scaffold( body: SizedBox( width: 900, height: 650, child: ChartEditor( slide: slide, onUpdate: onUpdate, onAddVariants: onAddVariants, ), ), ), ); } void main() { testWidgets('chart grid fills the available editor width', (tester) async { const spec = ChartSpec( x: ['A', 'B'], series: [ ChartSeries(name: 'Waarde', data: [10, 20]), ], ); final slide = Slide.create( SlideType.chart, ).copyWith(customMarkdown: spec.toBlock()); await tester.pumpWidget(_host(slide, (_) {})); await tester.pump(); final gridWidth = tester .getSize(find.byKey(const ValueKey('chart-grid'))) .width; expect(gridWidth, greaterThanOrEqualTo(760)); expect(tester.takeException(), isNull); }); testWidgets('moving a row keeps its values and color together', ( tester, ) async { const spec = ChartSpec( x: ['B', 'A'], rowColors: ['#EF4444', '#10B981'], series: [ ChartSeries(name: 'Waarde', data: [20, 10]), ], ); var updated = Slide.create( SlideType.chart, ).copyWith(customMarkdown: spec.toBlock()); await tester.pumpWidget(_host(updated, (slide) => updated = slide)); await tester.tap(find.byKey(const ValueKey('chart-row-up-1'))); await tester.pump(); final result = ChartSpec.parse(updated.customMarkdown); expect(result.x, ['A', 'B']); expect(result.rowColors, ['#10B981', '#EF4444']); expect(result.series.single.data, [10, 20]); }); testWidgets('sorting a value column moves complete rows', (tester) async { const spec = ChartSpec( x: ['A', 'B', 'C'], rowColors: ['#003399', '#FFCC00', '#EF4444'], series: [ ChartSeries(name: 'Waarde', data: [30, 10, 20]), ], ); var updated = Slide.create( SlideType.chart, ).copyWith(customMarkdown: spec.toBlock()); await tester.pumpWidget(_host(updated, (slide) => updated = slide)); await tester.tap(find.byKey(const ValueKey('chart-sort-0'))); await tester.pumpAndSettle(); await tester.tap(find.text('Oplopend sorteren')); await tester.pump(); final result = ChartSpec.parse(updated.customMarkdown); expect(result.x, ['B', 'C', 'A']); expect(result.rowColors, ['#FFCC00', '#EF4444', '#003399']); expect(result.series.single.data, [10, 20, 30]); }); testWidgets('pie dims the third series without disabling its input', ( tester, ) async { const spec = ChartSpec( type: ChartType.pie, x: ['A'], series: [ ChartSeries(name: 'Een', data: [1]), ChartSeries(name: 'Twee', data: [2]), ChartSeries(name: 'Drie', data: [3]), ], ); final slide = Slide.create( SlideType.chart, ).copyWith(customMarkdown: spec.toBlock()); await tester.pumpWidget(_host(slide, (_) {})); await tester.pump(); final column = tester.widget( find.byKey(const ValueKey('chart-series-column-2')), ); expect(column.color, const Color(0xFFE2E8F0)); final input = tester.widget( find.byKey(const ValueKey('v-0-0-2')), ); expect(input.enabled, isTrue); expect(tester.takeException(), isNull); }); testWidgets('bound fields are offered for bar/line and emit min/max', ( tester, ) async { const spec = ChartSpec( type: ChartType.bar, x: ['A'], series: [ ChartSeries(name: 'Waarde', data: [10]), ], ); var updated = Slide.create( SlideType.chart, ).copyWith(customMarkdown: spec.toBlock()); await tester.pumpWidget(_host(updated, (slide) => updated = slide)); await tester.pump(); expect(find.byKey(const ValueKey('chart-min-bound')), findsOneWidget); expect(find.byKey(const ValueKey('chart-max-bound')), findsOneWidget); await tester.enterText(find.byKey(const ValueKey('chart-max-bound')), '20'); await tester.pump(); expect(ChartSpec.parse(updated.customMarkdown).maxBound, 20); }); testWidgets('bound fields are hidden for a pie chart', (tester) async { const spec = ChartSpec( type: ChartType.pie, x: ['A'], series: [ ChartSeries(name: 'Een', data: [1]), ], ); final slide = Slide.create( SlideType.chart, ).copyWith(customMarkdown: spec.toBlock()); await tester.pumpWidget(_host(slide, (_) {})); await tester.pump(); expect(find.byKey(const ValueKey('chart-min-bound')), findsNothing); expect(find.byKey(const ValueKey('chart-max-bound')), findsNothing); }); testWidgets('chart variants reuse data in the chosen order', (tester) async { const spec = ChartSpec( type: ChartType.bar, title: 'Omzet', x: ['A', 'B'], series: [ ChartSeries(name: 'Waarde', data: [10, 20], color: '#003399'), ], ); final slide = Slide.create( SlideType.chart, ).copyWith(customMarkdown: spec.toBlock()); List? variants; await tester.pumpWidget( _host(slide, (_) {}, onAddVariants: (value) => variants = value), ); await tester.tap(find.byKey(const ValueKey('chart-create-variants'))); await tester.pumpAndSettle(); await tester.tap(find.byKey(const ValueKey('chart-variant-down-0'))); await tester.pump(); await tester.tap(find.text('Slides toevoegen')); await tester.pump(); final specs = variants!.map((s) => ChartSpec.parse(s.customMarkdown)); expect(specs.map((s) => s.type), [ ChartType.pie, ChartType.line, ChartType.radar, ]); expect(specs.first.x, ['A', 'B']); expect(specs.first.series.single.data, [10, 20]); expect(specs.first.series.single.color, '#003399'); }); }