function createMockSendCommandFn() {
  /**
   * Typescript fails to equate template type `C` here with `C` when pushing to this array.
   * Instead of sprinkling a couple ts-ignores, make `command` be any, but leave `C` for just
   * documentation purposes. This is an internal type, so it doesn't matter much.
   * @template {keyof LH.CrdpCommands} C
   * @type {Array<{command: C|any, sessionId?: string, response?: MockResponse<C>, delay?: number}>}
   */
  const mockResponses = [];
  const mockFnImpl = fnAny().mockImplementation(
    /**
     * @template {keyof LH.CrdpCommands} C
     * @param {C} command
     * @param {LH.CrdpCommands[C]['paramsType']} args
     */
    async (command, ...args) => {
      const indexOfResponse = mockResponses
        .findIndex(entry => entry.command === command && entry.sessionId === undefined);
      if (indexOfResponse === -1) throw new Error(`${command} unimplemented`);
      const {response, delay} = mockResponses[indexOfResponse];
      mockResponses.splice(indexOfResponse, 1);
      const returnValue = typeof response === 'function' ? response(...args) : response;
      if (delay) return new Promise(resolve => setTimeout(() => resolve(returnValue), delay));
      return returnValue;
    });

  const mockFn = Object.assign(mockFnImpl, {
    /**
     * @template {keyof LH.CrdpCommands} C
     * @param {C} command
     * @param {MockResponse<C>=} response
     * @param {number=} delay
     */
    mockResponse(command, response, delay) {
      mockResponses.push({command, response, delay});
      return mockFn;
    },
    /**
     * @template {keyof LH.CrdpCommands} C
     * @param {C} command
     * @param {string} sessionId
     * @param {MockResponse<C>=} response
     * @param {number=} delay
     */
    mockResponseToSession(command, sessionId, response, delay) {
      mockResponses.push({command, sessionId, response, delay});
      return mockFn;
    },
    /**
     * @param {keyof LH.CrdpCommands} command
     */
    findInvocation(command) {
      expect(mockFn).toHaveBeenCalledWith(command, expect.anything());
      const call = mockFn.mock.calls.find(call => call[0] === command);
      if (!call) throw new Error(`missing invocation for command: ${command}`);
      return call[1];
    },
    /**
     * @param {keyof LH.CrdpCommands} command
     */
    findAllInvocations(command) {
      return mockFn.mock.calls.filter(
        call => call[0] === command
      ).map(invocation => invocation[1]);
    },
  });

  return mockFn;
}
Creates a jest mock function whose implementation consumes mocked protocol responses matching the
requested command in the order they were mocked.

It is decorated with two methods:
   - `mockResponse` which pushes protocol message responses for consumption
   - `findInvocation` which asserts that `sendCommand` was invoked with the given command and
     returns the protocol message argument.

To mock an error response, use `send.mockResponse('Command', () => Promise.reject(error))`.