Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class _DropdownInputState<T> extends State<_DropdownInput<T>>
Widget build(BuildContext context) {
final theme = Theme.of(context);
return DropdownButtonFormField(
key: Key(widget.property.hashCode.toString()),
value: widget.property.valueDisplay,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (text) => inputValidator(text, property: widget.property),
Expand Down Expand Up @@ -204,10 +205,11 @@ class _TextInput<T> extends StatefulWidget {

class _TextInputState<T> extends State<_TextInput<T>>
with _PropertyInputMixin<_TextInput<T>, T>, AutoDisposeMixin {
String currentValue = '';
static const _paddingDiffComparedToDropdown = 1.0;

double paddingDiffComparedToDropdown = 1.0;
late FocusNode _focusNode;
String _currentValue = '';

late final FocusNode _focusNode;

@override
void initState() {
Expand All @@ -225,6 +227,7 @@ class _TextInputState<T> extends State<_TextInput<T>>
Widget build(BuildContext context) {
final theme = Theme.of(context);
return TextFormField(
key: Key(widget.property.hashCode.toString()),
focusNode: _focusNode,
initialValue: widget.property.valueDisplay,
enabled: widget.property.isEditable,
Expand All @@ -237,13 +240,13 @@ class _TextInputState<T> extends State<_TextInput<T>>
// Note: The text input has an extra pixel compared to the dropdown
// input. Therefore, to have their sizes match, subtract a half pixel
// from the padding.
padding: defaultSpacing - (paddingDiffComparedToDropdown / 2),
padding: defaultSpacing - (_paddingDiffComparedToDropdown / 2),
),
style: theme.fixedFontStyle,
onChanged: (newValue) {
clearServerError();
setState(() {
currentValue = newValue;
_currentValue = newValue;
});
},
onEditingComplete: _editProperty,
Expand All @@ -253,7 +256,7 @@ class _TextInputState<T> extends State<_TextInput<T>>
Future<void> _editProperty() async {
await editProperty(
widget.property,
valueAsString: currentValue,
valueAsString: _currentValue,
editPropertyCallback: widget.editProperty,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ void main() {
final LocationToArgsResult locationToArgsResult = {
(document: textDocument1, position: activeCursorPosition1): result1,
(document: textDocument2, position: activeCursorPosition2): result2,
(document: textDocument1, position: activeCursorPosition3): resultWithText,
(document: textDocument1, position: activeCursorPosition4): resultWithTitle,
};

late MockEditorClient mockEditorClient;
Expand Down Expand Up @@ -58,7 +60,9 @@ void main() {
Future<List<EditableArgument>> waitForEditableArgs() {
final argsCompleter = Completer<List<EditableArgument>>();
listener = () {
argsCompleter.complete(controller.editableWidgetData.value!.args);
if (!argsCompleter.isCompleted) {
argsCompleter.complete(controller.editableWidgetData.value!.args);
}
};
controller.editableWidgetData.addListener(listener!);
return argsCompleter.future;
Expand Down Expand Up @@ -131,6 +135,43 @@ void main() {
verifyEditableArgs(actual: editableArgs, expected: result2.args);
});
});

testWidgets('verify editable arguments update when widget changes', (
tester,
) async {
await tester.runAsync(() async {
// Load the property editor.
await tester.pumpWidget(wrap(propertyEditor));

// Send an active location changed event.
final editableArgsFuture1 = waitForEditableArgs();
eventController.add(activeLocationChangedEvent3);

// Wait for the expected editable args.
await editableArgsFuture1;
await tester.pumpAndSettle();

// Verify the inputs.
final textInput = _findTextFormField('text');
expect(textInput, findsOneWidget);
final textValue = _textFormFieldValue(textInput, tester: tester);
expect(textValue, equals('This is some text.'));

// Send an active location changed event.
final editableArgsFuture2 = waitForEditableArgs();
eventController.add(activeLocationChangedEvent4);

// Wait for the expected editable args.
await editableArgsFuture2;
await tester.pumpAndSettle();

// Verify the inputs.
final titleInput = _findTextFormField('title*');
expect(titleInput, findsOneWidget);
final titleValue = _textFormFieldValue(titleInput, tester: tester);
expect(titleValue, equals('Hello world!'));
});
});
});

group('inputs for editable arguments', () {
Expand Down Expand Up @@ -629,6 +670,14 @@ Finder _findTextFormField(String inputName) => find.ancestor(
matching: find.byType(TextFormField),
);

String? _textFormFieldValue(
Finder textFormFieldFinder, {
required WidgetTester tester,
}) {
final textFormFieldWidget = tester.widget<TextFormField>(textFormFieldFinder);
return textFormFieldWidget.initialValue;
}

Finder _labelForInput(Finder inputFinder, {required String matching}) {
final rowFinder = find.ancestor(of: inputFinder, matching: find.byType(Row));
final labelFinder = find.descendant(
Expand Down Expand Up @@ -802,6 +851,30 @@ final activeLocationChangedEvent2 = ActiveLocationChangedEvent(
textDocument: textDocument2,
);

// Location position 3
final activeCursorPosition3 = CursorPosition(character: 55, line: 2);
final anchorCursorPosition3 = CursorPosition(character: 60, line: 4);
final editorSelection3 = EditorSelection(
active: activeCursorPosition3,
anchor: anchorCursorPosition3,
);
final activeLocationChangedEvent3 = ActiveLocationChangedEvent(
selections: [editorSelection3],
textDocument: textDocument1,
);

// Location position 4
final activeCursorPosition4 = CursorPosition(character: 10, line: 11);
final anchorCursorPosition4 = CursorPosition(character: 12, line: 2);
final editorSelection4 = EditorSelection(
active: activeCursorPosition4,
anchor: anchorCursorPosition4,
);
final activeLocationChangedEvent4 = ActiveLocationChangedEvent(
selections: [editorSelection4],
textDocument: textDocument1,
);

// Widget name and documentation
const widgetName = 'MyFlutterWidget';

Expand Down Expand Up @@ -918,3 +991,22 @@ final resultWithWidgetNameAndDocsNoArgs = EditableArgumentsResult(
documentation: dartDocText,
args: [],
);

// Example results for text input state change test cases.
final textProperty = EditableArgument.fromJson({
'name': 'text',
'value': 'This is some text.',
'type': 'string',
'isEditable': true,
'isNullable': true,
'isRequired': false,
'hasArgument': true,
});
final resultWithText = EditableArgumentsResult(
name: 'WidgetWithText',
args: [textProperty],
);
final resultWithTitle = EditableArgumentsResult(
name: 'WidgetWithTitle',
args: [titleProperty],
);