feat(todo): comments on a task (ADR 0033, D36)
Plain text with links, written, edited and deleted in the task's sheet, counted on its row. They are sealed in `task_comment`, the task they belong to with them, and go with their task. Whats-New: Comments: write on a task, edit or delete what you wrote, and open its links. Whats-New-De: Kommentare: Schreibe zu einer Aufgabe, bearbeite oder lösche es und öffne Links darin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
6385d84cff
commit
016b74ff74
1 changed files with 20953 additions and 6 deletions
|
|
@ -9,6 +9,8 @@ import 'package:halkyon_app/testing.dart';
|
|||
import 'package:halkyon_todo_flutter/src/app/todo_app.dart';
|
||||
import 'package:halkyon_todo_flutter/src/app/todo_dependencies.dart';
|
||||
import 'package:halkyon_todo_flutter/src/core/privacy/todo_keys.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/comment/data/comment_repository.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/comment/widget/task_comments.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/filter/data/filter_repository.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/filter/model/saved_filter.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/filter/widget/filter_editor.dart';
|
||||
|
|
@ -70,6 +72,7 @@ void main() {
|
|||
late MemorySealedRowGateway taskRows;
|
||||
late MemorySealedRowGateway labelRows;
|
||||
late MemorySealedRowGateway filterRows;
|
||||
late MemorySealedRowGateway commentRows;
|
||||
late MemorySealedRowGateway settingsRows;
|
||||
late MemoryReminderGateway reminders;
|
||||
late MemoryLocationGateway locationGateway;
|
||||
|
|
@ -101,6 +104,7 @@ void main() {
|
|||
taskRows = MemorySealedRowGateway();
|
||||
labelRows = MemorySealedRowGateway();
|
||||
filterRows = MemorySealedRowGateway();
|
||||
commentRows = MemorySealedRowGateway();
|
||||
settingsRows = MemorySealedRowGateway();
|
||||
reminders = MemoryReminderGateway();
|
||||
locationGateway = MemoryLocationGateway();
|
||||
|
|
@ -204,6 +208,7 @@ void main() {
|
|||
),
|
||||
labels: LabelRepository(labelRows, keys),
|
||||
filters: FilterRepository(filterRows, keys),
|
||||
comments: CommentRepository(commentRows, keys),
|
||||
settings: settings,
|
||||
reminders: reminders,
|
||||
locationReminders: locationGateway,
|
||||
|
|
@ -406,6 +411,101 @@ void main() {
|
|||
expect(find.text('No labels yet.'), findsOneWidget);
|
||||
});
|
||||
|
||||
group('comments (D36)', () {
|
||||
Future<void> openTask(WidgetTester tester) async {
|
||||
await tester.runAsync(() async {
|
||||
final inbox = await ProjectRepository(
|
||||
projectRows,
|
||||
keys,
|
||||
).ensureInbox();
|
||||
await TaskRepository(
|
||||
taskRows,
|
||||
keys,
|
||||
).add(TaskContent(title: 'Vaccination', projectId: inbox));
|
||||
});
|
||||
projectRows.bringRemoteChanges();
|
||||
taskRows.bringRemoteChanges();
|
||||
await tester.pumpAndSettle();
|
||||
await goTab(tester, 'Inbox');
|
||||
await tester.tap(find.text('Vaccination'));
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> write(WidgetTester tester, String text) async {
|
||||
await tester.ensureVisible(find.byKey(commentFieldKey));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.enterText(find.byKey(commentFieldKey), text);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(commentSendKey));
|
||||
await tester.pumpAndSettle();
|
||||
commentRows.bringRemoteChanges();
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
testWidgets('a comment written shows in the sheet, the field empties, '
|
||||
'and nothing blank is sent', (tester) async {
|
||||
await start(tester, usedBefore: true);
|
||||
await openTask(tester);
|
||||
|
||||
await tester.ensureVisible(find.byKey(commentFieldKey));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.enterText(find.byKey(commentFieldKey), ' ');
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
tester.widget<IconButton>(find.byKey(commentSendKey)).onPressed,
|
||||
isNull,
|
||||
);
|
||||
|
||||
await write(tester, 'Ask the vet');
|
||||
|
||||
expect(find.text('Ask the vet', findRichText: true), findsOneWidget);
|
||||
expect(find.text('Comments 1'), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<TextField>(find.byKey(commentFieldKey))
|
||||
.controller!
|
||||
.text,
|
||||
isEmpty,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('a comment edited says so; one deleted is gone, after '
|
||||
'asking', (tester) async {
|
||||
await start(tester, usedBefore: true);
|
||||
await openTask(tester);
|
||||
await write(tester, 'Ask the vet');
|
||||
|
||||
await tester.tap(find.byTooltip('Comment menu'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Edit comment'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.enterText(
|
||||
find.descendant(
|
||||
of: find.byType(AlertDialog),
|
||||
matching: find.byType(TextField),
|
||||
),
|
||||
'Ask the nurse',
|
||||
);
|
||||
await tester.tap(find.text('Save'));
|
||||
await tester.pumpAndSettle();
|
||||
commentRows.bringRemoteChanges();
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Ask the nurse', findRichText: true), findsOneWidget);
|
||||
expect(find.textContaining(', edited'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.byTooltip('Comment menu'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Delete comment'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Delete comment').last);
|
||||
await tester.pumpAndSettle();
|
||||
commentRows.bringRemoteChanges();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Comments'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
group('filters and labels (D35)', () {
|
||||
Future<void> openFilters(WidgetTester tester) async {
|
||||
await goTab(tester, 'Browse');
|
||||
|
|
|
|||
Loading…
Reference in a new issue