query tests added

This commit is contained in:
Kingkor Roy Tirtho
2022-07-20 12:21:18 +06:00
parent 915f2aecfc
commit f0741045a5
12 changed files with 424 additions and 83 deletions
@@ -1,7 +1,7 @@
import 'package:fl_query/src/query_bowl.dart';
import 'package:flutter/widgets.dart';
abstract class BaseOperation<Data, StatusType> extends ChangeNotifier {
abstract class BaseOperation<Data> extends ChangeNotifier {
/// The number of times the query should refetch in the time of error
/// before giving up
final int retries;
@@ -14,7 +14,6 @@ abstract class BaseOperation<Data, StatusType> extends ChangeNotifier {
// all properties
Data? data;
dynamic error;
StatusType status;
/// total count of how many times the query retried to get a successful
/// result
@@ -34,7 +33,6 @@ abstract class BaseOperation<Data, StatusType> extends ChangeNotifier {
required this.cacheTime,
required this.retries,
required this.retryDelay,
required this.status,
required this.queryBowl,
this.data,
}) : updatedAt = DateTime.now();
@@ -58,10 +56,6 @@ abstract class BaseOperation<Data, StatusType> extends ChangeNotifier {
Set<ValueKey<String>> get mounts => _mounts;
bool get isSuccess;
bool get isError;
bool get isLoading;
bool get isIdle;
bool get isInactive => mounts.isEmpty;
bool get hasData => data != null;
bool get hasError => error != null;
@@ -1,22 +1,5 @@
import 'package:fl_query/src/query.dart';
/// How to make dependent Queries?
///
/// Pass a [QueryBowl] class/object to [task] that contains a method
/// [QueryBowl.dependOnQuery] that takes a [QueryJob] and uses that to get
/// the appropriate query for it or if it doesn't exist creates a new
/// instance. It listens to the changes of [Query] of the passed
/// [QueryJob] & calls the [notifyListener] method of running [Query]
///
/// If shown briefly
///
/// ```data
/// task: (queryKey, external, queryBowl){
/// final dependentQuery = queryBowl.dependOnQuery(dependentQueryJob);
/// return someAsyncTask();
/// }
/// ```
class QueryJob<T extends Object, Outside> {
// all params
String _queryKey;
+6 -7
View File
@@ -16,11 +16,13 @@ typedef MutationListener<T> = FutureOr<void> Function(T);
typedef MutationTaskFunction<T, V> = FutureOr<T> Function(
String queryKey, V variables);
class Mutation<T extends Object, V> extends BaseOperation<T, MutationStatus> {
class Mutation<T extends Object, V> extends BaseOperation<T> {
// all params
final String mutationKey;
MutationTaskFunction<T, V> task;
MutationStatus status;
@protected
final Set<MutationListener<T>> onDataListeners = {};
@protected
@@ -38,7 +40,8 @@ class Mutation<T extends Object, V> extends BaseOperation<T, MutationStatus> {
MutationListener<T>? onData,
MutationListener<dynamic>? onError,
MutationListener<V>? onMutate,
}) : super(cacheTime: cacheTime, status: MutationStatus.idle) {
}) : status = MutationStatus.idle,
super(cacheTime: cacheTime) {
if (onData != null) onDataListeners.add(onData);
if (onError != null) onErrorListeners.add(onError);
if (onMutate != null) onMutateListeners.add(onMutate);
@@ -52,11 +55,11 @@ class Mutation<T extends Object, V> extends BaseOperation<T, MutationStatus> {
required super.queryBowl,
}) : mutationKey = options.mutationKey,
task = options.task,
status = MutationStatus.idle,
super(
retries: options.retries ?? 3,
retryDelay: options.retryDelay ?? const Duration(milliseconds: 200),
cacheTime: options.cacheTime ?? const Duration(minutes: 5),
status: MutationStatus.idle,
) {
if (onData != null) onDataListeners.add(onData);
if (onError != null) onErrorListeners.add(onError);
@@ -160,13 +163,9 @@ class Mutation<T extends Object, V> extends BaseOperation<T, MutationStatus> {
A? cast<A>() => this is A ? this as A : null;
@override
bool get isError => status == MutationStatus.error;
@override
bool get isIdle => status == MutationStatus.idle;
@override
bool get isLoading => status == MutationStatus.loading;
@override
bool get isSuccess => status == MutationStatus.success;
@override
+21 -16
View File
@@ -36,7 +36,7 @@ typedef ListenerUnsubscriber = void Function();
typedef QueryUpdateFunction<T> = FutureOr<T> Function(T? oldData);
class Query<T extends Object, Outside> extends BaseOperation<T, QueryStatus> {
class Query<T extends Object, Outside> extends BaseOperation<T> {
// all params
final String queryKey;
QueryTaskFunction<T, Outside> task;
@@ -54,6 +54,8 @@ class Query<T extends Object, Outside> extends BaseOperation<T, QueryStatus> {
int refetchCount = 0;
bool enabled;
QueryStatus status;
@protected
final Set<QueryListener<T>> onDataListeners = Set<QueryListener<T>>();
@protected
@@ -89,10 +91,8 @@ class Query<T extends Object, Outside> extends BaseOperation<T, QueryStatus> {
}) : _staleTime = staleTime,
_initialData = initialData,
_externalData = externalData,
super(
status: QueryStatus.idle,
data: initialData,
) {
status = QueryStatus.idle,
super(data: initialData) {
if (onData != null) onDataListeners.add(onData);
if (onError != null) onErrorListeners.add(onError);
@@ -116,8 +116,8 @@ class Query<T extends Object, Outside> extends BaseOperation<T, QueryStatus> {
refetchInterval = options.refetchInterval,
refetchOnMount = options.refetchOnMount,
refetchOnReconnect = options.refetchOnReconnect,
status = QueryStatus.idle,
super(
status: QueryStatus.idle,
cacheTime: options.cacheTime ?? const Duration(minutes: 5),
retries: options.retries ?? 3,
retryDelay: options.retryDelay ?? const Duration(milliseconds: 200),
@@ -193,6 +193,7 @@ class Query<T extends Object, Outside> extends BaseOperation<T, QueryStatus> {
await onError(error);
}
notifyListeners();
break;
}
retryAttempts++;
}
@@ -219,7 +220,7 @@ class Query<T extends Object, Outside> extends BaseOperation<T, QueryStatus> {
/// if isLoading/isRefetching is true that means its already fetching/
/// refetching. So [_execute] again can create a race condition
if (isRefetching || isLoading) return data;
if (enabled && !fetched) await fetch();
if (enabled && !fetched) return await fetch();
status = QueryStatus.refetching;
refetchCount++;
// disabling the lazy query bound when query was actually called
@@ -245,7 +246,7 @@ class Query<T extends Object, Outside> extends BaseOperation<T, QueryStatus> {
notifyListeners();
}
setExternalData(Outside externalData) {
void setExternalData(Outside externalData) {
_prevUsedExternalData = _externalData;
_externalData = externalData;
}
@@ -289,10 +290,6 @@ class Query<T extends Object, Outside> extends BaseOperation<T, QueryStatus> {
notifyListeners();
}
Future<T?> _internalRefetch<X>(X dataOrError) {
return refetch();
}
bool get isStale {
/// when [_staleTime] is [Duration.zero], the query will always be
/// stale & will never refetch in the background. But can be inactive
@@ -304,20 +301,28 @@ class Query<T extends Object, Outside> extends BaseOperation<T, QueryStatus> {
return DateTime.now().isAfter(updatedAt.add(_staleTime));
}
@override
bool get isError => status == QueryStatus.error;
@override
bool get isIdle => status == QueryStatus.idle;
@override
bool get isLoading => status == QueryStatus.loading;
bool get isRefetching => status == QueryStatus.refetching;
@override
bool get isSuccess => status == QueryStatus.success;
A? cast<A>() => this is A ? this as A : null;
String get debugLabel => "Query($queryKey)";
@override
void mount(ValueKey<String> uKey) {
super.mount(uKey);
if (refetchOnMount == true && isStale) {
Connectivity().checkConnectivity().then((status) async {
if (isConnectedToInternet(status)) {
await refetch();
}
});
}
}
@override
String toString() {
return debugLabel;
+5 -3
View File
@@ -55,9 +55,11 @@ class _QueryBuilderState<T extends Object, Outside>
final hasExternalDataChanged = query!.externalData != null &&
query!.prevUsedExternalData != null &&
!isShallowEqual(query!.externalData!, query!.prevUsedExternalData!);
(query!.fetched && query!.refetchOnMount == true) || hasExternalDataChanged
? await query!.refetch()
: await query!.fetch();
if (query!.fetched && hasExternalDataChanged) {
await query!.refetch();
} else if (!query!.fetched) {
await query!.fetch();
}
}
@override