mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-06-28 01:45:55 +08:00
Add a FileStorage class
With a test!
This commit is contained in:
51
lib/file_storage.dart
Normal file
51
lib/file_storage.dart
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
|
import './note.dart';
|
||||||
|
|
||||||
|
class FileStorage {
|
||||||
|
final Future<Directory> Function() getDirectory;
|
||||||
|
|
||||||
|
FileStorage(this.getDirectory);
|
||||||
|
|
||||||
|
Future<List<Note>> loadNotes() async {
|
||||||
|
final dir = await getDirectory();
|
||||||
|
|
||||||
|
var notes = new List<Note>();
|
||||||
|
var lister = dir.list(recursive: false);
|
||||||
|
await for (var fileEntity in lister) {
|
||||||
|
Note note = await _loadNote(fileEntity);
|
||||||
|
notes.add(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
return notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Note> _loadNote(FileSystemEntity entity) async {
|
||||||
|
if (entity is! File) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var file = entity as File;
|
||||||
|
final string = await file.readAsString();
|
||||||
|
final json = JsonDecoder().convert(string);
|
||||||
|
return new Note.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Directory> saveNotes(List<Note> notes) async {
|
||||||
|
final dir = await getDirectory();
|
||||||
|
//await dir.delete(recursive: true);
|
||||||
|
|
||||||
|
for (var note in notes) {
|
||||||
|
var filePath = p.join(dir.path, note.id);
|
||||||
|
|
||||||
|
var file = new File(filePath);
|
||||||
|
var contents = JsonEncoder().convert(note.toJson());
|
||||||
|
await file.writeAsString(contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,43 @@
|
|||||||
class Note {
|
class Note implements Comparable {
|
||||||
|
final String id;
|
||||||
final DateTime createdAt;
|
final DateTime createdAt;
|
||||||
final String body;
|
final String body;
|
||||||
|
|
||||||
const Note({this.createdAt, this.body});
|
const Note({this.createdAt, this.body, this.id});
|
||||||
|
|
||||||
factory Note.fromJson(Map<String, dynamic> json) {
|
factory Note.fromJson(Map<String, dynamic> json) {
|
||||||
return new Note(
|
return new Note(
|
||||||
|
id: json['id'],
|
||||||
createdAt: DateTime.parse(json['createdAt']),
|
createdAt: DateTime.parse(json['createdAt']),
|
||||||
body: json['body'],
|
body: json['body'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
"createdAt": createdAt.toIso8601String(),
|
||||||
|
"body": body,
|
||||||
|
"id": id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode ^ createdAt.hashCode ^ body.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is Note &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
id == other.id &&
|
||||||
|
body == other.body &&
|
||||||
|
createdAt == other.createdAt;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Note{id: $id, body: $body, createdAt: $createdAt}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int compareTo(other) => createdAt.compareTo(other.createdAt);
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.2"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
|
@ -6,7 +6,7 @@ dependencies:
|
|||||||
sdk: flutter
|
sdk: flutter
|
||||||
http: "^0.11.3+16"
|
http: "^0.11.3+16"
|
||||||
intl: "^0.15.6"
|
intl: "^0.15.6"
|
||||||
|
path: "^1.5.1"
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
40
test/file_storage_test.dart
Normal file
40
test/file_storage_test.dart
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
|
import '../lib/note.dart';
|
||||||
|
import '../lib/file_storage.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
group('FileStorage', () {
|
||||||
|
var notes = [
|
||||||
|
Note(id: "1", body: "test", createdAt: new DateTime.now()),
|
||||||
|
Note(id: "2", body: "test2", createdAt: new DateTime.now()),
|
||||||
|
];
|
||||||
|
|
||||||
|
final directory = Directory.systemTemp.createTemp('__storage_test__');
|
||||||
|
final storage = FileStorage(() => directory);
|
||||||
|
|
||||||
|
tearDownAll(() async {
|
||||||
|
final tempDirectory = await directory;
|
||||||
|
tempDirectory.deleteSync(recursive: true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should persist Notes to disk', () async {
|
||||||
|
var dir = await storage.saveNotes(notes);
|
||||||
|
expect(dir.listSync(recursive: true).length, 2);
|
||||||
|
|
||||||
|
expect(File(p.join(dir.path, "1")).existsSync(), isTrue);
|
||||||
|
expect(File(p.join(dir.path, "2")).existsSync(), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should load Notes from disk', () async {
|
||||||
|
var loadedNotes = await storage.loadNotes();
|
||||||
|
loadedNotes.sort();
|
||||||
|
notes.sort();
|
||||||
|
|
||||||
|
expect(loadedNotes, notes);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -1,29 +0,0 @@
|
|||||||
// This is a basic Flutter widget test.
|
|
||||||
// To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter
|
|
||||||
// provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to
|
|
||||||
// find child widgets in the widget tree, read text, and verify that the values of widget properties
|
|
||||||
// are correct.
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
|
|
||||||
import 'package:journal/main.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
|
||||||
// Build our app and trigger a frame.
|
|
||||||
await tester.pumpWidget(new MyApp());
|
|
||||||
|
|
||||||
// Verify that our counter starts at 0.
|
|
||||||
expect(find.text('0'), findsOneWidget);
|
|
||||||
expect(find.text('1'), findsNothing);
|
|
||||||
|
|
||||||
// Tap the '+' icon and trigger a frame.
|
|
||||||
await tester.tap(find.byIcon(Icons.add));
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
// Verify that our counter has incremented.
|
|
||||||
expect(find.text('0'), findsNothing);
|
|
||||||
expect(find.text('1'), findsOneWidget);
|
|
||||||
});
|
|
||||||
}
|
|
Reference in New Issue
Block a user