Files
GitJournal/test/editors/note_editor_test.dart
Vishesh Handa 657721adc6 Update dart-git and stop using the Result class
Instead we're going to move back to standard exceptions.

Using a custom Result class has created far far more problems
- The Stacktraces aren't always right
- Sometimes one forgets to check the Result error
- All other exception throwing code needing to be converted to Results
- Non idiomatic Dart code

I think it's better to just go back to exceptions. They have their
problems, but overall, I think it's a better approach.
2023-11-24 14:03:30 +01:00

301 lines
9.2 KiB
Dart

/*
* SPDX-FileCopyrightText: 2022 Vishesh Handa <me@vhanda.in>
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import 'dart:io';
import 'package:dart_git/git.dart';
import 'package:dart_git/plumbing/git_hash.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:gitjournal/change_notifiers.dart';
import 'package:gitjournal/editors/common_types.dart';
import 'package:gitjournal/editors/note_body_editor.dart';
import 'package:gitjournal/editors/note_editor.dart';
import 'package:gitjournal/editors/note_title_editor.dart';
import 'package:gitjournal/l10n.dart';
import 'package:gitjournal/repository.dart';
import 'package:gitjournal/repository_manager.dart';
import 'package:gitjournal/settings/app_config.dart';
import 'package:path/path.dart' as p;
import 'package:shared_preferences/shared_preferences.dart';
import '../lib.dart';
void main() {
late GitJournalRepo repo;
late RepositoryManager repoManager;
late SharedPreferences pref;
late String repoPath;
setUpAll(gjSetupAllTests);
Future<void> _setup(
String head, {
Map<String, Object> sharedPrefValues = const {},
}) async {
var td = await TestData.load(
headHash: GitHash(head),
sharedPrefValues: sharedPrefValues,
);
repo = td.repo;
repoManager = td.repoManager;
pref = td.pref;
repoPath = td.repoPath;
}
Widget _buildApp(Widget widget) {
return GitJournalChangeNotifiers(
appConfig: AppConfig(),
repoManager: repoManager,
pref: pref,
child: Builder(builder: (context) {
return MaterialApp(
home: widget,
localizationsDelegates: gitJournalLocalizationDelegates,
supportedLocales: gitJournalSupportedLocales,
);
}),
);
}
testWidgets('New Note Title as FileName', (tester) async {
await tester.runAsync(
() async => await _setup('7fc65b59170bdc91013eb56cdc65fa3307f2e7de'),
);
var widget = NoteEditor.newNote(
repo.rootFolder,
repo.rootFolder,
EditorType.Markdown,
existingText: "",
existingImages: const [],
);
await tester.pumpWidget(_buildApp(widget));
await tester.pumpAndSettle();
var titleFinder = find.byType(NoteTitleEditor);
expect(titleFinder, findsOneWidget);
await tester.enterText(titleFinder, "Fake-Title");
await tester.pump();
var saveButtonFinder = find.byKey(const ValueKey('NewEntry'));
expect(saveButtonFinder, findsOneWidget);
await tester.tap(saveButtonFinder);
await tester.pumpAndSettle();
await tester.pumpAndSettle(const Duration(seconds: 1));
var file = File(p.join(repoPath, 'Fake-Title.md'));
expect(file.existsSync(), true);
});
testWidgets('New Note with Extra MetaData', (tester) async {
await tester.runAsync(
() async => await _setup('7fc65b59170bdc91013eb56cdc65fa3307f2e7de'),
);
var widget = NoteEditor.newNote(
repo.rootFolder,
repo.rootFolder,
EditorType.Markdown,
existingText: "",
existingImages: const [],
newNoteExtraProps: const {'foo': 1},
);
await tester.pumpWidget(_buildApp(widget));
await tester.pumpAndSettle();
var titleFinder = find.byType(NoteTitleEditor);
expect(titleFinder, findsOneWidget);
await tester.enterText(titleFinder, "Fake-Title");
await tester.pump();
var saveButtonFinder = find.byKey(const ValueKey('NewEntry'));
expect(saveButtonFinder, findsOneWidget);
await tester.runAsync(() async {
var saveButtonFinder = find.byKey(const ValueKey('NewEntry'));
expect(saveButtonFinder, findsOneWidget);
await tester.tap(saveButtonFinder);
await tester.pumpAndSettle();
await Future.delayed(const Duration(milliseconds: 100));
});
var file = File(p.join(repoPath, 'Fake-Title.md'));
expect(file.existsSync(), true);
var x = file.readAsStringSync();
expect(x.length, isNonZero);
var note = repo.rootFolder.getNoteWithSpec('Fake-Title.md')!;
expect(note.extraProps.length, 1);
expect(note.extraProps['foo'], 1);
});
testWidgets('Existing Note Rename and Exit', (tester) async {
await tester.runAsync(
() async => await _setup('7fc65b59170bdc91013eb56cdc65fa3307f2e7de'),
);
// FIXME: Use a proper size of a mobile, also set the DPI
await tester.binding.setSurfaceSize(const Size(10800, 23400));
await tester.pumpAndSettle();
var note = repo.rootFolder.getNoteWithSpec('doc.md')!;
var widget = NoteEditor.fromNote(note, repo.rootFolder);
await tester.pumpWidget(_buildApp(widget));
await tester.pumpAndSettle();
// Rename the note
var menuButton = find.byIcon(Icons.more_vert);
expect(menuButton, findsOneWidget);
await tester.tap(menuButton);
await tester.pumpAndSettle();
var editFileNameButton = find.byKey(const ValueKey('EditFileNameButton'));
expect(editFileNameButton, findsOneWidget);
await tester.tap(editFileNameButton);
await tester.pumpAndSettle();
var dialog = find.byType(AlertDialog);
expect(dialog, findsOneWidget);
await tester.showKeyboard(dialog);
tester.testTextInput.updateEditingValue(
const TextEditingValue(text: 'bugs.md'),
);
var renameButton = find.byKey(const ValueKey('RenameYes'));
expect(renameButton, findsOneWidget);
await tester.tap(renameButton);
await tester.pumpAndSettle();
// Exit the editor
await tester.runAsync(() async {
var saveButtonFinder = find.byKey(const ValueKey('NewEntry'));
expect(saveButtonFinder, findsOneWidget);
await tester.tap(saveButtonFinder);
await tester.pumpAndSettle();
await Future.delayed(const Duration(milliseconds: 100));
});
// Check the FileSystem
expect(File(p.join(repoPath, 'doc.md')).existsSync(), false);
expect(File(p.join(repoPath, 'bugs.md')).existsSync(), true);
// Check the rootFolder
expect(repo.rootFolder.getNoteWithSpec('doc.md'), null);
expect(repo.rootFolder.getNoteWithSpec('bugs.md'), isNotNull);
expect(repo.rootFolder.getAllNotes().length, 5);
// Check the view
var saveButtonFinder = find.byKey(const ValueKey('NewEntry'));
expect(saveButtonFinder, findsNothing);
});
testWidgets('Existing Note not modified', (tester) async {
var headHash = '7fc65b59170bdc91013eb56cdc65fa3307f2e7de';
await tester.runAsync(
() async => await _setup(headHash),
);
// FIXME: Use a proper size of a mobile, also set the DPI
await tester.binding.setSurfaceSize(const Size(10800, 23400));
await tester.pumpAndSettle();
var note = repo.rootFolder.getNoteWithSpec('doc.md')!;
var widget = NoteEditor.fromNote(note, repo.rootFolder);
await tester.pumpWidget(_buildApp(widget));
await tester.pumpAndSettle();
// Change the text
var bodyEditor = find.byType(NoteBodyEditor);
expect(bodyEditor, findsOneWidget);
await tester.showKeyboard(bodyEditor);
tester.testTextInput.updateEditingValue(
const TextEditingValue(text: '200 mgs of x\n'),
);
await tester.pumpAndSettle();
// expect(find.byIcon(Icons.close), findsOneWidget);
// expect(find.byIcon(Icons.check), findsNothing);
late Finder saveButtonFinder;
saveButtonFinder = find.byKey(const ValueKey('NewEntry'));
expect(saveButtonFinder, findsOneWidget);
// Exit the editor
await tester.runAsync(() async {
await tester.tap(saveButtonFinder);
await tester.pumpAndSettle();
await Future.delayed(const Duration(milliseconds: 1000));
});
await tester.pumpAndSettle();
// Check the view
saveButtonFinder = find.byKey(const ValueKey('NewEntry'));
expect(saveButtonFinder, findsNothing);
// Ensure nothing has changed
var gitRepo = GitRepository.load(repo.repoPath);
expect(gitRepo.headHash(), GitHash(headHash));
});
testWidgets('Editing a Note body with a heading', (tester) async {
await tester.runAsync(
() async => await _setup('fef4ef7341751cb583d768dc9a6b13deca552954'),
);
// FIXME: Use a proper size of a mobile, also set the DPI
await tester.binding.setSurfaceSize(const Size(10800, 23400));
await tester.pumpAndSettle();
// Open the note
var note = repo.rootFolder.getNoteWithSpec('heading.md')!;
var noteHash = GitHash('737943ab9672d967afa91641207a9a3592a522bf');
var widget = NoteEditor.fromNote(note, repo.rootFolder);
expect(note.oid, noteHash);
await tester.pumpWidget(_buildApp(widget));
await tester.pumpAndSettle();
// Make a modification to the body
var dialog = find.byType(NoteBodyEditor);
await tester.showKeyboard(dialog);
tester.testTextInput.updateEditingValue(
const TextEditingValue(text: '# dbg2e\n#dbg3'),
);
await tester.runAsync(() async {
// Save the Note
var saveButtonFinder = find.byKey(const ValueKey('NewEntry'));
expect(saveButtonFinder, findsOneWidget);
await tester.tap(saveButtonFinder);
await tester.pumpAndSettle();
// FIXME: Can this be avoided?
await Future.delayed(const Duration(milliseconds: 100));
});
note = repo.rootFolder.getNoteWithSpec('heading.md')!;
expect(note.oid, isNot(noteHash));
expect(note.title, "dbg1");
expect(note.body, '# dbg2e\n#dbg3');
});
}