mirrored_repositories/awesome-flutter/examples/plugins/packages/google_maps_flutter/google_maps_flutter_web/example
// Copyright 2013 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:async';
import 'dart:ui';
import 'dart:html' as html;

import 'package:integration_test/integration_test.dart';
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
import 'package:google_maps_flutter_web/google_maps_flutter_web.dart';
import 'package:google_maps/google_maps.dart' as gmaps;
import 'package:google_maps/google_maps_geometry.dart' as geometry;
import 'package:flutter_test/flutter_test.dart';

// This value is used when comparing the results of
// converting from a byte value to a double between 0 and 1.
// (For Color opacity values, for example)
const _acceptableDelta = 0.01;

/// Test Shapes (Circle, Polygon, Polyline)
void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  late gmaps.GMap map;

  setUp(() {
    map = gmaps.GMap(html.DivElement());
  });

  group('CirclesController', () {
    late StreamController<MapEvent> events;
    late CirclesController controller;

    setUp(() {
      events = StreamController<MapEvent>();
      controller = CirclesController(stream: events);
      controller.bindToMap(123, map);
    });

    testWidgets('addCircles', (WidgetTester tester) async {
      final circles = {
        Circle(circleId: CircleId('1')),
        Circle(circleId: CircleId('2')),
      };

      controller.addCircles(circles);

      expect(controller.circles.length, 2);
      expect(controller.circles, contains(CircleId('1')));
      expect(controller.circles, contains(CircleId('2')));
      expect(controller.circles, isNot(contains(CircleId('66'))));
    });

    testWidgets('changeCircles', (WidgetTester tester) async {
      final circles = {
        Circle(circleId: CircleId('1')),
      };
      controller.addCircles(circles);

      expect(controller.circles[CircleId('1')]?.circle?.visible, isTrue);

      final updatedCircles = {
        Circle(circleId: CircleId('1'), visible: false),
      };
      controller.changeCircles(updatedCircles);

      expect(controller.circles.length, 1);
      expect(controller.circles[CircleId('1')]?.circle?.visible, isFalse);
    });

    testWidgets('removeCircles', (WidgetTester tester) async {
      final circles = {
        Circle(circleId: CircleId('1')),
        Circle(circleId: CircleId('2')),
        Circle(circleId: CircleId('3')),
      };

      controller.addCircles(circles);

      expect(controller.circles.length, 3);

      // Remove some circles...
      final circleIdsToRemove = {
        CircleId('1'),
        CircleId('3'),
      };

      controller.removeCircles(circleIdsToRemove);

      expect(controller.circles.length, 1);
      expect(controller.circles, isNot(contains(CircleId('1'))));
      expect(controller.circles, contains(CircleId('2')));
      expect(controller.circles, isNot(contains(CircleId('3'))));
    });

    testWidgets('Converts colors to CSS', (WidgetTester tester) async {
      final circles = {
        Circle(
          circleId: CircleId('1'),
          fillColor: Color(0x7FFABADA),
          strokeColor: Color(0xFFC0FFEE),
        ),
      };

      controller.addCircles(circles);

      final circle = controller.circles.values.first.circle!;

      expect(circle.get('fillColor'), '#fabada');
      expect(circle.get('fillOpacity'), closeTo(0.5, _acceptableDelta));
      expect(circle.get('strokeColor'), '#c0ffee');
      expect(circle.get('strokeOpacity'), closeTo(1, _acceptableDelta));
    });
  });

  group('PolygonsController', () {
    late StreamController<MapEvent> events;
    late PolygonsController controller;

    setUp(() {
      events = StreamController<MapEvent>();
      controller = PolygonsController(stream: events);
      controller.bindToMap(123, map);
    });

    testWidgets('addPolygons', (WidgetTester tester) async {
      final polygons = {
        Polygon(polygonId: PolygonId('1')),
        Polygon(polygonId: PolygonId('2')),
      };

      controller.addPolygons(polygons);

      expect(controller.polygons.length, 2);
      expect(controller.polygons, contains(PolygonId('1')));
      expect(controller.polygons, contains(PolygonId('2')));
      expect(controller.polygons, isNot(contains(PolygonId('66'))));
    });

    testWidgets('changePolygons', (WidgetTester tester) async {
      final polygons = {
        Polygon(polygonId: PolygonId('1')),
      };
      controller.addPolygons(polygons);

      expect(controller.polygons[PolygonId('1')]?.polygon?.visible, isTrue);

      // Update the polygon
      final updatedPolygons = {
        Polygon(polygonId: PolygonId('1'), visible: false),
      };
      controller.changePolygons(updatedPolygons);

      expect(controller.polygons.length, 1);
      expect(controller.polygons[PolygonId('1')]?.polygon?.visible, isFalse);
    });

    testWidgets('removePolygons', (WidgetTester tester) async {
      final polygons = {
        Polygon(polygonId: PolygonId('1')),
        Polygon(polygonId: PolygonId('2')),
        Polygon(polygonId: PolygonId('3')),
      };

      controller.addPolygons(polygons);

      expect(controller.polygons.length, 3);

      // Remove some polygons...
      final polygonIdsToRemove = {
        PolygonId('1'),
        PolygonId('3'),
      };

      controller.removePolygons(polygonIdsToRemove);

      expect(controller.polygons.length, 1);
      expect(controller.polygons, isNot(contains(PolygonId('1'))));
      expect(controller.polygons, contains(PolygonId('2')));
      expect(controller.polygons, isNot(contains(PolygonId('3'))));
    });

    testWidgets('Converts colors to CSS', (WidgetTester tester) async {
      final polygons = {
        Polygon(
          polygonId: PolygonId('1'),
          fillColor: Color(0x7FFABADA),
          strokeColor: Color(0xFFC0FFEE),
        ),
      };

      controller.addPolygons(polygons);

      final polygon = controller.polygons.values.first.polygon!;

      expect(polygon.get('fillColor'), '#fabada');
      expect(polygon.get('fillOpacity'), closeTo(0.5, _acceptableDelta));
      expect(polygon.get('strokeColor'), '#c0ffee');
      expect(polygon.get('strokeOpacity'), closeTo(1, _acceptableDelta));
    });

    testWidgets('Handle Polygons with holes', (WidgetTester tester) async {
      final polygons = {
        Polygon(
          polygonId: PolygonId('BermudaTriangle'),
          points: [
            LatLng(25.774, -80.19),
            LatLng(18.466, -66.118),
            LatLng(32.321, -64.757),
          ],
          holes: [
            [
              LatLng(28.745, -70.579),
              LatLng(29.57, -67.514),
              LatLng(27.339, -66.668),
            ],
          ],
        ),
      };

      controller.addPolygons(polygons);

      expect(controller.polygons.length, 1);
      expect(controller.polygons, contains(PolygonId('BermudaTriangle')));
      expect(controller.polygons, isNot(contains(PolygonId('66'))));
    });

    testWidgets('Polygon with hole has a hole', (WidgetTester tester) async {
      final polygons = {
        Polygon(
          polygonId: PolygonId('BermudaTriangle'),
          points: [
            LatLng(25.774, -80.19),
            LatLng(18.466, -66.118),
            LatLng(32.321, -64.757),
          ],
          holes: [
            [
              LatLng(28.745, -70.579),
              LatLng(29.57, -67.514),
              LatLng(27.339, -66.668),
            ],
          ],
        ),
      };

      controller.addPolygons(polygons);

      final polygon = controller.polygons.values.first.polygon;
      final pointInHole = gmaps.LatLng(28.632, -68.401);

      expect(geometry.Poly.containsLocation(pointInHole, polygon), false);
    });

    testWidgets('Hole Path gets reversed to display correctly',
        (WidgetTester tester) async {
      final polygons = {
        Polygon(
          polygonId: PolygonId('BermudaTriangle'),
          points: [
            LatLng(25.774, -80.19),
            LatLng(18.466, -66.118),
            LatLng(32.321, -64.757),
          ],
          holes: [
            [
              LatLng(27.339, -66.668),
              LatLng(29.57, -67.514),
              LatLng(28.745, -70.579),
            ],
          ],
        ),
      };

      controller.addPolygons(polygons);

      final paths = controller.polygons.values.first.polygon!.paths!;

      expect(paths.getAt(1)?.getAt(0)?.lat, 28.745);
      expect(paths.getAt(1)?.getAt(1)?.lat, 29.57);
      expect(paths.getAt(1)?.getAt(2)?.lat, 27.339);
    });
  });

  group('PolylinesController', () {
    late StreamController<MapEvent> events;
    late PolylinesController controller;

    setUp(() {
      events = StreamController<MapEvent>();
      controller = PolylinesController(stream: events);
      controller.bindToMap(123, map);
    });

    testWidgets('addPolylines', (WidgetTester tester) async {
      final polylines = {
        Polyline(polylineId: PolylineId('1')),
        Polyline(polylineId: PolylineId('2')),
      };

      controller.addPolylines(polylines);

      expect(controller.lines.length, 2);
      expect(controller.lines, contains(PolylineId('1')));
      expect(controller.lines, contains(PolylineId('2')));
      expect(controller.lines, isNot(contains(PolylineId('66'))));
    });

    testWidgets('changePolylines', (WidgetTester tester) async {
      final polylines = {
        Polyline(polylineId: PolylineId('1')),
      };
      controller.addPolylines(polylines);

      expect(controller.lines[PolylineId('1')]?.line?.visible, isTrue);

      final updatedPolylines = {
        Polyline(polylineId: PolylineId('1'), visible: false),
      };
      controller.changePolylines(updatedPolylines);

      expect(controller.lines.length, 1);
      expect(controller.lines[PolylineId('1')]?.line?.visible, isFalse);
    });

    testWidgets('removePolylines', (WidgetTester tester) async {
      final polylines = {
        Polyline(polylineId: PolylineId('1')),
        Polyline(polylineId: PolylineId('2')),
        Polyline(polylineId: PolylineId('3')),
      };

      controller.addPolylines(polylines);

      expect(controller.lines.length, 3);

      // Remove some polylines...
      final polylineIdsToRemove = {
        PolylineId('1'),
        PolylineId('3'),
      };

      controller.removePolylines(polylineIdsToRemove);

      expect(controller.lines.length, 1);
      expect(controller.lines, isNot(contains(PolylineId('1'))));
      expect(controller.lines, contains(PolylineId('2')));
      expect(controller.lines, isNot(contains(PolylineId('3'))));
    });

    testWidgets('Converts colors to CSS', (WidgetTester tester) async {
      final lines = {
        Polyline(
          polylineId: PolylineId('1'),
          color: Color(0x7FFABADA),
        ),
      };

      controller.addPolylines(lines);

      final line = controller.lines.values.first.line!;

      expect(line.get('strokeColor'), '#fabada');
      expect(line.get('strokeOpacity'), closeTo(0.5, _acceptableDelta));
    });
  });
}
