// 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.

// @dart = 2.8

import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import '../rendering/mock_canvas.dart';
import '../widgets/semantics_tester.dart';

int count = 0;

void main() {
  testWidgets('Middle still in center with asymmetrical actions', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoNavigationBar(
          leading: CupertinoButton(child: Text('Something'), onPressed: null,),
          middle: Text('Title'),
        ),
      ),
    );

    // Expect the middle of the title to be exactly in the middle of the screen.
    expect(tester.getCenter(find.text('Title')).dx, 400.0);
  });

  testWidgets('Middle still in center with back button', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoNavigationBar(
          middle: Text('Title'),
        ),
      ),
    );

    tester.state<NavigatorState>(find.byType(Navigator)).push(CupertinoPageRoute<void>(
      builder: (BuildContext context) {
        return const CupertinoNavigationBar(
          middle: Text('Page 2'),
        );
      },
    ));

    await tester.pump();
    await tester.pump(const Duration(milliseconds: 500));

    // Expect the middle of the title to be exactly in the middle of the screen.
    expect(tester.getCenter(find.text('Page 2')).dx, 400.0);
  });

  testWidgets('Opaque background does not add blur effects, non-opaque background adds blur effects', (WidgetTester tester) async {
    const CupertinoDynamicColor background = CupertinoDynamicColor.withBrightness(
      color: Color(0xFFE5E5E5),
      darkColor: Color(0xF3E5E5E5),
    );

    await tester.pumpWidget(
      const CupertinoApp(
        theme: CupertinoThemeData(brightness: Brightness.light),
        home: CupertinoNavigationBar(
          middle: Text('Title'),
          backgroundColor: background,
        ),
      ),
    );
    expect(find.byType(BackdropFilter), findsNothing);
    expect(find.byType(CupertinoNavigationBar), paints..rect(color: background.color));

    await tester.pumpWidget(
      const CupertinoApp(
        theme: CupertinoThemeData(brightness: Brightness.dark),
        home: CupertinoNavigationBar(
          middle: Text('Title'),
          backgroundColor: background,
        ),
      ),
    );
    expect(find.byType(BackdropFilter), findsOneWidget);
    expect(find.byType(CupertinoNavigationBar), paints..rect(color: background.darkColor));
  });

  testWidgets('Non-opaque background adds blur effects', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoNavigationBar(
          middle: Text('Title'),
        ),
      ),
    );
    expect(find.byType(BackdropFilter), findsOneWidget);
  });

  testWidgets('Can specify custom padding', (WidgetTester tester) async {
    final Key middleBox = GlobalKey();
    await tester.pumpWidget(
      CupertinoApp(
        home: Align(
          alignment: Alignment.topCenter,
          child: CupertinoNavigationBar(
            leading: const CupertinoButton(child: Text('Cheetah'), onPressed: null),
            // Let the box take all the vertical space to test vertical padding but let
            // the nav bar position it horizontally.
            middle: Align(
              key: middleBox,
              alignment: Alignment.center,
              widthFactor: 1.0,
              child: const Text('Title'),
            ),
            trailing: const CupertinoButton(child: Text('Puma'), onPressed: null),
            padding: const EdgeInsetsDirectional.only(
              start: 10.0,
              end: 20.0,
              top: 3.0,
              bottom: 4.0,
            ),
          ),
        ),
      ),
    );

    expect(tester.getRect(find.byKey(middleBox)).top, 3.0);
    // 44 is the standard height of the nav bar.
    expect(
      tester.getRect(find.byKey(middleBox)).bottom,
      // 44 is the standard height of the nav bar.
      44.0 - 4.0,
    );

    expect(tester.getTopLeft(find.widgetWithText(CupertinoButton, 'Cheetah')).dx, 10.0);
    expect(tester.getTopRight(find.widgetWithText(CupertinoButton, 'Puma')).dx, 800.0 - 20.0);

    // Title is still exactly centered.
    expect(tester.getCenter(find.text('Title')).dx, 400.0);
  });

  testWidgets('Can specify custom brightness', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoNavigationBar(
          backgroundColor: Color(0xF0F9F9F9),
          brightness: Brightness.dark,
        ),
      ),
    );

    final AnnotatedRegion<SystemUiOverlayStyle> region1 = tester.allWidgets
        .whereType<AnnotatedRegion<SystemUiOverlayStyle>>()
        .single;
    expect(region1.value, SystemUiOverlayStyle.light);

    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoNavigationBar(
          backgroundColor: Color(0xF01D1D1D),
          brightness: Brightness.light,
        ),
      ),
    );

    final AnnotatedRegion<SystemUiOverlayStyle> region2 = tester.allWidgets
        .whereType<AnnotatedRegion<SystemUiOverlayStyle>>()
        .single;
    expect(region2.value, SystemUiOverlayStyle.dark);

    await tester.pumpWidget(
      const CupertinoApp(
        home: CustomScrollView(
          slivers: <Widget>[
            CupertinoSliverNavigationBar(
              largeTitle: Text('Title'),
              backgroundColor: Color(0xF0F9F9F9),
              brightness: Brightness.dark,
            )
          ],
        ),
      ),
    );

    final AnnotatedRegion<SystemUiOverlayStyle> region3 = tester.allWidgets
        .whereType<AnnotatedRegion<SystemUiOverlayStyle>>()
        .single;
    expect(region3.value, SystemUiOverlayStyle.light);

    await tester.pumpWidget(
      const CupertinoApp(
        home: CustomScrollView(
          slivers: <Widget>[
            CupertinoSliverNavigationBar(
              largeTitle: Text('Title'),
              backgroundColor: Color(0xF01D1D1D),
              brightness: Brightness.light,
            )
          ],
        ),
      ),
    );

    final AnnotatedRegion<SystemUiOverlayStyle> region4 = tester.allWidgets
        .whereType<AnnotatedRegion<SystemUiOverlayStyle>>()
        .single;
    expect(region4.value, SystemUiOverlayStyle.dark);
  });

  testWidgets('Padding works in RTL', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: Align(
            alignment: Alignment.topCenter,
            child: CupertinoNavigationBar(
              leading: CupertinoButton(child: Text('Cheetah'), onPressed: null),
              // Let the box take all the vertical space to test vertical padding but let
              // the nav bar position it horizontally.
              middle: Text('Title'),
              trailing: CupertinoButton(child: Text('Puma'), onPressed: null),
              padding: EdgeInsetsDirectional.only(
                start: 10.0,
                end: 20.0,
              ),
            ),
          ),
        ),
      ),
    );

    expect(tester.getTopRight(find.widgetWithText(CupertinoButton, 'Cheetah')).dx, 800.0 - 10.0);
    expect(tester.getTopLeft(find.widgetWithText(CupertinoButton, 'Puma')).dx, 20.0);

    // Title is still exactly centered.
    expect(tester.getCenter(find.text('Title')).dx, 400.0);
  });

  testWidgets('Nav bar uses theme defaults', (WidgetTester tester) async {
    count = 0x000000;
    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoNavigationBar(
          leading: CupertinoButton(
            onPressed: () { },
            child: _ExpectStyles(color: CupertinoColors.systemBlue.color, index: 0x000001),
          ),
          middle: const _ExpectStyles(color: CupertinoColors.black, index: 0x000100),
          trailing: CupertinoButton(
            onPressed: () { },
            child: _ExpectStyles(color: CupertinoColors.systemBlue.color, index: 0x010000),
          ),
        ),
      ),
    );
    expect(count, 0x010101);
  });

  testWidgets('Nav bar respects themes', (WidgetTester tester) async {
    count = 0x000000;
    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(brightness: Brightness.dark),
        home: CupertinoNavigationBar(
          leading: CupertinoButton(
            onPressed: () { },
            child: _ExpectStyles(color: CupertinoColors.systemBlue.darkColor, index: 0x000001),
          ),
          middle: const _ExpectStyles(color: CupertinoColors.white, index: 0x000100),
          trailing: CupertinoButton(
            onPressed: () { },
            child: _ExpectStyles(color: CupertinoColors.systemBlue.darkColor, index: 0x010000),
          ),
        ),
      ),
    );
    expect(count, 0x010101);
  });

  testWidgets('Theme active color can be overridden', (WidgetTester tester) async {
    count = 0x000000;
    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoNavigationBar(
          leading: CupertinoButton(
            onPressed: () { },
            child: const _ExpectStyles(color: Color(0xFF001122), index: 0x000001),
          ),
          middle: const _ExpectStyles(color: Color(0xFF000000), index: 0x000100),
          trailing: CupertinoButton(
            onPressed: () { },
            child: const _ExpectStyles(color: Color(0xFF001122), index: 0x010000),
          ),
          actionsForegroundColor: const Color(0xFF001122),
        ),
      ),
    );
    expect(count, 0x010101);
  });

  testWidgets('No slivers with no large titles', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoPageScaffold(
          navigationBar: CupertinoNavigationBar(
            middle: Text('Title'),
          ),
          child: Center(),
        ),
      ),
    );

    expect(find.byType(SliverPersistentHeader), findsNothing);
  });

  testWidgets('Media padding is applied to CupertinoSliverNavigationBar', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController();
    final Key leadingKey = GlobalKey();
    final Key middleKey = GlobalKey();
    final Key trailingKey = GlobalKey();
    final Key titleKey = GlobalKey();
    await tester.pumpWidget(
      CupertinoApp(
        home: MediaQuery(
          data: const MediaQueryData(
            padding: EdgeInsets.only(
              top: 10.0,
              left: 20.0,
              bottom: 30.0,
              right: 40.0,
            ),
          ),
          child: CupertinoPageScaffold(
            child: CustomScrollView(
              controller: scrollController,
              slivers: <Widget>[
                CupertinoSliverNavigationBar(
                  leading: Placeholder(key: leadingKey),
                  middle: Placeholder(key: middleKey),
                  largeTitle: Text('Large Title', key: titleKey),
                  trailing: Placeholder(key: trailingKey),
                ),
                SliverToBoxAdapter(
                  child: Container(
                    height: 1200.0,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );

    // Media padding applied to leading (T,L), middle (T), trailing (T, R).
    expect(tester.getTopLeft(find.byKey(leadingKey)), const Offset(16.0 + 20.0, 10.0));
    expect(tester.getRect(find.byKey(middleKey)).top, 10.0);
    expect(tester.getTopRight(find.byKey(trailingKey)), const Offset(800.0 - 16.0 - 40.0, 10.0));

    // Top and left padding is applied to large title.
    expect(tester.getTopLeft(find.byKey(titleKey)), const Offset(16.0 + 20.0, 54.0 + 10.0));
  });

  testWidgets('Large title nav bar scrolls', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController();
    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoPageScaffold(
          child: CustomScrollView(
            controller: scrollController,
            slivers: <Widget>[
              const CupertinoSliverNavigationBar(
                largeTitle: Text('Title'),
              ),
              SliverToBoxAdapter(
                child: Container(
                  height: 1200.0,
                ),
              ),
            ],
          ),
        ),
      ),
    );

    expect(scrollController.offset, 0.0);
    expect(tester.getTopLeft(find.byType(NavigationToolbar)).dy, 0.0);
    expect(tester.getSize(find.byType(NavigationToolbar)).height, 44.0);

    expect(find.text('Title'), findsNWidgets(2)); // Though only one is visible.

    List<Element> titles = tester.elementList(find.text('Title'))
        .toList()
        ..sort((Element a, Element b) {
          final RenderParagraph aParagraph = a.renderObject as RenderParagraph;
          final RenderParagraph bParagraph = b.renderObject as RenderParagraph;
          return aParagraph.text.style.fontSize.compareTo(bParagraph.text.style.fontSize);
        });

    Iterable<double> opacities = titles.map<double>((Element element) {
      final RenderAnimatedOpacity renderOpacity = element.findAncestorRenderObjectOfType<RenderAnimatedOpacity>();
      return renderOpacity.opacity.value;
    });

    expect(opacities, <double> [
      0.0, // Initially the smaller font title is invisible.
      1.0, // The larger font title is visible.
    ]);

    expect(tester.getTopLeft(find.widgetWithText(OverflowBox, 'Title')).dy, 44.0);
    expect(tester.getSize(find.widgetWithText(OverflowBox, 'Title')).height, 52.0);

    scrollController.jumpTo(600.0);
    await tester.pump(); // Once to trigger the opacity animation.
    await tester.pump(const Duration(milliseconds: 300));

    titles = tester.elementList(find.text('Title'))
        .toList()
        ..sort((Element a, Element b) {
          final RenderParagraph aParagraph = a.renderObject as RenderParagraph;
          final RenderParagraph bParagraph = b.renderObject as RenderParagraph;
          return aParagraph.text.style.fontSize.compareTo(bParagraph.text.style.fontSize);
        });

    opacities = titles.map<double>((Element element) {
      final RenderAnimatedOpacity renderOpacity = element.findAncestorRenderObjectOfType<RenderAnimatedOpacity>();
      return renderOpacity.opacity.value;
    });

    expect(opacities, <double> [
      1.0, // Smaller font title now visible
      0.0, // Larger font title invisible.
    ]);

    // The persistent toolbar doesn't move or change size.
    expect(tester.getTopLeft(find.byType(NavigationToolbar)).dy, 0.0);
    expect(tester.getSize(find.byType(NavigationToolbar)).height, 44.0);

    expect(tester.getTopLeft(find.widgetWithText(OverflowBox, 'Title')).dy, 44.0);
    // The OverflowBox is squished with the text in it.
    expect(tester.getSize(find.widgetWithText(OverflowBox, 'Title')).height, 0.0);
  });

  testWidgets('User specified middle is always visible in sliver', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController();
    final Key segmentedControlsKey = UniqueKey();
    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoPageScaffold(
          child: CustomScrollView(
            controller: scrollController,
            slivers: <Widget>[
              CupertinoSliverNavigationBar(
                middle: ConstrainedBox(
                  constraints: const BoxConstraints(maxWidth: 200.0),
                  child: CupertinoSegmentedControl<int>(
                    key: segmentedControlsKey,
                    children: const <int, Widget>{
                      0: Text('Option A'),
                      1: Text('Option B'),
                    },
                    onValueChanged: (int selected) { },
                    groupValue: 0,
                  ),
                ),
                largeTitle: const Text('Title'),
              ),
              SliverToBoxAdapter(
                child: Container(
                  height: 1200.0,
                ),
              ),
            ],
          ),
        ),
      ),
    );

    expect(scrollController.offset, 0.0);
    expect(tester.getTopLeft(find.byType(NavigationToolbar)).dy, 0.0);
    expect(tester.getSize(find.byType(NavigationToolbar)).height, 44.0);

    expect(find.text('Title'), findsOneWidget);
    expect(tester.getCenter(find.byKey(segmentedControlsKey)).dx, 400.0);

    expect(tester.getTopLeft(find.widgetWithText(OverflowBox, 'Title')).dy, 44.0);
    expect(tester.getSize(find.widgetWithText(OverflowBox, 'Title')).height, 52.0);

    scrollController.jumpTo(600.0);
    await tester.pump(); // Once to trigger the opacity animation.
    await tester.pump(const Duration(milliseconds: 300));

    expect(tester.getCenter(find.byKey(segmentedControlsKey)).dx, 400.0);
    // The large title is invisible now.
    expect(
      tester.renderObject<RenderAnimatedOpacity>(
        find.widgetWithText(AnimatedOpacity, 'Title')
      ).opacity.value,
      0.0,
    );
  });

  testWidgets('Small title can be overridden', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController();
    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoPageScaffold(
          child: CustomScrollView(
            controller: scrollController,
            slivers: <Widget>[
              const CupertinoSliverNavigationBar(
                middle: Text('Different title'),
                largeTitle: Text('Title'),
              ),
              SliverToBoxAdapter(
                child: Container(
                  height: 1200.0,
                ),
              ),
            ],
          ),
        ),
      ),
    );

    expect(scrollController.offset, 0.0);
    expect(tester.getTopLeft(find.byType(NavigationToolbar)).dy, 0.0);
    expect(tester.getSize(find.byType(NavigationToolbar)).height, 44.0);

    expect(find.text('Title'), findsOneWidget);
    expect(find.text('Different title'), findsOneWidget);

    RenderAnimatedOpacity largeTitleOpacity =
        tester.element(find.text('Title')).findAncestorRenderObjectOfType<RenderAnimatedOpacity>();
    // Large title initially visible.
    expect(
      largeTitleOpacity.opacity.value,
      1.0,
    );
    // Middle widget not even wrapped with RenderOpacity, i.e. is always visible.
    expect(
      tester.element(find.text('Different title')).findAncestorRenderObjectOfType<RenderOpacity>(),
      isNull,
    );

    expect(tester.getBottomLeft(find.text('Title')).dy, 44.0 + 52.0 - 8.0); // Static part + extension - padding.

    scrollController.jumpTo(600.0);
    await tester.pump(); // Once to trigger the opacity animation.
    await tester.pump(const Duration(milliseconds: 300));

    largeTitleOpacity =
        tester.element(find.text('Title')).findAncestorRenderObjectOfType<RenderAnimatedOpacity>();
    // Large title no longer visible.
    expect(
      largeTitleOpacity.opacity.value,
      0.0,
    );

    // The persistent toolbar doesn't move or change size.
    expect(tester.getTopLeft(find.byType(NavigationToolbar)).dy, 0.0);
    expect(tester.getSize(find.byType(NavigationToolbar)).height, 44.0);

    expect(tester.getBottomLeft(find.text('Title')).dy, 44.0 - 8.0); // Extension gone, (static part - padding) left.
  });

  testWidgets('Auto back/close button', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoNavigationBar(
          middle: Text('Home page'),
        ),
      ),
    );

    expect(find.byType(CupertinoButton), findsNothing);

    tester.state<NavigatorState>(find.byType(Navigator)).push(CupertinoPageRoute<void>(
      builder: (BuildContext context) {
        return const CupertinoNavigationBar(
          middle: Text('Page 2'),
        );
      },
    ));

    await tester.pump();
    await tester.pump(const Duration(milliseconds: 500));

    expect(find.byType(CupertinoButton), findsOneWidget);
    expect(find.text(String.fromCharCode(CupertinoIcons.back.codePoint)), findsOneWidget);

    tester.state<NavigatorState>(find.byType(Navigator)).push(CupertinoPageRoute<void>(
      fullscreenDialog: true,
      builder: (BuildContext context) {
        return const CupertinoNavigationBar(
          middle: Text('Dialog page'),
        );
      },
    ));

    await tester.pump();
    await tester.pump(const Duration(milliseconds: 500));

    expect(find.widgetWithText(CupertinoButton, 'Close'), findsOneWidget);

    // Test popping goes back correctly.
    await tester.tap(find.text('Close'));

    await tester.pump();
    await tester.pump(const Duration(milliseconds: 500));

    expect(find.text('Page 2'), findsOneWidget);

    await tester.tap(find.text(String.fromCharCode(CupertinoIcons.back.codePoint)));

    await tester.pump();
    await tester.pump(const Duration(milliseconds: 500));

    expect(find.text('Home page'), findsOneWidget);
  });

  testWidgets('Long back label turns into "back"', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Placeholder(),
      ),
    );

    tester.state<NavigatorState>(find.byType(Navigator)).push(
      CupertinoPageRoute<void>(
        builder: (BuildContext context) {
          return const CupertinoPageScaffold(
            navigationBar: CupertinoNavigationBar(
              previousPageTitle: '012345678901',
            ),
            child: Placeholder(),
          );
        }
      )
    );

    await tester.pump();
    await tester.pump(const Duration(milliseconds: 500));

    expect(find.widgetWithText(CupertinoButton, '012345678901'), findsOneWidget);

    tester.state<NavigatorState>(find.byType(Navigator)).push(
      CupertinoPageRoute<void>(
        builder: (BuildContext context) {
          return const CupertinoPageScaffold(
            navigationBar: CupertinoNavigationBar(
              previousPageTitle: '0123456789012',
            ),
            child: Placeholder(),
          );
        }
      )
    );

    await tester.pump();
    await tester.pump(const Duration(milliseconds: 500));
    expect(find.widgetWithText(CupertinoButton, 'Back'), findsOneWidget);
  });

  testWidgets('Border should be displayed by default', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoNavigationBar(
          middle: Text('Title'),
        ),
      ),
    );

    final DecoratedBox decoratedBox = tester.widgetList(find.descendant(
      of: find.byType(CupertinoNavigationBar),
      matching: find.byType(DecoratedBox),
    )).first as DecoratedBox;
    expect(decoratedBox.decoration.runtimeType, BoxDecoration);

    final BoxDecoration decoration = decoratedBox.decoration as BoxDecoration;
    expect(decoration.border, isNotNull);

    final BorderSide side = decoration.border.bottom;
    expect(side, isNotNull);
  });

  testWidgets('Overrides border color', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoNavigationBar(
          middle: Text('Title'),
          border: Border(
            bottom: BorderSide(
              color: Color(0xFFAABBCC),
              width: 0.0,
            ),
          ),
        ),
      ),
    );

    final DecoratedBox decoratedBox = tester.widgetList(find.descendant(
      of: find.byType(CupertinoNavigationBar),
      matching: find.byType(DecoratedBox),
    )).first as DecoratedBox;
    expect(decoratedBox.decoration.runtimeType, BoxDecoration);

    final BoxDecoration decoration = decoratedBox.decoration as BoxDecoration;
    expect(decoration.border, isNotNull);

    final BorderSide side = decoration.border.bottom;
    expect(side, isNotNull);
    expect(side.color, const Color(0xFFAABBCC));
  });

  testWidgets('Border should not be displayed when null', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoNavigationBar(
          middle: Text('Title'),
          border: null,
        ),
      ),
    );

    final DecoratedBox decoratedBox = tester.widgetList(find.descendant(
      of: find.byType(CupertinoNavigationBar),
      matching: find.byType(DecoratedBox),
    )).first as DecoratedBox;
    expect(decoratedBox.decoration.runtimeType, BoxDecoration);

    final BoxDecoration decoration = decoratedBox.decoration as BoxDecoration;
    expect(decoration.border, isNull);
  });

  testWidgets('Border is displayed by default in sliver nav bar', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoPageScaffold(
          child: CustomScrollView(
            slivers: <Widget>[
              CupertinoSliverNavigationBar(
                largeTitle: Text('Large Title'),
              ),
            ],
          ),
        ),
      ),
    );

    final DecoratedBox decoratedBox = tester.widgetList(find.descendant(
      of: find.byType(CupertinoSliverNavigationBar),
      matching: find.byType(DecoratedBox),
    )).first as DecoratedBox;
    expect(decoratedBox.decoration.runtimeType, BoxDecoration);

    final BoxDecoration decoration = decoratedBox.decoration as BoxDecoration;
    expect(decoration.border, isNotNull);

    final BorderSide bottom = decoration.border.bottom;
    expect(bottom, isNotNull);
  });

  testWidgets('Border is not displayed when null in sliver nav bar', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoPageScaffold(
          child: CustomScrollView(
            slivers: <Widget>[
              CupertinoSliverNavigationBar(
                largeTitle: Text('Large Title'),
                border: null,
              ),
            ],
          ),
        ),
      ),
    );

    final DecoratedBox decoratedBox = tester.widgetList(find.descendant(
      of: find.byType(CupertinoSliverNavigationBar),
      matching: find.byType(DecoratedBox),
    )).first as DecoratedBox;
    expect(decoratedBox.decoration.runtimeType, BoxDecoration);

    final BoxDecoration decoration = decoratedBox.decoration as BoxDecoration;
    expect(decoration.border, isNull);
  });

  testWidgets('CupertinoSliverNavigationBar has semantics', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);

    await tester.pumpWidget(const CupertinoApp(
      home: CupertinoPageScaffold(
        child: CustomScrollView(
          slivers: <Widget>[
            CupertinoSliverNavigationBar(
              largeTitle: Text('Large Title'),
              border: null,
            ),
          ],
        ),
      ),
    ));

    expect(semantics.nodesWith(
      label: 'Large Title',
      flags: <SemanticsFlag>[SemanticsFlag.isHeader],
      textDirection: TextDirection.ltr,
    ), hasLength(1));

    semantics.dispose();
  });

  testWidgets('CupertinoNavigationBar has semantics', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);

    await tester.pumpWidget(CupertinoApp(
      home: CupertinoPageScaffold(
        navigationBar: const CupertinoNavigationBar(
          middle: Text('Fixed Title'),
        ),
        child: Container(),
      ),
    ));

    expect(semantics.nodesWith(
      label: 'Fixed Title',
      flags: <SemanticsFlag>[SemanticsFlag.isHeader],
      textDirection: TextDirection.ltr,
    ), hasLength(1));

    semantics.dispose();
  });

  testWidgets('Border can be overridden in sliver nav bar', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoPageScaffold(
          child: CustomScrollView(
            slivers: <Widget>[
              CupertinoSliverNavigationBar(
                largeTitle: Text('Large Title'),
                border: Border(
                  bottom: BorderSide(
                    color: Color(0xFFAABBCC),
                    width: 0.0,
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );

    final DecoratedBox decoratedBox = tester.widgetList(find.descendant(
      of: find.byType(CupertinoSliverNavigationBar),
      matching: find.byType(DecoratedBox),
    )).first as DecoratedBox;
    expect(decoratedBox.decoration.runtimeType, BoxDecoration);

    final BoxDecoration decoration = decoratedBox.decoration as BoxDecoration;
    expect(decoration.border, isNotNull);

    final BorderSide top = decoration.border.top;
    expect(top, isNotNull);
    expect(top, BorderSide.none);
    final BorderSide bottom = decoration.border.bottom;
    expect(bottom, isNotNull);
    expect(bottom.color, const Color(0xFFAABBCC));
  });

  testWidgets(
    'Standard title golden',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const CupertinoApp(
          home: RepaintBoundary(
            child: CupertinoPageScaffold(
              navigationBar: CupertinoNavigationBar(
                middle: Text('Bling bling'),
              ),
              child: Center(),
            ),
          ),
        ),
      );

      await expectLater(
        find.byType(RepaintBoundary).last,
        matchesGoldenFile('nav_bar_test.standard_title.png'),
      );
    },
  );

  testWidgets(
    'Large title golden',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        CupertinoApp(
          home: RepaintBoundary(
            child: CupertinoPageScaffold(
              child: CustomScrollView(
                slivers: <Widget>[
                  const CupertinoSliverNavigationBar(
                    largeTitle: Text('Bling bling'),
                  ),
                  SliverToBoxAdapter(
                    child: Container(
                      height: 1200.0,
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      );

      await expectLater(
        find.byType(RepaintBoundary).last,
        matchesGoldenFile('nav_bar_test.large_title.png'),
      );
    },
  );


  testWidgets('NavBar draws a light system bar for a dark background', (WidgetTester tester) async {
    await tester.pumpWidget(
      WidgetsApp(
        color: const Color(0xFFFFFFFF),
        onGenerateRoute: (RouteSettings settings) {
          return CupertinoPageRoute<void>(
            settings: settings,
            builder: (BuildContext context) {
              return const CupertinoNavigationBar(
                middle: Text('Test'),
                backgroundColor: Color(0xFF000000),
              );
            },
          );
        },
      ),
    );
    expect(SystemChrome.latestStyle, SystemUiOverlayStyle.light);
  });

  testWidgets('NavBar draws a dark system bar for a light background', (WidgetTester tester) async {
    await tester.pumpWidget(
      WidgetsApp(
        color: const Color(0xFFFFFFFF),
        onGenerateRoute: (RouteSettings settings) {
          return CupertinoPageRoute<void>(
            settings: settings,
            builder: (BuildContext context) {
              return const CupertinoNavigationBar(
                middle: Text('Test'),
                backgroundColor: Color(0xFFFFFFFF),
              );
            },
          );
        },
      ),
    );
    expect(SystemChrome.latestStyle, SystemUiOverlayStyle.dark);
  });

  testWidgets('CupertinoNavigationBarBackButton shows an error when manually added outside a route', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoNavigationBarBackButton()
    );

    final dynamic exception = tester.takeException();
    expect(exception, isAssertionError);
    expect(exception.toString(), contains('CupertinoNavigationBarBackButton should only be used in routes that can be popped'));
  });

  testWidgets('CupertinoNavigationBarBackButton shows an error when placed in a route that cannot be popped', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: CupertinoNavigationBarBackButton(),
      ),
    );

    final dynamic exception = tester.takeException();
    expect(exception, isAssertionError);
    expect(exception.toString(), contains('CupertinoNavigationBarBackButton should only be used in routes that can be popped'));
  });

  testWidgets('CupertinoNavigationBarBackButton with a custom onPressed callback can be placed anywhere', (WidgetTester tester) async {
    bool backPressed = false;

    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoNavigationBarBackButton(
          onPressed: () => backPressed = true,
        ),
      ),
    );

    expect(tester.takeException(), isNull);
    expect(find.text(String.fromCharCode(CupertinoIcons.back.codePoint)), findsOneWidget);

    await tester.tap(find.byType(CupertinoNavigationBarBackButton));

    expect(backPressed, true);
  });

  testWidgets(
    'Manually inserted CupertinoNavigationBarBackButton still automatically '
        'show previous page title when possible',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const CupertinoApp(
          home: Placeholder(),
        ),
      );

      tester.state<NavigatorState>(find.byType(Navigator)).push(
        CupertinoPageRoute<void>(
          title: 'An iPod',
          builder: (BuildContext context) {
            return const CupertinoPageScaffold(
              navigationBar: CupertinoNavigationBar(),
              child: Placeholder(),
            );
          },
        ),
      );

      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      tester.state<NavigatorState>(find.byType(Navigator)).push(
        CupertinoPageRoute<void>(
          title: 'A Phone',
          builder: (BuildContext context) {
            return const CupertinoNavigationBarBackButton();
          },
        ),
      );

      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      expect(find.widgetWithText(CupertinoButton, 'An iPod'), findsOneWidget);
    },
  );

  testWidgets(
    'CupertinoNavigationBarBackButton onPressed overrides default pop behavior',
    (WidgetTester tester) async {
      bool backPressed = false;
      await tester.pumpWidget(
        const CupertinoApp(
          home: Placeholder(),
        ),
      );

      tester.state<NavigatorState>(find.byType(Navigator)).push(
        CupertinoPageRoute<void>(
          title: 'An iPod',
          builder: (BuildContext context) {
            return const CupertinoPageScaffold(
              navigationBar: CupertinoNavigationBar(),
              child: Placeholder(),
            );
          },
        ),
      );

      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      tester.state<NavigatorState>(find.byType(Navigator)).push(
        CupertinoPageRoute<void>(
          title: 'A Phone',
          builder: (BuildContext context) {
            return CupertinoPageScaffold(
              navigationBar: CupertinoNavigationBar(
                leading: CupertinoNavigationBarBackButton(
                  onPressed: () => backPressed = true,
                ),
              ),
              child: const Placeholder(),
            );
          },
        ),
      );

      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      await tester.tap(find.byType(CupertinoNavigationBarBackButton));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 500));

      // The second page is still on top and didn't pop.
      expect(find.text('A Phone'), findsOneWidget);
      // Custom onPressed called.
      expect(backPressed, true);
    },
  );

  testWidgets('textScaleFactor is set to 1.0', (WidgetTester tester) async {
    await tester.pumpWidget(
      CupertinoApp(
        home: Builder(builder: (BuildContext context) {
          return MediaQuery(
            data: MediaQuery.of(context).copyWith(textScaleFactor: 99),
            child: CupertinoPageScaffold(
              child: CustomScrollView(
                slivers: <Widget>[
                  const CupertinoSliverNavigationBar(
                    leading: Text('leading'),
                    middle: Text('middle'),
                    largeTitle: Text('Large Title'),
                    trailing: Text('trailing'),
                  ),
                  SliverToBoxAdapter(
                    child: Container(
                      child: const Text('content'),
                    ),
                  ),
                ],
              ),
            ),
          );
        }),
      ),
    );

    final Iterable<RichText> barItems = tester.widgetList<RichText>(
      find.descendant(
        of: find.byType(CupertinoSliverNavigationBar),
        matching: find.byType(RichText),
      ),
    );

    final Iterable<RichText> contents = tester.widgetList<RichText>(
      find.descendant(
        of: find.text('content'),
        matching: find.byType(RichText),
      ),
    );

    expect(barItems.length, greaterThan(0));
    expect(barItems.any((RichText t) => t.textScaleFactor != 1), isFalse);

    expect(contents.length, greaterThan(0));
    expect(contents.any((RichText t) => t.textScaleFactor != 99), isFalse);

    // Also works with implicitly added widgets.
    tester.state<NavigatorState>(find.byType(Navigator)).push(CupertinoPageRoute<void>(
      title: 'title',
      builder: (BuildContext context) {
        return MediaQuery(
          data: MediaQuery.of(context).copyWith(textScaleFactor: 99),
          child: Container(
            child: const CupertinoPageScaffold(
              child: CustomScrollView(
                slivers: <Widget>[
                  CupertinoSliverNavigationBar(
                    automaticallyImplyLeading: true,
                    automaticallyImplyTitle: true,
                    previousPageTitle: 'previous title',
                  ),
                ],
              ),
            ),
          ),
        );
      },
    ));

    await tester.pump();
    await tester.pump(const Duration(milliseconds: 500));

    final Iterable<RichText> barItems2 = tester.widgetList<RichText>(
      find.descendant(
        of: find.byType(CupertinoSliverNavigationBar),
        matching: find.byType(RichText),
      ),
    );

    expect(barItems2.length, greaterThan(0));
    expect(barItems2.any((RichText t) => t.textScaleFactor != 1), isFalse);
  });
}

class _ExpectStyles extends StatelessWidget {
  const _ExpectStyles({ this.color, this.index });

  final Color color;
  final int index;

  @override
  Widget build(BuildContext context) {
    final TextStyle style = DefaultTextStyle.of(context).style;
    expect(style.color, isSameColorAs(color));
    expect(style.fontFamily, '.SF Pro Text');
    expect(style.fontSize, 17.0);
    expect(style.letterSpacing, -0.41);
    count += index;
    return Container();
  }
}
