Files
deepseek-harness/packages/experimental/forge-github/tests/fixtures.ts
T
Yichen Jiang a71553a3fd feat(forge-github): sync viewed files and read and act on the pull request overview
Status reads add review requests, latest reviews, closing issue
references, and whether the viewer may update or rebase the head.
Viewed files are read through the files listing, bounded by the new
maxViewedFiles, and set with markFileAsViewed or unmarkFileAsViewed after
a head check. Failed GitHub Actions runs are rerun through the REST API,
reviews are requested with requestReviewsByLogin, and branches are
updated with expectedHeadOid. Every mutation goes through the sender
review writes use, now in mutation.ts.
2026-11-09 17:12:50 +08:00

97 lines
3.8 KiB
TypeScript

import type { ChangeRequestRef, ForgeRepository } from '@deepseek-ai/dsh-experimental-forge'
/** Repository on github.com used across the provider tests. */
export const demo: ForgeRepository = { forge: 'github', host: 'github.com', owner: 'octo', name: 'demo' }
/** Build a pull request reference in `demo` or another repository. */
export function pull(number: number, repository: ForgeRepository = demo): ChangeRequestRef {
return { repository, number }
}
/** One CheckRun context node as GitHub returns it. */
export function checkRun(name: string, status: string, conclusion: string | null, workflow: string | null = 'ci'): Record<string, unknown> {
return {
__typename: 'CheckRun', id: 'check-1', databaseId: 1,
name,
status,
conclusion,
detailsUrl: `https://github.com/octo/demo/actions/runs/1/job/${name}`,
startedAt: status === 'QUEUED' ? null : '2026-10-09T01:00:00Z',
completedAt: status === 'COMPLETED' ? '2026-10-09T01:02:07Z' : null,
checkSuite: {
app: { id: 'github-actions' },
workflowRun: workflow === null ? null : { databaseId: 7, event: 'pull_request', workflow: { id: workflow, name: workflow } },
},
}
}
/** One StatusContext node as GitHub returns it. */
export function statusContext(context: string, state: string): Record<string, unknown> {
return { __typename: 'StatusContext', context, state, targetUrl: null, createdAt: '2026-10-09T01:00:00Z' }
}
/** Merge settings of a repository that allows squash and merge commits and whose viewer may merge, usually with a merge commit. */
export function repositorySettings(overrides: Record<string, unknown> = {}): Record<string, unknown> {
return {
squashMergeAllowed: true,
mergeCommitAllowed: true,
rebaseMergeAllowed: false,
viewerPermission: 'WRITE',
viewerDefaultMergeMethod: 'MERGE',
...overrides,
}
}
/** A pull request node with the fields the snapshot query selects. */
export function pullRequestNode(number: number, overrides: Record<string, unknown> = {}, contexts: unknown[] = [], rollupState: string | null = 'SUCCESS'): Record<string, unknown> {
return {
id: `pull-${number}`,
number,
url: `https://github.com/octo/demo/pull/${number}`,
title: `Change ${number}`,
state: 'OPEN',
isDraft: false,
updatedAt: '2026-10-09T01:02:03Z',
closedAt: null,
author: { login: 'octo' },
headRefName: `topic-${number}`,
headRefOid: 'f'.repeat(40),
baseRefName: 'master',
baseRefOid: 'b'.repeat(40),
additions: 128,
deletions: 14,
mergeable: 'MERGEABLE',
mergeStateStatus: 'CLEAN',
reviewDecision: null,
viewerCanUpdateBranch: false,
canBeRebased: false,
reviewThreads: threadPage([true, false, false]),
reviewRequests: { totalCount: 0, nodes: [] },
latestReviews: { totalCount: 0, nodes: [] },
latestOpinionatedReviews: { totalCount: 0, nodes: [] },
closingIssuesReferences: { totalCount: 0, nodes: [] },
commits: {
nodes: [{
commit: {
statusCheckRollup: rollupState === null ? null : {
id: `rollup-${number}`, state: rollupState,
contexts: { pageInfo: { hasNextPage: false, endCursor: null }, nodes: contexts },
},
},
}],
},
...overrides,
}
}
/** A review thread connection page as GitHub returns it. */
export interface ThreadPage {
readonly pageInfo: { readonly hasNextPage: boolean; readonly endCursor: string | null }
readonly nodes: { readonly isResolved: boolean }[]
}
/** One review thread connection page with the threads' resolution, followed by the page after `next` when it is a cursor. */
export function threadPage(resolved: readonly boolean[], next: string | null = null): ThreadPage {
return { pageInfo: { hasNextPage: next !== null, endCursor: next }, nodes: resolved.map(isResolved => ({ isResolved })) }
}