test(web): gitea issue creation — wire api coverage, module docs, section comment

The Gitea create-issue path (server route, client, wire api, facade, UI
button/dialog) landed with the forge user-lookup work; close the remaining
verification/documentation gaps:

- wire: gitea.test.ts covers issueCreate (POST /api/gitea/issues/create,
  full/optional body, error throw)
- docs: DOCUMENTATION.md lists createIssue client method and the
  POST /repos/{owner}/{repo}/issues endpoint (labels as names)
- ui: fix stale 'read-only by design' JSDoc in GiteaIssuesSection — creation
  is offered here and the detail view provides edit/close/reopen
This commit is contained in:
2026-08-16 16:29:25 +00:00
parent 3b3799f79e
commit 66adb65377
3 changed files with 83 additions and 3 deletions
+77
View File
@@ -260,6 +260,83 @@ describe('createWebGiteaAPI', () => {
await expect(api.prMerge({ directory: '/workspace', number: 12 })).rejects.toThrow('Bad Gateway');
});
it('posts to /api/gitea/issues/create with the input body and returns the created issue', async () => {
const created = {
connected: true,
repo: null,
issue: {
number: 42,
title: 'Broken build',
url: 'https://gitea.example/owner/repo/issues/42',
state: 'open',
author: { username: 'octocat', id: 1 },
labels: ['bug'],
},
};
runtimeFetchMock.mockResolvedValueOnce(Response.json(created));
const api = await createAPI();
await expect(api.issueCreate!({
directory: '/workspace',
title: 'Broken build',
body: 'The build is failing',
labels: ['bug'],
owner: 'group',
repo: 'repo',
})).resolves.toEqual(created);
expect(runtimeFetchMock).toHaveBeenCalledWith('/api/gitea/issues/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify({
directory: '/workspace',
title: 'Broken build',
body: 'The build is failing',
labels: ['bug'],
owner: 'group',
repo: 'repo',
}),
});
});
it('omits optional body/labels/owner/repo from the issueCreate body when absent', async () => {
const created = {
connected: true,
repo: null,
issue: {
number: 43,
title: 'Title only',
url: 'https://gitea.example/owner/repo/issues/43',
state: 'open',
author: { username: 'octocat', id: 1 },
labels: [],
},
};
runtimeFetchMock.mockResolvedValueOnce(Response.json(created));
const api = await createAPI();
await expect(api.issueCreate!({ directory: '/workspace', title: 'Title only' })).resolves.toEqual(created);
expect(runtimeFetchMock).toHaveBeenCalledWith('/api/gitea/issues/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify({ directory: '/workspace', title: 'Title only' }),
});
});
it('throws the server error when issueCreate fails', async () => {
runtimeFetchMock.mockResolvedValueOnce(Response.json(
{ error: 'Your Gitea token needs write:repository scope to create issues' },
{ status: 400 },
));
const api = await createAPI();
await expect(api.issueCreate!({
directory: '/workspace',
title: 'Broken build',
})).rejects.toThrow('Your Gitea token needs write:repository scope to create issues');
});
it('parses branches and the default branch from repoBranches', async () => {
runtimeFetchMock.mockResolvedValueOnce(Response.json({ branches: ['main', 'feat/api'], defaultBranch: 'main' }));