| // 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 'package:flutter/rendering.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| import 'rendering_tester.dart'; |
| |
| void main() { |
| TestRenderingFlutterBinding.ensureInitialized(); |
| |
| group('RenderAligningShiftedBox', () { |
| test('RenderAligningShiftedBox has computeDryBaseline method implemented', () { |
| final positionedBox = RenderPositionedBox(); |
| |
| // Verify the method exists and can be called |
| expect( |
| () => positionedBox.computeDryBaseline( |
| const BoxConstraints(maxWidth: 100.0, maxHeight: 100.0), |
| TextBaseline.alphabetic, |
| ), |
| returnsNormally, |
| ); |
| |
| // Test with no child - should return null |
| final double? baseline = positionedBox.computeDryBaseline( |
| const BoxConstraints(maxWidth: 100.0, maxHeight: 100.0), |
| TextBaseline.alphabetic, |
| ); |
| expect(baseline, isNull); |
| }); |
| |
| test('computeDryBaseline returns null when child is null', () { |
| final positioner = RenderPositionedBox(alignment: Alignment.topLeft); |
| |
| final double? baseline = positioner.computeDryBaseline( |
| const BoxConstraints(maxWidth: 100.0, maxHeight: 100.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| expect(baseline, isNull); |
| }); |
| |
| test('computeDryBaseline returns null when child has no baseline', () { |
| final child = MockRenderBoxNoBaseline(); |
| final positioner = RenderPositionedBox(child: child); |
| |
| final double? baseline = positioner.computeDryBaseline( |
| const BoxConstraints(maxWidth: 100.0, maxHeight: 100.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| expect(baseline, isNull); |
| }); |
| |
| test('computeDryBaseline works with center alignment', () { |
| final child = MockRenderBox(); |
| final positioner = RenderPositionedBox(child: child); |
| |
| final double? baseline = positioner.computeDryBaseline( |
| const BoxConstraints(maxWidth: 200.0, maxHeight: 200.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| // Should return child's baseline (40.0) plus the vertical offset from centering |
| expect(baseline, isNotNull); |
| expect(baseline! > 40.0, isTrue); // Should be greater than child's baseline due to centering |
| }); |
| |
| test('computeDryBaseline works with top-left alignment', () { |
| final child = MockRenderBox(); |
| final positioner = RenderPositionedBox(alignment: Alignment.topLeft, child: child); |
| |
| final double? baseline = positioner.computeDryBaseline( |
| const BoxConstraints(maxWidth: 200.0, maxHeight: 200.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| // Should return exactly child's baseline (40.0) since no vertical offset with topLeft |
| expect(baseline, equals(40.0)); |
| }); |
| |
| test('computeDryBaseline works with bottom-right alignment', () { |
| final child = MockRenderBox(); |
| final positioner = RenderPositionedBox(alignment: Alignment.bottomRight, child: child); |
| |
| final double? baseline = positioner.computeDryBaseline( |
| const BoxConstraints(maxWidth: 200.0, maxHeight: 200.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| // Should return child's baseline plus significant vertical offset from bottom alignment |
| expect(baseline, isNotNull); |
| expect(baseline! > 100.0, isTrue); // Should be much greater due to bottom alignment |
| }); |
| |
| test('computeDryBaseline with different TextBaseline types', () { |
| final child = MockRenderBox(); |
| final positioner = RenderPositionedBox(alignment: Alignment.topLeft, child: child); |
| |
| // Test alphabetic baseline |
| final double? alphabeticBaseline = positioner.computeDryBaseline( |
| const BoxConstraints(maxWidth: 100.0, maxHeight: 100.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| // Test ideographic baseline |
| final double? ideographicBaseline = positioner.computeDryBaseline( |
| const BoxConstraints(maxWidth: 100.0, maxHeight: 100.0), |
| TextBaseline.ideographic, |
| ); |
| |
| expect(alphabeticBaseline, isNotNull); |
| expect(ideographicBaseline, isNotNull); |
| // Both should return the same value since our mock returns 40.0 for both |
| expect(alphabeticBaseline, equals(ideographicBaseline)); |
| }); |
| |
| test('computeDryBaseline works with width and height factors', () { |
| final child = MockRenderBox(); |
| final positioner = RenderPositionedBox( |
| alignment: Alignment.topLeft, |
| widthFactor: 2.0, |
| heightFactor: 1.5, |
| child: child, |
| ); |
| |
| final double? baseline = positioner.computeDryBaseline( |
| const BoxConstraints(maxWidth: 200.0, maxHeight: 200.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| // Should return child's baseline since topLeft alignment |
| expect(baseline, equals(40.0)); |
| }); |
| |
| test('computeDryBaseline works with infinite constraints', () { |
| final child = MockRenderBox(); |
| final positioner = RenderPositionedBox(alignment: Alignment.topLeft, child: child); |
| |
| final double? baseline = positioner.computeDryBaseline( |
| const BoxConstraints(), |
| TextBaseline.alphabetic, |
| ); |
| |
| expect(baseline, equals(40.0)); |
| }); |
| }); |
| |
| group('Other RenderShiftedBox classes', () { |
| test('RenderConstrainedOverflowBox computeDryBaseline', () { |
| final child = MockRenderBox(); |
| final constrainedBox = RenderConstrainedOverflowBox( |
| alignment: Alignment.topLeft, |
| child: child, |
| ); |
| |
| final double? baseline = constrainedBox.computeDryBaseline( |
| const BoxConstraints(maxWidth: 100.0, maxHeight: 100.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| expect(baseline, isNotNull); |
| }); |
| |
| test('RenderSizedOverflowBox computeDryBaseline', () { |
| final child = MockRenderBox(); |
| final sizedBox = RenderSizedOverflowBox( |
| requestedSize: const Size(100.0, 100.0), |
| alignment: Alignment.topLeft, |
| child: child, |
| ); |
| |
| final double? baseline = sizedBox.computeDryBaseline( |
| const BoxConstraints(maxWidth: 200.0, maxHeight: 200.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| expect(baseline, isNotNull); |
| }); |
| |
| test('RenderFractionallySizedOverflowBox computeDryBaseline', () { |
| final child = MockRenderBox(); |
| final fractionalBox = RenderFractionallySizedOverflowBox( |
| alignment: Alignment.topLeft, |
| widthFactor: 0.5, |
| heightFactor: 0.5, |
| child: child, |
| ); |
| |
| final double? baseline = fractionalBox.computeDryBaseline( |
| const BoxConstraints(maxWidth: 200.0, maxHeight: 200.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| expect(baseline, isNotNull); |
| }); |
| |
| test('RenderPadding computeDryBaseline', () { |
| final child = MockRenderBox(); |
| final padding = RenderPadding(padding: const EdgeInsets.all(10.0), child: child); |
| |
| final double? baseline = padding.computeDryBaseline( |
| const BoxConstraints(maxWidth: 100.0, maxHeight: 100.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| expect(baseline, isNotNull); |
| }); |
| |
| test('RenderBaseline computeDryBaseline', () { |
| final child = MockRenderBox(); |
| final baselineBox = RenderBaseline( |
| baseline: 30.0, |
| baselineType: TextBaseline.alphabetic, |
| child: child, |
| ); |
| |
| final double? baseline = baselineBox.computeDryBaseline( |
| const BoxConstraints(maxWidth: 100.0, maxHeight: 100.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| expect(baseline, isNotNull); |
| }); |
| |
| test('computeDryBaseline handles edge cases consistently', () { |
| // Test with very small constraints |
| final child = MockRenderBox(); |
| final positioner = RenderPositionedBox(child: child); |
| |
| final double? smallBaseline = positioner.computeDryBaseline( |
| const BoxConstraints(maxWidth: 1.0, maxHeight: 1.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| expect(smallBaseline, isNotNull); |
| |
| // Test with zero constraints |
| final double? zeroBaseline = positioner.computeDryBaseline( |
| const BoxConstraints.tightFor(width: 0.0, height: 0.0), |
| TextBaseline.alphabetic, |
| ); |
| |
| expect(zeroBaseline, isNotNull); |
| }); |
| }); |
| } |
| |
| // Mock render box for testing |
| class MockRenderBox extends RenderBox { |
| @override |
| Size computeDryLayout(BoxConstraints constraints) { |
| return constraints.constrain(const Size(50.0, 50.0)); |
| } |
| |
| @override |
| double? computeDryBaseline(BoxConstraints constraints, TextBaseline baseline) { |
| return 40.0; // Mock baseline at 40 pixels from top |
| } |
| |
| @override |
| void performLayout() { |
| size = constraints.constrain(const Size(50.0, 50.0)); |
| } |
| } |
| |
| // Mock render box that has no baseline for testing |
| class MockRenderBoxNoBaseline extends RenderBox { |
| @override |
| Size computeDryLayout(BoxConstraints constraints) { |
| return constraints.constrain(const Size(50.0, 50.0)); |
| } |
| |
| @override |
| double? computeDryBaseline(BoxConstraints constraints, TextBaseline baseline) { |
| return null; // No baseline |
| } |
| |
| @override |
| void performLayout() { |
| size = constraints.constrain(const Size(50.0, 50.0)); |
| } |
| } |