2024-01-05 17:30:54 +08:00
|
|
|
import 'package:appflowy/plugins/database/grid/presentation/grid_page.dart';
|
|
|
|
import 'package:appflowy/plugins/database/grid/presentation/widgets/header/type_option/select/select_option.dart';
|
2024-01-24 23:59:45 +08:00
|
|
|
import 'package:appflowy/util/field_type_extension.dart';
|
2023-06-14 22:16:33 +08:00
|
|
|
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
|
2023-12-31 07:29:40 +08:00
|
|
|
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
|
2023-07-15 08:45:44 +07:00
|
|
|
import 'package:flutter/material.dart';
|
2023-06-14 22:16:33 +08:00
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:integration_test/integration_test.dart';
|
2024-01-24 23:59:45 +08:00
|
|
|
import 'package:intl/intl.dart';
|
2023-06-14 22:16:33 +08:00
|
|
|
|
2023-11-27 18:54:31 -08:00
|
|
|
import '../util/database_test_op.dart';
|
|
|
|
import '../util/util.dart';
|
2023-06-14 22:16:33 +08:00
|
|
|
|
|
|
|
void main() {
|
|
|
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
|
2023-11-29 04:42:53 +08:00
|
|
|
group('grid field editor:', () {
|
2023-06-14 22:16:33 +08:00
|
|
|
testWidgets('rename existing field', (tester) async {
|
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
2023-12-27 11:42:39 +08:00
|
|
|
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);
|
2023-06-14 22:16:33 +08:00
|
|
|
|
|
|
|
// Invoke the field editor
|
|
|
|
await tester.tapGridFieldWithName('Name');
|
2024-01-24 23:59:45 +08:00
|
|
|
await tester.tapEditFieldButton();
|
2023-06-14 22:16:33 +08:00
|
|
|
|
|
|
|
await tester.renameField('hello world');
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
|
|
|
await tester.tapGridFieldWithName('hello world');
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
});
|
|
|
|
|
|
|
|
testWidgets('update field type of existing field', (tester) async {
|
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
2023-12-27 11:42:39 +08:00
|
|
|
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);
|
2023-06-14 22:16:33 +08:00
|
|
|
|
|
|
|
// Invoke the field editor
|
|
|
|
await tester.tapGridFieldWithName('Type');
|
2024-01-24 23:59:45 +08:00
|
|
|
await tester.tapEditFieldButton();
|
2023-06-14 22:16:33 +08:00
|
|
|
|
2024-01-24 23:59:45 +08:00
|
|
|
await tester.tapSwitchFieldTypeButton();
|
2023-06-14 22:16:33 +08:00
|
|
|
await tester.selectFieldType(FieldType.Checkbox);
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
|
|
|
await tester.assertFieldTypeWithFieldName(
|
|
|
|
'Type',
|
|
|
|
FieldType.Checkbox,
|
|
|
|
);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
});
|
|
|
|
|
|
|
|
testWidgets('create a field and rename it', (tester) async {
|
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
|
|
|
// create a new grid
|
2023-12-27 11:42:39 +08:00
|
|
|
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);
|
2023-06-14 22:16:33 +08:00
|
|
|
|
|
|
|
// create a field
|
|
|
|
await tester.createField(FieldType.Checklist, 'checklist');
|
|
|
|
|
|
|
|
// check the field is created successfully
|
|
|
|
await tester.findFieldWithName('checklist');
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
});
|
|
|
|
|
|
|
|
testWidgets('delete field', (tester) async {
|
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
2023-12-27 11:42:39 +08:00
|
|
|
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);
|
2023-06-14 22:16:33 +08:00
|
|
|
|
|
|
|
// create a field
|
|
|
|
await tester.createField(FieldType.Checkbox, 'New field 1');
|
|
|
|
|
|
|
|
// Delete the field
|
|
|
|
await tester.tapGridFieldWithName('New field 1');
|
|
|
|
await tester.tapDeletePropertyButton();
|
|
|
|
|
|
|
|
// confirm delete
|
|
|
|
await tester.tapDialogOkButton();
|
|
|
|
|
|
|
|
await tester.noFieldWithName('New field 1');
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
});
|
|
|
|
|
|
|
|
testWidgets('duplicate field', (tester) async {
|
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
2023-12-27 11:42:39 +08:00
|
|
|
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);
|
2023-06-14 22:16:33 +08:00
|
|
|
|
|
|
|
// create a field
|
|
|
|
await tester.scrollToRight(find.byType(GridPage));
|
|
|
|
await tester.tapNewPropertyButton();
|
|
|
|
await tester.renameField('New field 1');
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
2023-11-29 04:42:53 +08:00
|
|
|
// duplicate the field
|
2023-06-14 22:16:33 +08:00
|
|
|
await tester.tapGridFieldWithName('New field 1');
|
|
|
|
await tester.tapDuplicatePropertyButton();
|
|
|
|
|
|
|
|
await tester.findFieldWithName('New field 1 (copy)');
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
});
|
|
|
|
|
2023-11-29 04:42:53 +08:00
|
|
|
testWidgets('insert field on either side of a field', (tester) async {
|
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
2023-12-27 11:42:39 +08:00
|
|
|
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);
|
2023-11-29 04:42:53 +08:00
|
|
|
|
|
|
|
await tester.scrollToRight(find.byType(GridPage));
|
|
|
|
|
|
|
|
// insert new field to the right
|
|
|
|
await tester.tapGridFieldWithName('Type');
|
|
|
|
await tester.tapInsertFieldButton(left: false, name: 'Right');
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
await tester.findFieldWithName('Right');
|
|
|
|
|
|
|
|
// insert new field to the right
|
|
|
|
await tester.tapGridFieldWithName('Type');
|
|
|
|
await tester.tapInsertFieldButton(left: true, name: "Left");
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
await tester.findFieldWithName('Left');
|
|
|
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
});
|
|
|
|
|
2023-11-23 16:43:29 +08:00
|
|
|
testWidgets('create checklist field', (tester) async {
|
2023-06-14 22:16:33 +08:00
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
2023-12-27 11:42:39 +08:00
|
|
|
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);
|
2023-06-14 22:16:33 +08:00
|
|
|
|
|
|
|
await tester.scrollToRight(find.byType(GridPage));
|
|
|
|
await tester.tapNewPropertyButton();
|
|
|
|
|
|
|
|
// Open the type option menu
|
2024-01-24 23:59:45 +08:00
|
|
|
await tester.tapSwitchFieldTypeButton();
|
2023-06-14 22:16:33 +08:00
|
|
|
|
|
|
|
await tester.selectFieldType(FieldType.Checklist);
|
|
|
|
|
|
|
|
// After update the field type, the cells should be updated
|
|
|
|
await tester.findCellByFieldType(FieldType.Checklist);
|
|
|
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
});
|
|
|
|
|
|
|
|
testWidgets('create list of fields', (tester) async {
|
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
2023-12-27 11:42:39 +08:00
|
|
|
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);
|
2023-06-14 22:16:33 +08:00
|
|
|
|
|
|
|
for (final fieldType in [
|
|
|
|
FieldType.Checklist,
|
|
|
|
FieldType.DateTime,
|
|
|
|
FieldType.Number,
|
|
|
|
FieldType.URL,
|
|
|
|
FieldType.MultiSelect,
|
|
|
|
FieldType.LastEditedTime,
|
|
|
|
FieldType.CreatedTime,
|
|
|
|
FieldType.Checkbox,
|
|
|
|
]) {
|
|
|
|
await tester.scrollToRight(find.byType(GridPage));
|
|
|
|
await tester.tapNewPropertyButton();
|
|
|
|
await tester.renameField(fieldType.name);
|
|
|
|
|
|
|
|
// Open the type option menu
|
2024-01-24 23:59:45 +08:00
|
|
|
await tester.tapSwitchFieldTypeButton();
|
2023-06-14 22:16:33 +08:00
|
|
|
|
|
|
|
await tester.selectFieldType(fieldType);
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
|
|
|
// After update the field type, the cells should be updated
|
|
|
|
await tester.findCellByFieldType(fieldType);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
}
|
|
|
|
});
|
2023-07-15 08:45:44 +07:00
|
|
|
|
2024-01-24 23:59:45 +08:00
|
|
|
testWidgets('field types with empty type option editor', (tester) async {
|
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
|
|
|
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);
|
|
|
|
|
|
|
|
for (final fieldType in [
|
|
|
|
FieldType.RichText,
|
|
|
|
FieldType.Checkbox,
|
|
|
|
FieldType.Checklist,
|
|
|
|
FieldType.URL,
|
|
|
|
]) {
|
|
|
|
// create the field
|
|
|
|
await tester.scrollToRight(find.byType(GridPage));
|
|
|
|
await tester.tapNewPropertyButton();
|
|
|
|
await tester.renameField(fieldType.i18n);
|
|
|
|
|
|
|
|
// change field type
|
|
|
|
await tester.tapSwitchFieldTypeButton();
|
|
|
|
await tester.selectFieldType(fieldType);
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
|
|
|
// open the field editor
|
|
|
|
await tester.tapGridFieldWithName(fieldType.i18n);
|
|
|
|
await tester.tapEditFieldButton();
|
|
|
|
|
|
|
|
// check type option editor is empty
|
|
|
|
tester.expectEmptyTypeOptionEditor();
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
testWidgets('number field type option', (tester) async {
|
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
|
|
|
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);
|
|
|
|
await tester.scrollToRight(find.byType(GridPage));
|
|
|
|
|
|
|
|
// create a number field
|
|
|
|
await tester.tapNewPropertyButton();
|
|
|
|
await tester.renameField("Number");
|
|
|
|
await tester.tapSwitchFieldTypeButton();
|
|
|
|
await tester.selectFieldType(FieldType.Number);
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
|
|
|
// enter some data into the first number cell
|
|
|
|
await tester.editCell(
|
|
|
|
rowIndex: 0,
|
|
|
|
fieldType: FieldType.Number,
|
|
|
|
input: '123',
|
|
|
|
);
|
|
|
|
// edit the next cell to force the previous cell at row 0 to lose focus
|
|
|
|
await tester.editCell(
|
|
|
|
rowIndex: 1,
|
|
|
|
fieldType: FieldType.Number,
|
|
|
|
input: '0.2',
|
|
|
|
);
|
|
|
|
tester.assertCellContent(
|
|
|
|
rowIndex: 0,
|
|
|
|
fieldType: FieldType.Number,
|
|
|
|
content: '123',
|
|
|
|
);
|
|
|
|
|
|
|
|
// open editor and change number format
|
|
|
|
await tester.tapGridFieldWithName('Number');
|
|
|
|
await tester.tapEditFieldButton();
|
|
|
|
await tester.changeNumberFieldFormat();
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
|
|
|
// assert number format has been changed
|
|
|
|
tester.assertCellContent(
|
|
|
|
rowIndex: 0,
|
|
|
|
fieldType: FieldType.Number,
|
|
|
|
content: '\$123',
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2023-07-15 08:45:44 +07:00
|
|
|
testWidgets('add option', (tester) async {
|
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
2023-12-27 11:42:39 +08:00
|
|
|
await tester.createNewPageWithNameUnderParent(
|
2023-07-31 19:06:01 +07:00
|
|
|
layout: ViewLayoutPB.Grid,
|
|
|
|
);
|
2023-07-15 08:45:44 +07:00
|
|
|
|
2024-01-24 23:59:45 +08:00
|
|
|
// invoke the field editor
|
2023-07-15 08:45:44 +07:00
|
|
|
await tester.tapGridFieldWithName('Type');
|
2024-01-24 23:59:45 +08:00
|
|
|
await tester.tapEditFieldButton();
|
2023-07-15 08:45:44 +07:00
|
|
|
|
|
|
|
// tap 'add option' button
|
|
|
|
await tester.tapAddSelectOptionButton();
|
|
|
|
const text = 'Hello AppFlowy';
|
|
|
|
final inputField = find.descendant(
|
|
|
|
of: find.byType(CreateOptionTextField),
|
|
|
|
matching: find.byType(TextField),
|
|
|
|
);
|
|
|
|
await tester.enterText(inputField, text);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
await tester.testTextInput.receiveAction(TextInputAction.done);
|
2024-01-24 23:59:45 +08:00
|
|
|
await tester.pumpAndSettle(const Duration(milliseconds: 500));
|
2023-07-15 08:45:44 +07:00
|
|
|
|
|
|
|
// check the result
|
|
|
|
tester.expectToSeeText(text);
|
|
|
|
});
|
2024-01-24 23:59:45 +08:00
|
|
|
|
|
|
|
testWidgets('date time field type options', (tester) async {
|
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
|
|
|
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);
|
|
|
|
await tester.scrollToRight(find.byType(GridPage));
|
|
|
|
|
|
|
|
// create a date field
|
|
|
|
await tester.tapNewPropertyButton();
|
|
|
|
await tester.renameField(FieldType.DateTime.i18n);
|
|
|
|
await tester.tapSwitchFieldTypeButton();
|
|
|
|
await tester.selectFieldType(FieldType.DateTime);
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
|
|
|
// edit the first date cell
|
|
|
|
await tester.tapCellInGrid(rowIndex: 0, fieldType: FieldType.DateTime);
|
|
|
|
await tester.toggleIncludeTime();
|
|
|
|
final now = DateTime.now();
|
|
|
|
await tester.selectDay(content: now.day);
|
|
|
|
|
|
|
|
await tester.dismissCellEditor();
|
|
|
|
|
|
|
|
tester.assertCellContent(
|
|
|
|
rowIndex: 0,
|
|
|
|
fieldType: FieldType.DateTime,
|
|
|
|
content: DateFormat('MMM dd, y HH:mm').format(now),
|
|
|
|
);
|
|
|
|
|
|
|
|
// open editor and change date & time format
|
|
|
|
await tester.tapGridFieldWithName(FieldType.DateTime.i18n);
|
|
|
|
await tester.tapEditFieldButton();
|
|
|
|
await tester.changeDateFormat();
|
|
|
|
await tester.changeTimeFormat();
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
|
|
|
// assert date format has been changed
|
|
|
|
tester.assertCellContent(
|
|
|
|
rowIndex: 0,
|
|
|
|
fieldType: FieldType.DateTime,
|
|
|
|
content: DateFormat('dd/MM/y hh:mm a').format(now),
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
testWidgets('last modified and created at field type options',
|
|
|
|
(tester) async {
|
|
|
|
await tester.initializeAppFlowy();
|
|
|
|
await tester.tapGoButton();
|
|
|
|
|
|
|
|
await tester.createNewPageWithNameUnderParent(layout: ViewLayoutPB.Grid);
|
|
|
|
final created = DateTime.now();
|
|
|
|
|
|
|
|
// create a created at field
|
|
|
|
await tester.tapNewPropertyButton();
|
|
|
|
await tester.renameField(FieldType.CreatedTime.i18n);
|
|
|
|
await tester.tapSwitchFieldTypeButton();
|
|
|
|
await tester.selectFieldType(FieldType.CreatedTime);
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
|
|
|
// create a last modified field
|
|
|
|
await tester.tapNewPropertyButton();
|
|
|
|
await tester.renameField(FieldType.LastEditedTime.i18n);
|
|
|
|
await tester.tapSwitchFieldTypeButton();
|
|
|
|
await tester.selectFieldType(FieldType.LastEditedTime);
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
|
|
|
final modified = DateTime.now();
|
|
|
|
|
|
|
|
tester.assertCellContent(
|
|
|
|
rowIndex: 0,
|
|
|
|
fieldType: FieldType.CreatedTime,
|
|
|
|
content: DateFormat('MMM dd, y HH:mm').format(created),
|
|
|
|
);
|
|
|
|
tester.assertCellContent(
|
|
|
|
rowIndex: 0,
|
|
|
|
fieldType: FieldType.LastEditedTime,
|
|
|
|
content: DateFormat('MMM dd, y HH:mm').format(modified),
|
|
|
|
);
|
|
|
|
|
|
|
|
// open field editor and change date & time format
|
|
|
|
await tester.tapGridFieldWithName(FieldType.LastEditedTime.i18n);
|
|
|
|
await tester.tapEditFieldButton();
|
|
|
|
await tester.changeDateFormat();
|
|
|
|
await tester.changeTimeFormat();
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
|
|
|
// open field editor and change date & time format
|
|
|
|
await tester.tapGridFieldWithName(FieldType.CreatedTime.i18n);
|
|
|
|
await tester.tapEditFieldButton();
|
|
|
|
await tester.changeDateFormat();
|
|
|
|
await tester.changeTimeFormat();
|
|
|
|
await tester.dismissFieldEditor();
|
|
|
|
|
|
|
|
// assert format has been changed
|
|
|
|
tester.assertCellContent(
|
|
|
|
rowIndex: 0,
|
|
|
|
fieldType: FieldType.CreatedTime,
|
|
|
|
content: DateFormat('dd/MM/y hh:mm a').format(created),
|
|
|
|
);
|
|
|
|
tester.assertCellContent(
|
|
|
|
rowIndex: 0,
|
|
|
|
fieldType: FieldType.LastEditedTime,
|
|
|
|
content: DateFormat('dd/MM/y hh:mm a').format(modified),
|
|
|
|
);
|
|
|
|
});
|
2023-06-14 22:16:33 +08:00
|
|
|
});
|
|
|
|
}
|