{"record":{"id":"19c5632b639c1249","repo":"angular/components","slug":"no-keys-have-been-specified","errorCode":null,"errorMessage":"No keys have been specified.","messagePattern":"No keys have been specified\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cdk/testing/protractor/protractor-element.ts","lineNumber":185,"sourceCode":"      modifiers = first;\n      rest = modifiersAndKeys.slice(1);\n    } else {\n      modifiers = {};\n      rest = modifiersAndKeys;\n    }\n\n    const modifierKeys = toProtractorModifierKeys(modifiers);\n    const keys = rest\n      .map(k => (typeof k === 'string' ? k.split('') : [keyMap[k]]))\n      .reduce((arr, k) => arr.concat(k), [])\n      // Key.chord doesn't work well with geckodriver (mozilla/geckodriver#1502),\n      // so avoid it if no modifier keys are required.\n      .map(k => (modifierKeys.length > 0 ? Key.chord(...modifierKeys, k) : k));\n\n    // Throw an error if no keys have been specified. Calling this function with no\n    // keys should not result in a focus event being dispatched unexpectedly.\n    if (keys.length === 0) {\n      throw getNoKeysSpecifiedError();\n    }\n\n    return this.element.sendKeys(...keys);\n  }\n\n  /**\n   * Gets the text from the element.\n   * @param options Options that affect what text is included.\n   */\n  async text(options?: TextOptions): Promise<string> {\n    if (options?.exclude) {\n      return browser.executeScript(_getTextWithExcludedElements, this.element, options.exclude);\n    }\n    // We don't go through Protractor's `getText`, because it excludes text from hidden elements.\n    return browser.executeScript(`return (arguments[0].textContent || '').trim()`, this.element);\n  }\n\n  /**","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/cdk/testing/protractor/protractor-element.ts#L167-L203","documentation":"Thrown by ProtractorElement.sendKeys when called with an empty keys array. Dispatching keys with nothing to send would still trigger a focus event, which the library considers an unexpected side effect, so it throws getNoKeysSpecifiedError instead.","triggerScenarios":"Calling await element.sendKeys() with no arguments, with an array spread that is empty (sendKeys(...arr) where arr === []), or passing only falsy values filtered out upstream.","commonSituations":"Parameterized test helpers that accumulate keys and pass none (e.g. pressing only Ctrl via modifierKeys but no actual key), data-driven tests with an empty key list.","solutions":["Pass at least one key or character: sendKeys('Enter') not sendKeys().","Check that the array being spread is non-empty before calling.","If only modifier keys are needed, send a chord explicitly with a real key, e.g. sendKeys(`${control}a`)."],"exampleFix":"// before\nawait input.sendKeys(...keys); // keys may be []\n// after\nif (keys.length) await input.sendKeys(...keys);","handlingStrategy":"validation","validationCode":"if (!keys || keys.length === 0) return; // nothing to send\nawait element.sendKeys(...keys);","typeGuard":"const hasKeys = (k: string[] | undefined): k is [string, ...string[]] => Array.isArray(k) && k.length > 0;","tryCatchPattern":"try { await element.sendKeys(...keys); } catch (e) { if ((e as Error).message.includes('No keys have been specified')) return; throw e; }","preventionTips":["Guard spread calls sendKeys(...arr) for empty arrays","Ensure modifier-key tests also include a real key"],"tags":["angular-cdk","testing","test-element","protractor","keyboard-input"],"backgroundTag":"no-keys-specified","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}