import 'dart:io'; import 'dart:typed_data'; import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:hepan_everyday/app/tp_launch_page.dart'; import 'package:hepan_everyday/widgets/tp_logo.dart'; void main() { testWidgets('logo preserves calendar, bindings and smile from supplied art', ( tester, ) async { final boundaryKey = GlobalKey(); await tester.pumpWidget( MaterialApp( home: Center( child: RepaintBoundary( key: boundaryKey, child: const TpLogo(size: 200), ), ), ), ); final pixels = await _capture(tester, boundaryKey, 'tpschedule-logo'); expect(_pixel(pixels, 200, 40, 100), [255, 210, 42, 255]); expect(_pixel(pixels, 200, 73, 50), [255, 255, 255, 255]); expect(_pixel(pixels, 200, 100, 115), [255, 255, 255, 255]); final background = _pixel(pixels, 200, 10, 100); expect(background[2], closeTo(255, 3)); expect(background[0], inInclusiveRange(42, 63)); expect(background[1], inInclusiveRange(108, 209)); }); testWidgets('foreground logo leaves its surround transparent', ( tester, ) async { final boundaryKey = GlobalKey(); await tester.pumpWidget( MaterialApp( home: Center( child: RepaintBoundary( key: boundaryKey, child: const TpLogo(size: 200, background: false), ), ), ), ); final pixels = await _capture(tester, boundaryKey); expect(_pixel(pixels, 200, 10, 10)[3], 0); expect(_pixel(pixels, 200, 40, 100), [255, 210, 42, 255]); }); testWidgets('launch fills the screen with brand blue in dark mode', ( tester, ) async { final boundaryKey = GlobalKey(); await tester.pumpWidget( MaterialApp( theme: ThemeData.dark(), home: RepaintBoundary(key: boundaryKey, child: const TpLaunchPage()), ), ); expect(find.text('TPSchedule'), findsOneWidget); final logo = tester.widget(find.byType(TpLogo)); expect(logo.background, isFalse); final pixels = await _capture(tester, boundaryKey, 'tpschedule-launch'); for (final point in [const Offset(10, 10), const Offset(790, 590)]) { final pixel = _pixel(pixels, 800, point.dx.toInt(), point.dy.toInt()); expect(pixel[2], closeTo(255, 3)); expect(pixel[0], inInclusiveRange(42, 63)); expect(pixel[1], inInclusiveRange(108, 209)); expect(pixel[3], 255); } expect(tester.takeException(), isNull); }); } Future _capture( WidgetTester tester, GlobalKey key, [ String? previewName, ]) async { final boundary = key.currentContext!.findRenderObject()! as RenderRepaintBoundary; return (await tester.runAsync(() async { final image = await boundary.toImage(pixelRatio: 1); final bytes = await image.toByteData(format: ui.ImageByteFormat.rawRgba); if (const bool.fromEnvironment('TP_BRAND_PREVIEW') && previewName != null) { final png = await image.toByteData(format: ui.ImageByteFormat.png); final output = File('../dist/screenshots/$previewName.png'); await output.parent.create(recursive: true); await output.writeAsBytes(png!.buffer.asUint8List()); } image.dispose(); return bytes!.buffer.asUint8List(); }))!; } List _pixel(Uint8List pixels, int width, int x, int y) => pixels.sublist((y * width + x) * 4, (y * width + x) * 4 + 4);