mirror of
https://github.com/kuhyx/todo-app.git
synced 2026-11-10 22:47:01 +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>
71 lines
2.5 KiB
Dart
71 lines
2.5 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:todo/cli/cli_args.dart';
|
|
import 'package:todo/data/note.dart';
|
|
|
|
void expectUsage(List<String> argv, String fragment) {
|
|
expect(
|
|
() => CliArgs.parse(argv),
|
|
throwsA(
|
|
isA<UsageError>().having((e) => e.message, 'message', contains(fragment)),
|
|
),
|
|
);
|
|
}
|
|
|
|
void main() {
|
|
test('add reads the task fields', () {
|
|
final args = CliArgs.parse([
|
|
'--repo',
|
|
'kuhyx/todo',
|
|
'--done-check',
|
|
'flutter test',
|
|
'--by',
|
|
'claude',
|
|
]);
|
|
expect(args.mode, CliMode.add);
|
|
expect(args.opts.repo, 'kuhyx/todo');
|
|
expect(args.opts.doneCheck, 'flutter test');
|
|
expect(args.opts.by, 'claude');
|
|
expect(args.status, isNull);
|
|
});
|
|
|
|
test('list and search take --repo and --status as filters', () {
|
|
final list = CliArgs.parse(['--list', '--repo', 'kuhyx/a.b-c_d']);
|
|
expect(list.mode, CliMode.list);
|
|
expect(list.opts.repo, 'kuhyx/a.b-c_d');
|
|
expect(list.status, isNull);
|
|
final search = CliArgs.parse(['--search', 'gate', '--status', 'done']);
|
|
expect(search.mode, CliMode.search);
|
|
expect(search.opts.query, 'gate');
|
|
expect(search.status, Status.done);
|
|
});
|
|
|
|
test('close takes an id and evidence', () {
|
|
final args = CliArgs.parse(['--close', 'abcdefgh', '--evidence', 'x 0']);
|
|
expect(args.mode, CliMode.close);
|
|
expect(args.id, 'abcdefgh');
|
|
expect(args.opts.evidence, 'x 0');
|
|
});
|
|
|
|
test('close is refused without evidence', () {
|
|
expectUsage(['--close', 'abcdefgh'], '--close needs --evidence');
|
|
expectUsage(['--close', 'a', '--evidence', ' '], '--close needs');
|
|
});
|
|
|
|
test('task flags are refused outside their modes', () {
|
|
expectUsage(['--evidence', 'e'], '--evidence only applies to --close');
|
|
expectUsage(['--list', '--by', 'kuhy'], '--by only applies when adding');
|
|
expectUsage(['--list', '--done-check', 'x'], 'only applies when adding');
|
|
expectUsage(['--get', 'a', '--repo', 'kuhyx/x'], '--repo only applies');
|
|
expectUsage(['--list', '--close', 'a'], 'mutually exclusive');
|
|
expectUsage(['--search', 'q', '--list'], 'mutually exclusive');
|
|
});
|
|
|
|
test('values are validated', () {
|
|
expectUsage(['--by', 'bob'], '--by must be one of claude|kuhy');
|
|
expectUsage(['--repo', 'todo'], '--repo must look like owner/name');
|
|
expectUsage(['--repo', 'kuhyx/to do'], 'owner/name');
|
|
expectUsage(['--done-check', ' '], '--done-check must not be empty');
|
|
expectUsage(['--search', ''], '--search must not be empty');
|
|
});
|
|
}
|