Skip to content

[rfw] Add Flexible widget support to core widgets #9750

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/rfw/lib/src/flutter/core_widgets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import 'runtime.dart';
/// * [DefaultTextStyle]
/// * [Directionality]
/// * [Expanded]
/// * [Flexible]
/// * [FittedBox]
/// * [FractionallySizedBox]
/// * [GestureDetector]
Expand Down Expand Up @@ -349,6 +350,14 @@ Map<String, LocalWidgetBuilder> get _coreWidgetsDefinitions => <String, LocalWid
);
},

'Flexible': (BuildContext context, DataSource source) {
return Flexible(
flex: source.v<int>(['flex']) ?? 1,
fit: ArgumentDecoders.enumValue<FlexFit>(FlexFit.values, source, ['fit']) ?? FlexFit.loose,
child: source.child(['child']),
);
},

'FittedBox': (BuildContext context, DataSource source) {
return FittedBox(
fit: ArgumentDecoders.enumValue<BoxFit>(BoxFit.values, source, ['fit']) ?? BoxFit.contain,
Expand Down
133 changes: 133 additions & 0 deletions packages/rfw/test/core_widgets_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -300,4 +300,137 @@ void main() {
expect(renderClip.clipBehavior, equals(Clip.antiAlias));
expect(renderClip.borderRadius, equals(BorderRadius.zero));
});

testWidgets('Flexible widget', (WidgetTester tester) async {
final Runtime runtime = Runtime()
..update(const LibraryName(<String>['core']), createCoreWidgets());
addTearDown(runtime.dispose);
final DynamicContent data = DynamicContent();

// Test Flexible with default values
runtime.update(const LibraryName(<String>['test']), parseLibraryFile('''
import core;
widget root = Directionality(
textDirection: "ltr",
child: Column(
children: [
Flexible(
child: Text(text: "Default flexible"),
),
],
),
);
'''));

await tester.pumpWidget(
RemoteWidget(
runtime: runtime,
data: data,
widget: const FullyQualifiedWidgetName(LibraryName(<String>['test']), 'root'),
),
);
await tester.pump();
expect(find.byType(Flexible), findsOneWidget);
final Flexible defaultFlexible = tester.widget<Flexible>(find.byType(Flexible));
expect(defaultFlexible.flex, equals(1));
expect(defaultFlexible.fit, equals(FlexFit.loose));

// Test Flexible with custom flex value
runtime.update(const LibraryName(<String>['test']), parseLibraryFile('''
import core;
widget root = Directionality(
textDirection: "ltr",
child: Column(
children: [
Flexible(
flex: 3,
child: Text(text: "Custom flex"),
),
],
),
);
'''));
await tester.pumpAndSettle();
final Flexible customFlexFlexible = tester.widget<Flexible>(find.byType(Flexible));
expect(customFlexFlexible.flex, equals(3));
expect(customFlexFlexible.fit, equals(FlexFit.loose));

// Test Flexible with fit: "tight"
runtime.update(const LibraryName(<String>['test']), parseLibraryFile('''
import core;
widget root = Directionality(
textDirection: "ltr",
child: Column(
children: [
Flexible(
flex: 2,
fit: "tight",
child: Text(text: "Tight fit"),
),
],
),
);
'''));
await tester.pumpAndSettle();
final Flexible tightFlexible = tester.widget<Flexible>(find.byType(Flexible));
expect(tightFlexible.flex, equals(2));
expect(tightFlexible.fit, equals(FlexFit.tight));

// Test Flexible with fit: "loose"
runtime.update(const LibraryName(<String>['test']), parseLibraryFile('''
import core;
widget root = Directionality(
textDirection: "ltr",
child: Column(
children: [
Flexible(
flex: 4,
fit: "loose",
child: Text(text: "Loose fit"),
),
],
),
);
'''));
await tester.pumpAndSettle();
final Flexible looseFlexible = tester.widget<Flexible>(find.byType(Flexible));
expect(looseFlexible.flex, equals(4));
expect(looseFlexible.fit, equals(FlexFit.loose));

// Test multiple Flexible widgets in a Column
runtime.update(const LibraryName(<String>['test']), parseLibraryFile('''
import core;
widget root = Directionality(
textDirection: "ltr",
child: Column(
children: [
Flexible(
flex: 1,
fit: "loose",
child: Text(text: "First"),
),
Flexible(
flex: 2,
fit: "tight",
child: Text(text: "Second"),
),
Flexible(
flex: 1,
child: Text(text: "Third"),
),
],
),
);
'''));
await tester.pumpAndSettle();
expect(find.byType(Flexible), findsNWidgets(3));

final List<Flexible> flexibleWidgets = tester.widgetList<Flexible>(find.byType(Flexible)).toList();
expect(flexibleWidgets[0].flex, equals(1));
expect(flexibleWidgets[0].fit, equals(FlexFit.loose));
expect(flexibleWidgets[1].flex, equals(2));
expect(flexibleWidgets[1].fit, equals(FlexFit.tight));
expect(flexibleWidgets[2].flex, equals(1));
expect(flexibleWidgets[2].fit, equals(FlexFit.loose));
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test cases for the Flexible widget are comprehensive, but the implementation is quite repetitive. Each scenario re-defines the entire widget root and has similar boilerplate code.

To improve readability and maintainability, you could refactor this by extracting the common test logic into a helper function. This would make the test suite more concise and easier to extend in the future.

Here's an example of what a helper function could look like:

Future<void> _testFlexible(
  WidgetTester tester,
  Runtime runtime, {
  required String rfwSnippet,
  required void Function(Flexible flexible) verifier,
}) async {
  runtime.update(const LibraryName(<String>['test']), parseLibraryFile('''
    import core;
    widget root = Directionality(
      textDirection: "ltr",
      child: Column(
        children: [
          $rfwSnippet
        ],
      ),
    );
  '''));
  await tester.pumpAndSettle();
  verifier(tester.widget(find.byType(Flexible)));
}

Each test case would then become a much simpler call to this helper.

}