{"version":3,"file":"pure.cjs","sources":["../../src/pure.ts"],"sourcesContent":["import childProcess from \"node:child_process\";\nimport { performance } from \"node:perf_hooks\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport stripFinalNewline from \"strip-final-newline\";\nimport { _runObservers } from \"./mutation-observer\";\nimport { getQueriesForElement } from \"./get-queries-for-instance\";\nimport userEvent from \"./user-event/index\";\nimport { bindObjectFnsToInstance, setCurrentInstance } from \"./helpers\";\nimport { fireEvent } from \"./events\";\nimport { getConfig } from \"./config\";\nimport { logCLI } from \"./pretty-cli\";\nimport type { TestInstance } from \"./types\";\nimport type * as queries from \"./queries/index\";\nimport type { SpawnOptionsWithoutStdio } from \"node:child_process\";\nimport type { BoundFunction } from \"./get-queries-for-instance\";\n\nconst __curDir =\n  typeof __dirname === \"undefined\"\n    ? // @ts-ignore ESM requires this, but it doesn't work in Node18\n      path.dirname(fileURLToPath(import.meta.url))\n    : __dirname;\n\nexport interface RenderOptions {\n  cwd: string;\n  debug: boolean;\n  spawnOpts: Omit<SpawnOptionsWithoutStdio, \"cwd\">;\n}\n\ntype UserEvent = typeof userEvent;\n\nexport type RenderResult = TestInstance & {\n  userEvent: {\n    [P in keyof UserEvent]: BoundFunction<UserEvent[P]>;\n  };\n} & { [P in keyof typeof queries]: BoundFunction<(typeof queries)[P]> };\n\nconst mountedInstances = new Set<TestInstance>();\n\nasync function render(\n  command: string,\n  args: Array<string> = [],\n  opts: Partial<RenderOptions> = {},\n): Promise<RenderResult> {\n  const { cwd = __curDir, spawnOpts = {} } = opts;\n\n  const exec = childProcess.spawn(command, args, {\n    ...spawnOpts,\n    cwd,\n    shell: true,\n  });\n\n  // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n  let _readyPromiseInternals: null | { resolve: Function; reject: Function } =\n    null;\n\n  let _resolved = false;\n\n  const execOutputAPI = {\n    __exitCode: null as null | number,\n    _isOutputAPI: true,\n    _isReady: new Promise(\n      (resolve, reject) => (_readyPromiseInternals = { resolve, reject }),\n    ),\n    process: exec,\n    // Clear buffer of stdout to do more accurate `t.regex` checks\n    clear() {\n      execOutputAPI.stdoutArr = [];\n      execOutputAPI.stderrArr = [];\n    },\n    debug(maxLength?: number) {\n      logCLI(execOutputAPI, maxLength);\n    },\n    // An array of strings gathered from stdout when unable to do\n    // `await stdout` because of inquirer interactive prompts\n    stdoutArr: [] as Array<{ contents: Buffer | string; timestamp: number }>,\n    stderrArr: [] as Array<{ contents: Buffer | string; timestamp: number }>,\n    hasExit() {\n      return this.__exitCode === null ? null : { exitCode: this.__exitCode };\n    },\n    getStdallStr(): string {\n      return this.stderrArr\n        .concat(this.stdoutArr)\n        .sort((a, b) => (a.timestamp < b.timestamp ? -1 : 1))\n        .map((obj) => obj.contents)\n        .join(\"\\n\");\n    },\n  } as TestInstance & {\n    __exitCode: null | number;\n    _isOutputAPI: true;\n    _isReady: Promise<void>;\n  };\n\n  mountedInstances.add(execOutputAPI as unknown as TestInstance);\n\n  exec.stdout.on(\"data\", (result: string | Buffer) => {\n    // `on('spawn') doesn't work the same way in Node12.\n    // Instead, we have to rely on this working as-expected.\n    if (_readyPromiseInternals && !_resolved) {\n      _readyPromiseInternals.resolve();\n      _resolved = true;\n    }\n\n    const resStr = stripFinalNewline(result as string);\n    execOutputAPI.stdoutArr.push({\n      contents: resStr,\n      timestamp: performance.now(),\n    });\n    _runObservers();\n  });\n\n  exec.stderr.on(\"data\", (result: string | Buffer) => {\n    if (_readyPromiseInternals && !_resolved) {\n      _readyPromiseInternals.resolve();\n      _resolved = true;\n    }\n\n    const resStr = stripFinalNewline(result as string);\n    execOutputAPI.stderrArr.push({\n      contents: resStr,\n      timestamp: performance.now(),\n    });\n    _runObservers();\n  });\n\n  exec.on(\"error\", (result) => {\n    if (_readyPromiseInternals) {\n      _readyPromiseInternals.reject(result);\n    }\n  });\n\n  exec.on(\"spawn\", () => {\n    setTimeout(() => {\n      if (_readyPromiseInternals && !_resolved) {\n        _readyPromiseInternals.resolve();\n        _resolved = true;\n      }\n    }, getConfig().renderAwaitTime);\n  });\n\n  exec.on(\"exit\", (code) => {\n    execOutputAPI.__exitCode = code ?? 0;\n  });\n\n  setCurrentInstance(execOutputAPI);\n\n  await execOutputAPI._isReady;\n\n  function getStdallStr(this: Omit<TestInstance, \"getStdallStr\">) {\n    return this.stderrArr\n      .concat(this.stdoutArr)\n      .sort((a, b) => (a.timestamp < b.timestamp ? -1 : 1))\n      .map((obj) => obj.contents)\n      .join(\"\\n\");\n  }\n\n  return Object.assign(\n    execOutputAPI,\n    {\n      userEvent: bindObjectFnsToInstance(execOutputAPI, userEvent as never),\n      getStdallStr: getStdallStr.bind(execOutputAPI),\n    },\n    getQueriesForElement(execOutputAPI),\n  ) as TestInstance as RenderResult;\n}\n\nfunction cleanup() {\n  return Promise.all(Array.from(mountedInstances).map(cleanupAtInstance));\n}\n\n// maybe one day we'll expose this (perhaps even as a utility returned by render).\n// but let's wait until someone asks for it.\nasync function cleanupAtInstance(instance: TestInstance) {\n  await fireEvent.sigkill(instance);\n\n  mountedInstances.delete(instance);\n}\n\nexport { render, cleanup };\n"],"names":["fileURLToPath","logCLI","performance","_runObservers","getConfig","setCurrentInstance","bindObjectFnsToInstance","userEvent","getQueriesForElement","fireEvent"],"mappings":"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"}