diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..a9e2c109 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: dart +dart: + - dev + - stable \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 215aafab..d81bd143 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 1.1.2 +* Added tests, because tests. + # 1.1.1 * Dart 2 fixes. diff --git a/README.md b/README.md index 1522410c..ffed353b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ # file_service +[![Pub](https://img.shields.io/pub/v/angel_file_service.svg)](https://pub.dartlang.org/packages/angel_file_service) +[![build status](https://travis-ci.org/angel-dart/file_service.svg)](https://travis-ci.org/angel-dart/file_service) + Angel service that persists data to a file on disk, stored as a JSON list. It uses a simple mutex to prevent race conditions, and caches contents in memory until changes are made. diff --git a/lib/angel_file_service.dart b/lib/angel_file_service.dart index 1a0daf9a..11a7957f 100644 --- a/lib/angel_file_service.dart +++ b/lib/angel_file_service.dart @@ -19,6 +19,11 @@ class JsonFileService extends Service { allowQuery: allowQuery != false); } + Map _coerceStringDynamic(Map m) { + return m.keys.fold>( + {}, (out, k) => out..[k.toString()] = m[k]); + } + Future _load() { return _mutex.withResource(() async { if (!await file.exists()) await file.writeAsString(json.encode([])); @@ -32,18 +37,10 @@ class JsonFileService extends Service { var contents = await file.readAsString(); - try { - var list = json.decode(contents) as Iterable; - _store.items.clear(); // Clear exist in-memory copy - _store.items.addAll(list.map((x) => - _revive(x) as Map)); // Insert all new entries - } catch (e) { - if (_store.app is Angel) { - (_store.app as Angel) - .logger - .warning('WARNING: Failed to reload contents of ${file.path}.'); - } - } + var list = json.decode(contents) as Iterable; + _store.items.clear(); // Clear exist in-memory copy + _store.items.addAll(list.map((x) => + _coerceStringDynamic(_revive(x) as Map))); // Insert all new entries } }); } diff --git a/pubspec.yaml b/pubspec.yaml index b25acdc8..611b646c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_file_service -version: 1.1.1 +version: 1.1.2 description: Angel service that persists data to a file on disk. author: Tobe O homepage: https://github.com/angel-dart/file_service @@ -9,4 +9,6 @@ dependencies: angel_framework: ^1.1.0-alpha dart2_constant: ^1.0.0 file: ^2.0.0 - pool: ^1.0.0 \ No newline at end of file + pool: ^1.0.0 +dev_dependencies: + test: \ No newline at end of file diff --git a/test/all_test.dart b/test/all_test.dart new file mode 100644 index 00000000..c266fdfd --- /dev/null +++ b/test/all_test.dart @@ -0,0 +1,72 @@ +import 'package:angel_file_service/angel_file_service.dart'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:test/test.dart'; + +main() { + MemoryFileSystem fs; + File dbFile; + JsonFileService service; + + setUp(() async { + fs = new MemoryFileSystem(); + dbFile = fs.file('db.json'); + service = new JsonFileService(dbFile); + + await dbFile.writeAsString(''' + [ + {"id": "0", "foo": "bar"}, + {"id": "1", "foo": "baz"}, + {"id": "2", "foo": "quux"} + ] + '''); + }); + + tearDown(() => service.close()); + + test('index no params', () async { + expect(await service.index(), [ + {"id": "0", "foo": "bar"}, + {"id": "1", "foo": "baz"}, + {"id": "2", "foo": "quux"} + ]); + }); + + test('index with query', () async { + expect( + await service.index({ + 'query': {'foo': 'bar'} + }), + [ + {"id": "0", "foo": "bar"} + ], + ); + }); + + test('read', () async { + expect( + await service.read('2'), + {"id": "2", "foo": "quux"}, + ); + }); + + test('modify', () async { + await service.modify('2', {'baz': 'quux'}); + expect(await service.read('2'), containsPair('baz', 'quux')); + }); + + test('update', () async { + await service.update('2', {'baz': 'quux'}); + expect(await service.read('2'), containsPair('baz', 'quux')); + expect(await service.read('2'), isNot(containsPair('foo', 'quux'))); + }); + + test('delete', () async { + await service.remove('2'); + expect(await service.index(), [ + {"id": "0", "foo": "bar"}, + {"id": "1", "foo": "baz"} + ]); + }); +}