key method

Future<void> key(
  1. String chord, {
  2. Shot? shot,
  3. Settle? settle,
})

Presses a key — escape, enter, tab, arrowDown — or a chord: meta+k, shift+tab, control+s.

chord is +-separated: the last name fires, and everything before it is held down for it and released after, in reverse. Names are LogicalKeyboardKey debug names spelled any way that reads, a single character, or one of cmd, ctrl, alt, opt, shift, esc — each modifier meaning its left key, which is what a SingleActivator checks for. A Mac shortcut and its Windows twin are two chords.

For shortcuts and navigation, never for typing. A character reaches a field through the platform's text input rather than through a key event, so key('a') into a focused field leaves it empty, in a running app as much as here; enterText is the verb that types.

A keystroke dispatches from whatever holds focus, upwards, and with nothing focused it passes above every Shortcuts the app declares. So a key nothing took, pressed while nothing held focus, is refused rather than reported done — the one way this verb could otherwise do nothing silently.

The live drive's key, the same names and the same keystroke, so a chord worked out against the running app ports as written.

Implementation

Future<void> key(String chord, {Shot? shot, Settle? settle}) => _step(
  shot,
  settle,
  () async {
    KeyChord keys;
    try {
      keys = KeyChord.parse(chord, verb: 's.key');
    } on TargetError catch (error) {
      throw ScenarioTargetError(error.message);
    }
    if (keys.held case var key?) {
      throw ScenarioTargetError(
        '${key.debugName} is already held down: it was pressed through '
        '`s.tester` and not released. `s.key("$chord")` presses every key '
        'of its chord itself, so release it first or leave it out of the '
        'chord.',
      );
    }
    var handled = await keys.press();
    if (!handled && nothingFocused) {
      throw ScenarioTargetError(
        '`s.key("$chord")` went nowhere: nothing in the app holds focus, so '
        "none of the app's `Shortcuts` received it. Give the app focus "
        'first: `s.tap` a control, `s.enterText` into a field, or set '
        '`autofocus: true` on the widget the shortcut belongs to. The keys '
        'were pressed and released, so nothing is stuck.',
      );
    }
  },
  verb: 'key',
  target: chord,
);