mirror of
https://github.com/kuhyx/todo-app.git
synced 2026-11-11 16:34:05 +01:00
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file-length / file length <= 250 lines (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
release-apk / release (APK) (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Four optional note fields (repo, done_check, by, evidence) in the crdt_sync record, written only when set, so editing a plain idea stays wire-identical to v3 (note_repository_sync_compat_test). The log is schemaless: no stored schema version; the legacy sqlite reader stays at v3. NoteFilter gains a sources facet (ideas / every repo task / one repo); search also matches the repo. The notes list shows only open ideas by default (no badge); the filter sheet adds Ideas, Repo tasks and one chip per repo when repo tasks exist. The per-note sheet shows the task fields read-only. BACKLOG.md markers carry the new attributes, entity-escaped. CLI: --repo --done-check --by on add, --close <id> --evidence (refused without), --list [--repo] [--status], --search, and every id flag takes a unique 8-character prefix. --list prints id8, status, priority, repo, title. install_hooks.sh: the wrapper finds pre-commit's generated hook next to itself, so commits from a git worktree (where .git is a file) work. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
80 lines
2.2 KiB
Dart
80 lines
2.2 KiB
Dart
/// Runs `runCli` against a [FakeRtdb] from a temp HOME. Not a `*_test.dart`.
|
|
library;
|
|
|
|
import 'dart:io';
|
|
|
|
import 'package:crdt_sync/crdt_sync.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:todo/cli/cli_runner.dart';
|
|
import 'package:todo/cli/cli_session.dart';
|
|
import 'package:todo/data/note.dart';
|
|
import 'package:todo/data/note_repository.dart';
|
|
|
|
import 'fake_rtdb.dart';
|
|
|
|
class CliHarness {
|
|
CliHarness() {
|
|
final home = Directory('${tmp.path}/home')..createSync();
|
|
Directory('${home.path}/.config/todo').createSync(recursive: true);
|
|
writeSeedCredentials(
|
|
tmp,
|
|
).copySync('${home.path}/.config/todo/firebase_auth.json');
|
|
env = {'HOME': home.path, 'XDG_DATA_HOME': '${tmp.path}/xdg'};
|
|
}
|
|
|
|
final tmp = Directory.systemTemp.createTempSync('cli_harness');
|
|
final db = FakeRtdb();
|
|
late final Map<String, String> env;
|
|
final out = StringBuffer();
|
|
final err = StringBuffer();
|
|
|
|
void dispose() => tmp.deleteSync(recursive: true);
|
|
|
|
String dir(String name) => '${tmp.path}/$name';
|
|
|
|
Future<int> run(List<String> argv, {SessionOpener? opener}) async {
|
|
out.clear();
|
|
err.clear();
|
|
return runCli(
|
|
argv,
|
|
env: env,
|
|
out: out,
|
|
err: err,
|
|
readStdin: () async => '',
|
|
open:
|
|
opener ??
|
|
(d, {required seedCredentials}) => CliSession.open(
|
|
d,
|
|
seedCredentials: seedCredentials,
|
|
httpClient: db.client,
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Adds a note from node [node] and returns its id.
|
|
Future<String> add(String text, [List<String> extra = const []]) async {
|
|
expect(await run(['--data-dir', dir('a'), '--text', text, ...extra]), 0);
|
|
return out.toString().trim();
|
|
}
|
|
|
|
/// Publishes [notes] as another device's log.
|
|
void seedPeer(List<Note> notes) {
|
|
db.files['todo-sync/notes/peer~2Ejson'] = logToJson({
|
|
for (final n in notes) n.id: NoteRepository.recordAtNoteTime(n, 'peer'),
|
|
});
|
|
}
|
|
}
|
|
|
|
Note fixtureNote(String id, String text, {String? repo}) {
|
|
final at = DateTime.utc(2026, 11);
|
|
return Note(
|
|
id: id,
|
|
text: text,
|
|
priority: Priority.medium,
|
|
status: Status.todo,
|
|
createdAt: at,
|
|
updatedAt: at,
|
|
repo: repo,
|
|
);
|
|
}
|