summaryrefslogtreecommitdiff
path: root/test/log_service_test.dart
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-08 00:05:39 +0300
committerPaul Buetow <paul@buetow.org>2026-05-08 00:05:39 +0300
commit3e4bacb7b939b1de98a2fb07115f638750637357 (patch)
tree0897a6854d1c3ca3b1d0252657e992abbba061ba /test/log_service_test.dart
parent665b150727ee7259e398d38d1f6bc51b4c2d4a1c (diff)
Rewrite as Flutter app and rename to Quicklogmain
Drop the Go/Fyne implementation and replace it with a native Flutter app targeting Android (primary) and Linux desktop (development). Rename quicklogger -> quicklog throughout (project, applicationId, MethodChannel, cache filename, AppBar title, Linux binary). Storage on Android moves to /Android/data/org.buetow.quicklog/files/ so MANAGE_EXTERNAL_STORAGE is no longer required. Share-intent receive is preserved via a Kotlin ShareActivity that writes shared text to the app cache, which Dart reads through a MethodChannel on app resume; MainActivity also accepts SEND directly so launchers that prefer the main target work. New since the Fyne version: an entry browser screen with read-only viewer and long-press delete. Cross-compiling to Android ARM from amd64 Linux no longer needs Docker / fyne-cross / NDK -- flutter build apk emits ARM binaries directly. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Diffstat (limited to 'test/log_service_test.dart')
-rw-r--r--test/log_service_test.dart67
1 files changed, 67 insertions, 0 deletions
diff --git a/test/log_service_test.dart b/test/log_service_test.dart
new file mode 100644
index 0000000..969d1f8
--- /dev/null
+++ b/test/log_service_test.dart
@@ -0,0 +1,67 @@
+import 'dart:io';
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:path/path.dart' as p;
+import 'package:quicklog/services/log_service.dart';
+
+void main() {
+ group('logEntry', () {
+ late Directory tmp;
+
+ setUp(() async {
+ tmp = await Directory.systemTemp.createTemp('ql-test-');
+ });
+
+ tearDown(() async {
+ if (await tmp.exists()) await tmp.delete(recursive: true);
+ });
+
+ test('writes a file with ql-YYMMDD-HHMMSS.md filename pattern', () async {
+ final f = await logEntry(tmp.path, 'hello');
+ expect(p.basename(f.path), matches(RegExp(r'^ql-\d{6}-\d{6}\.md$')));
+ expect(await f.readAsString(), 'hello');
+ });
+
+ test('preserves arbitrary content including unicode and newlines', () async {
+ const text = 'line 1\nläine 2\n第三行';
+ final f = await logEntry(tmp.path, text);
+ expect(await f.readAsString(), text);
+ });
+
+ test('uses the provided timestamp when given', () async {
+ final ts = DateTime(2026, 5, 7, 14, 30, 45);
+ final f = await logEntry(tmp.path, 'x', now: ts);
+ expect(p.basename(f.path), 'ql-260507-143045.md');
+ });
+
+ test('throws on a non-existent directory', () async {
+ final bad = p.join(tmp.path, 'does', 'not', 'exist');
+ expect(() => logEntry(bad, 'x'), throwsA(isA<FileSystemException>()));
+ });
+ });
+
+ group('listEntries', () {
+ late Directory tmp;
+ setUp(() async => tmp = await Directory.systemTemp.createTemp('ql-list-'));
+ tearDown(() async {
+ if (await tmp.exists()) await tmp.delete(recursive: true);
+ });
+
+ test('returns entries sorted newest first and skips malformed names', () async {
+ await File(p.join(tmp.path, 'ql-260101-000000.md')).writeAsString('a');
+ await File(p.join(tmp.path, 'ql-260102-000000.md')).writeAsString('b');
+ await File(p.join(tmp.path, 'random.md')).writeAsString('skip');
+ await File(p.join(tmp.path, 'ql-bad-format.md')).writeAsString('skip');
+
+ final entries = await listEntries(tmp.path);
+ expect(entries.length, 2);
+ expect(p.basename(entries[0].file.path), 'ql-260102-000000.md');
+ expect(p.basename(entries[1].file.path), 'ql-260101-000000.md');
+ });
+
+ test('returns empty list for missing directory', () async {
+ final entries = await listEntries(p.join(tmp.path, 'nope'));
+ expect(entries, isEmpty);
+ });
+ });
+}