// 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/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('SizedBox constructors', (WidgetTester tester) async {
    const SizedBox a = SizedBox();
    expect(a.width, isNull);
    expect(a.height, isNull);

    const SizedBox b = SizedBox(width: 10.0);
    expect(b.width, 10.0);
    expect(b.height, isNull);

    const SizedBox c = SizedBox(width: 10.0, height: 20.0);
    expect(c.width, 10.0);
    expect(c.height, 20.0);

    final SizedBox d = SizedBox.fromSize();
    expect(d.width, isNull);
    expect(d.height, isNull);

    final SizedBox e = SizedBox.fromSize(size: const Size(1.0, 2.0));
    expect(e.width, 1.0);
    expect(e.height, 2.0);

    const SizedBox f = SizedBox.expand();
    expect(f.width, double.infinity);
    expect(f.height, double.infinity);

    const SizedBox g = SizedBox.shrink();
    expect(g.width, 0.0);
    expect(g.height, 0.0);
  });

  testWidgets('SizedBox - no child', (WidgetTester tester) async {
    final GlobalKey patient = GlobalKey();

    await tester.pumpWidget(
      Center(
        child: SizedBox(
          key: patient,
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(0.0, 0.0)));

    await tester.pumpWidget(
      Center(
        child: SizedBox(
          key: patient,
          height: 0.0,
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(0.0, 0.0)));

    await tester.pumpWidget(
      Center(
        child: SizedBox(
          key: patient,
          width: 0.0,
          height: 0.0,
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(0.0, 0.0)));

    await tester.pumpWidget(
      Center(
        child: SizedBox(
          key: patient,
          width: 100.0,
          height: 100.0,
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(100.0, 100.0)));

    await tester.pumpWidget(
      Center(
        child: SizedBox(
          key: patient,
          width: 1000.0,
          height: 1000.0,
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(800.0, 600.0)));

    await tester.pumpWidget(
      Center(
        child: SizedBox.expand(
          key: patient,
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(800.0, 600.0)));

    await tester.pumpWidget(
      Center(
        child: SizedBox.shrink(
          key: patient,
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(0.0, 0.0)));
  });

  testWidgets('SizedBox - container child', (WidgetTester tester) async {
    final GlobalKey patient = GlobalKey();

    await tester.pumpWidget(
      Center(
        child: SizedBox(
          key: patient,
          child: Container(),
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(800.0, 600.0)));

    await tester.pumpWidget(
      Center(
        child: SizedBox(
          key: patient,
          height: 0.0,
          child: Container(),
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(800.0, 0.0)));

    await tester.pumpWidget(
      Center(
        child: SizedBox(
          key: patient,
          width: 0.0,
          height: 0.0,
          child: Container(),
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(0.0, 0.0)));

    await tester.pumpWidget(
      Center(
        child: SizedBox(
          key: patient,
          width: 100.0,
          height: 100.0,
          child: Container(),
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(100.0, 100.0)));

    await tester.pumpWidget(
      Center(
        child: SizedBox(
          key: patient,
          width: 1000.0,
          height: 1000.0,
          child: Container(),
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(800.0, 600.0)));

    await tester.pumpWidget(
      Center(
        child: SizedBox.expand(
          key: patient,
          child: Container(),
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(800.0, 600.0)));

    await tester.pumpWidget(
      Center(
        child: SizedBox.shrink(
          key: patient,
          child: Container(),
        ),
      ),
    );
    expect(patient.currentContext.size, equals(const Size(0.0, 0.0)));
  });
}
