Add a FileStorage class

With a test!
This commit is contained in:
Vishesh Handa
2018-05-21 15:31:34 +02:00
parent 40caa985d7
commit 4fcc6d9120
6 changed files with 125 additions and 33 deletions

51
lib/file_storage.dart Normal file
View 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;
}
}

View File

@ -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);
} }

View File

@ -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"

View File

@ -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:

View 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);
});
});
}

View File

@ -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);
});
}