runScenarios function
Future<void>
runScenarios(
- FutureOr<
void> testMain(), { - ScenarioProfile? profile,
- Shots? shots,
- bool keyboard = true,
- bool shadows = true,
- ScenarioNetwork? network,
- Settle? settle,
- ScenarioReelEdit? reel,
- ScenarioTime? time,
Also loads the project's fonts, once, before anything is declared — the
step flutter test otherwise leaves to each project's own
flutter_test_config.dart. Without it this lane measures text in the
fallback font while the flutterware harness measures it in the real one,
and the disagreement surfaces as overflows on screens that do not overflow.
Implementation
Future<void> runScenarios(
FutureOr<void> Function() testMain, {
ScenarioProfile? profile,
Shots? shots,
bool keyboard = true,
bool shadows = true,
ScenarioNetwork? network,
Settle? settle,
ScenarioReelEdit? reel,
ScenarioTime? time,
}) async {
// Under the flutterware runner this is called to *ask* what the folder is
// for, not to declare anything: the harness reads the profile here and
// declares the files itself, one pass, with the axes the request named.
// Whatever setup the config does around `testMain` still runs — which is the
// point of coming through this door rather than parsing the file.
// Armed before the probe returns, not after: under the harness this function
// is called only to *ask* what the folder is for, so anything below the
// early return never runs in the runner's lane. The harness arms it too, for
// the folder that declares no config at all.
TranslationIndex.recording = true;
if (scenarioProbing) {
scenarioProbedProfile = profile;
scenarioProbedShots = shots;
scenarioProbedKeyboard = keyboard;
scenarioProbedShadows = shadows;
scenarioProbedNetwork = network;
scenarioProbedTime = time;
scenarioProbedSettle = settle;
scenarioProbedReel = reel;
return;
}
// The clock, resolved the way `network` resolves `FW_NETWORK`: the argument,
// else the environment, else fake. Under the harness this never runs — the
// probe returned above — and the harness said its own clock when it built
// its binding. Resolved before the fonts because the binding has to exist
// before anything touches the engine.
var resolvedTime =
time ??
switch (Platform.environment['FW_TIME']) {
null || '' => null,
var raw => parseScenarioTime(raw),
};
if (resolvedTime?.isReal ?? false) {
ensureLiveScenarioBinding(animations: resolvedTime!.animations);
}
scenarioHarnessTime = resolvedTime ?? ScenarioTime.fake;
// Before the first declaration and after the probe returns: the harness
// loads its own, and a scenario laid out in the fallback font reports itself
// as `RenderFlex overflowed by 3.5 pixels` rather than as a font problem.
//
// The defaults too, and only here: this line runs under bare `flutter test`
// alone — the harness probes and returns above — which is exactly the lane
// whose `--use-test-fonts` boxes every family nobody loads bytes for. See
// [loadDefaultScenarioFonts] for why the harness must not do this.
await loadScenarioFonts();
await loadDefaultScenarioFonts();
var assignments = scenarioAssignments(profile);
scenarioAmbientShots = shots;
scenarioAmbientKeyboard = keyboard;
scenarioAmbientShadows = shadows;
scenarioAmbientNetwork = network;
scenarioAmbientTime = resolvedTime;
scenarioAmbientSettle = settle;
scenarioAmbientReel = reel;
try {
for (var assignment in assignments) {
scenarioAmbientAssignment = assignment;
// More than one pass means the same scenario is declared more than once,
// so its name has to say which is which. One pass leaves names alone —
// nobody wants `Counter [iPhone 16 · en]` in a suite that runs one way.
scenarioAmbientIsMatrix = assignments.length > 1;
await testMain();
}
} finally {
scenarioAmbientAssignment = null;
scenarioAmbientIsMatrix = false;
scenarioAmbientShots = null;
scenarioAmbientKeyboard = null;
scenarioAmbientShadows = null;
scenarioAmbientNetwork = null;
scenarioAmbientSettle = null;
scenarioAmbientReel = null;
}
}