diff --git a/lib/entity/album.dart b/lib/entity/album.dart index 0a85cef9..e735bf5f 100644 --- a/lib/entity/album.dart +++ b/lib/entity/album.dart @@ -174,7 +174,8 @@ class Album with EquatableMixin { ); } - Map _toRemoteJson() { + @visibleForTesting + Map toRemoteJson() { return { "version": version, "lastUpdated": lastUpdated.toIso8601String(), @@ -184,7 +185,8 @@ class Album with EquatableMixin { }; } - Map _toAppDbJson() { + @visibleForTesting + Map toAppDbJson() { return { "version": version, "lastUpdated": lastUpdated.toIso8601String(), @@ -283,7 +285,7 @@ class AlbumRemoteDataSource implements AlbumDataSource { final fileRepo = FileRepo(FileWebdavDataSource()); try { await PutFileBinary(fileRepo)( - account, filePath, utf8.encode(jsonEncode(album._toRemoteJson()))); + account, filePath, utf8.encode(jsonEncode(album.toRemoteJson()))); } on ApiException catch (e) { if (e.response.statusCode == 404) { _log.info("[create] Missing album dir, creating"); @@ -291,7 +293,7 @@ class AlbumRemoteDataSource implements AlbumDataSource { await _createDir(account); // then retry await PutFileBinary(fileRepo)( - account, filePath, utf8.encode(jsonEncode(album._toRemoteJson()))); + account, filePath, utf8.encode(jsonEncode(album.toRemoteJson()))); } else { rethrow; } @@ -307,7 +309,7 @@ class AlbumRemoteDataSource implements AlbumDataSource { _log.info("[update] ${album.albumFile.path}"); final fileRepo = FileRepo(FileWebdavDataSource()); await PutFileBinary(fileRepo)(account, album.albumFile.path, - utf8.encode(jsonEncode(album._toRemoteJson()))); + utf8.encode(jsonEncode(album.toRemoteJson()))); } @override @@ -359,7 +361,7 @@ class AlbumAppDbDataSource implements AlbumDataSource { db.transaction(AppDb.albumStoreName, idbModeReadWrite); final store = transaction.objectStore(AppDb.albumStoreName); await store.put( - album._toAppDbJson(), _getCacheKey(account, album.albumFile)); + album.toAppDbJson(), _getCacheKey(account, album.albumFile)); }); } @@ -433,7 +435,7 @@ class AlbumCachedDataSource implements AlbumDataSource { final transaction = db.transaction(AppDb.albumStoreName, idbModeReadWrite); final store = transaction.objectStore(AppDb.albumStoreName); - await store.put(result._toAppDbJson(), _getCacheKey(account, albumFile)); + await store.put(result.toAppDbJson(), _getCacheKey(account, albumFile)); }); } diff --git a/pubspec.lock b/pubspec.lock index aa23357d..a8404720 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,20 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "20.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.0" android_intent: dependency: "direct main" description: @@ -15,6 +29,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.2" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.5.0" bloc: dependency: "direct main" description: @@ -22,6 +50,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "7.0.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" cached_network_image: dependency: "direct main" description: @@ -43,6 +78,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + cli_util: + dependency: transitive + description: + name: cli_util + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" clock: dependency: transitive description: @@ -85,6 +127,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + coverage: + dependency: transitive + description: + name: coverage + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" crypto: dependency: transitive description: @@ -179,6 +235,13 @@ packages: description: flutter source: sdk version: "0.0.0" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" google_maps_flutter: dependency: "direct main" description: @@ -207,6 +270,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.13.1" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" http_parser: dependency: transitive description: @@ -251,6 +321,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.17.0" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" js: dependency: transitive description: @@ -286,6 +363,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" nested: dependency: transitive description: @@ -293,6 +377,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" octo_image: dependency: transitive description: @@ -300,6 +391,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0+1" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" page_view_indicators: dependency: "direct main" description: @@ -377,6 +475,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.0" process: dependency: transitive description: @@ -391,6 +496,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.0.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" quiver: dependency: transitive description: @@ -454,11 +566,53 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + shelf_static: + dependency: transitive + description: + name: shelf_static + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + source_maps: + dependency: transitive + description: + name: source_maps + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.10" source_span: dependency: transitive description: @@ -487,6 +641,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" stream_transform: dependency: transitive description: @@ -515,6 +676,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + test: + dependency: "direct dev" + description: + name: test + url: "https://pub.dartlang.org" + source: hosted + version: "1.16.8" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + test_core: + dependency: transitive + description: + name: test_core + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.19" tuple: dependency: "direct main" description: @@ -585,6 +767,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + vm_service: + dependency: transitive + description: + name: vm_service + url: "https://pub.dartlang.org" + source: hosted + version: "6.2.0" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" win32: dependency: transitive description: @@ -606,6 +816,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.0.2" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" sdks: dart: ">=2.12.0 <3.0.0" flutter: ">=1.24.0-10.2.pre" diff --git a/pubspec.yaml b/pubspec.yaml index c888687a..3b71b274 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -63,6 +63,7 @@ dependencies: xml: ^5.0.2 dev_dependencies: + test: ^1.16.8 # flutter_test: # sdk: flutter # integration_test: diff --git a/test/entity/album_test.dart b/test/entity/album_test.dart new file mode 100644 index 00000000..210fea35 --- /dev/null +++ b/test/entity/album_test.dart @@ -0,0 +1,312 @@ +import 'package:nc_photos/entity/album.dart'; +import 'package:nc_photos/entity/file.dart'; +import 'package:test/test.dart'; + +void main() { + group("Album", () { + group("fromJson", () { + test("lastUpdated", () { + final json = { + "version": Album.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "items": [], + }; + expect( + Album.fromJson(json), + Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "", + items: [], + )); + }); + + test("name", () { + final json = { + "version": Album.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "name": "album", + "items": [], + }; + expect( + Album.fromJson(json), + Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "album", + items: [], + )); + }); + + test("items", () { + final json = { + "version": Album.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "name": "", + "items": [ + { + "type": "file", + "content": { + "file": { + "path": "/remote.php/dav/files/admin/test1.jpg", + }, + }, + }, + { + "type": "file", + "content": { + "file": { + "path": "/remote.php/dav/files/admin/test2.jpg", + }, + }, + }, + ] + }; + expect( + Album.fromJson(json), + Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "", + items: [ + AlbumFileItem( + file: File(path: "/remote.php/dav/files/admin/test1.jpg"), + ), + AlbumFileItem( + file: File(path: "/remote.php/dav/files/admin/test2.jpg"), + ), + ], + )); + }); + + test("albumFile", () { + final json = { + "version": Album.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "items": [], + "albumFile": { + "path": "/remote.php/dav/files/admin/test1.jpg", + }, + }; + expect( + Album.fromJson(json), + Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "", + items: [], + albumFile: File(path: "/remote.php/dav/files/admin/test1.jpg"), + )); + }); + }); + + group("toRemoteJson", () { + test("lastUpdated", () { + final album = Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "", + items: [], + ); + expect(album.toRemoteJson(), { + "version": Album.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "name": "", + "items": [], + }); + }); + + test("name", () { + final album = Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "album", + items: [], + ); + expect(album.toRemoteJson(), { + "version": Album.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "name": "album", + "items": [], + }); + }); + + test("items", () { + final album = Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "", + items: [ + AlbumFileItem( + file: File(path: "/remote.php/dav/files/admin/test1.jpg"), + ), + AlbumFileItem( + file: File(path: "/remote.php/dav/files/admin/test2.jpg"), + ), + ], + ); + expect(album.toRemoteJson(), { + "version": Album.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "name": "", + "items": [ + { + "type": "file", + "content": { + "file": { + "path": "/remote.php/dav/files/admin/test1.jpg", + }, + }, + }, + { + "type": "file", + "content": { + "file": { + "path": "/remote.php/dav/files/admin/test2.jpg", + }, + }, + }, + ] + }); + }); + }); + + group("toAppDbJson", () { + test("lastUpdated", () { + final album = Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "", + items: [], + ); + expect(album.toAppDbJson(), { + "version": Album.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "name": "", + "items": [], + }); + }); + + test("name", () { + final album = Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "album", + items: [], + ); + expect(album.toAppDbJson(), { + "version": Album.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "name": "album", + "items": [], + }); + }); + + test("items", () { + final album = Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "", + items: [ + AlbumFileItem( + file: File(path: "/remote.php/dav/files/admin/test1.jpg"), + ), + AlbumFileItem( + file: File(path: "/remote.php/dav/files/admin/test2.jpg"), + ), + ], + ); + expect(album.toAppDbJson(), { + "version": Album.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "name": "", + "items": [ + { + "type": "file", + "content": { + "file": { + "path": "/remote.php/dav/files/admin/test1.jpg", + }, + }, + }, + { + "type": "file", + "content": { + "file": { + "path": "/remote.php/dav/files/admin/test2.jpg", + }, + }, + }, + ] + }); + }); + + test("albumFile", () { + final album = Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "", + items: [], + albumFile: File(path: "/remote.php/dav/files/admin/test1.jpg"), + ); + expect(album.toAppDbJson(), { + "version": Album.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "name": "", + "items": [], + "albumFile": { + "path": "/remote.php/dav/files/admin/test1.jpg", + }, + }); + }); + }); + + group("versioned", () { + test("v1", () { + final album = Album.versioned( + version: 1, + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "album", + items: [ + AlbumFileItem( + file: File(path: "/remote.php/dav/files/admin/test1.jpg"), + ), + AlbumFileItem( + file: File(path: "/remote.php/dav/files/admin/test2.jpg"), + ), + ], + albumFile: File(path: "/remote.php/dav/files/admin/test1.jpg"), + ); + expect( + album, + Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "album", + items: [], + albumFile: File(path: "/remote.php/dav/files/admin/test1.jpg"), + )); + }); + + test("v2", () { + final album = Album.versioned( + version: 2, + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "album", + items: [ + AlbumFileItem( + file: File(path: "/remote.php/dav/files/admin/test1.jpg"), + ), + AlbumFileItem( + file: File(path: "/remote.php/dav/files/admin/test2.jpg"), + ), + ], + albumFile: File(path: "/remote.php/dav/files/admin/test1.jpg"), + ); + expect( + album, + Album( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + name: "album", + items: [ + AlbumFileItem( + file: File(path: "/remote.php/dav/files/admin/test1.jpg"), + ), + AlbumFileItem( + file: File(path: "/remote.php/dav/files/admin/test2.jpg"), + ), + ], + albumFile: File(path: "/remote.php/dav/files/admin/test1.jpg"), + )); + }); + }); + }); +} diff --git a/test/entity/exif_test.dart b/test/entity/exif_test.dart new file mode 100644 index 00000000..8bb1d658 --- /dev/null +++ b/test/entity/exif_test.dart @@ -0,0 +1,157 @@ +import 'dart:typed_data'; + +import 'package:equatable/equatable.dart'; +import 'package:exifdart/exifdart.dart'; +import 'package:nc_photos/entity/exif.dart'; +import 'package:test/test.dart'; + +void main() { + group("Exif", () { + group("toJson", () { + test("int", () { + final exif = Exif({ + "ImageWidth": 1024, + }); + expect(exif.toJson(), { + "ImageWidth": 1024, + }); + }); + + test("String", () { + final exif = Exif({ + "Make": "dummy", + }); + expect(exif.toJson(), { + "Make": "dummy", + }); + }); + + test("Rational", () { + final exif = Exif({ + "XResolution": Rational(72, 1), + }); + expect(exif.toJson(), { + "XResolution": {"numerator": 72, "denominator": 1}, + }); + }); + + test("List", () { + final exif = Exif({ + "YCbCrSubSampling": [2, 2], + }); + expect(exif.toJson(), { + "YCbCrSubSampling": [2, 2], + }); + }); + + test("List", () { + final exif = Exif({ + "GPSLatitude": [Rational(2, 1), Rational(3, 1), Rational(4, 100)], + }); + expect(exif.toJson(), { + "GPSLatitude": [ + {"numerator": 2, "denominator": 1}, + {"numerator": 3, "denominator": 1}, + {"numerator": 4, "denominator": 100}, + ], + }); + }); + + test("MakerNote", () { + final exif = Exif({ + "MakerNote": Uint8List.fromList([0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF]), + }); + expect(exif.toJson(), { + "MakerNote": "ADNmmcz_", + }); + }); + }); + + group("fromJson", () { + test("int", () { + final json = { + "ImageWidth": 1024, + }; + expect( + Exif.fromJson(json), + Exif({ + "ImageWidth": 1024, + })); + }); + + test("String", () { + final json = { + "Make": "dummy", + }; + expect( + Exif.fromJson(json), + Exif({ + "Make": "dummy", + })); + }); + + test("Rational", () { + final json = { + "XResolution": {"numerator": 72, "denominator": 1}, + }; + final Rational exif = Exif.fromJson(json)["XResolution"]; + expect(exif.makeComparable(), _Rational(72, 1)); + }); + + test("List", () { + final json = { + "YCbCrSubSampling": [2, 2], + }; + expect( + Exif.fromJson(json), + Exif({ + "YCbCrSubSampling": [2, 2], + })); + }); + + test("List", () { + final json = { + "GPSLatitude": [ + {"numerator": 2, "denominator": 1}, + {"numerator": 3, "denominator": 1}, + {"numerator": 4, "denominator": 100}, + ], + }; + final List exif = + Exif.fromJson(json)["GPSLatitude"].cast(); + expect(exif.map((e) => e.makeComparable()).toList(), + [_Rational(2, 1), _Rational(3, 1), _Rational(4, 100)]); + }); + + test("MakerNote", () { + final json = { + "MakerNote": "ADNmmcz_", + }; + expect( + Exif.fromJson(json), + Exif({ + "MakerNote": + Uint8List.fromList([0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF]), + })); + }); + }); + }); +} + +extension on Rational { + _Rational makeComparable() => _Rational.of(this); +} + +class _Rational extends Rational with EquatableMixin { + _Rational(int numerator, int denominator) : super(numerator, denominator); + + factory _Rational.of(Rational r) { + return _Rational(r.numerator, r.denominator); + } + + @override + get props => [ + numerator, + denominator, + ]; +} diff --git a/test/entity/file_test.dart b/test/entity/file_test.dart new file mode 100644 index 00000000..253fcd22 --- /dev/null +++ b/test/entity/file_test.dart @@ -0,0 +1,708 @@ +import 'package:nc_photos/entity/exif.dart'; +import 'package:nc_photos/entity/file.dart'; +import 'package:test/test.dart'; + +void main() { + group("compareFileDateTimeDescending", () { + test("lastModified a>b", () { + final a = File( + path: "/remote.php/dav/files/admin/test1.jpg", + lastModified: DateTime.utc(2021), + ); + final b = File( + path: "/remote.php/dav/files/admin/test2.jpg", + lastModified: DateTime.utc(2020), + ); + expect(compareFileDateTimeDescending(a, b), lessThan(0)); + }); + + test("lastModified ab", () { + final a = File( + path: "/remote.php/dav/files/admin/test1.jpg", + metadata: Metadata( + exif: Exif({ + "DateTimeOriginal": "2021:01:02 03:04:05", + }), + ), + ); + final b = File( + path: "/remote.php/dav/files/admin/test2.jpg", + metadata: Metadata( + exif: Exif({ + "DateTimeOriginal": "2020:01:02 03:04:05", + }), + ), + ); + expect(compareFileDateTimeDescending(a, b), lessThan(0)); + }); + + test("exif a{ + "version": Metadata.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + }; + expect(Metadata.fromJson(json), + Metadata(lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901))); + }); + + test("fileEtag", () { + final json = { + "version": Metadata.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "fileEtag": "8a3e0799b6f0711c23cc2d93950eceb5", + }; + expect( + Metadata.fromJson(json), + Metadata( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + fileEtag: "8a3e0799b6f0711c23cc2d93950eceb5", + )); + }); + + test("imageWidth", () { + final json = { + "version": Metadata.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "imageWidth": 1024, + }; + expect( + Metadata.fromJson(json), + Metadata( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + imageWidth: 1024, + )); + }); + + test("imageHeight", () { + final json = { + "version": Metadata.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "imageHeight": 768, + }; + expect( + Metadata.fromJson(json), + Metadata( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + imageHeight: 768, + )); + }); + + test("exif", () { + final json = { + "version": Metadata.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "exif": { + "Make": "dummy", + }, + }; + expect( + Metadata.fromJson(json), + Metadata( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + exif: Exif({ + "Make": "dummy", + }), + )); + }); + }); + + group("toJson", () { + test("lastUpdated", () { + final metadata = + Metadata(lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901)); + expect(metadata.toJson(), { + "version": Metadata.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + }); + }); + + test("fileEtag", () { + final metadata = Metadata( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + fileEtag: "8a3e0799b6f0711c23cc2d93950eceb5", + ); + expect(metadata.toJson(), { + "version": Metadata.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "fileEtag": "8a3e0799b6f0711c23cc2d93950eceb5", + }); + }); + + test("imageWidth", () { + final metadata = Metadata( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + imageWidth: 1024, + ); + expect(metadata.toJson(), { + "version": Metadata.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "imageWidth": 1024, + }); + }); + + test("imageHeight", () { + final metadata = Metadata( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + imageHeight: 768, + ); + expect(metadata.toJson(), { + "version": Metadata.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "imageHeight": 768, + }); + }); + + test("exif", () { + final metadata = Metadata( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + exif: Exif({ + "Make": "dummy", + }), + ); + expect(metadata.toJson(), { + "version": Metadata.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + "exif": { + "Make": "dummy", + }, + }); + }); + }); + }); + + group("MetadataUpgraderV1", () { + test("call webp", () { + final json = { + "version": 1, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + }; + expect(MetadataUpgraderV1(fileContentType: "image/webp")(json), null); + }); + + test("call jpeg", () { + final json = { + "version": 1, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + }; + expect( + MetadataUpgraderV1(fileContentType: "image/jpeg")(json), + { + "version": 1, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + }); + }); + }); + + group("MetadataUpgraderV2", () { + test("call rotated jpeg", () { + final json = { + "version": 2, + "exif": { + "Orientation": 5, + }, + "imageWidth": 1024, + "imageHeight": 768, + }; + expect( + MetadataUpgraderV2(fileContentType: "image/jpeg")(json), + { + "version": 2, + "exif": { + "Orientation": 5, + }, + "imageWidth": 768, + "imageHeight": 1024, + }); + }); + + test("call non-rotated jpeg", () { + final json = { + "version": 2, + "exif": { + "Orientation": 1, + }, + "imageWidth": 1024, + "imageHeight": 768, + }; + expect( + MetadataUpgraderV2(fileContentType: "image/jpeg")(json), + { + "version": 2, + "exif": { + "Orientation": 1, + }, + "imageWidth": 1024, + "imageHeight": 768, + }); + }); + + test("call webp", () { + final json = { + "version": 2, + "exif": { + "Orientation": 5, + }, + "imageWidth": 1024, + "imageHeight": 768, + }; + expect( + MetadataUpgraderV2(fileContentType: "image/webp")(json), + { + "version": 2, + "exif": { + "Orientation": 5, + }, + "imageWidth": 1024, + "imageHeight": 768, + }); + }); + }); + + group("File", () { + group("fromJson", () { + test("path", () { + final json = { + "path": "/remote.php/dav/files/admin/test.jpg", + }; + final file = File.fromJson(json); + expect(file, File(path: "/remote.php/dav/files/admin/test.jpg")); + }); + + test("contentLength", () { + final json = { + "path": "", + "contentLength": 123, + }; + final file = File.fromJson(json); + expect(file, File(path: "", contentLength: 123)); + }); + + test("contentType", () { + final json = { + "path": "", + "contentType": "image/jpeg", + }; + final file = File.fromJson(json); + expect(file, File(path: "", contentType: "image/jpeg")); + }); + + test("etag", () { + final json = { + "path": "", + "etag": "8a3e0799b6f0711c23cc2d93950eceb5", + }; + final file = File.fromJson(json); + expect(file, File(path: "", etag: "8a3e0799b6f0711c23cc2d93950eceb5")); + }); + + test("lastModified", () { + final json = { + "path": "", + "lastModified": "2020-01-02T03:04:05.678901Z", + }; + final file = File.fromJson(json); + expect( + file, + File( + path: "", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + )); + }); + + test("isCollection", () { + final json = { + "path": "", + "isCollection": true, + }; + final file = File.fromJson(json); + expect(file, File(path: "", isCollection: true)); + }); + + test("usedBytes", () { + final json = { + "path": "", + "usedBytes": 123456, + }; + final file = File.fromJson(json); + expect(file, File(path: "", usedBytes: 123456)); + }); + + test("hasPreview", () { + final json = { + "path": "", + "hasPreview": true, + }; + final file = File.fromJson(json); + expect(file, File(path: "", hasPreview: true)); + }); + + test("metadata", () { + final json = { + "path": "", + "metadata": { + "version": Metadata.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + }, + }; + final file = File.fromJson(json); + expect( + file, + File( + path: "", + metadata: Metadata( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + ), + )); + }); + }); + + group("toJson", () { + test("path", () { + final file = File(path: "/remote.php/dav/files/admin/test.jpg"); + expect(file.toJson(), { + "path": "/remote.php/dav/files/admin/test.jpg", + }); + }); + + test("contentLength", () { + final file = File( + path: "/remote.php/dav/files/admin/test.jpg", contentLength: 123); + expect(file.toJson(), { + "path": "/remote.php/dav/files/admin/test.jpg", + "contentLength": 123, + }); + }); + + test("contentType", () { + final file = File( + path: "/remote.php/dav/files/admin/test.jpg", + contentType: "image/jpeg"); + expect(file.toJson(), { + "path": "/remote.php/dav/files/admin/test.jpg", + "contentType": "image/jpeg", + }); + }); + + test("etag", () { + final file = File( + path: "/remote.php/dav/files/admin/test.jpg", + etag: "8a3e0799b6f0711c23cc2d93950eceb5"); + expect(file.toJson(), { + "path": "/remote.php/dav/files/admin/test.jpg", + "etag": "8a3e0799b6f0711c23cc2d93950eceb5", + }); + }); + + test("lastModified", () { + final file = File( + path: "/remote.php/dav/files/admin/test.jpg", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901)); + expect(file.toJson(), { + "path": "/remote.php/dav/files/admin/test.jpg", + "lastModified": "2020-01-02T03:04:05.678901Z", + }); + }); + + test("isCollection", () { + final file = File( + path: "/remote.php/dav/files/admin/test.jpg", isCollection: true); + expect(file.toJson(), { + "path": "/remote.php/dav/files/admin/test.jpg", + "isCollection": true, + }); + }); + + test("usedBytes", () { + final file = File( + path: "/remote.php/dav/files/admin/test.jpg", usedBytes: 123456); + expect(file.toJson(), { + "path": "/remote.php/dav/files/admin/test.jpg", + "usedBytes": 123456, + }); + }); + + test("hasPreview", () { + final file = File( + path: "/remote.php/dav/files/admin/test.jpg", hasPreview: true); + expect(file.toJson(), { + "path": "/remote.php/dav/files/admin/test.jpg", + "hasPreview": true, + }); + }); + + test("metadata", () { + final file = File( + path: "/remote.php/dav/files/admin/test.jpg", + metadata: Metadata( + lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + )); + expect(file.toJson(), { + "path": "/remote.php/dav/files/admin/test.jpg", + "metadata": { + "version": Metadata.version, + "lastUpdated": "2020-01-02T03:04:05.678901Z", + }, + }); + }); + }); + + group("copyWith", () { + final src = File( + path: "/remote.php/dav/files/admin/test.jpg", + contentLength: 123, + contentType: "image/jpeg", + etag: "8a3e0799b6f0711c23cc2d93950eceb5", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + isCollection: true, + usedBytes: 123456, + hasPreview: true, + metadata: null, + ); + + test("path", () { + final file = src.copyWith(path: "/remote.php/dav/files/admin/test.png"); + expect( + file, + File( + path: "/remote.php/dav/files/admin/test.png", + contentLength: 123, + contentType: "image/jpeg", + etag: "8a3e0799b6f0711c23cc2d93950eceb5", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + isCollection: true, + usedBytes: 123456, + hasPreview: true, + )); + }); + + test("contentLength", () { + final file = src.copyWith(contentLength: 321); + expect( + file, + File( + path: "/remote.php/dav/files/admin/test.jpg", + contentLength: 321, + contentType: "image/jpeg", + etag: "8a3e0799b6f0711c23cc2d93950eceb5", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + isCollection: true, + usedBytes: 123456, + hasPreview: true, + )); + }); + + test("contentType", () { + final file = src.copyWith(contentType: "image/png"); + expect( + file, + File( + path: "/remote.php/dav/files/admin/test.jpg", + contentLength: 123, + contentType: "image/png", + etag: "8a3e0799b6f0711c23cc2d93950eceb5", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + isCollection: true, + usedBytes: 123456, + hasPreview: true, + )); + }); + + test("etag", () { + final file = src.copyWith(etag: "000"); + expect( + file, + File( + path: "/remote.php/dav/files/admin/test.jpg", + contentLength: 123, + contentType: "image/jpeg", + etag: "000", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + isCollection: true, + usedBytes: 123456, + hasPreview: true, + )); + }); + + test("lastModified", () { + final now = DateTime.now(); + final file = src.copyWith(lastModified: now); + expect( + file, + File( + path: "/remote.php/dav/files/admin/test.jpg", + contentLength: 123, + contentType: "image/jpeg", + etag: "8a3e0799b6f0711c23cc2d93950eceb5", + lastModified: now, + isCollection: true, + usedBytes: 123456, + hasPreview: true, + )); + }); + + test("isCollection", () { + final file = src.copyWith(isCollection: false); + expect( + file, + File( + path: "/remote.php/dav/files/admin/test.jpg", + contentLength: 123, + contentType: "image/jpeg", + etag: "8a3e0799b6f0711c23cc2d93950eceb5", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + isCollection: false, + usedBytes: 123456, + hasPreview: true, + )); + }); + + test("usedBytes", () { + final file = src.copyWith(usedBytes: 999999); + expect( + file, + File( + path: "/remote.php/dav/files/admin/test.jpg", + contentLength: 123, + contentType: "image/jpeg", + etag: "8a3e0799b6f0711c23cc2d93950eceb5", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + isCollection: true, + usedBytes: 999999, + hasPreview: true, + )); + }); + + test("hasPreview", () { + final file = src.copyWith(hasPreview: false); + expect( + file, + File( + path: "/remote.php/dav/files/admin/test.jpg", + contentLength: 123, + contentType: "image/jpeg", + etag: "8a3e0799b6f0711c23cc2d93950eceb5", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + isCollection: true, + usedBytes: 123456, + hasPreview: false, + )); + }); + + test("metadata", () { + final metadata = Metadata(); + final file = src.copyWith(metadata: metadata); + expect( + file, + File( + path: "/remote.php/dav/files/admin/test.jpg", + contentLength: 123, + contentType: "image/jpeg", + etag: "8a3e0799b6f0711c23cc2d93950eceb5", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + isCollection: true, + usedBytes: 123456, + hasPreview: true, + metadata: metadata, + )); + }); + }); + + test("withoutMetadata", () { + final file = File( + path: "/remote.php/dav/files/admin/test.jpg", + contentLength: 123, + contentType: "image/jpeg", + etag: "8a3e0799b6f0711c23cc2d93950eceb5", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + isCollection: true, + usedBytes: 123456, + hasPreview: true, + metadata: Metadata(), + ); + expect( + file.withoutMetadata(), + File( + path: "/remote.php/dav/files/admin/test.jpg", + contentLength: 123, + contentType: "image/jpeg", + etag: "8a3e0799b6f0711c23cc2d93950eceb5", + lastModified: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901), + isCollection: true, + usedBytes: 123456, + hasPreview: true, + )); + }); + + test("strippedPath", () { + final file = File(path: "/remote.php/dav/files/admin/test.jpg"); + expect(file.strippedPath, "admin/test.jpg"); + }); + }); +}