(opts = {})
| 96 | } |
| 97 | |
| 98 | function makeGithub(opts = {}) { |
| 99 | const createReviewCalls = []; |
| 100 | const issueComments = []; |
| 101 | const updatedComments = []; |
| 102 | const listCommentsCalls = []; |
| 103 | const listReviewCommentsCalls = []; |
| 104 | const listReviewsCalls = []; |
| 105 | const listFilesCalls = []; |
| 106 | const getPullCalls = []; |
| 107 | // Interleaved log of write operations (createReview / createComment / |
| 108 | // updateComment) in call order, so tests can assert positioning invariants |
| 109 | // such as "summary created before review" without timing the calls. |
| 110 | const ops = []; |
| 111 | // Per-comment attempt counter, keyed by commentKey, so perCommentError can be |
| 112 | // attempt-aware (e.g. "429 on attempt 0, succeed on attempt 1"). |
| 113 | const perCommentAttempts = new Map(); |
| 114 | |
| 115 | function successRemaining() { |
| 116 | return opts.successRemaining != null ? String(opts.successRemaining) : "5000"; |
| 117 | } |
| 118 | |
| 119 | // Inline comment objects recorded in BATCH createReview calls only, so tests |
| 120 | // can simulate "this comment already landed on the server" without predicting |
| 121 | // the random IDs from newCommentId(). Under multi-batch (N < toSend.length) |
| 122 | // there are several batch calls (body === REVIEW_TAG), so this scans ALL batch |
| 123 | // calls — not just createReviewCalls[0]. Scoped to batch calls so batch-level |
| 124 | // landing (echoPosted) stays disjoint from per-comment landing (landedKeys, |
| 125 | // which reads per-comment calls with body === ""). |
| 126 | function batchPostedComments() { |
| 127 | const out = []; |
| 128 | for (const call of createReviewCalls) { |
| 129 | if ((call.body || "") !== REVIEW_TAG) continue; |
| 130 | for (const c of call.comments || []) { |
| 131 | const m = /<!--\s*(ocr-\d+-\d+-[a-f0-9]+)\s*-->/.exec(c.body || ""); |
| 132 | if (m) { |
| 133 | out.push({ |
| 134 | path: c.path, |
| 135 | body: c.body, |
| 136 | side: c.side || "RIGHT", |
| 137 | start_line: c.start_line, |
| 138 | line: c.line, |
| 139 | }); |
| 140 | } |
| 141 | } |
| 142 | } |
| 143 | return out; |
| 144 | } |
| 145 | |
| 146 | // Count of batch createReview calls issued so far (body === REVIEW_TAG), so a |
| 147 | // per-batch-index error spec can target e.g. "fail batch #2 but not #1". |
| 148 | function batchCallCount() { |
| 149 | let n = 0; |
| 150 | for (const call of createReviewCalls) { |
| 151 | if ((call.body || "") === REVIEW_TAG) n++; |
| 152 | } |
| 153 | return n; |
| 154 | } |
| 155 |
no test coverage detected