mirror of
https://github.com/kuhyx/todo-app.git
synced 2026-07-04 15:23:02 +02:00
Notes list & filtering: - Text-search filter plus independent date-range filters for both created and last-updated (AND-combined), a priority filter, and a new status filter. Default view hides Done/Abandoned and renders as "unfiltered" (no badge for the default state); fixed badge clipping. - NoteSort options wired into the list UI; watchCount() for the "N saved". Status & priority: - New Status enum (toDo/inProgress/Done/Abandoned) as a settable + filterable attribute on every note, with capture-screen dropdown. - Removed "None" priority: every note is Low/Medium/High, default Medium. Schema migration v2->v3 rewrites legacy priority 0 -> Medium. Export / import: - NotesMarkdown round-trippable single-file format with HTML-comment markers. - Settings "Export notes" (mobile share sheet / desktop writes ~/todo/BACKLOG.md) and "Import notes" (file picker + safe newer-wins merge by id). Structured template: - Every new note pre-fills the richer what/where/must/nice/out/done/depends/ estimate/refs scaffold. Tests: - New fast (~5s), deterministic suite via FakeNoteRepository (no DB timers) and injected http/file-selector/url-launcher fakes. 86 tests, 96.2% line coverage (note.dart & sync_service.dart at 100%, settings 98.7%). Mobile-only share branch excluded via coverage:ignore (unreachable on the Linux test host). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
85 lines
2.5 KiB
Dart
85 lines
2.5 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:todo/data/note.dart';
|
|
import 'package:todo/sync/notes_markdown.dart';
|
|
|
|
void main() {
|
|
Note note(
|
|
String id,
|
|
String text, {
|
|
Priority priority = Priority.medium,
|
|
Status status = Status.todo,
|
|
DateTime? createdAt,
|
|
DateTime? updatedAt,
|
|
}) {
|
|
final t = DateTime(2026, 6, 15, 9, 30, 15, 123);
|
|
return Note(
|
|
id: id,
|
|
text: text,
|
|
priority: priority,
|
|
status: status,
|
|
createdAt: createdAt ?? t,
|
|
updatedAt: updatedAt ?? t,
|
|
);
|
|
}
|
|
|
|
test('export then parse round-trips every field', () {
|
|
final original = [
|
|
note('a', 'first idea', priority: Priority.high, status: Status.done),
|
|
note(
|
|
'b',
|
|
'multi-line\nbody with - dashes\nand 1. a list',
|
|
priority: Priority.low,
|
|
status: Status.inProgress,
|
|
),
|
|
];
|
|
|
|
final parsed = NotesMarkdown.parse(NotesMarkdown.export(original));
|
|
|
|
expect(parsed, hasLength(2));
|
|
for (var i = 0; i < original.length; i++) {
|
|
expect(parsed[i].id, original[i].id);
|
|
expect(parsed[i].text, original[i].text);
|
|
expect(parsed[i].priority, original[i].priority);
|
|
expect(parsed[i].status, original[i].status);
|
|
expect(parsed[i].createdAt, original[i].createdAt);
|
|
expect(parsed[i].updatedAt, original[i].updatedAt);
|
|
}
|
|
});
|
|
|
|
test('export of an empty list yields just the header', () {
|
|
final out = NotesMarkdown.export([]);
|
|
expect(out.trim(), NotesMarkdown.header);
|
|
expect(NotesMarkdown.parse(out), isEmpty);
|
|
});
|
|
|
|
test('parse tolerates missing/unknown fields with defaults', () {
|
|
const content = '''
|
|
<!-- todo-backlog v1 -->
|
|
|
|
<!-- @note priority="bogus" status="" -->
|
|
a hand-written note with no id
|
|
''';
|
|
final parsed = NotesMarkdown.parse(content);
|
|
|
|
expect(parsed, hasLength(1));
|
|
expect(parsed.single.text, 'a hand-written note with no id');
|
|
// Missing id => a fresh UUID is generated (non-empty).
|
|
expect(parsed.single.id, isNotEmpty);
|
|
// Unknown/blank enum names fall back to the defaults.
|
|
expect(parsed.single.priority, Priority.medium);
|
|
expect(parsed.single.status, Status.todo);
|
|
});
|
|
|
|
test('parse ignores text before the first note marker', () {
|
|
const content = '''
|
|
<!-- todo-backlog v1 -->
|
|
Some preamble a user typed that is not a note.
|
|
|
|
<!-- @note id="x" priority="medium" status="todo" -->
|
|
real note
|
|
''';
|
|
final parsed = NotesMarkdown.parse(content);
|
|
expect(parsed.map((n) => n.text), ['real note']);
|
|
});
|
|
}
|