Test case for LsDirBloc

This commit is contained in:
Ming Ming 2021-08-17 03:05:00 +08:00
parent e9659509a8
commit f430e8f3cd
6 changed files with 252 additions and 6 deletions

View file

@ -1,11 +1,12 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/file/data_source.dart';
import 'package:nc_photos/use_case/ls.dart';
class LsDirBlocItem {
class LsDirBlocItem with EquatableMixin {
LsDirBlocItem(this.file, this.children);
@override
@ -32,6 +33,12 @@ class LsDirBlocItem {
return product;
}
@override
get props => [
file,
children,
];
final File file;
/// Child directories under this directory
@ -77,18 +84,25 @@ class LsDirBlocQuery extends LsDirBlocEvent {
final int depth;
}
abstract class LsDirBlocState {
abstract class LsDirBlocState with EquatableMixin {
const LsDirBlocState(this.account, this.root, this.items);
@override
toString() {
return "$runtimeType {"
"account: $account, "
"root: ${root.path}"
"root: ${root.path}, "
"items: List {length: ${items.length}}, "
"}";
}
@override
get props => [
account,
root,
items,
];
final Account? account;
final File root;
final List<LsDirBlocItem> items;
@ -121,12 +135,20 @@ class LsDirBlocFailure extends LsDirBlocState {
"}";
}
@override
get props => [
...super.props,
exception,
];
final dynamic exception;
}
/// A bloc that return all directories under a dir recursively
class LsDirBloc extends Bloc<LsDirBlocEvent, LsDirBlocState> {
LsDirBloc() : super(LsDirBlocInit());
LsDirBloc({
this.fileRepo = const FileRepo(const FileWebdavDataSource()),
}) : super(LsDirBlocInit());
@override
mapEventToState(LsDirBlocEvent event) async* {
@ -150,7 +172,7 @@ class LsDirBloc extends Bloc<LsDirBlocEvent, LsDirBlocState> {
final product = <LsDirBlocItem>[];
var files = _cache[ev.root.path];
if (files == null) {
files = (await Ls(FileRepo(FileWebdavDataSource()))(ev.account, ev.root))
files = (await Ls(fileRepo)(ev.account, ev.root))
.where((f) => f.isCollection ?? false)
.toList();
_cache[ev.root.path] = files;
@ -165,6 +187,8 @@ class LsDirBloc extends Bloc<LsDirBlocEvent, LsDirBlocState> {
return product;
}
final FileRepo fileRepo;
final _cache = <String, List<File>>{};
static final _log = Logger("bloc.ls_dir.LsDirBloc");

View file

@ -456,7 +456,7 @@ extension FileExtension on File {
}
class FileRepo {
FileRepo(this.dataSrc);
const FileRepo(this.dataSrc);
/// See [FileDataSource.list]
Future<List<File>> list(Account account, File root) =>

View file

@ -22,6 +22,8 @@ import 'package:uuid/uuid.dart';
import 'package:xml/xml.dart';
class FileWebdavDataSource implements FileDataSource {
const FileWebdavDataSource();
@override
list(
Account account,

View file

@ -50,6 +50,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "7.0.0"
bloc_test:
dependency: "direct dev"
description:
name: bloc_test
url: "https://pub.dartlang.org"
source: hosted
version: "8.1.0"
boolean_selector:
dependency: transitive
description:
@ -412,6 +419,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
mocktail:
dependency: transitive
description:
name: mocktail
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.4"
nested:
dependency: transitive
description:

View file

@ -79,6 +79,7 @@ dependencies:
dev_dependencies:
test: any
bloc_test: any
# flutter_test:
# sdk: flutter
# integration_test:

205
test/bloc/ls_dir_test.dart Normal file
View file

@ -0,0 +1,205 @@
import 'dart:typed_data';
import 'package:bloc_test/bloc_test.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/bloc/ls_dir.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/or_null.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
void main() {
final _buildBloc = () => LsDirBloc(fileRepo: _MockFileRepo());
final _buildAccount =
() => Account("http", "example.com", "admin", "pass", [""]);
group("ListDir", () {
group("LsDirBlocQuery", () {
test("initial state", () {
final bloc = _buildBloc();
expect(bloc.state.account, null);
expect(bloc.state.root, File(path: ""));
expect(bloc.state.items, []);
});
blocTest(
"inital",
build: _buildBloc,
expect: () => [],
);
blocTest<LsDirBloc, LsDirBlocState>(
"query 1 subdir",
build: _buildBloc,
act: (bloc) => bloc.add(LsDirBlocQuery(
_buildAccount(), File(path: "remote.php/dav/files/admin"))),
expect: () => [
LsDirBlocLoading(
_buildAccount(), File(path: "remote.php/dav/files/admin"), []),
LsDirBlocSuccess(
_buildAccount(), File(path: "remote.php/dav/files/admin"), [
LsDirBlocItem(
File(
path: "remote.php/dav/files/admin/d1",
isCollection: true,
),
null,
),
]),
],
);
blocTest<LsDirBloc, LsDirBlocState>(
"query n subdir",
build: _buildBloc,
act: (bloc) => bloc.add(LsDirBlocQuery(
_buildAccount(), File(path: "remote.php/dav/files/admin/d1"))),
expect: () => [
LsDirBlocLoading(
_buildAccount(), File(path: "remote.php/dav/files/admin/d1"), []),
LsDirBlocSuccess(
_buildAccount(), File(path: "remote.php/dav/files/admin/d1"), [
LsDirBlocItem(
File(
path: "remote.php/dav/files/admin/d1/d2-1",
isCollection: true,
),
null,
),
LsDirBlocItem(
File(
path: "remote.php/dav/files/admin/d1/d2-2",
isCollection: true,
),
null,
),
]),
],
);
blocTest<LsDirBloc, LsDirBlocState>(
"query 0 subdir",
build: _buildBloc,
act: (bloc) => bloc.add(LsDirBlocQuery(
_buildAccount(), File(path: "remote.php/dav/files/admin/d1/d2-2"))),
expect: () => [
LsDirBlocLoading(_buildAccount(),
File(path: "remote.php/dav/files/admin/d1/d2-2"), []),
LsDirBlocSuccess(_buildAccount(),
File(path: "remote.php/dav/files/admin/d1/d2-2"), []),
],
);
blocTest<LsDirBloc, LsDirBlocState>(
"query depth 2",
build: _buildBloc,
act: (bloc) => bloc.add(LsDirBlocQuery(
_buildAccount(), File(path: "remote.php/dav/files/admin"),
depth: 2)),
expect: () => [
LsDirBlocLoading(
_buildAccount(), File(path: "remote.php/dav/files/admin"), []),
LsDirBlocSuccess(
_buildAccount(), File(path: "remote.php/dav/files/admin"), [
LsDirBlocItem(
File(
path: "remote.php/dav/files/admin/d1",
isCollection: true,
),
[
LsDirBlocItem(
File(
path: "remote.php/dav/files/admin/d1/d2-1",
isCollection: true,
),
null,
),
LsDirBlocItem(
File(
path: "remote.php/dav/files/admin/d1/d2-2",
isCollection: true,
),
null,
),
],
),
]),
],
);
});
});
}
class _MockFileRepo implements FileRepo {
@override
Future<void> copy(Object account, File f, String destination,
{bool? shouldOverwrite}) {
throw UnimplementedError();
}
@override
Future<void> createDir(Account account, String path) {
throw UnimplementedError();
}
@override
FileDataSource get dataSrc => throw UnimplementedError();
@override
Future<Uint8List> getBinary(Account account, File file) {
throw UnimplementedError();
}
@override
Future<List<File>> list(Account account, File root) async {
await Future.delayed(const Duration(seconds: 1));
return [
File(
path: "remote.php/dav/files/admin/test1.jpg",
),
File(
path: "remote.php/dav/files/admin/d1",
isCollection: true,
),
File(
path: "remote.php/dav/files/admin/d1/test2.jpg",
),
File(
path: "remote.php/dav/files/admin/d1/d2-1",
isCollection: true,
),
File(
path: "remote.php/dav/files/admin/d1/d2-2",
isCollection: true,
),
File(
path: "remote.php/dav/files/admin/d1/d2-1/d3",
isCollection: true,
),
].where((element) => path.dirname(element.path) == root.path).toList();
}
@override
Future<void> move(Account account, File f, String destination,
{bool? shouldOverwrite}) {
throw UnimplementedError();
}
@override
Future<void> putBinary(Account account, String path, Uint8List content) {
throw UnimplementedError();
}
@override
Future<void> remove(Account account, File file) {
throw UnimplementedError();
}
@override
Future<void> updateProperty(Account account, File file,
{OrNull<Metadata>? metadata,
OrNull<bool>? isArchived,
OrNull<DateTime>? overrideDateTime}) {
throw UnimplementedError();
}
}