Unverified Commit 829bdeb4 authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

Fixing accidental merge from WIP branch. (#32520)

Revert "Merge branch 'master' into master"

This reverts commit e3a03c04, reversing
changes made to 64749826.
parent e3a03c04
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
...@@ -822,6 +823,43 @@ void main() { ...@@ -822,6 +823,43 @@ 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 { testWidgets('scrollController can be removed or added', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics(); final SemanticsHandle handle = tester.ensureSemantics();
int lastSelectedItem; int lastSelectedItem;
...@@ -895,35 +933,6 @@ void main() { ...@@ -895,35 +933,6 @@ void main() {
expect(lastSelectedItem, 1); expect(lastSelectedItem, 1);
handle.dispose(); 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 }) { Widget _buildPicker({ FixedExtentScrollController controller, ValueChanged<int> onSelectedItemChanged }) {
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
...@@ -799,9 +801,12 @@ void main() { ...@@ -799,9 +801,12 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary).last, find.byType(RepaintBoundary).last,
matchesSkiaGoldFile('nav_bar_test.standard_title.png'), matchesGoldenFile('nav_bar_test.standard_title.1.png'),
); );
}, },
// TODO(xster): remove once https://github.com/flutter/flutter/issues/17483
// is fixed.
skip: !Platform.isLinux,
); );
testWidgets( testWidgets(
...@@ -830,10 +835,13 @@ void main() { ...@@ -830,10 +835,13 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary).last, find.byType(RepaintBoundary).last,
matchesSkiaGoldFile('nav_bar_test.large_title.png'), matchesGoldenFile('nav_bar_test.large_title.1.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 { testWidgets('NavBar draws a light system bar for a dark background', (WidgetTester tester) async {
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -1325,9 +1327,9 @@ void main() { ...@@ -1325,9 +1327,9 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary), find.byType(RepaintBoundary),
matchesSkiaGoldFile('segmented_control_test.0.png'), matchesGoldenFile('segmented_control_test.0.0.png'),
); );
}); }, skip: !Platform.isLinux);
testWidgets('Golden Test Pressed State', (WidgetTester tester) async { testWidgets('Golden Test Pressed State', (WidgetTester tester) async {
final Map<int, Widget> children = <int, Widget>{}; final Map<int, Widget> children = <int, Widget>{};
...@@ -1363,7 +1365,7 @@ void main() { ...@@ -1363,7 +1365,7 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary), find.byType(RepaintBoundary),
matchesSkiaGoldFile('segmented_control_test.1.png'), matchesGoldenFile('segmented_control_test.1.0.png'),
); );
}); }, skip: !Platform.isLinux);
} }
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -71,15 +73,15 @@ void main() { ...@@ -71,15 +73,15 @@ void main() {
await pump(FloatingActionButtonLocation.endDocked); await pump(FloatingActionButtonLocation.endDocked);
await expectLater( await expectLater(
find.byKey(key), find.byKey(key),
matchesSkiaGoldFile('bottom_app_bar.custom_shape.1.png'), matchesGoldenFile('bottom_app_bar.custom_shape.1.png'),
); );
await pump(FloatingActionButtonLocation.centerDocked); await pump(FloatingActionButtonLocation.centerDocked);
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await expectLater( await expectLater(
find.byKey(key), find.byKey(key),
matchesSkiaGoldFile('bottom_app_bar.custom_shape.2.png'), matchesGoldenFile('bottom_app_bar.custom_shape.2.png'),
); );
}); }, skip: !Platform.isLinux);
testWidgets('color defaults to Theme.bottomAppBarColor', (WidgetTester tester) async { testWidgets('color defaults to Theme.bottomAppBarColor', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -80,7 +82,8 @@ void main() { ...@@ -80,7 +82,8 @@ void main() {
await expectLater( await expectLater(
find.byKey(_painterKey), find.byKey(_painterKey),
matchesSkiaGoldFile('bottom_app_bar_theme.custom_shape.png'), matchesGoldenFile('bottom_app_bar_theme.custom_shape.png'),
skip: !Platform.isLinux,
); );
}); });
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -137,7 +139,8 @@ void main() { ...@@ -137,7 +139,8 @@ void main() {
await expectLater( await expectLater(
find.byKey(painterKey), find.byKey(painterKey),
matchesSkiaGoldFile('card_theme.custom_shape.png'), matchesGoldenFile('card_theme.custom_shape.png'),
skip: !Platform.isLinux,
); );
}); });
} }
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -130,7 +132,8 @@ void main() { ...@@ -130,7 +132,8 @@ void main() {
await expectLater( await expectLater(
find.byKey(_painterKey), find.byKey(_painterKey),
matchesSkiaGoldFile('dialog_theme.dialog_with_custom_border.png'), matchesGoldenFile('dialog_theme.dialog_with_custom_border.png'),
skip: !Platform.isLinux,
); );
}); });
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'dart:math' as math; import 'dart:math' as math;
import 'dart:ui' show window; import 'dart:ui' show window;
...@@ -140,7 +141,8 @@ void main() { ...@@ -140,7 +141,8 @@ void main() {
assert(tester.renderObject(buttonFinder).attached); assert(tester.renderObject(buttonFinder).attached);
await expectLater( await expectLater(
find.ancestor(of: buttonFinder, matching: find.byType(RepaintBoundary)).first, find.ancestor(of: buttonFinder, matching: find.byType(RepaintBoundary)).first,
matchesSkiaGoldFile('dropdown_test.default.png'), matchesGoldenFile('dropdown_test.default.0.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -152,7 +154,8 @@ void main() { ...@@ -152,7 +154,8 @@ void main() {
assert(tester.renderObject(buttonFinder).attached); assert(tester.renderObject(buttonFinder).attached);
await expectLater( await expectLater(
find.ancestor(of: buttonFinder, matching: find.byType(RepaintBoundary)).first, find.ancestor(of: buttonFinder, matching: find.byType(RepaintBoundary)).first,
matchesSkiaGoldFile('dropdown_test.expanded.png'), matchesGoldenFile('dropdown_test.expanded.0.png'),
skip: !Platform.isLinux,
); );
}); });
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
...@@ -680,7 +681,8 @@ void main() { ...@@ -680,7 +681,8 @@ void main() {
await tester.pump(const Duration(milliseconds: 1000)); await tester.pump(const Duration(milliseconds: 1000));
await expectLater( await expectLater(
find.byKey(key), find.byKey(key),
matchesSkiaGoldFile('floating_action_button_test.clip.png'), matchesGoldenFile('floating_action_button_test.clip.2.png'), // .clip.1.png is obsolete and can be removed
skip: !Platform.isLinux,
); );
}); });
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:io' show Platform;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -2019,15 +2020,19 @@ void main() { ...@@ -2019,15 +2020,19 @@ void main() {
await tester.pumpWidget(buildFrame(TextDirection.ltr)); await tester.pumpWidget(buildFrame(TextDirection.ltr));
await expectLater( await expectLater(
find.byType(InputDecorator), find.byType(InputDecorator),
matchesSkiaGoldFile('input_decorator.outline_icon_label.ltr.png'), matchesGoldenFile('input_decorator.outline_icon_label.ltr.png'),
skip: !Platform.isLinux,
); );
await tester.pumpWidget(buildFrame(TextDirection.rtl)); await tester.pumpWidget(buildFrame(TextDirection.rtl));
await expectLater( await expectLater(
find.byType(InputDecorator), find.byType(InputDecorator),
matchesSkiaGoldFile('input_decorator.outline_icon_label.rtl.png'), matchesGoldenFile('input_decorator.outline_icon_label.rtl.png'),
skip: !Platform.isLinux,
); );
}); },
skip: !Platform.isLinux,
);
testWidgets('InputDecorationTheme.toString()', (WidgetTester tester) async { testWidgets('InputDecorationTheme.toString()', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/19305 // Regression test for https://github.com/flutter/flutter/issues/19305
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/painting.dart'; import 'package:flutter/painting.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -616,7 +618,8 @@ void main() { ...@@ -616,7 +618,8 @@ void main() {
await expectLater( await expectLater(
find.byKey(painterKey), find.byKey(painterKey),
matchesSkiaGoldFile('material.border_paint_above.png'), matchesGoldenFile('material.border_paint_above.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -656,7 +659,8 @@ void main() { ...@@ -656,7 +659,8 @@ void main() {
await expectLater( await expectLater(
find.byKey(painterKey), find.byKey(painterKey),
matchesSkiaGoldFile('material.border_paint_below.png'), matchesGoldenFile('material.border_paint_below.png'),
skip: !Platform.isLinux,
); );
}); });
}); });
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -276,7 +277,8 @@ void main() { ...@@ -276,7 +277,8 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await expectLater( await expectLater(
find.byKey(painterKey), find.byKey(painterKey),
matchesSkiaGoldFile('radio.ink_ripple.png'), matchesGoldenFile('radio.ink_ripple.png'),
skip: !Platform.isLinux,
); );
}); });
} }
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -267,7 +269,8 @@ void main() { ...@@ -267,7 +269,8 @@ void main() {
await expectLater( await expectLater(
find.byKey(_painterKey), find.byKey(_painterKey),
matchesSkiaGoldFile('tab_bar_theme.tab_indicator_size_tab.png'), matchesGoldenFile('tab_bar_theme.tab_indicator_size_tab.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -278,7 +281,8 @@ void main() { ...@@ -278,7 +281,8 @@ void main() {
await expectLater( await expectLater(
find.byKey(_painterKey), find.byKey(_painterKey),
matchesSkiaGoldFile('tab_bar_theme.tab_indicator_size_label.png'), matchesGoldenFile('tab_bar_theme.tab_indicator_size_label.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -294,7 +298,8 @@ void main() { ...@@ -294,7 +298,8 @@ void main() {
await expectLater( await expectLater(
find.byKey(_painterKey), find.byKey(_painterKey),
matchesSkiaGoldFile('tab_bar_theme.custom_tab_indicator.png'), matchesGoldenFile('tab_bar_theme.custom_tab_indicator.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -310,7 +315,8 @@ void main() { ...@@ -310,7 +315,8 @@ void main() {
await expectLater( await expectLater(
find.byKey(_painterKey), find.byKey(_painterKey),
matchesSkiaGoldFile('tab_bar_theme.beveled_rect_indicator.png'), matchesGoldenFile('tab_bar_theme.beveled_rect_indicator.png'),
skip: !Platform.isLinux,
); );
}); });
} }
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/painting.dart'; import 'package:flutter/painting.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -71,7 +72,8 @@ void main() { ...@@ -71,7 +72,8 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary), find.byType(RepaintBoundary),
matchesSkiaGoldFile('continuous_rectangle_border.golden_test_even_radii.png'), matchesGoldenFile('continuous_rectangle_border.golden_test_even_radii.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -92,7 +94,8 @@ void main() { ...@@ -92,7 +94,8 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary), find.byType(RepaintBoundary),
matchesSkiaGoldFile('continuous_rectangle_border.golden_test_varying_radii.png'), matchesGoldenFile('continuous_rectangle_border.golden_test_varying_radii.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -110,7 +113,8 @@ void main() { ...@@ -110,7 +113,8 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary), find.byType(RepaintBoundary),
matchesSkiaGoldFile('continuous_rectangle_border.golden_test_large_radii.png'), matchesGoldenFile('continuous_rectangle_border.golden_test_large_radii.png'),
skip: !Platform.isLinux,
); );
}); });
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -49,9 +51,11 @@ void main() { ...@@ -49,9 +51,11 @@ void main() {
await expectLater( await expectLater(
find.byType(RichText), find.byType(RichText),
matchesSkiaGoldFile('localized_fonts.rich_text.styled_text_span.png'), matchesGoldenFile('localized_fonts.rich_text.styled_text_span.png'),
); );
}); },
skip: !Platform.isLinux,
);
testWidgets( testWidgets(
'Text with locale-specific glyphs, ambient locale', 'Text with locale-specific glyphs, ambient locale',
...@@ -99,9 +103,11 @@ void main() { ...@@ -99,9 +103,11 @@ void main() {
await expectLater( await expectLater(
find.byType(Row), find.byType(Row),
matchesSkiaGoldFile('localized_fonts.text_ambient_locale.chars.png'), matchesGoldenFile('localized_fonts.text_ambient_locale.chars.png'),
); );
}); },
skip: !Platform.isLinux,
);
testWidgets( testWidgets(
'Text with locale-specific glyphs, explicit locale', 'Text with locale-specific glyphs, explicit locale',
...@@ -141,8 +147,10 @@ void main() { ...@@ -141,8 +147,10 @@ void main() {
await expectLater( await expectLater(
find.byType(Row), find.byType(Row),
matchesSkiaGoldFile('localized_fonts.text_explicit_locale.chars.png'), matchesGoldenFile('localized_fonts.text_explicit_locale.chars.png'),
); );
}); },
skip: !Platform.isLinux,
);
} }
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
...@@ -42,7 +43,8 @@ void main() { ...@@ -42,7 +43,8 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('backdrop_filter_test.cull_rect.png'), matchesGoldenFile('backdrop_filter_test.cull_rect.1.png'),
skip: !Platform.isLinux,
); );
}); });
} }
...@@ -356,7 +356,7 @@ void main() { ...@@ -356,7 +356,7 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.ClipRect.png'), matchesGoldenFile('clip.ClipRect.1.png'),
); );
}); });
...@@ -396,7 +396,7 @@ void main() { ...@@ -396,7 +396,7 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.ClipRectOverlay.png'), matchesGoldenFile('clip.ClipRectOverlay.1.png'),
); );
}); });
...@@ -445,7 +445,7 @@ void main() { ...@@ -445,7 +445,7 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.ClipRRect.png'), matchesGoldenFile('clip.ClipRRect.1.png'),
); );
}); });
...@@ -488,7 +488,7 @@ void main() { ...@@ -488,7 +488,7 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.ClipOval.png'), matchesGoldenFile('clip.ClipOval.1.png'),
); );
}); });
...@@ -536,7 +536,7 @@ void main() { ...@@ -536,7 +536,7 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.ClipPath.png'), matchesGoldenFile('clip.ClipPath.1.png'),
); );
}); });
...@@ -581,7 +581,7 @@ void main() { ...@@ -581,7 +581,7 @@ void main() {
await tester.pumpWidget(genPhysicalModel(Clip.antiAlias)); await tester.pumpWidget(genPhysicalModel(Clip.antiAlias));
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.PhysicalModel.antiAlias.png'), matchesGoldenFile('clip.PhysicalModel.antiAlias.1.png'),
); );
}); });
...@@ -589,7 +589,7 @@ void main() { ...@@ -589,7 +589,7 @@ void main() {
await tester.pumpWidget(genPhysicalModel(Clip.hardEdge)); await tester.pumpWidget(genPhysicalModel(Clip.hardEdge));
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.PhysicalModel.hardEdge.png'), matchesGoldenFile('clip.PhysicalModel.hardEdge.1.png'),
); );
}); });
...@@ -599,7 +599,7 @@ void main() { ...@@ -599,7 +599,7 @@ void main() {
await tester.pumpWidget(genPhysicalModel(Clip.antiAliasWithSaveLayer)); await tester.pumpWidget(genPhysicalModel(Clip.antiAliasWithSaveLayer));
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.PhysicalModel.antiAliasWithSaveLayer.png'), matchesGoldenFile('clip.PhysicalModel.antiAliasWithSaveLayer.png'),
); );
}); });
...@@ -641,7 +641,7 @@ void main() { ...@@ -641,7 +641,7 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.PhysicalModel.default.png'), matchesGoldenFile('clip.PhysicalModel.default.1.png'),
); );
}); });
...@@ -690,7 +690,7 @@ void main() { ...@@ -690,7 +690,7 @@ void main() {
await tester.pumpWidget(genPhysicalShape(Clip.antiAlias)); await tester.pumpWidget(genPhysicalShape(Clip.antiAlias));
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.PhysicalShape.antiAlias.png'), matchesGoldenFile('clip.PhysicalShape.antiAlias.1.png'),
); );
}); });
...@@ -698,7 +698,7 @@ void main() { ...@@ -698,7 +698,7 @@ void main() {
await tester.pumpWidget(genPhysicalShape(Clip.hardEdge)); await tester.pumpWidget(genPhysicalShape(Clip.hardEdge));
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.PhysicalShape.hardEdge.png'), matchesGoldenFile('clip.PhysicalShape.hardEdge.1.png'),
); );
}); });
...@@ -706,7 +706,7 @@ void main() { ...@@ -706,7 +706,7 @@ void main() {
await tester.pumpWidget(genPhysicalShape(Clip.antiAliasWithSaveLayer)); await tester.pumpWidget(genPhysicalShape(Clip.antiAliasWithSaveLayer));
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.PhysicalShape.antiAliasWithSaveLayer.png'), matchesGoldenFile('clip.PhysicalShape.antiAliasWithSaveLayer.png'),
); );
}); });
...@@ -752,7 +752,7 @@ void main() { ...@@ -752,7 +752,7 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('clip.PhysicalShape.default.png'), matchesGoldenFile('clip.PhysicalShape.default.1.png'),
); );
}); });
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -90,9 +92,9 @@ void main() { ...@@ -90,9 +92,9 @@ void main() {
await expectLater( await expectLater(
find.byKey(const ValueKey<int>(1)), find.byKey(const ValueKey<int>(1)),
matchesSkiaGoldFile('editable_text_test.0.png'), matchesGoldenFile('editable_text_test.0.3.png'),
); );
}); }, skip: !Platform.isLinux);
testWidgets('cursor layout has correct radius', (WidgetTester tester) async { testWidgets('cursor layout has correct radius', (WidgetTester tester) async {
final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>(); final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
...@@ -141,9 +143,9 @@ void main() { ...@@ -141,9 +143,9 @@ void main() {
await expectLater( await expectLater(
find.byKey(const ValueKey<int>(1)), find.byKey(const ValueKey<int>(1)),
matchesSkiaGoldFile('editable_text_test.1.png'), matchesGoldenFile('editable_text_test.1.3.png'),
); );
}); }, skip: !Platform.isLinux);
testWidgets('Cursor animates on iOS', (WidgetTester tester) async { testWidgets('Cursor animates on iOS', (WidgetTester tester) async {
final Widget widget = MaterialApp( final Widget widget = MaterialApp(
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -20,7 +22,8 @@ void main() { ...@@ -20,7 +22,8 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary), find.byType(RepaintBoundary),
matchesSkiaGoldFile('invert_colors_test.0.png'), matchesGoldenFile('invert_colors_test.0.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -38,7 +41,8 @@ void main() { ...@@ -38,7 +41,8 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary), find.byType(RepaintBoundary),
matchesSkiaGoldFile('invert_colors_test.1.png'), matchesGoldenFile('invert_colors_test.1.png'),
skip: !Platform.isLinux,
); );
}); });
} }
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -535,7 +537,8 @@ void main() { ...@@ -535,7 +537,8 @@ void main() {
await expectLater( await expectLater(
find.byKey(const Key('list_wheel_scroll_view')), find.byKey(const Key('list_wheel_scroll_view')),
matchesSkiaGoldFile('list_wheel_scroll_view.center_child.magnified.png'), matchesGoldenFile('list_wheel_scroll_view.center_child.magnified.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -589,7 +592,8 @@ void main() { ...@@ -589,7 +592,8 @@ void main() {
await expectLater( await expectLater(
find.byKey(const Key('list_wheel_scroll_view')), find.byKey(const Key('list_wheel_scroll_view')),
matchesSkiaGoldFile('list_wheel_scroll_view.curved_wheel.left.png'), matchesGoldenFile('list_wheel_scroll_view.curved_wheel.left.png'),
skip: !Platform.isLinux,
); );
}); });
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
...@@ -177,7 +179,8 @@ void main() { ...@@ -177,7 +179,8 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('opacity_test.offset.png'), matchesGoldenFile('opacity_test.offset.1.png'),
skip: !Platform.isLinux,
); );
}); });
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'dart:math' as math show pi; import 'dart:math' as math show pi;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
...@@ -110,7 +111,8 @@ void main() { ...@@ -110,7 +111,8 @@ void main() {
expect(exception.diagnostics.first.toString(), startsWith('A RenderFlex overflowed by ')); expect(exception.diagnostics.first.toString(), startsWith('A RenderFlex overflowed by '));
await expectLater( await expectLater(
find.byKey(key), find.byKey(key),
matchesSkiaGoldFile('physical_model_overflow.png'), matchesGoldenFile('physical_model_overflow.png'),
skip: !Platform.isLinux,
); );
}); });
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
...@@ -23,15 +25,18 @@ void main() { ...@@ -23,15 +25,18 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('shadow.BoxDecoration.disabled.png'), matchesGoldenFile('shadow.BoxDecoration.disabled.png'),
); );
debugDisableShadows = false; debugDisableShadows = false;
tester.binding.reassembleApplication(); tester.binding.reassembleApplication();
await tester.pump(); await tester.pump();
await expectLater( if (Platform.isLinux) {
find.byType(Container), // TODO(ianh): use the skip argument instead once that doesn't hang, https://github.com/dart-lang/test/issues/830
matchesSkiaGoldFile('shadow.BoxDecoration.enabled.png'), await expectLater(
); find.byType(Container),
matchesGoldenFile('shadow.BoxDecoration.enabled.png'),
); // shadows render differently on different platforms
}
debugDisableShadows = true; debugDisableShadows = true;
}); });
...@@ -56,11 +61,11 @@ void main() { ...@@ -56,11 +61,11 @@ void main() {
await tester.pumpWidget(build(elevation)); await tester.pumpWidget(build(elevation));
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('shadow.ShapeDecoration.$elevation.png'), matchesGoldenFile('shadow.ShapeDecoration.$elevation.png'),
); );
} }
debugDisableShadows = true; debugDisableShadows = true;
}); }, skip: !Platform.isLinux); // shadows render differently on different platforms
testWidgets('Shadows with PhysicalLayer', (WidgetTester tester) async { testWidgets('Shadows with PhysicalLayer', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -83,15 +88,18 @@ void main() { ...@@ -83,15 +88,18 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('shadow.PhysicalModel.disabled.0.png'), matchesGoldenFile('shadow.PhysicalModel.disabled.png'),
); );
debugDisableShadows = false; debugDisableShadows = false;
tester.binding.reassembleApplication(); tester.binding.reassembleApplication();
await tester.pump(); await tester.pump();
await expectLater( if (Platform.isLinux) {
find.byType(Container), // TODO(ianh): use the skip argument instead once that doesn't hang, https://github.com/dart-lang/test/issues/830
matchesSkiaGoldFile('shadow.PhysicalModel.enabled.png'), await expectLater(
); find.byType(Container),
matchesGoldenFile('shadow.PhysicalModel.enabled.png'),
); // shadows render differently on different platforms
}
debugDisableShadows = true; debugDisableShadows = true;
}); });
...@@ -120,9 +128,9 @@ void main() { ...@@ -120,9 +128,9 @@ void main() {
await tester.pumpWidget(build(elevation.toDouble())); await tester.pumpWidget(build(elevation.toDouble()));
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('shadow.PhysicalModel.disabled.1.$elevation.png'), matchesGoldenFile('shadow.PhysicalShape.$elevation.1.png'),
); );
} }
debugDisableShadows = true; debugDisableShadows = true;
}); }, skip: !Platform.isLinux); // shadows render differently on different platforms
} }
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
...@@ -29,7 +31,7 @@ void main() { ...@@ -29,7 +31,7 @@ void main() {
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('text_golden.Centered.png'), matchesGoldenFile('text_golden.Centered.png'),
); );
await tester.pumpWidget( await tester.pumpWidget(
...@@ -53,9 +55,9 @@ void main() { ...@@ -53,9 +55,9 @@ void main() {
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('text_golden.Centered.wrap.png'), matchesGoldenFile('text_golden.Centered.wrap.png'),
); );
}); }, skip: !Platform.isLinux);
testWidgets('Text Foreground', (WidgetTester tester) async { testWidgets('Text Foreground', (WidgetTester tester) async {
...@@ -84,7 +86,7 @@ void main() { ...@@ -84,7 +86,7 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary), find.byType(RepaintBoundary),
matchesSkiaGoldFile('text_golden.Foreground.gradient.png'), matchesGoldenFile('text_golden.Foreground.gradient.png'),
); );
await tester.pumpWidget( await tester.pumpWidget(
...@@ -106,7 +108,7 @@ void main() { ...@@ -106,7 +108,7 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary), find.byType(RepaintBoundary),
matchesSkiaGoldFile('text_golden.Foreground.stroke.png'), matchesGoldenFile('text_golden.Foreground.stroke.png'),
); );
await tester.pumpWidget( await tester.pumpWidget(
...@@ -129,9 +131,9 @@ void main() { ...@@ -129,9 +131,9 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary), find.byType(RepaintBoundary),
matchesSkiaGoldFile('text_golden.Foreground.stroke_and_gradient.png'), matchesGoldenFile('text_golden.Foreground.stroke_and_gradient.png'),
); );
}); }, skip: !Platform.isLinux);
// TODO(garyq): This test requires an update when the background // TODO(garyq): This test requires an update when the background
// drawing from the beginning of the line bug is fixed. The current // drawing from the beginning of the line bug is fixed. The current
...@@ -179,9 +181,9 @@ void main() { ...@@ -179,9 +181,9 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary), find.byType(RepaintBoundary),
matchesSkiaGoldFile('text_golden.Background.png'), matchesGoldenFile('text_golden.Background.png'),
); );
}); }, skip: !Platform.isLinux);
testWidgets('Text Fade', (WidgetTester tester) async { testWidgets('Text Fade', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -215,9 +217,9 @@ void main() { ...@@ -215,9 +217,9 @@ void main() {
await expectLater( await expectLater(
find.byType(RepaintBoundary).first, find.byType(RepaintBoundary).first,
matchesSkiaGoldFile('text_golden.Fade.1.png'), matchesGoldenFile('text_golden.Fade.1.png'),
); );
}); }, skip: !Platform.isLinux);
testWidgets('Default Strut text', (WidgetTester tester) async { testWidgets('Default Strut text', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -240,9 +242,10 @@ void main() { ...@@ -240,9 +242,10 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('text_golden.StrutDefault.png'), matchesGoldenFile('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 { testWidgets('Strut text 1', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -267,9 +270,10 @@ void main() { ...@@ -267,9 +270,10 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('text_golden.Strut.1.png'), matchesGoldenFile('text_golden.Strut.1.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 { testWidgets('Strut text 2', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -295,9 +299,10 @@ void main() { ...@@ -295,9 +299,10 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('text_golden.Strut.2.png'), matchesGoldenFile('text_golden.Strut.2.1.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 { testWidgets('Strut text rich', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -346,9 +351,10 @@ void main() { ...@@ -346,9 +351,10 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('text_golden.Strut.3.png'), matchesGoldenFile('text_golden.Strut.3.1.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 { testWidgets('Strut text font fallback', (WidgetTester tester) async {
// Font Fallback // Font Fallback
...@@ -381,9 +387,10 @@ void main() { ...@@ -381,9 +387,10 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('text_golden.Strut.4.png'), matchesGoldenFile('text_golden.Strut.4.1.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 { testWidgets('Strut text rich forceStrutHeight', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -432,9 +439,10 @@ void main() { ...@@ -432,9 +439,10 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('text_golden.StrutForce.1.png'), matchesGoldenFile('text_golden.StrutForce.1.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 { testWidgets('Decoration thickness', (WidgetTester tester) async {
final TextDecoration allDecorations = TextDecoration.combine( final TextDecoration allDecorations = TextDecoration.combine(
...@@ -470,9 +478,9 @@ void main() { ...@@ -470,9 +478,9 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('text_golden.Decoration.1.png'), matchesGoldenFile('text_golden.Decoration.1.0.png'),
); );
}); }, skip: !Platform.isLinux); // Coretext uses different thicknesses for decoration
testWidgets('Decoration thickness', (WidgetTester tester) async { testWidgets('Decoration thickness', (WidgetTester tester) async {
final TextDecoration allDecorations = TextDecoration.combine( final TextDecoration allDecorations = TextDecoration.combine(
...@@ -509,7 +517,7 @@ void main() { ...@@ -509,7 +517,7 @@ void main() {
); );
await expectLater( await expectLater(
find.byType(Container), find.byType(Container),
matchesSkiaGoldFile('text_golden.DecorationThickness.1.png'), matchesGoldenFile('text_golden.DecorationThickness.1.0.png'),
); );
}); }, skip: !Platform.isLinux); // Coretext uses different thicknesses for decoration
} }
...@@ -1896,7 +1896,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1896,7 +1896,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
expect(expectedChildLayerCount, equals(2)); expect(expectedChildLayerCount, equals(2));
await expectLater( await expectLater(
layer.toImage(renderObject.semanticBounds.inflate(50.0)), layer.toImage(renderObject.semanticBounds.inflate(50.0)),
matchesSkiaGoldFile('inspector.repaint_boundary_margin.png'), matchesGoldenFile('inspector.repaint_boundary_margin.png'),
skip: !Platform.isLinux,
); );
// Regression test for how rendering with a pixel scale other than 1.0 // Regression test for how rendering with a pixel scale other than 1.0
...@@ -1906,7 +1907,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1906,7 +1907,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
renderObject.semanticBounds.inflate(50.0), renderObject.semanticBounds.inflate(50.0),
pixelRatio: 0.5, pixelRatio: 0.5,
), ),
matchesSkiaGoldFile('inspector.repaint_boundary_margin_small.png'), matchesGoldenFile('inspector.repaint_boundary_margin_small.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -1914,7 +1916,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1914,7 +1916,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
renderObject.semanticBounds.inflate(50.0), renderObject.semanticBounds.inflate(50.0),
pixelRatio: 2.0, pixelRatio: 2.0,
), ),
matchesSkiaGoldFile('inspector.repaint_boundary_margin_large.png'), matchesGoldenFile('inspector.repaint_boundary_margin_large.png'),
skip: !Platform.isLinux,
); );
final Layer layerParent = layer.parent; final Layer layerParent = layer.parent;
...@@ -1929,7 +1932,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1929,7 +1932,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
width: 300.0, width: 300.0,
height: 300.0, height: 300.0,
), ),
matchesSkiaGoldFile('inspector.repaint_boundary.png'), matchesGoldenFile('inspector.repaint_boundary.png'),
skip: !Platform.isLinux,
); );
// Verify that taking a screenshot didn't change the layers associated with // Verify that taking a screenshot didn't change the layers associated with
...@@ -1946,7 +1950,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1946,7 +1950,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 500.0, height: 500.0,
margin: 50.0, margin: 50.0,
), ),
matchesSkiaGoldFile('inspector.repaint_boundary_margin.png'), matchesGoldenFile('inspector.repaint_boundary_margin.png'),
skip: !Platform.isLinux,
); );
// Verify that taking a screenshot didn't change the layers associated with // Verify that taking a screenshot didn't change the layers associated with
...@@ -1966,7 +1971,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1966,7 +1971,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 300.0, height: 300.0,
debugPaint: true, debugPaint: true,
), ),
matchesSkiaGoldFile('inspector.repaint_boundary_debugPaint.png'), matchesGoldenFile('inspector.repaint_boundary_debugPaint.png'),
skip: !Platform.isLinux,
); );
// Verify that taking a screenshot with debug paint on did not change // Verify that taking a screenshot with debug paint on did not change
// the number of children the layer has. // the number of children the layer has.
...@@ -1976,7 +1982,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1976,7 +1982,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
// hasn't changed the regular render of the widget. // hasn't changed the regular render of the widget.
await expectLater( await expectLater(
find.byType(RepaintBoundaryWithDebugPaint), find.byType(RepaintBoundaryWithDebugPaint),
matchesSkiaGoldFile('inspector.repaint_boundary.png'), matchesGoldenFile('inspector.repaint_boundary.png'),
skip: !Platform.isLinux,
); );
expect(renderObject.debugLayer, equals(layer)); expect(renderObject.debugLayer, equals(layer));
...@@ -1989,7 +1996,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1989,7 +1996,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
width: 100.0, width: 100.0,
height: 100.0, height: 100.0,
), ),
matchesSkiaGoldFile('inspector.container.png'), matchesGoldenFile('inspector.container.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -1999,7 +2007,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1999,7 +2007,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 100.0, height: 100.0,
debugPaint: true, debugPaint: true,
), ),
matchesSkiaGoldFile('inspector.container_debugPaint.png'), matchesGoldenFile('inspector.container_debugPaint.png'),
skip: !Platform.isLinux,
); );
{ {
...@@ -2019,7 +2028,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2019,7 +2028,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 100.0, height: 100.0,
debugPaint: true, debugPaint: true,
), ),
matchesSkiaGoldFile('inspector.container_debugPaint.png'), matchesGoldenFile('inspector.container_debugPaint.png'),
skip: !Platform.isLinux,
); );
expect(container.debugNeedsLayout, isFalse); expect(container.debugNeedsLayout, isFalse);
} }
...@@ -2031,7 +2041,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2031,7 +2041,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
width: 50.0, width: 50.0,
height: 100.0, height: 100.0,
), ),
matchesSkiaGoldFile('inspector.container_small.png'), matchesGoldenFile('inspector.container_small.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -2041,7 +2052,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2041,7 +2052,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 400.0, height: 400.0,
maxPixelRatio: 3.0, maxPixelRatio: 3.0,
), ),
matchesSkiaGoldFile('inspector.container_large.png'), matchesGoldenFile('inspector.container_large.png'),
skip: !Platform.isLinux,
); );
// This screenshot will show the clip rect debug paint but no other // This screenshot will show the clip rect debug paint but no other
...@@ -2053,7 +2065,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2053,7 +2065,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 100.0, height: 100.0,
debugPaint: true, debugPaint: true,
), ),
matchesSkiaGoldFile('inspector.clipRect_debugPaint.png'), matchesGoldenFile('inspector.clipRect_debugPaint.png'),
skip: !Platform.isLinux,
); );
final Element clipRect = find.byType(ClipRRect).evaluate().single; final Element clipRect = find.byType(ClipRRect).evaluate().single;
...@@ -2067,10 +2080,10 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2067,10 +2080,10 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
); );
// Add a margin so that the clip icon shows up in the screenshot. // Add a margin so that the clip icon shows up in the screenshot.
// This golden image is platform dependent due to the clip icon. // This golden image is platform dependent due to the clip icon.
final String platform = Platform.operatingSystem;
await expectLater( await expectLater(
clipRectScreenshot, clipRectScreenshot,
matchesSkiaGoldFile('inspector.clipRect_debugPaint_margin.$platform.png'), matchesGoldenFile('inspector.clipRect_debugPaint_margin.png'),
skip: !Platform.isLinux,
); );
// Verify we get the same image if we go through the service extension // Verify we get the same image if we go through the service extension
...@@ -2109,7 +2122,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2109,7 +2122,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 300.0, height: 300.0,
debugPaint: true, debugPaint: true,
), ),
matchesSkiaGoldFile('inspector.padding_debugPaint.png'), matchesGoldenFile('inspector.padding_debugPaint.png'),
skip: !Platform.isLinux,
); );
// The bounds for this box crop its rendered content. // The bounds for this box crop its rendered content.
...@@ -2120,7 +2134,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2120,7 +2134,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
height: 300.0, height: 300.0,
debugPaint: true, debugPaint: true,
), ),
matchesSkiaGoldFile('inspector.sizedBox_debugPaint.png'), matchesGoldenFile('inspector.sizedBox_debugPaint.1.png'),
skip: !Platform.isLinux,
); );
// Verify that setting a margin includes the previously cropped content. // Verify that setting a margin includes the previously cropped content.
...@@ -2132,7 +2147,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2132,7 +2147,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
margin: 50.0, margin: 50.0,
debugPaint: true, debugPaint: true,
), ),
matchesSkiaGoldFile('inspector.sizedBox_debugPaint_margin.png'), matchesGoldenFile('inspector.sizedBox_debugPaint_margin.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -2203,7 +2219,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2203,7 +2219,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
await expectLater( await expectLater(
find.byKey(mainStackKey), find.byKey(mainStackKey),
matchesSkiaGoldFile('inspector.composited_transform.only_offsets.png'), matchesGoldenFile('inspector.composited_transform.only_offsets.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -2212,12 +2229,14 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2212,12 +2229,14 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
width: 5000.0, width: 5000.0,
height: 500.0, height: 500.0,
), ),
matchesSkiaGoldFile('inspector.composited_transform.only_offsets_follower.png'), matchesGoldenFile('inspector.composited_transform.only_offsets_follower.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
WidgetInspectorService.instance.screenshot(find.byType(Stack).evaluate().first, width: 300.0, height: 300.0), WidgetInspectorService.instance.screenshot(find.byType(Stack).evaluate().first, width: 300.0, height: 300.0),
matchesSkiaGoldFile('inspector.composited_transform.only_offsets_small.png'), matchesGoldenFile('inspector.composited_transform.only_offsets_small.1.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -2226,7 +2245,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2226,7 +2245,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
width: 500.0, width: 500.0,
height: 500.0, height: 500.0,
), ),
matchesSkiaGoldFile('inspector.composited_transform.only_offsets_target.png'), matchesGoldenFile('inspector.composited_transform.only_offsets_target.png'),
skip: !Platform.isLinux,
); );
}); });
...@@ -2298,7 +2318,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2298,7 +2318,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
// screenshots of specific subtrees are reasonable. // screenshots of specific subtrees are reasonable.
await expectLater( await expectLater(
find.byKey(mainStackKey), find.byKey(mainStackKey),
matchesSkiaGoldFile('inspector.composited_transform.with_rotations.png'), matchesGoldenFile('inspector.composited_transform.with_rotations.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -2307,7 +2328,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2307,7 +2328,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
width: 500.0, width: 500.0,
height: 500.0, height: 500.0,
), ),
matchesSkiaGoldFile('inspector.composited_transform.with_rotations_small.png'), matchesGoldenFile('inspector.composited_transform.with_rotations_small.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -2316,7 +2338,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2316,7 +2338,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
width: 500.0, width: 500.0,
height: 500.0, height: 500.0,
), ),
matchesSkiaGoldFile('inspector.composited_transform.with_rotations_target.png'), matchesGoldenFile('inspector.composited_transform.with_rotations_target.png'),
skip: !Platform.isLinux,
); );
await expectLater( await expectLater(
...@@ -2325,7 +2348,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2325,7 +2348,8 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
width: 500.0, width: 500.0,
height: 500.0, height: 500.0,
), ),
matchesSkiaGoldFile('inspector.composited_transform.with_rotations_follower.png'), matchesGoldenFile('inspector.composited_transform.with_rotations_follower.png'),
skip: !Platform.isLinux,
); );
// Make sure taking screenshots hasn't modified the positions of the // Make sure taking screenshots hasn't modified the positions of the
......
...@@ -3,20 +3,16 @@ ...@@ -3,20 +3,16 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/local.dart'; import 'package:file/local.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:meta/meta.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'; import 'package:flutter_goldens_client/client.dart';
export '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 /// Main method that can be used in a `flutter_test_config.dart` file to set
/// [goldenFileComparator] to an instance of [FlutterGoldenFileComparator] that /// [goldenFileComparator] to an instance of [FlutterGoldenFileComparator] that
/// works for the current test. /// works for the current test.
...@@ -29,12 +25,12 @@ Future<void> main(FutureOr<void> testMain()) async { ...@@ -29,12 +25,12 @@ Future<void> main(FutureOr<void> testMain()) async {
/// ///
/// Within the https://github.com/flutter/flutter repository, it's important /// 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 /// not to check-in binaries in order to keep the size of the repository to a
/// minimum. To satisfy this requirement, this comparator uses the /// minimum. To satisfy this requirement, this comparator retrieves the golden
/// [SkiaGoldClient] to upload widgets for framework-related golden tests and /// files from a sibling repository, `flutter/goldens`.
/// process results.
/// ///
/// This comparator will instantiate the [SkiaGoldClient] and process the /// This comparator will locally clone the `flutter/goldens` repository into
/// results of the test. /// the `$FLUTTER_ROOT/bin/cache/pkg/goldens` folder, then perform the comparison against
/// the files therein.
class FlutterGoldenFileComparator implements GoldenFileComparator { class FlutterGoldenFileComparator implements GoldenFileComparator {
/// Creates a [FlutterGoldenFileComparator] that will resolve golden file /// Creates a [FlutterGoldenFileComparator] that will resolve golden file
/// URIs relative to the specified [basedir]. /// URIs relative to the specified [basedir].
...@@ -53,51 +49,48 @@ class FlutterGoldenFileComparator implements GoldenFileComparator { ...@@ -53,51 +49,48 @@ class FlutterGoldenFileComparator implements GoldenFileComparator {
@visibleForTesting @visibleForTesting
final FileSystem fs; final FileSystem fs;
/// Instance of the [SkiaGoldClient] for executing tests.
final SkiaGoldClient _skiaClient = SkiaGoldClient();
/// Creates a new [FlutterGoldenFileComparator] that mirrors the relative /// Creates a new [FlutterGoldenFileComparator] that mirrors the relative
/// path resolution of the default [goldenFileComparator]. /// path resolution of the default [goldenFileComparator].
/// ///
/// The [defaultComparator] parameter is visible for testing /// 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
/// purposes only. /// purposes only.
static Future<FlutterGoldenFileComparator> fromDefaultComparator({ static Future<FlutterGoldenFileComparator> fromDefaultComparator({
GoldensClient goldens,
LocalFileComparator defaultComparator, LocalFileComparator defaultComparator,
}) async { }) async {
defaultComparator ??= goldenFileComparator; defaultComparator ??= goldenFileComparator;
// Prepare the goldens repo.
goldens ??= GoldensClient();
await goldens.prepare();
// Calculate the appropriate basedir for the current test context. // Calculate the appropriate basedir for the current test context.
const FileSystem fs = LocalFileSystem(); final FileSystem fs = goldens.fs;
final Directory testDirectory = fs.directory(defaultComparator.basedir); final Directory testDirectory = fs.directory(defaultComparator.basedir);
final Directory flutterRoot = fs.directory(Platform.environment[_kFlutterRootKey]); final String testDirectoryRelativePath = fs.path.relative(testDirectory.path, from: goldens.flutterRoot.path);
final Directory goldenRoot = flutterRoot.childDirectory(fs.path.join( return FlutterGoldenFileComparator(goldens.repositoryRoot.childDirectory(testDirectoryRelativePath).uri);
'bin',
'cache',
'pkg',
'goldens',
));
final String testDirectoryRelativePath = fs.path.relative(
testDirectory.path,
from: flutterRoot.path,
);
return FlutterGoldenFileComparator(goldenRoot.childDirectory(testDirectoryRelativePath).uri);
} }
@override @override
Future<bool> compare(Uint8List imageBytes, Uri golden) async { Future<bool> compare(Uint8List imageBytes, Uri golden) async {
final File goldenFile = _getGoldenFile(golden); final File goldenFile = _getGoldenFile(golden);
if(!goldenFile.existsSync()) { if (!goldenFile.existsSync()) {
throw test_package.TestFailure('Could not be compared against non-existent file: "$golden"'); throw TestFailure('Could not be compared against non-existent file: "$golden"');
} }
final bool authorized = await _skiaClient.auth(fs.directory(basedir)); final List<int> goldenBytes = await goldenFile.readAsBytes();
if (!authorized) { // TODO(tvolkert): Improve the intelligence of this comparison.
// TODO(Piinks): Clean up for final implementation on CI, https://github.com/flutter/flutter/pull/31630 if (goldenBytes.length != imageBytes.length) {
return true; return false;
//throw test_package.TestFailure('Could not authorize golctl.');
} }
await _skiaClient.imgtestInit(); for (int i = 0; i < goldenBytes.length; i++) {
if (goldenBytes[i] != imageBytes[i]) {
return await _skiaClient.imgtestAdd(golden.path, goldenFile); return false;
}
}
return true;
} }
@override @override
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' as io;
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:file/file.dart'; import 'package:file/file.dart';
...@@ -13,57 +14,49 @@ import 'package:platform/platform.dart'; ...@@ -13,57 +14,49 @@ import 'package:platform/platform.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
const String _kFlutterRoot = '/flutter'; const String _kFlutterRoot = '/flutter';
//const String _kGoldenRoot = '$_kFlutterRoot/bin/cache/pkg/goldens'; const String _kRepositoryRoot = '$_kFlutterRoot/bin/cache/pkg/goldens';
//const String _kVersionFile = '$_kFlutterRoot/bin/internal/goldens.version'; const String _kVersionFile = '$_kFlutterRoot/bin/internal/goldens.version';
//const String _kGoldensVersion = '123456abcdef'; const String _kGoldensVersion = '123456abcdef';
// TODO(Piinks): Finish testing, https://github.com/flutter/flutter/pull/31630
void main() { void main() {
MemoryFileSystem fs; MemoryFileSystem fs;
FakePlatform platform; FakePlatform platform;
MockProcessManager process; MockProcessManager process;
//Directory flutter;
//Directory golden;
setUp(() async { setUp(() {
fs = MemoryFileSystem(); fs = MemoryFileSystem();
platform = FakePlatform(environment: <String, String>{ platform = FakePlatform(environment: <String, String>{'FLUTTER_ROOT': _kFlutterRoot});
'FLUTTER_ROOT': _kFlutterRoot,
// TODO(Piinks): Add other env vars for testing, https://github.com/flutter/flutter/pull/31630
});
process = MockProcessManager(); process = MockProcessManager();
//flutter = await fs.directory(_kFlutterRoot).create(recursive: true); fs.directory(_kFlutterRoot).createSync(recursive: true);
//golden = await fs.directory(_kGoldenRoot).create(recursive: true); fs.directory(_kRepositoryRoot).createSync(recursive: true);
//fs.file(_kVersionFile).createSync(recursive: true); fs.file(_kVersionFile).createSync(recursive: true);
//fs.file(_kVersionFile).writeAsStringSync(_kGoldensVersion); fs.file(_kVersionFile).writeAsStringSync(_kGoldensVersion);
}); });
group('SkiaGoldClient', () { group('GoldensClient', () {
//SkiaGoldClient skiaGold; GoldensClient goldens;
setUp(() { setUp(() {
//skiaGold = goldens = GoldensClient(
SkiaGoldClient(
fs: fs, fs: fs,
platform: platform, platform: platform,
process: process, process: process,
); );
}); });
group('auth', () { group('prepare', () {
// check for successful auth - return true test('performs minimal work if versions match', () async {
// check for unsuccessful auth - throw NonZeroExitCode when(process.run(any, workingDirectory: anyNamed('workingDirectory')))
// check for unavailable auth (not on CI) - return false .thenAnswer((_) => Future<io.ProcessResult>.value(io.ProcessResult(123, 0, _kGoldensVersion, '')));
// check for redundant work await goldens.prepare();
});
// Verify that we only spawned `git rev-parse HEAD`
group('init', () { final VerificationResult verifyProcessRun =
// check for successful init - return true verify(process.run(captureAny, workingDirectory: captureAnyNamed('workingDirectory')));
// check for unsuccessful init - throw NonZeroExitCode verifyProcessRun.called(1);
// Check for redundant work expect(verifyProcessRun.captured.first, <String>['git', 'rev-parse', 'HEAD']);
}); expect(verifyProcessRun.captured.last, _kRepositoryRoot);
});
group('imgtest', () {
}); });
}); });
...@@ -81,22 +74,21 @@ void main() { ...@@ -81,22 +74,21 @@ void main() {
group('fromDefaultComparator', () { group('fromDefaultComparator', () {
test('calculates the basedir correctly', () async { test('calculates the basedir correctly', () async {
// final MockSkiaGoldClient skiaGold = MockSkiaGoldClient(); final MockGoldensClient goldens = MockGoldensClient();
// final MockLocalFileComparator defaultComparator = MockLocalFileComparator(); final MockLocalFileComparator defaultComparator = MockLocalFileComparator();
// final Directory flutterRoot = fs.directory('/foo')..createSync(recursive: true); final Directory flutterRoot = fs.directory('/foo')..createSync(recursive: true);
// final Directory skiaGoldRoot = flutterRoot.childDirectory('bar')..createSync(recursive: true); final Directory goldensRoot = flutterRoot.childDirectory('bar')..createSync(recursive: true);
// when(skiaGold.fs).thenReturn(fs); when(goldens.fs).thenReturn(fs);
// when(skiaGold.flutterRoot).thenReturn(flutterRoot); when(goldens.flutterRoot).thenReturn(flutterRoot);
// when(skiaGold.repositoryRoot).thenReturn(skiaGoldRoot); when(goldens.repositoryRoot).thenReturn(goldensRoot);
// when(defaultComparator.basedir).thenReturn(flutterRoot.childDirectory('baz').uri); when(defaultComparator.basedir).thenReturn(flutterRoot.childDirectory('baz').uri);
// comparator = await FlutterGoldenFileComparator.fromDefaultComparator( comparator = await FlutterGoldenFileComparator.fromDefaultComparator(
// goldens: goldens, defaultComparator: defaultComparator); goldens: goldens, defaultComparator: defaultComparator);
// expect(comparator.basedir, fs.directory('/foo/bar/baz').uri); expect(comparator.basedir, fs.directory('/foo/bar/baz').uri);
}); });
}); });
group('compare', () { group('compare', () {
test('throws if golden file is not found', () async { test('throws if golden file is not found', () async {
try { try {
await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png')); await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
...@@ -106,32 +98,21 @@ void main() { ...@@ -106,32 +98,21 @@ void main() {
} }
}); });
// TODO(Piinks): This is currently disabled in flutter_goldens.dart, https://github.com/flutter/flutter/pull/31630 test('returns false if golden bytes do not match', () async {
// test('throws if goldctl has not been authorized', () async { final File goldenFile = fs.file('/path/to/flutter/bin/cache/goldens/test/foo/bar/test.png')
// // See that preceding test does not leave auth behind [52] ..createSync(recursive: true);
// try { goldenFile.writeAsBytesSync(<int>[4, 5, 6], flush: true);
// await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png')); final bool result = await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
// fail('TestFailure expected but not thrown'); expect(result, isFalse);
// } on TestFailure catch (error) { });
// expect(error.message, contains('Could not authorize goldctl.'));
// } test('returns true if golden bytes match', () async {
// }); final File goldenFile = fs.file('/path/to/flutter/bin/cache/goldens/test/foo/bar/test.png')
// 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 ..createSync(recursive: true);
// test('returns false if skia gold test fails', () async { goldenFile.writeAsBytesSync(<int>[1, 2, 3], flush: true);
// final File goldenFile = fs.file('/path/to/flutter/bin/cache/goldens/test/foo/bar/test.png') final bool result = await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
// ..createSync(recursive: true); expect(result, isTrue);
// 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', () { group('update', () {
...@@ -155,5 +136,5 @@ void main() { ...@@ -155,5 +136,5 @@ void main() {
} }
class MockProcessManager extends Mock implements ProcessManager {} class MockProcessManager extends Mock implements ProcessManager {}
class MockSkiaGoldClient extends Mock implements SkiaGoldClient {} class MockGoldensClient extends Mock implements GoldensClient {}
class MockLocalFileComparator extends Mock implements LocalFileComparator {} class MockLocalFileComparator extends Mock implements LocalFileComparator {}
...@@ -3,12 +3,10 @@ ...@@ -3,12 +3,10 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:convert' as convert;
import 'dart:io' as io; import 'dart:io' as io;
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/local.dart'; import 'package:file/local.dart';
import 'package:path/path.dart' as path;
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
...@@ -17,210 +15,163 @@ import 'package:process/process.dart'; ...@@ -17,210 +15,163 @@ import 'package:process/process.dart';
// https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package%3Aflutter // https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package%3Aflutter
const String _kFlutterRootKey = 'FLUTTER_ROOT'; const String _kFlutterRootKey = 'FLUTTER_ROOT';
const String _kGoldctlKey = 'GOLDCTL';
const String _kServiceAccountKey = 'GOLD_SERVICE_ACCOUNT'; /// A class that represents a clone of the https://github.com/flutter/goldens
const String _kSkiaGoldInstance = 'SKIA_GOLD_INSTANCE'; /// repository, nested within the `bin/cache` directory of the caller's Flutter
/// repository.
/// A class that represents the Skia Gold client for golden file testing. class GoldensClient {
class SkiaGoldClient { /// Create a handle to a local clone of the goldens repository.
/// Create a handle to a local workspace for the Skia Gold Client. GoldensClient({
SkiaGoldClient({
this.fs = const LocalFileSystem(), this.fs = const LocalFileSystem(),
this.platform = const LocalPlatform(), this.platform = const LocalPlatform(),
this.process = const LocalProcessManager(), this.process = const LocalProcessManager(),
}); });
/// The file system to use for storing local files for running imgtests. /// The file system to use for storing the local clone of the repository.
/// ///
/// This is useful in tests, where a local file system (the default) can be /// This is useful in tests, where a local file system (the default) can
/// replaced by a memory file system. /// be replaced by a memory file system.
final FileSystem fs; final FileSystem fs;
/// A wrapper for the [dart:io.Platform] API. /// A wrapper for the [dart:io.Platform] API.
/// ///
/// This is useful in tests, where the system platform (the default) can be /// This is useful in tests, where the system platform (the default) can
/// replaced by a mock platform instance. /// be replaced by a mock platform instance.
final Platform platform; final Platform platform;
/// A controller for launching sub-processes. /// A controller for launching subprocesses.
/// ///
/// This is useful in tests, where the real process manager (the default) can /// This is useful in tests, where the real process manager (the default)
/// be replaced by a mock process manager that doesn't really create /// can be replaced by a mock process manager that doesn't really create
/// sub-processes. /// subprocesses.
final ProcessManager process; final ProcessManager process;
Directory _workDirectory; RandomAccessFile _lock;
// TODO(Piinks): Environment variables are temporary for local testing, https://github.com/flutter/flutter/pull/31630
/// The local [Directory] where the Flutter repository is hosted. /// The local [Directory] where the Flutter repository is hosted.
/// ///
/// Uses the [fs] file system. /// Uses the [fs] file system.
Directory get flutterRoot => fs.directory(platform.environment[_kFlutterRootKey]); Directory get flutterRoot => fs.directory(platform.environment[_kFlutterRootKey]);
/// The [path] to the local [Directory] where the goldctl tool is hosted. /// The local [Directory] where the goldens repository is hosted.
///
/// Uses the [platform] [environment] in this iteration.
String get _goldctl => platform.environment[_kGoldctlKey];
/// The [path] to the local [Directory] where the service account key is
/// hosted.
/// ///
/// Uses the [platform] [environment] in this iteration. /// Uses the [fs] file system.
String get _serviceAccount => platform.environment[_kServiceAccountKey]; Directory get repositoryRoot => flutterRoot.childDirectory(fs.path.join('bin', 'cache', 'pkg', 'goldens'));
/// The name of the Skia Gold Flutter instance. /// Prepares the local clone of the `flutter/goldens` repository for golden
/// file testing.
/// ///
/// Uses the [platform] [environment] in this iteration. /// This ensures that the goldens repository has been cloned into its
String get _skiaGoldInstance => platform.environment[_kSkiaGoldInstance]; /// expected location within `bin/cache` and that it is synced to the Git
/// revision specified in `bin/internal/goldens.version`.
/// Prepares the local work space for golden file testing and initializes the
/// goldctl authorization for executing tests.
/// ///
/// This ensures that the goldctl tool is authorized and ready for testing. /// While this is preparing the repository, it obtains a file lock such that
Future<bool> auth(Directory workDirectory) async { /// [GoldensClient] instances in other processes or isolates will not
_workDirectory = workDirectory; /// duplicate the work that this is doing.
Future<void> prepare() async {
// TODO(Piinks): Cleanup for final CI implementation, https://github.com/flutter/flutter/pull/31630 final String goldensCommit = await _getGoldensCommit();
if (_serviceAccount == null) String currentCommit = await _getCurrentCommit();
return false; // Not in the proper environment for golden file testing. if (currentCommit != goldensCommit) {
await _obtainLock();
final File authFile = _workDirectory.childFile(fs.path.join( try {
'temp', // Check the current commit again now that we have the lock.
'auth_opt.json' currentCommit = await _getCurrentCommit();
)); if (currentCommit != goldensCommit) {
if (!authFile.existsSync()) { if (currentCommit == null) {
final List<String> authArguments = <String>[ await _initRepository();
'auth', }
'--service-account', _serviceAccount, await _checkCanSync();
'--work-dir', _workDirectory.childDirectory('temp').path, await _syncTo(goldensCommit);
]; }
} finally {
final io.ProcessResult authResults = io.Process.runSync( await _releaseLock();
_goldctl,
authArguments
);
if (authResults.exitCode != 0) {
final StringBuffer buf = StringBuffer();
buf
..writeln('Flutter + Skia Gold auth failed.')
..writeln('stdout: ${authResults.stdout}')
..writeln('stderr: ${authResults.stderr}');
throw NonZeroExitCode(authResults.exitCode, buf.toString());
} }
} }
return true;
} }
Future<void> imgtestInit() async { Future<String> _getGoldensCommit() async {
final File keysFile = _workDirectory.childFile('keys.json'); final File versionFile = flutterRoot.childFile(fs.path.join('bin', 'internal', 'goldens.version'));
return (await versionFile.readAsString()).trim();
if(!keysFile.existsSync() || await _isNewCommit()) { }
final String commitHash = await _getCommitHash();
final String keys = '${_workDirectory.path}keys.json';
final String failures = '${_workDirectory.path}failures.json';
await io.File(keys).writeAsString(_getKeysJSON());
await io.File(failures).create();
final List<String> imgtestInitArguments = <String>[
'imgtest', 'init',
'--instance', _skiaGoldInstance,
'--work-dir', _workDirectory.childDirectory('temp').path,
'--commit', commitHash,
'--keys-file', keys,
'--failure-file', failures,
'--passfail',
];
if(imgtestInitArguments.contains(null)) {
final StringBuffer buf = StringBuffer();
buf.writeln('Null argument for Skia Gold imgtest init:');
imgtestInitArguments.forEach(buf.writeln);
throw NonZeroExitCode(1, buf.toString());
}
final io.ProcessResult imgtestInitResult = io.Process.runSync( Future<String> _getCurrentCommit() async {
_goldctl, if (!repositoryRoot.existsSync()) {
imgtestInitArguments, return null;
} else {
final io.ProcessResult revParse = await process.run(
<String>['git', 'rev-parse', 'HEAD'],
workingDirectory: repositoryRoot.path,
); );
return revParse.exitCode == 0 ? revParse.stdout.trim() : null;
if (imgtestInitResult.exitCode != 0) {
final StringBuffer buf = StringBuffer();
buf
..writeln('Flutter + Skia Gold imgtest init failed.')
..writeln('stdout: ${imgtestInitResult.stdout}')
..writeln('stderr: ${imgtestInitResult.stderr}');
throw NonZeroExitCode(imgtestInitResult.exitCode, buf.toString());
}
} }
} }
Future<bool> imgtestAdd(String testName, File goldenFile) async { Future<void> _initRepository() async {
final List<String> imgtestArguments = <String>[ await repositoryRoot.create(recursive: true);
'imgtest', 'add', await _runCommands(
'--work-dir', _workDirectory.childDirectory('temp').path, <String>[
'--test-name', testName, 'git init',
'--png-file', goldenFile.path, 'git remote add upstream https://github.com/flutter/goldens.git',
]; 'git remote set-url --push upstream git@github.com:flutter/goldens.git',
],
workingDirectory: repositoryRoot,
);
}
if(imgtestArguments.contains(null)) { Future<void> _checkCanSync() async {
final io.ProcessResult result = await process.run(
<String>['git', 'status', '--porcelain'],
workingDirectory: repositoryRoot.path,
);
if (result.stdout.trim().isNotEmpty) {
final StringBuffer buf = StringBuffer(); final StringBuffer buf = StringBuffer();
buf.writeln('Null argument for Skia Gold imgtest add:'); buf
imgtestArguments.forEach(buf.writeln); ..writeln('flutter_goldens git checkout at ${repositoryRoot.path} has local changes and cannot be synced.')
..writeln('To reset your client to a clean state, and lose any local golden test changes:')
..writeln('cd ${repositoryRoot.path}')
..writeln('git reset --hard HEAD')
..writeln('git clean -x -d -f -f');
throw NonZeroExitCode(1, buf.toString()); throw NonZeroExitCode(1, buf.toString());
} }
}
final io.ProcessResult imgtestResult = io.Process.runSync( Future<void> _syncTo(String commit) async {
_goldctl, await _runCommands(
imgtestArguments, <String>[
'git pull upstream master',
'git fetch upstream $commit',
'git reset --hard FETCH_HEAD',
],
workingDirectory: repositoryRoot,
); );
if (imgtestResult.exitCode != 0) {
final StringBuffer buf = StringBuffer();
buf
..writeln('Flutter + Skia Gold imgtest add failed.')
..writeln('If this is the first execution of this test, it may need to be triaged.')
..writeln('In this case, re-run the test after triage is completed.\n')
..writeln('stdout: ${imgtestResult.stdout}')
..writeln('stderr: ${imgtestResult.stderr}');
throw NonZeroExitCode(imgtestResult.exitCode, buf.toString());
}
return true;
} }
Future<String> _getCommitHash() async { Future<void> _runCommands(
// TODO(Piinks): Remove after pre-commit tests can be ingested by Skia Gold, https://github.com/flutter/flutter/pull/31630 List<String> commands, {
return 'e51947241b37790a9e4e33bfdef59aaa9b930851'; Directory workingDirectory,
// if (!flutterRoot.existsSync()) { }) async {
// return null; for (String command in commands) {
// } else { final List<String> parts = command.split(' ');
// final io.ProcessResult revParse = await process.run( final io.ProcessResult result = await process.run(
// <String>['git', 'rev-parse', 'HEAD'], parts,
// workingDirectory: flutterRoot.path, workingDirectory: workingDirectory?.path,
// ); );
// return revParse.exitCode == 0 ? revParse.stdout.trim() : null; if (result.exitCode != 0) {
throw NonZeroExitCode(result.exitCode, result.stderr);
}
}
} }
Future<bool> _isNewCommit() async { Future<void> _obtainLock() async {
// auth file is there, need to check if we are on a new commit final File lockFile = flutterRoot.childFile(fs.path.join('bin', 'cache', 'goldens.lockfile'));
final File resultFile = _workDirectory.childFile(fs.path.join( await lockFile.create(recursive: true);
'temp', _lock = await lockFile.open(mode: io.FileMode.write);
'result-state.json' await _lock.lock(io.FileLock.blockingExclusive);
));
final String contents = await resultFile.readAsString();
final Map<String, dynamic> resultJSON = convert.json.decode(contents);
final String lastTestedCommit = resultJSON['SharedConfig']['gitHash'];
final String currentCommit = await _getCommitHash();
return lastTestedCommit == currentCommit ? false : true;
} }
String _getKeysJSON() { Future<void> _releaseLock() async {
// TODO(Piinks): Parse out cleaner key information, https://github.com/flutter/flutter/pull/31630 await _lock.close();
return convert.json.encode( _lock = null;
<String, dynamic>{
'Operating System' : io.Platform.operatingSystem,
'Operating System Version' : io.Platform.operatingSystemVersion,
'Dart Version' : io.Platform.version,
});
} }
} }
/// Exception that signals a process' exit with a non-zero exit code. /// Exception that signals a process' exit with a non-zero exit code.
...@@ -242,4 +193,4 @@ class NonZeroExitCode implements Exception { ...@@ -242,4 +193,4 @@ class NonZeroExitCode implements Exception {
String toString() { String toString() {
return 'Exit code $exitCode: $stderr'; return 'Exit code $exitCode: $stderr';
} }
} }
\ No newline at end of file
...@@ -332,43 +332,6 @@ AsyncMatcher matchesGoldenFile(dynamic key) { ...@@ -332,43 +332,6 @@ AsyncMatcher matchesGoldenFile(dynamic key) {
throw ArgumentError('Unexpected type for golden file: ${key.runtimeType}'); 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 /// Asserts that a [Finder], [Future<ui.Image>], or [ui.Image] matches a
/// reference image identified by [image]. /// reference image identified by [image].
/// ///
...@@ -1763,53 +1726,6 @@ class _MatchesGoldenFile extends AsyncMatcher { ...@@ -1763,53 +1726,6 @@ class _MatchesGoldenFile extends AsyncMatcher {
description.add('one widget whose rasterized image matches golden image "$key"'); 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 { class _MatchesSemanticsData extends Matcher {
_MatchesSemanticsData({ _MatchesSemanticsData({
this.label, this.label,
......
...@@ -402,88 +402,6 @@ void main() { ...@@ -402,88 +402,6 @@ 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', () { group('matchesSemanticsData', () {
testWidgets('matches SemanticsData', (WidgetTester tester) async { testWidgets('matches SemanticsData', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics(); final SemanticsHandle handle = tester.ensureSemantics();
......
...@@ -6,6 +6,7 @@ import 'dart:async'; ...@@ -6,6 +6,7 @@ import 'dart:async';
import 'dart:collection'; import 'dart:collection';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:flutter_goldens_client/client.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
...@@ -138,14 +139,13 @@ class UpdatePackagesCommand extends FlutterCommand { ...@@ -138,14 +139,13 @@ class UpdatePackagesCommand extends FlutterCommand {
// The dev/integration_tests/android_views integration test depends on an assets // 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 // 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. // repository is cloned locally before we verify or update pubspecs.
// TODO(katelovett): Resolve dependency for android_views living in goldens repository printStatus('Cloning goldens repository...');
// printStatus('Cloning goldens repository...'); try {
// try { final GoldensClient goldensClient = GoldensClient();
// final GoldensClient goldensClient = GoldensClient(); await goldensClient.prepare();
// await goldensClient.prepare(); } on NonZeroExitCode catch (e) {
// } on NonZeroExitCode catch (e) { throwToolExit(e.stderr, exitCode: e.exitCode);
// throwToolExit(e.stderr, exitCode: e.exitCode); }
// }
if (isVerifyOnly) { if (isVerifyOnly) {
bool needsUpdate = false; 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