Unverified Commit e3a03c04 authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

Merge branch 'master' into master

parents 64749826 4676c66b
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'dart:ui';
import 'package:flutter/cupertino.dart';
......@@ -823,43 +822,6 @@ void main() {
);
});
testWidgets('DatePicker golden tests', (WidgetTester tester) async {
await tester.pumpWidget(
CupertinoApp(
home: Center(
child: SizedBox(
width: 400,
height: 400,
child: RepaintBoundary(
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.dateAndTime,
initialDateTime: DateTime(2019, 1, 1, 4),
onDateTimeChanged: (_) {},
),
)
),
)
)
);
await expectLater(
find.byType(CupertinoDatePicker),
matchesGoldenFile('date_picker_test.datetime.initial.1.png'),
skip: !Platform.isLinux
);
// Slightly drag the hour component to make the current hour off-center.
await tester.drag(find.text('4'), Offset(0, _kRowOffset.dy / 2));
await tester.pump();
await expectLater(
find.byType(CupertinoDatePicker),
matchesGoldenFile('date_picker_test.datetime.drag.1.png'),
skip: !Platform.isLinux
);
});
});
testWidgets('scrollController can be removed or added', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
int lastSelectedItem;
......@@ -933,6 +895,35 @@ void main() {
expect(lastSelectedItem, 1);
handle.dispose();
});
testWidgets('DatePicker golden tests', (WidgetTester tester) async {
await tester.pumpWidget(
CupertinoApp(
home: SizedBox(
width: 200,
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.dateAndTime,
initialDateTime: DateTime(2019, 1, 1, 4),
onDateTimeChanged: (_) {},
)
)
)
);
await expectLater(
find.byType(CupertinoDatePicker),
matchesSkiaGoldFile('date_picker_test.datetime.initial.png'),
);
// Slightly drag the hour component to make the current hour off-center.
await tester.drag(find.text('4'), Offset(0, _kRowOffset.dy / 2));
await tester.pump();
await expectLater(
find.byType(CupertinoDatePicker),
matchesSkiaGoldFile('date_picker_test.datetime.drag.png'),
);
});
}
Widget _buildPicker({ FixedExtentScrollController controller, ValueChanged<int> onSelectedItemChanged }) {
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
......@@ -801,12 +799,9 @@ void main() {
await expectLater(
find.byType(RepaintBoundary).last,
matchesGoldenFile('nav_bar_test.standard_title.1.png'),
matchesSkiaGoldFile('nav_bar_test.standard_title.png'),
);
},
// TODO(xster): remove once https://github.com/flutter/flutter/issues/17483
// is fixed.
skip: !Platform.isLinux,
);
testWidgets(
......@@ -835,13 +830,10 @@ void main() {
await expectLater(
find.byType(RepaintBoundary).last,
matchesGoldenFile('nav_bar_test.large_title.1.png'),
matchesSkiaGoldFile('nav_bar_test.large_title.png'),
);
},
// TODO(xster): remove once https://github.com/flutter/flutter/issues/17483
// is fixed.
skip: !Platform.isLinux,
);
);
testWidgets('NavBar draws a light system bar for a dark background', (WidgetTester tester) async {
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:flutter/widgets.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -1327,9 +1325,9 @@ void main() {
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('segmented_control_test.0.0.png'),
matchesSkiaGoldFile('segmented_control_test.0.png'),
);
}, skip: !Platform.isLinux);
});
testWidgets('Golden Test Pressed State', (WidgetTester tester) async {
final Map<int, Widget> children = <int, Widget>{};
......@@ -1365,7 +1363,7 @@ void main() {
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('segmented_control_test.1.0.png'),
matchesSkiaGoldFile('segmented_control_test.1.png'),
);
}, skip: !Platform.isLinux);
});
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
......@@ -73,15 +71,15 @@ void main() {
await pump(FloatingActionButtonLocation.endDocked);
await expectLater(
find.byKey(key),
matchesGoldenFile('bottom_app_bar.custom_shape.1.png'),
matchesSkiaGoldFile('bottom_app_bar.custom_shape.1.png'),
);
await pump(FloatingActionButtonLocation.centerDocked);
await tester.pumpAndSettle();
await expectLater(
find.byKey(key),
matchesGoldenFile('bottom_app_bar.custom_shape.2.png'),
matchesSkiaGoldFile('bottom_app_bar.custom_shape.2.png'),
);
}, skip: !Platform.isLinux);
});
testWidgets('color defaults to Theme.bottomAppBarColor', (WidgetTester tester) async {
await tester.pumpWidget(
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -82,8 +80,7 @@ void main() {
await expectLater(
find.byKey(_painterKey),
matchesGoldenFile('bottom_app_bar_theme.custom_shape.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('bottom_app_bar_theme.custom_shape.png'),
);
});
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'dart:ui';
import 'package:flutter/material.dart';
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -139,8 +137,7 @@ void main() {
await expectLater(
find.byKey(painterKey),
matchesGoldenFile('card_theme.custom_shape.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('card_theme.custom_shape.png'),
);
});
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -132,8 +130,7 @@ void main() {
await expectLater(
find.byKey(_painterKey),
matchesGoldenFile('dialog_theme.dialog_with_custom_border.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('dialog_theme.dialog_with_custom_border.png'),
);
});
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'dart:math' as math;
import 'dart:ui' show window;
......@@ -141,8 +140,7 @@ void main() {
assert(tester.renderObject(buttonFinder).attached);
await expectLater(
find.ancestor(of: buttonFinder, matching: find.byType(RepaintBoundary)).first,
matchesGoldenFile('dropdown_test.default.0.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('dropdown_test.default.png'),
);
});
......@@ -154,8 +152,7 @@ void main() {
assert(tester.renderObject(buttonFinder).attached);
await expectLater(
find.ancestor(of: buttonFinder, matching: find.byType(RepaintBoundary)).first,
matchesGoldenFile('dropdown_test.expanded.0.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('dropdown_test.expanded.png'),
);
});
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'dart:ui';
import 'package:flutter/material.dart';
......@@ -681,8 +680,7 @@ void main() {
await tester.pump(const Duration(milliseconds: 1000));
await expectLater(
find.byKey(key),
matchesGoldenFile('floating_action_button_test.clip.2.png'), // .clip.1.png is obsolete and can be removed
skip: !Platform.isLinux,
matchesSkiaGoldFile('floating_action_button_test.clip.png'),
);
});
......
......@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
......@@ -2020,19 +2019,15 @@ void main() {
await tester.pumpWidget(buildFrame(TextDirection.ltr));
await expectLater(
find.byType(InputDecorator),
matchesGoldenFile('input_decorator.outline_icon_label.ltr.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('input_decorator.outline_icon_label.ltr.png'),
);
await tester.pumpWidget(buildFrame(TextDirection.rtl));
await expectLater(
find.byType(InputDecorator),
matchesGoldenFile('input_decorator.outline_icon_label.rtl.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('input_decorator.outline_icon_label.rtl.png'),
);
},
skip: !Platform.isLinux,
);
});
testWidgets('InputDecorationTheme.toString()', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/19305
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/rendering.dart';
......@@ -618,8 +616,7 @@ void main() {
await expectLater(
find.byKey(painterKey),
matchesGoldenFile('material.border_paint_above.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('material.border_paint_above.png'),
);
});
......@@ -659,8 +656,7 @@ void main() {
await expectLater(
find.byKey(painterKey),
matchesGoldenFile('material.border_paint_below.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('material.border_paint_below.png'),
);
});
});
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'dart:ui';
import 'package:flutter/rendering.dart';
......@@ -277,8 +276,7 @@ void main() {
await tester.pumpAndSettle();
await expectLater(
find.byKey(painterKey),
matchesGoldenFile('radio.ink_ripple.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('radio.ink_ripple.png'),
);
});
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -269,8 +267,7 @@ void main() {
await expectLater(
find.byKey(_painterKey),
matchesGoldenFile('tab_bar_theme.tab_indicator_size_tab.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('tab_bar_theme.tab_indicator_size_tab.png'),
);
});
......@@ -281,8 +278,7 @@ void main() {
await expectLater(
find.byKey(_painterKey),
matchesGoldenFile('tab_bar_theme.tab_indicator_size_label.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('tab_bar_theme.tab_indicator_size_label.png'),
);
});
......@@ -298,8 +294,7 @@ void main() {
await expectLater(
find.byKey(_painterKey),
matchesGoldenFile('tab_bar_theme.custom_tab_indicator.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('tab_bar_theme.custom_tab_indicator.png'),
);
});
......@@ -315,8 +310,7 @@ void main() {
await expectLater(
find.byKey(_painterKey),
matchesGoldenFile('tab_bar_theme.beveled_rect_indicator.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('tab_bar_theme.beveled_rect_indicator.png'),
);
});
}
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -72,8 +71,7 @@ void main() {
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('continuous_rectangle_border.golden_test_even_radii.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('continuous_rectangle_border.golden_test_even_radii.png'),
);
});
......@@ -94,8 +92,7 @@ void main() {
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('continuous_rectangle_border.golden_test_varying_radii.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('continuous_rectangle_border.golden_test_varying_radii.png'),
);
});
......@@ -113,8 +110,7 @@ void main() {
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('continuous_rectangle_border.golden_test_large_radii.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('continuous_rectangle_border.golden_test_large_radii.png'),
);
});
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -51,11 +49,9 @@ void main() {
await expectLater(
find.byType(RichText),
matchesGoldenFile('localized_fonts.rich_text.styled_text_span.png'),
matchesSkiaGoldFile('localized_fonts.rich_text.styled_text_span.png'),
);
},
skip: !Platform.isLinux,
);
});
testWidgets(
'Text with locale-specific glyphs, ambient locale',
......@@ -103,11 +99,9 @@ void main() {
await expectLater(
find.byType(Row),
matchesGoldenFile('localized_fonts.text_ambient_locale.chars.png'),
matchesSkiaGoldFile('localized_fonts.text_ambient_locale.chars.png'),
);
},
skip: !Platform.isLinux,
);
});
testWidgets(
'Text with locale-specific glyphs, explicit locale',
......@@ -147,10 +141,8 @@ void main() {
await expectLater(
find.byType(Row),
matchesGoldenFile('localized_fonts.text_explicit_locale.chars.png'),
matchesSkiaGoldFile('localized_fonts.text_explicit_locale.chars.png'),
);
},
skip: !Platform.isLinux,
);
});
}
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'dart:ui';
import 'package:flutter/widgets.dart';
......@@ -43,8 +42,7 @@ void main() {
);
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('backdrop_filter_test.cull_rect.1.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('backdrop_filter_test.cull_rect.png'),
);
});
}
......@@ -356,7 +356,7 @@ void main() {
);
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.ClipRect.1.png'),
matchesSkiaGoldFile('clip.ClipRect.png'),
);
});
......@@ -396,7 +396,7 @@ void main() {
);
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.ClipRectOverlay.1.png'),
matchesSkiaGoldFile('clip.ClipRectOverlay.png'),
);
});
......@@ -445,7 +445,7 @@ void main() {
);
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.ClipRRect.1.png'),
matchesSkiaGoldFile('clip.ClipRRect.png'),
);
});
......@@ -488,7 +488,7 @@ void main() {
);
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.ClipOval.1.png'),
matchesSkiaGoldFile('clip.ClipOval.png'),
);
});
......@@ -536,7 +536,7 @@ void main() {
);
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.ClipPath.1.png'),
matchesSkiaGoldFile('clip.ClipPath.png'),
);
});
......@@ -581,7 +581,7 @@ void main() {
await tester.pumpWidget(genPhysicalModel(Clip.antiAlias));
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.PhysicalModel.antiAlias.1.png'),
matchesSkiaGoldFile('clip.PhysicalModel.antiAlias.png'),
);
});
......@@ -589,7 +589,7 @@ void main() {
await tester.pumpWidget(genPhysicalModel(Clip.hardEdge));
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.PhysicalModel.hardEdge.1.png'),
matchesSkiaGoldFile('clip.PhysicalModel.hardEdge.png'),
);
});
......@@ -599,7 +599,7 @@ void main() {
await tester.pumpWidget(genPhysicalModel(Clip.antiAliasWithSaveLayer));
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.PhysicalModel.antiAliasWithSaveLayer.png'),
matchesSkiaGoldFile('clip.PhysicalModel.antiAliasWithSaveLayer.png'),
);
});
......@@ -641,7 +641,7 @@ void main() {
);
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.PhysicalModel.default.1.png'),
matchesSkiaGoldFile('clip.PhysicalModel.default.png'),
);
});
......@@ -690,7 +690,7 @@ void main() {
await tester.pumpWidget(genPhysicalShape(Clip.antiAlias));
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.PhysicalShape.antiAlias.1.png'),
matchesSkiaGoldFile('clip.PhysicalShape.antiAlias.png'),
);
});
......@@ -698,7 +698,7 @@ void main() {
await tester.pumpWidget(genPhysicalShape(Clip.hardEdge));
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.PhysicalShape.hardEdge.1.png'),
matchesSkiaGoldFile('clip.PhysicalShape.hardEdge.png'),
);
});
......@@ -706,7 +706,7 @@ void main() {
await tester.pumpWidget(genPhysicalShape(Clip.antiAliasWithSaveLayer));
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.PhysicalShape.antiAliasWithSaveLayer.png'),
matchesSkiaGoldFile('clip.PhysicalShape.antiAliasWithSaveLayer.png'),
);
});
......@@ -752,7 +752,7 @@ void main() {
);
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('clip.PhysicalShape.default.1.png'),
matchesSkiaGoldFile('clip.PhysicalShape.default.png'),
);
});
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -92,9 +90,9 @@ void main() {
await expectLater(
find.byKey(const ValueKey<int>(1)),
matchesGoldenFile('editable_text_test.0.3.png'),
matchesSkiaGoldFile('editable_text_test.0.png'),
);
}, skip: !Platform.isLinux);
});
testWidgets('cursor layout has correct radius', (WidgetTester tester) async {
final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
......@@ -143,9 +141,9 @@ void main() {
await expectLater(
find.byKey(const ValueKey<int>(1)),
matchesGoldenFile('editable_text_test.1.3.png'),
matchesSkiaGoldFile('editable_text_test.1.png'),
);
}, skip: !Platform.isLinux);
});
testWidgets('Cursor animates on iOS', (WidgetTester tester) async {
final Widget widget = MaterialApp(
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -22,8 +20,7 @@ void main() {
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('invert_colors_test.0.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('invert_colors_test.0.png'),
);
});
......@@ -41,8 +38,7 @@ void main() {
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('invert_colors_test.1.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('invert_colors_test.1.png'),
);
});
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
......@@ -537,8 +535,7 @@ void main() {
await expectLater(
find.byKey(const Key('list_wheel_scroll_view')),
matchesGoldenFile('list_wheel_scroll_view.center_child.magnified.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('list_wheel_scroll_view.center_child.magnified.png'),
);
});
......@@ -592,8 +589,7 @@ void main() {
await expectLater(
find.byKey(const Key('list_wheel_scroll_view')),
matchesGoldenFile('list_wheel_scroll_view.curved_wheel.left.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('list_wheel_scroll_view.curved_wheel.left.png'),
);
});
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
......@@ -179,8 +177,7 @@ void main() {
);
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('opacity_test.offset.1.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('opacity_test.offset.png'),
);
});
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'dart:math' as math show pi;
import 'package:flutter/material.dart';
......@@ -111,8 +110,7 @@ void main() {
expect(exception.diagnostics.first.toString(), startsWith('A RenderFlex overflowed by '));
await expectLater(
find.byKey(key),
matchesGoldenFile('physical_model_overflow.png'),
skip: !Platform.isLinux,
matchesSkiaGoldFile('physical_model_overflow.png'),
);
});
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
......@@ -25,18 +23,15 @@ void main() {
);
await expectLater(
find.byType(Container),
matchesGoldenFile('shadow.BoxDecoration.disabled.png'),
matchesSkiaGoldFile('shadow.BoxDecoration.disabled.png'),
);
debugDisableShadows = false;
tester.binding.reassembleApplication();
await tester.pump();
if (Platform.isLinux) {
// TODO(ianh): use the skip argument instead once that doesn't hang, https://github.com/dart-lang/test/issues/830
await expectLater(
find.byType(Container),
matchesGoldenFile('shadow.BoxDecoration.enabled.png'),
); // shadows render differently on different platforms
}
await expectLater(
find.byType(Container),
matchesSkiaGoldFile('shadow.BoxDecoration.enabled.png'),
);
debugDisableShadows = true;
});
......@@ -61,11 +56,11 @@ void main() {
await tester.pumpWidget(build(elevation));
await expectLater(
find.byType(Container),
matchesGoldenFile('shadow.ShapeDecoration.$elevation.png'),
matchesSkiaGoldFile('shadow.ShapeDecoration.$elevation.png'),
);
}
debugDisableShadows = true;
}, skip: !Platform.isLinux); // shadows render differently on different platforms
});
testWidgets('Shadows with PhysicalLayer', (WidgetTester tester) async {
await tester.pumpWidget(
......@@ -88,18 +83,15 @@ void main() {
);
await expectLater(
find.byType(Container),
matchesGoldenFile('shadow.PhysicalModel.disabled.png'),
matchesSkiaGoldFile('shadow.PhysicalModel.disabled.0.png'),
);
debugDisableShadows = false;
tester.binding.reassembleApplication();
await tester.pump();
if (Platform.isLinux) {
// TODO(ianh): use the skip argument instead once that doesn't hang, https://github.com/dart-lang/test/issues/830
await expectLater(
find.byType(Container),
matchesGoldenFile('shadow.PhysicalModel.enabled.png'),
); // shadows render differently on different platforms
}
await expectLater(
find.byType(Container),
matchesSkiaGoldFile('shadow.PhysicalModel.enabled.png'),
);
debugDisableShadows = true;
});
......@@ -128,9 +120,9 @@ void main() {
await tester.pumpWidget(build(elevation.toDouble()));
await expectLater(
find.byType(Container),
matchesGoldenFile('shadow.PhysicalShape.$elevation.1.png'),
matchesSkiaGoldFile('shadow.PhysicalModel.disabled.1.$elevation.png'),
);
}
debugDisableShadows = true;
}, skip: !Platform.isLinux); // shadows render differently on different platforms
});
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
......@@ -31,7 +29,7 @@ void main() {
await expectLater(
find.byType(Container),
matchesGoldenFile('text_golden.Centered.png'),
matchesSkiaGoldFile('text_golden.Centered.png'),
);
await tester.pumpWidget(
......@@ -55,9 +53,9 @@ void main() {
await expectLater(
find.byType(Container),
matchesGoldenFile('text_golden.Centered.wrap.png'),
matchesSkiaGoldFile('text_golden.Centered.wrap.png'),
);
}, skip: !Platform.isLinux);
});
testWidgets('Text Foreground', (WidgetTester tester) async {
......@@ -86,7 +84,7 @@ void main() {
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('text_golden.Foreground.gradient.png'),
matchesSkiaGoldFile('text_golden.Foreground.gradient.png'),
);
await tester.pumpWidget(
......@@ -108,7 +106,7 @@ void main() {
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('text_golden.Foreground.stroke.png'),
matchesSkiaGoldFile('text_golden.Foreground.stroke.png'),
);
await tester.pumpWidget(
......@@ -131,9 +129,9 @@ void main() {
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('text_golden.Foreground.stroke_and_gradient.png'),
matchesSkiaGoldFile('text_golden.Foreground.stroke_and_gradient.png'),
);
}, skip: !Platform.isLinux);
});
// TODO(garyq): This test requires an update when the background
// drawing from the beginning of the line bug is fixed. The current
......@@ -181,9 +179,9 @@ void main() {
await expectLater(
find.byType(RepaintBoundary),
matchesGoldenFile('text_golden.Background.png'),
matchesSkiaGoldFile('text_golden.Background.png'),
);
}, skip: !Platform.isLinux);
});
testWidgets('Text Fade', (WidgetTester tester) async {
await tester.pumpWidget(
......@@ -217,9 +215,9 @@ void main() {
await expectLater(
find.byType(RepaintBoundary).first,
matchesGoldenFile('text_golden.Fade.1.png'),
matchesSkiaGoldFile('text_golden.Fade.1.png'),
);
}, skip: !Platform.isLinux);
});
testWidgets('Default Strut text', (WidgetTester tester) async {
await tester.pumpWidget(
......@@ -242,10 +240,9 @@ void main() {
);
await expectLater(
find.byType(Container),
matchesGoldenFile('text_golden.StrutDefault.png'),
matchesSkiaGoldFile('text_golden.StrutDefault.png'),
);
}, skip: true); // Should only be on linux (skip: !Platform.isLinux).
// Disabled for now until font inconsistency is resolved.
});
testWidgets('Strut text 1', (WidgetTester tester) async {
await tester.pumpWidget(
......@@ -270,10 +267,9 @@ void main() {
);
await expectLater(
find.byType(Container),
matchesGoldenFile('text_golden.Strut.1.1.png'),
matchesSkiaGoldFile('text_golden.Strut.1.png'),
);
}, skip: true); // Should only be on linux (skip: !Platform.isLinux).
// Disabled for now until font inconsistency is resolved.
});
testWidgets('Strut text 2', (WidgetTester tester) async {
await tester.pumpWidget(
......@@ -299,10 +295,9 @@ void main() {
);
await expectLater(
find.byType(Container),
matchesGoldenFile('text_golden.Strut.2.1.png'),
matchesSkiaGoldFile('text_golden.Strut.2.png'),
);
}, skip: true); // Should only be on linux (skip: !Platform.isLinux).
// Disabled for now until font inconsistency is resolved.
});
testWidgets('Strut text rich', (WidgetTester tester) async {
await tester.pumpWidget(
......@@ -351,10 +346,9 @@ void main() {
);
await expectLater(
find.byType(Container),
matchesGoldenFile('text_golden.Strut.3.1.png'),
matchesSkiaGoldFile('text_golden.Strut.3.png'),
);
}, skip: true); // Should only be on linux (skip: !Platform.isLinux).
// Disabled for now until font inconsistency is resolved.
});
testWidgets('Strut text font fallback', (WidgetTester tester) async {
// Font Fallback
......@@ -387,10 +381,9 @@ void main() {
);
await expectLater(
find.byType(Container),
matchesGoldenFile('text_golden.Strut.4.1.png'),
matchesSkiaGoldFile('text_golden.Strut.4.png'),
);
}, skip: true); // Should only be on linux (skip: !Platform.isLinux).
// Disabled for now until font inconsistency is resolved.
});
testWidgets('Strut text rich forceStrutHeight', (WidgetTester tester) async {
await tester.pumpWidget(
......@@ -439,10 +432,9 @@ void main() {
);
await expectLater(
find.byType(Container),
matchesGoldenFile('text_golden.StrutForce.1.1.png'),
matchesSkiaGoldFile('text_golden.StrutForce.1.png'),
);
}, skip: true); // Should only be on linux (skip: !Platform.isLinux).
// Disabled for now until font inconsistency is resolved.
});
testWidgets('Decoration thickness', (WidgetTester tester) async {
final TextDecoration allDecorations = TextDecoration.combine(
......@@ -478,9 +470,9 @@ void main() {
);
await expectLater(
find.byType(Container),
matchesGoldenFile('text_golden.Decoration.1.0.png'),
matchesSkiaGoldFile('text_golden.Decoration.1.png'),
);
}, skip: !Platform.isLinux); // Coretext uses different thicknesses for decoration
});
testWidgets('Decoration thickness', (WidgetTester tester) async {
final TextDecoration allDecorations = TextDecoration.combine(
......@@ -517,7 +509,7 @@ void main() {
);
await expectLater(
find.byType(Container),
matchesGoldenFile('text_golden.DecorationThickness.1.0.png'),
matchesSkiaGoldFile('text_golden.DecorationThickness.1.png'),
);
}, skip: !Platform.isLinux); // Coretext uses different thicknesses for decoration
});
}
......@@ -3,16 +3,20 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:meta/meta.dart';
import 'package:test_api/test_api.dart' as test_package show TestFailure;
import 'package:flutter_goldens_client/client.dart';
export 'package:flutter_goldens_client/client.dart';
const String _kFlutterRootKey = 'FLUTTER_ROOT';
/// Main method that can be used in a `flutter_test_config.dart` file to set
/// [goldenFileComparator] to an instance of [FlutterGoldenFileComparator] that
/// works for the current test.
......@@ -25,12 +29,12 @@ Future<void> main(FutureOr<void> testMain()) async {
///
/// Within the https://github.com/flutter/flutter repository, it's important
/// not to check-in binaries in order to keep the size of the repository to a
/// minimum. To satisfy this requirement, this comparator retrieves the golden
/// files from a sibling repository, `flutter/goldens`.
/// minimum. To satisfy this requirement, this comparator uses the
/// [SkiaGoldClient] to upload widgets for framework-related golden tests and
/// process results.
///
/// This comparator will locally clone the `flutter/goldens` repository into
/// the `$FLUTTER_ROOT/bin/cache/pkg/goldens` folder, then perform the comparison against
/// the files therein.
/// This comparator will instantiate the [SkiaGoldClient] and process the
/// results of the test.
class FlutterGoldenFileComparator implements GoldenFileComparator {
/// Creates a [FlutterGoldenFileComparator] that will resolve golden file
/// URIs relative to the specified [basedir].
......@@ -49,48 +53,51 @@ class FlutterGoldenFileComparator implements GoldenFileComparator {
@visibleForTesting
final FileSystem fs;
/// Instance of the [SkiaGoldClient] for executing tests.
final SkiaGoldClient _skiaClient = SkiaGoldClient();
/// Creates a new [FlutterGoldenFileComparator] that mirrors the relative
/// path resolution of the default [goldenFileComparator].
///
/// By the time the future completes, the clone of the `flutter/goldens`
/// repository is guaranteed to be ready use.
///
/// The [goldens] and [defaultComparator] parameters are visible for testing
/// The [defaultComparator] parameter is visible for testing
/// purposes only.
static Future<FlutterGoldenFileComparator> fromDefaultComparator({
GoldensClient goldens,
LocalFileComparator defaultComparator,
}) async {
defaultComparator ??= goldenFileComparator;
// Prepare the goldens repo.
goldens ??= GoldensClient();
await goldens.prepare();
// Calculate the appropriate basedir for the current test context.
final FileSystem fs = goldens.fs;
const FileSystem fs = LocalFileSystem();
final Directory testDirectory = fs.directory(defaultComparator.basedir);
final String testDirectoryRelativePath = fs.path.relative(testDirectory.path, from: goldens.flutterRoot.path);
return FlutterGoldenFileComparator(goldens.repositoryRoot.childDirectory(testDirectoryRelativePath).uri);
final Directory flutterRoot = fs.directory(Platform.environment[_kFlutterRootKey]);
final Directory goldenRoot = flutterRoot.childDirectory(fs.path.join(
'bin',
'cache',
'pkg',
'goldens',
));
final String testDirectoryRelativePath = fs.path.relative(
testDirectory.path,
from: flutterRoot.path,
);
return FlutterGoldenFileComparator(goldenRoot.childDirectory(testDirectoryRelativePath).uri);
}
@override
Future<bool> compare(Uint8List imageBytes, Uri golden) async {
final File goldenFile = _getGoldenFile(golden);
if (!goldenFile.existsSync()) {
throw TestFailure('Could not be compared against non-existent file: "$golden"');
}
final List<int> goldenBytes = await goldenFile.readAsBytes();
// TODO(tvolkert): Improve the intelligence of this comparison.
if (goldenBytes.length != imageBytes.length) {
return false;
if(!goldenFile.existsSync()) {
throw test_package.TestFailure('Could not be compared against non-existent file: "$golden"');
}
for (int i = 0; i < goldenBytes.length; i++) {
if (goldenBytes[i] != imageBytes[i]) {
return false;
}
final bool authorized = await _skiaClient.auth(fs.directory(basedir));
if (!authorized) {
// TODO(Piinks): Clean up for final implementation on CI, https://github.com/flutter/flutter/pull/31630
return true;
//throw test_package.TestFailure('Could not authorize golctl.');
}
return true;
await _skiaClient.imgtestInit();
return await _skiaClient.imgtestAdd(golden.path, goldenFile);
}
@override
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' as io;
import 'dart:typed_data';
import 'package:file/file.dart';
......@@ -14,49 +13,57 @@ import 'package:platform/platform.dart';
import 'package:process/process.dart';
const String _kFlutterRoot = '/flutter';
const String _kRepositoryRoot = '$_kFlutterRoot/bin/cache/pkg/goldens';
const String _kVersionFile = '$_kFlutterRoot/bin/internal/goldens.version';
const String _kGoldensVersion = '123456abcdef';
//const String _kGoldenRoot = '$_kFlutterRoot/bin/cache/pkg/goldens';
//const String _kVersionFile = '$_kFlutterRoot/bin/internal/goldens.version';
//const String _kGoldensVersion = '123456abcdef';
// TODO(Piinks): Finish testing, https://github.com/flutter/flutter/pull/31630
void main() {
MemoryFileSystem fs;
FakePlatform platform;
MockProcessManager process;
//Directory flutter;
//Directory golden;
setUp(() {
setUp(() async {
fs = MemoryFileSystem();
platform = FakePlatform(environment: <String, String>{'FLUTTER_ROOT': _kFlutterRoot});
platform = FakePlatform(environment: <String, String>{
'FLUTTER_ROOT': _kFlutterRoot,
// TODO(Piinks): Add other env vars for testing, https://github.com/flutter/flutter/pull/31630
});
process = MockProcessManager();
fs.directory(_kFlutterRoot).createSync(recursive: true);
fs.directory(_kRepositoryRoot).createSync(recursive: true);
fs.file(_kVersionFile).createSync(recursive: true);
fs.file(_kVersionFile).writeAsStringSync(_kGoldensVersion);
//flutter = await fs.directory(_kFlutterRoot).create(recursive: true);
//golden = await fs.directory(_kGoldenRoot).create(recursive: true);
//fs.file(_kVersionFile).createSync(recursive: true);
//fs.file(_kVersionFile).writeAsStringSync(_kGoldensVersion);
});
group('GoldensClient', () {
GoldensClient goldens;
group('SkiaGoldClient', () {
//SkiaGoldClient skiaGold;
setUp(() {
goldens = GoldensClient(
//skiaGold =
SkiaGoldClient(
fs: fs,
platform: platform,
process: process,
);
});
group('prepare', () {
test('performs minimal work if versions match', () async {
when(process.run(any, workingDirectory: anyNamed('workingDirectory')))
.thenAnswer((_) => Future<io.ProcessResult>.value(io.ProcessResult(123, 0, _kGoldensVersion, '')));
await goldens.prepare();
// Verify that we only spawned `git rev-parse HEAD`
final VerificationResult verifyProcessRun =
verify(process.run(captureAny, workingDirectory: captureAnyNamed('workingDirectory')));
verifyProcessRun.called(1);
expect(verifyProcessRun.captured.first, <String>['git', 'rev-parse', 'HEAD']);
expect(verifyProcessRun.captured.last, _kRepositoryRoot);
});
group('auth', () {
// check for successful auth - return true
// check for unsuccessful auth - throw NonZeroExitCode
// check for unavailable auth (not on CI) - return false
// check for redundant work
});
group('init', () {
// check for successful init - return true
// check for unsuccessful init - throw NonZeroExitCode
// Check for redundant work
});
group('imgtest', () {
});
});
......@@ -74,21 +81,22 @@ void main() {
group('fromDefaultComparator', () {
test('calculates the basedir correctly', () async {
final MockGoldensClient goldens = MockGoldensClient();
final MockLocalFileComparator defaultComparator = MockLocalFileComparator();
final Directory flutterRoot = fs.directory('/foo')..createSync(recursive: true);
final Directory goldensRoot = flutterRoot.childDirectory('bar')..createSync(recursive: true);
when(goldens.fs).thenReturn(fs);
when(goldens.flutterRoot).thenReturn(flutterRoot);
when(goldens.repositoryRoot).thenReturn(goldensRoot);
when(defaultComparator.basedir).thenReturn(flutterRoot.childDirectory('baz').uri);
comparator = await FlutterGoldenFileComparator.fromDefaultComparator(
goldens: goldens, defaultComparator: defaultComparator);
expect(comparator.basedir, fs.directory('/foo/bar/baz').uri);
// final MockSkiaGoldClient skiaGold = MockSkiaGoldClient();
// final MockLocalFileComparator defaultComparator = MockLocalFileComparator();
// final Directory flutterRoot = fs.directory('/foo')..createSync(recursive: true);
// final Directory skiaGoldRoot = flutterRoot.childDirectory('bar')..createSync(recursive: true);
// when(skiaGold.fs).thenReturn(fs);
// when(skiaGold.flutterRoot).thenReturn(flutterRoot);
// when(skiaGold.repositoryRoot).thenReturn(skiaGoldRoot);
// when(defaultComparator.basedir).thenReturn(flutterRoot.childDirectory('baz').uri);
// comparator = await FlutterGoldenFileComparator.fromDefaultComparator(
// goldens: goldens, defaultComparator: defaultComparator);
// expect(comparator.basedir, fs.directory('/foo/bar/baz').uri);
});
});
group('compare', () {
test('throws if golden file is not found', () async {
try {
await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
......@@ -98,21 +106,32 @@ void main() {
}
});
test('returns false if golden bytes do not match', () async {
final File goldenFile = fs.file('/path/to/flutter/bin/cache/goldens/test/foo/bar/test.png')
..createSync(recursive: true);
goldenFile.writeAsBytesSync(<int>[4, 5, 6], flush: true);
final bool result = await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
expect(result, isFalse);
});
test('returns true if golden bytes match', () async {
final File goldenFile = fs.file('/path/to/flutter/bin/cache/goldens/test/foo/bar/test.png')
..createSync(recursive: true);
goldenFile.writeAsBytesSync(<int>[1, 2, 3], flush: true);
final bool result = await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
expect(result, isTrue);
});
// TODO(Piinks): This is currently disabled in flutter_goldens.dart, https://github.com/flutter/flutter/pull/31630
// test('throws if goldctl has not been authorized', () async {
// // See that preceding test does not leave auth behind [52]
// try {
// await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
// fail('TestFailure expected but not thrown');
// } on TestFailure catch (error) {
// expect(error.message, contains('Could not authorize goldctl.'));
// }
// });
// TODO(Piinks): Add methods to Mock SkiaGoldClient to inform the comparator and test for proper behavior. See matcher_test.dart for model, https://github.com/flutter/flutter/pull/31630
// test('returns false if skia gold test fails', () async {
// final File goldenFile = fs.file('/path/to/flutter/bin/cache/goldens/test/foo/bar/test.png')
// ..createSync(recursive: true);
// goldenFile.writeAsBytesSync(<int>[4, 5, 6], flush: true);
// final bool result = await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
// expect(result, isFalse);
// });
//
// test('returns true if skia gold test passes', () async {
// final File goldenFile = fs.file('/path/to/flutter/bin/cache/goldens/test/foo/bar/test.png')
// ..createSync(recursive: true);
// goldenFile.writeAsBytesSync(<int>[1, 2, 3], flush: true);
// final bool result = await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
// expect(result, isTrue);
// });
});
group('update', () {
......@@ -136,5 +155,5 @@ void main() {
}
class MockProcessManager extends Mock implements ProcessManager {}
class MockGoldensClient extends Mock implements GoldensClient {}
class MockSkiaGoldClient extends Mock implements SkiaGoldClient {}
class MockLocalFileComparator extends Mock implements LocalFileComparator {}
......@@ -332,6 +332,43 @@ AsyncMatcher matchesGoldenFile(dynamic key) {
throw ArgumentError('Unexpected type for golden file: ${key.runtimeType}');
}
/// Asserts that a [Finder], [Future<ui.Image>], or [ui.Image] matches the
/// golden image file identified by [key] through Skia Gold.
///
/// For the case of a [Finder], the [Finder] must match exactly one widget and
/// the rendered image of the first [RepaintBoundary] ancestor of the widget is
/// treated as the image for the widget.
///
/// [key] may be either a [Uri] or a [String] representation of a URI.
///
/// This is an asynchronous matcher, meaning that callers should use
/// [expectLater] when using this matcher and await the future returned by
/// [expectLater].
///
/// ## Sample code
///
/// ```dart
/// await expectLater(find.text('Save'), matchesSkiaGoldFile('save.png'));
/// await expectLater(image, matchesSkiaGoldFile('save.png'));
/// await expectLater(imageFuture, matchesSkiaGoldFile('save.png'));
/// ```
///
/// See also:
///
/// * [FlutterGoldenFileComparator], which acts as the backend for this matcher.
/// * [SkiaGoldClient], which the [FlutterGoldenFileComparator] uses to execute
/// and process results of testing with Skia Gold.
/// * [flutter_test] for a discussion of test configurations, whereby callers
/// may swap out the backend for this matcher.
AsyncMatcher matchesSkiaGoldFile(dynamic key) {
if (key is Uri) {
return _MatchesSkiaGoldFile(key);
} else if (key is String) {
return _MatchesSkiaGoldFile.forStringPath(key);
}
throw ArgumentError('Unexpected type for Skia Gold file: ${key.runtimeType}');
}
/// Asserts that a [Finder], [Future<ui.Image>], or [ui.Image] matches a
/// reference image identified by [image].
///
......@@ -1726,6 +1763,53 @@ class _MatchesGoldenFile extends AsyncMatcher {
description.add('one widget whose rasterized image matches golden image "$key"');
}
class _MatchesSkiaGoldFile extends AsyncMatcher {
const _MatchesSkiaGoldFile(this.key);
_MatchesSkiaGoldFile.forStringPath(String path) : key = Uri.parse(path);
final Uri key;
@override
Future<String> matchAsync(dynamic item) async {
Future<ui.Image> imageFuture;
if (item is Future<ui.Image>) {
imageFuture = item;
}else if (item is ui.Image) {
imageFuture = Future<ui.Image>.value(item);
} else {
final Finder finder = item;
final Iterable<Element> elements = finder.evaluate();
if (elements.isEmpty) {
return 'could not be rendered because no widget was found.';
} else if (elements.length > 1) {
return 'matched too many widgets.';
}
imageFuture = _captureImage(elements.single);
}
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
return binding.runAsync<String>(() async {
final ui.Image image = await imageFuture;
final ByteData bytes = await image.toByteData(format: ui.ImageByteFormat.png)
.timeout(const Duration(seconds: 10), onTimeout: () => null);
if (bytes == null)
return 'Failed to generate screenshot from engine within the 10,000ms timeout';
await goldenFileComparator.update(key, bytes.buffer.asUint8List());
try {
final bool success = await goldenFileComparator.compare(null, key);
return success ? null : 'Skia Gold test fail.';
} on TestFailure catch (ex) {
return ex.message;
}
}, additionalTime: const Duration(seconds: 11));
}
@override
Description describe(Description description) =>
description.add('one widget whose rasterized images matches Skia Gold image $key');
}
class _MatchesSemanticsData extends Matcher {
_MatchesSemanticsData({
this.label,
......
......@@ -402,6 +402,88 @@ void main() {
});
});
group('matchesSkiaGoldFile', () {
_FakeComparator comparator;
Widget boilerplate(Widget child) {
return Directionality(
textDirection: TextDirection.ltr,
child: child,
);
}
setUp(() {
comparator = _FakeComparator();
goldenFileComparator = comparator;
});
group('matches', () {
testWidgets('if comparator succeeds', (WidgetTester tester) async {
await tester.pumpWidget(boilerplate(const Text('hello')));
final Finder finder = find.byType(Text);
await expectLater(finder, matchesSkiaGoldFile('foo.png'));
expect(comparator.invocation, _ComparatorInvocation.compare);
expect(comparator.imageBytes, null);
expect(comparator.golden, Uri.parse('foo.png'));
});
});
group('does not match', () {
testWidgets('if comparator returns false', (WidgetTester tester) async {
comparator.behavior = _ComparatorBehavior.returnFalse;
await tester.pumpWidget(boilerplate(const Text('hello')));
final Finder finder = find.byType(Text);
try {
await expectLater(finder, matchesSkiaGoldFile('foo.png'));
fail('TestFailure expected but not thrown');
} on TestFailure catch (error) {
expect(comparator.invocation, _ComparatorInvocation.compare);
expect(error.message, contains('does not match'));
}
});
testWidgets('if comparator throws', (WidgetTester tester) async {
comparator.behavior = _ComparatorBehavior.throwTestFailure;
await tester.pumpWidget(boilerplate(const Text('hello')));
final Finder finder = find.byType(Text);
try {
await expectLater(finder, matchesSkiaGoldFile('foo.png'));
fail('TestFailure expected but not thrown');
} on TestFailure catch (error) {
expect(comparator.invocation, _ComparatorInvocation.compare);
expect(error.message, contains('fake message'));
}
});
testWidgets('if finder finds no widgets', (WidgetTester tester) async {
await tester.pumpWidget(boilerplate(Container()));
final Finder finder = find.byType(Text);
try {
await expectLater(finder, matchesSkiaGoldFile('foo.png'));
fail('TestFailure expected but not thrown');
} on TestFailure catch (error) {
expect(comparator.invocation, isNull);
expect(error.message, contains('no widget was found'));
}
});
testWidgets(
'if finder finds multiple widgets', (WidgetTester tester) async {
await tester.pumpWidget(boilerplate(Column(
children: const <Widget>[Text('hello'), Text('world')],
)));
final Finder finder = find.byType(Text);
try {
await expectLater(finder, matchesSkiaGoldFile('foo.png'));
fail('TestFailure expected but not thrown');
} on TestFailure catch (error) {
expect(comparator.invocation, isNull);
expect(error.message, contains('too many widgets'));
}
});
});
});
group('matchesSemanticsData', () {
testWidgets('matches SemanticsData', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
......
......@@ -6,7 +6,6 @@ import 'dart:async';
import 'dart:collection';
import 'package:meta/meta.dart';
import 'package:flutter_goldens_client/client.dart';
import '../base/common.dart';
import '../base/file_system.dart';
......@@ -139,13 +138,14 @@ class UpdatePackagesCommand extends FlutterCommand {
// The dev/integration_tests/android_views integration test depends on an assets
// package that is in the goldens repository. We need to make sure that the goldens
// repository is cloned locally before we verify or update pubspecs.
printStatus('Cloning goldens repository...');
try {
final GoldensClient goldensClient = GoldensClient();
await goldensClient.prepare();
} on NonZeroExitCode catch (e) {
throwToolExit(e.stderr, exitCode: e.exitCode);
}
// TODO(katelovett): Resolve dependency for android_views living in goldens repository
// printStatus('Cloning goldens repository...');
// try {
// final GoldensClient goldensClient = GoldensClient();
// await goldensClient.prepare();
// } on NonZeroExitCode catch (e) {
// throwToolExit(e.stderr, exitCode: e.exitCode);
// }
if (isVerifyOnly) {
bool needsUpdate = false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment