// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'dart:math' as math; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/painting.dart'; void main() { group('CircularNotchedRectangle', () { test("guest and host don't overlap", () { const CircularNotchedRectangle shape = CircularNotchedRectangle(); const Rect host = Rect.fromLTRB(0.0, 100.0, 300.0, 300.0); const Rect guest = Rect.fromLTWH(50.0, 50.0, 10.0, 10.0); final Path actualPath = shape.getOuterPath(host, guest); final Path expectedPath = Path()..addRect(host); expect( actualPath, coversSameAreaAs( expectedPath, areaToCompare: host.inflate(5.0), sampleSize: 40, ), ); }); test('guest center above host', () { const CircularNotchedRectangle shape = CircularNotchedRectangle(); const Rect host = Rect.fromLTRB(0.0, 100.0, 300.0, 300.0); const Rect guest = Rect.fromLTRB(190.0, 85.0, 210.0, 105.0); final Path actualPath = shape.getOuterPath(host, guest); expect(pathDoesNotContainCircle(actualPath, guest), isTrue); }); test('guest center below host', () { const CircularNotchedRectangle shape = CircularNotchedRectangle(); const Rect host = Rect.fromLTRB(0.0, 100.0, 300.0, 300.0); const Rect guest = Rect.fromLTRB(190.0, 95.0, 210.0, 115.0); final Path actualPath = shape.getOuterPath(host, guest); expect(pathDoesNotContainCircle(actualPath, guest), isTrue); }); test('no guest is ok', () { const Rect host = Rect.fromLTRB(0.0, 100.0, 300.0, 300.0); expect( const CircularNotchedRectangle().getOuterPath(host, null), coversSameAreaAs( Path()..addRect(host), areaToCompare: host.inflate(800.0), sampleSize: 100, ), ); }); test('AutomaticNotchedShape - with guest', () { expect( const AutomaticNotchedShape( RoundedRectangleBorder(), RoundedRectangleBorder(), ).getOuterPath( const Rect.fromLTWH(-200.0, -100.0, 50.0, 100.0), const Rect.fromLTWH(-175.0, -110.0, 100.0, 100.0), ), coversSameAreaAs( Path() ..moveTo(-200.0, -100.0) ..lineTo(-150.0, -100.0) ..lineTo(-150.0, -10.0) ..lineTo(-175.0, -10.0) ..lineTo(-175.0, 0.0) ..lineTo(-200.0, 0.0) ..close(), areaToCompare: const Rect.fromLTWH(-300.0, -300.0, 600.0, 600.0), sampleSize: 100, ), ); }, skip: isBrowser); test('AutomaticNotchedShape - no guest', () { expect( const AutomaticNotchedShape( RoundedRectangleBorder(), RoundedRectangleBorder(), ).getOuterPath( const Rect.fromLTWH(-200.0, -100.0, 50.0, 100.0), null, ), coversSameAreaAs( Path() ..moveTo(-200.0, -100.0) ..lineTo(-150.0, -100.0) ..lineTo(-150.0, 0.0) ..lineTo(-200.0, 0.0) ..close(), areaToCompare: const Rect.fromLTWH(-300.0, -300.0, 600.0, 600.0), sampleSize: 100, ), ); }); }); } bool pathDoesNotContainCircle(Path path, Rect circleBounds) { assert(circleBounds.width == circleBounds.height); final double radius = circleBounds.width / 2.0; for (double theta = 0.0; theta <= 2.0 * math.pi; theta += math.pi / 20.0) { for (double i = 0.0; i < 1; i += 0.01) { final double x = i * radius * math.cos(theta); final double y = i * radius * math.sin(theta); if (path.contains(Offset(x,y) + circleBounds.center)) return false; } } return true; }