function runCli(dir, args = [], options = {}) {
  const promise = runPrettierCli(dir, args, options);
  const getters = {
    get status() {
      return promise.then(({ status }) => status);
    },
    get stdout() {
      return promise.then(({ stdout }) => stdout);
    },
    get stderr() {
      return promise.then(({ stderr }) => stderr);
    },
    get write() {
      return promise.then(({ write }) => write);
    },
    test: testResult,
    then(onFulfilled, onRejected) {
      return promise.then(onFulfilled, onRejected);
    },
  };

  return getters;

  function testResult(testOptions) {
    test(options.title || "", async () => {
      const result = await promise;

      let snapshot;
      for (const name of ["status", "stdout", "stderr", "write"]) {
        let value = result[name];
        // \r is trimmed from jest snapshots by default;
        // manually replacing this character with /*CR*/ to test its true presence
        // If ignoreLineEndings is specified, \r is simply deleted instead
        if (name === "stdout" || name === "stderr") {
          value = result[name].replace(
            /\r/gu,
            options.ignoreLineEndings ? "" : "/*CR*/",
          );
        }

        if (name in testOptions) {
          if (name === "status" && testOptions[name] === "non-zero") {
            expect(value).not.toBe(0);
          } else if (typeof testOptions[name] === "function") {
            testOptions[name](value);
          } else {
            expect(value).toEqual(testOptions[name]);
          }
        } else {
          snapshot = snapshot ?? {};
          snapshot[name] = value;
        }
      }

      if (snapshot) {
        expect(snapshot).toMatchSnapshot();
      }
    });

    return getters;
  }
}
@param {string} dir
@param {string[]} [args]
@param {CliTestOptions} [options]