waitAllUnordered method
The same as waitAllUnorderedGetLast
, but instead of returning just the last info,
it returns a list with the end info for each action.
If you pass action types to ignore
, they will be ignored (the test won't fail when
encountering them, and won't collect testInfo for them). This method will remember all
ignored actions and wait for them to finish, so that they don't "leak" to the next wait.
An action type cannot exist in both actionTypes
and ignore
lists.
If ignore
is null, it will use the global ignore provided in the
StoreTester constructor, if any. If ignore
is an empty list, it
will disable that global ignore.
Implementation
Future<TestInfoList<St>> waitAllUnordered(
List<Type> actionTypes, {
int? timeoutInSeconds,
List<Type>? ignore,
}) async {
assert(actionTypes.isNotEmpty);
timeoutInSeconds ??= defaultTimeout;
ignore ??= _ignore;
// Actions which are expected can't also be ignored.
var intersection = ignore.toSet().intersection(actionTypes.toSet());
if (intersection.isNotEmpty)
throw StoreException("Actions $intersection "
"should not be expected and ignored.");
TestInfoList<St> infoList = TestInfoList<St>();
List<Type> actionsIni = List.from(actionTypes);
List<Type> actionsEnd = List.from(actionTypes);
TestInfo<St>? testInfo;
// Saves ignored actions INI.
// Note: This relies on Actions not overriding operator ==.
List<ReduxAction?> ignoredActions = [];
while (actionsIni.isNotEmpty || actionsEnd.isNotEmpty) {
try {
testInfo = await _next(timeoutInSeconds: timeoutInSeconds);
while (ignore.contains(testInfo!.type)) {
//
// Saves ignored actions.
if (ignore.contains(testInfo.type)) {
if (testInfo.isINI)
ignoredActions.add(testInfo.action);
else
ignoredActions.remove(testInfo.action);
}
testInfo = await (_next(timeoutInSeconds: timeoutInSeconds));
}
} on StoreExceptionTimeout catch (error) {
error.addDetail("These actions were not dispatched: "
"$actionsIni INI.");
error.addDetail("These actions haven't finished: "
"$actionsEnd END.");
rethrow;
}
var action = testInfo.type;
if (testInfo.isINI) {
if (!actionsIni.remove(action))
throw StoreException("Unexpected action was dispatched: "
"$action INI.");
} else {
if (!actionsEnd.remove(action))
throw StoreException("Unexpected action was dispatched: "
"$action END.");
// Only save the END states.
infoList._add(testInfo);
}
}
// Wait for all ignored actions to finish, so that they don't "leak" to the next wait.
while (ignoredActions.isNotEmpty) {
testInfo = await _next();
var wasIgnored = ignoredActions.remove(testInfo.action);
if (!wasIgnored && ignore.contains(testInfo.type)) {
if (testInfo.isINI)
ignoredActions.add(testInfo.action);
else
ignoredActions.remove(testInfo.action);
continue;
}
if (!testInfo.isEND || !wasIgnored)
throw StoreException("Got this unexpected action: "
"${testInfo.type} ${testInfo.ini ? "INI" : "END"}.");
}
lastInfo = infoList.last;
return infoList;
}