Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions actions/setup/js/close_issue.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -51,39 +51,33 @@ const mockCore = { debug: vi.fn(), info: vi.fn(), warning: vi.fn(), error: vi.fn
}),
it("should close specific issue when target is *", async () => {
(setAgentOutput({ items: [{ type: "close_issue", issue_number: 100, body: "Closing this issue." }] }),
(process.env.GH_AW_CLOSE_ISSUE_TARGET = "*"),
mockGithub.rest.issues.get.mockResolvedValue({ data: { number: 100, title: "[refactor] Refactor Test", labels: [{ name: "refactoring" }], state: "open", html_url: "https://github.com/testowner/testrepo/issues/100" } }),
mockGithub.rest.issues.createComment.mockResolvedValue({ data: { id: 456, html_url: "https://github.com/testowner/testrepo/issues/100#issuecomment-456" } }),
mockGithub.rest.issues.update.mockResolvedValue({ data: { number: 100, html_url: "https://github.com/testowner/testrepo/issues/100", title: "[refactor] Refactor Test" } }),
await eval(`(async () => { ${closeIssueScript}; await main(); })()`),
await eval(`(async () => { ${closeIssueScript}; await main({ target: "*" }); })()`),
expect(mockGithub.rest.issues.get).toHaveBeenCalledWith({ owner: "testowner", repo: "testrepo", issue_number: 100 }),
expect(mockCore.setOutput).toHaveBeenCalledWith("issue_number", 100));
}),
it("should filter by required title prefix", async () => {
(setAgentOutput({ items: [{ type: "close_issue", issue_number: 50, body: "Closing this issue." }] }),
(process.env.GH_AW_CLOSE_ISSUE_TARGET = "*"),
(process.env.GH_AW_CLOSE_ISSUE_REQUIRED_TITLE_PREFIX = "[refactor] "),
mockGithub.rest.issues.get.mockResolvedValue({ data: { number: 50, title: "[bug] Bug Fix", labels: [], state: "open", html_url: "https://github.com/testowner/testrepo/issues/50" } }),
await eval(`(async () => { ${closeIssueScript}; await main(); })()`),
await eval(`(async () => { ${closeIssueScript}; await main({ target: "*", required_title_prefix: "[refactor] " }); })()`),
expect(mockGithub.rest.issues.get).toHaveBeenCalled(),
expect(mockGithub.rest.issues.update).not.toHaveBeenCalled(),
expect(mockCore.info).toHaveBeenCalledWith(expect.stringContaining("does not have required title prefix")));
}),
it("should filter by required labels", async () => {
(setAgentOutput({ items: [{ type: "close_issue", issue_number: 60, body: "Closing this issue." }] }),
(process.env.GH_AW_CLOSE_ISSUE_TARGET = "*"),
(process.env.GH_AW_CLOSE_ISSUE_REQUIRED_LABELS = "automated,stale"),
mockGithub.rest.issues.get.mockResolvedValue({ data: { number: 60, title: "Test Issue", labels: [{ name: "bug" }], state: "open", html_url: "https://github.com/testowner/testrepo/issues/60" } }),
await eval(`(async () => { ${closeIssueScript}; await main(); })()`),
await eval(`(async () => { ${closeIssueScript}; await main({ target: "*", required_labels: ["automated", "stale"] }); })()`),
expect(mockGithub.rest.issues.get).toHaveBeenCalled(),
expect(mockGithub.rest.issues.update).not.toHaveBeenCalled(),
expect(mockCore.info).toHaveBeenCalledWith(expect.stringContaining("does not have required labels")));
}),
it("should skip already closed issues", async () => {
(setAgentOutput({ items: [{ type: "close_issue", issue_number: 70, body: "Closing this issue." }] }),
(process.env.GH_AW_CLOSE_ISSUE_TARGET = "*"),
mockGithub.rest.issues.get.mockResolvedValue({ data: { number: 70, title: "Already Closed", labels: [], state: "closed", html_url: "https://github.com/testowner/testrepo/issues/70" } }),
await eval(`(async () => { ${closeIssueScript}; await main(); })()`),
await eval(`(async () => { ${closeIssueScript}; await main({ target: "*" }); })()`),
expect(mockGithub.rest.issues.get).toHaveBeenCalled(),
expect(mockGithub.rest.issues.update).not.toHaveBeenCalled(),
expect(mockCore.info).toHaveBeenCalledWith("Issue #70 is already closed, skipping"));
Expand Down
15 changes: 5 additions & 10 deletions actions/setup/js/create_discussion.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ const mockCore = {
mockGithub.graphql.mockResolvedValueOnce({ createDiscussion: { discussion: { id: "D_test789", number: 1, title: "[ai] Test Discussion", url: "https://github.com/testowner/testrepo/discussions/1" } } }));
const validOutput = { items: [{ type: "create_discussion", title: "Test Discussion", body: "Test discussion body" }] };
(setAgentOutput(validOutput),
(process.env.GH_AW_DISCUSSION_TITLE_PREFIX = "[ai] "),
await eval(`(async () => { ${createDiscussionScript}; await main(); })()`),
await eval(`(async () => { ${createDiscussionScript}; await main({ title_prefix: "[ai] " }); })()`),
expect(mockGithub.graphql).toHaveBeenCalledWith(expect.stringContaining("mutation($repositoryId: ID!, $categoryId: ID!, $title: String!, $body: String!)"), expect.objectContaining({ title: "[ai] Test Discussion" })));
}),
it("should use specified category ID when configured", async () => {
Expand All @@ -112,8 +111,7 @@ const mockCore = {
mockGithub.graphql.mockResolvedValueOnce({ createDiscussion: { discussion: { id: "D_test789", number: 1, title: "Test Discussion", url: "https://github.com/testowner/testrepo/discussions/1" } } }));
const validOutput = { items: [{ type: "create_discussion", title: "Test Discussion", body: "Test discussion body" }] };
(setAgentOutput(validOutput),
(process.env.GH_AW_DISCUSSION_CATEGORY = "DIC_custom789"),
await eval(`(async () => { ${createDiscussionScript}; await main(); })()`),
await eval(`(async () => { ${createDiscussionScript}; await main({ category: "DIC_custom789" }); })()`),
expect(mockGithub.graphql).toHaveBeenCalledWith(expect.stringContaining("mutation($repositoryId: ID!, $categoryId: ID!, $title: String!, $body: String!)"), expect.objectContaining({ categoryId: "DIC_custom789" })));
}),
it("should handle repositories without discussions enabled gracefully", async () => {
Expand All @@ -140,8 +138,7 @@ const mockCore = {
mockGithub.graphql.mockResolvedValueOnce({ createDiscussion: { discussion: { id: "D_test789", number: 1, title: "Test Discussion", url: "https://github.com/testowner/testrepo/discussions/1" } } }));
const validOutput = { items: [{ type: "create_discussion", title: "Test Discussion", body: "Test discussion body" }] };
(setAgentOutput(validOutput),
(process.env.GH_AW_DISCUSSION_CATEGORY = "Custom"),
await eval(`(async () => { ${createDiscussionScript}; await main(); })()`),
await eval(`(async () => { ${createDiscussionScript}; await main({ category: "Custom" }); })()`),
expect(mockCore.info).toHaveBeenCalledWith("Using category by name: Custom (DIC_custom789)"),
expect(mockGithub.graphql).toHaveBeenCalledWith(expect.stringContaining("mutation($repositoryId: ID!, $categoryId: ID!, $title: String!, $body: String!)"), expect.objectContaining({ categoryId: "DIC_custom789" })));
}),
Expand All @@ -160,8 +157,7 @@ const mockCore = {
mockGithub.graphql.mockResolvedValueOnce({ createDiscussion: { discussion: { id: "D_test789", number: 1, title: "Test Discussion", url: "https://github.com/testowner/testrepo/discussions/1" } } }));
const validOutput = { items: [{ type: "create_discussion", title: "Test Discussion", body: "Test discussion body" }] };
(setAgentOutput(validOutput),
(process.env.GH_AW_DISCUSSION_CATEGORY = "custom-category"),
await eval(`(async () => { ${createDiscussionScript}; await main(); })()`),
await eval(`(async () => { ${createDiscussionScript}; await main({ category: "custom-category" }); })()`),
expect(mockCore.info).toHaveBeenCalledWith("Using category by slug: Custom Category (DIC_custom789)"),
expect(mockGithub.graphql).toHaveBeenCalledWith(expect.stringContaining("mutation($repositoryId: ID!, $categoryId: ID!, $title: String!, $body: String!)"), expect.objectContaining({ categoryId: "DIC_custom789" })));
}),
Expand All @@ -170,8 +166,7 @@ const mockCore = {
mockGithub.graphql.mockResolvedValueOnce({ createDiscussion: { discussion: { id: "D_test789", number: 1, title: "Test Discussion", url: "https://github.com/testowner/testrepo/discussions/1" } } }));
const validOutput = { items: [{ type: "create_discussion", title: "Test Discussion", body: "Test discussion body" }] };
(setAgentOutput(validOutput),
(process.env.GH_AW_DISCUSSION_CATEGORY = "NonExistent"),
await eval(`(async () => { ${createDiscussionScript}; await main(); })()`),
await eval(`(async () => { ${createDiscussionScript}; await main({ category: "NonExistent" }); })()`),
expect(mockCore.warning).toHaveBeenCalledWith('Category "NonExistent" not found by ID, name, or slug. Available categories: General'),
expect(mockCore.info).toHaveBeenCalledWith("Falling back to default category: General (DIC_test456)"),
expect(mockGithub.graphql).toHaveBeenCalledWith(expect.stringContaining("mutation($repositoryId: ID!, $categoryId: ID!, $title: String!, $body: String!)"), expect.objectContaining({ categoryId: "DIC_test456" })));
Expand Down
20 changes: 8 additions & 12 deletions actions/setup/js/update_issue.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -71,39 +71,36 @@ const mockCore = {
expect(mockGithub.rest.issues.update).not.toHaveBeenCalled());
}),
it("should update issue title successfully", async () => {
(setAgentOutput({ items: [{ type: "update_issue", title: "Updated issue title" }] }), (process.env.GH_AW_UPDATE_TITLE = "true"), (global.context.eventName = "issues"));
(setAgentOutput({ items: [{ type: "update_issue", title: "Updated issue title" }] }), (global.context.eventName = "issues"));
const mockIssue = { number: 123, title: "Updated issue title", html_url: "https://github.com/testowner/testrepo/issues/123" };
(mockGithub.rest.issues.update.mockResolvedValue({ data: mockIssue }),
await eval(`(async () => { ${updateIssueScript}; await main(); })()`),
await eval(`(async () => { ${updateIssueScript}; await main({ allow_title: true }); })()`),
expect(mockGithub.rest.issues.update).toHaveBeenCalledWith({ owner: "testowner", repo: "testrepo", issue_number: 123, title: "Updated issue title" }),
expect(mockCore.setOutput).toHaveBeenCalledWith("issue_number", 123),
expect(mockCore.setOutput).toHaveBeenCalledWith("issue_url", mockIssue.html_url),
expect(mockCore.summary.addRaw).toHaveBeenCalled(),
expect(mockCore.summary.write).toHaveBeenCalled());
}),
it("should update issue status successfully", async () => {
(setAgentOutput({ items: [{ type: "update_issue", status: "closed" }] }), (process.env.GH_AW_UPDATE_STATUS = "true"), (global.context.eventName = "issues"));
(setAgentOutput({ items: [{ type: "update_issue", status: "closed" }] }), (global.context.eventName = "issues"));
const mockIssue = { number: 123, html_url: "https://github.com/testowner/testrepo/issues/123" };
(mockGithub.rest.issues.update.mockResolvedValue({ data: mockIssue }),
await eval(`(async () => { ${updateIssueScript}; await main(); })()`),
await eval(`(async () => { ${updateIssueScript}; await main({ allow_status: true }); })()`),
expect(mockGithub.rest.issues.update).toHaveBeenCalledWith({ owner: "testowner", repo: "testrepo", issue_number: 123, state: "closed" }));
}),
it("should update multiple fields successfully", async () => {
(setAgentOutput({ items: [{ type: "update_issue", title: "New title", body: "New body content", status: "open" }] }),
(process.env.GH_AW_UPDATE_TITLE = "true"),
(process.env.GH_AW_UPDATE_BODY = "true"),
(process.env.GH_AW_UPDATE_STATUS = "true"),
(global.context.eventName = "issues"));
const mockIssue = { number: 123, html_url: "https://github.com/testowner/testrepo/issues/123" };
(mockGithub.rest.issues.update.mockResolvedValue({ data: mockIssue }),
await eval(`(async () => { ${updateIssueScript}; await main(); })()`),
await eval(`(async () => { ${updateIssueScript}; await main({ allow_title: true, allow_body: true, allow_status: true }); })()`),
expect(mockGithub.rest.issues.update).toHaveBeenCalledWith({ owner: "testowner", repo: "testrepo", issue_number: 123, title: "New title", body: "New body content", state: "open" }));
}),
it('should handle explicit issue number with target "*"', async () => {
(setAgentOutput({ items: [{ type: "update_issue", issue_number: 456, title: "Updated title" }] }), (process.env.GH_AW_UPDATE_TITLE = "true"), (process.env.GH_AW_UPDATE_TARGET = "*"), (global.context.eventName = "push"));
(setAgentOutput({ items: [{ type: "update_issue", issue_number: 456, title: "Updated title" }] }), (global.context.eventName = "push"));
const mockIssue = { number: 456, html_url: "https://github.com/testowner/testrepo/issues/456" };
(mockGithub.rest.issues.update.mockResolvedValue({ data: mockIssue }),
await eval(`(async () => { ${updateIssueScript}; await main(); })()`),
await eval(`(async () => { ${updateIssueScript}; await main({ allow_title: true, target: "*" }); })()`),
expect(mockGithub.rest.issues.update).toHaveBeenCalledWith({ owner: "testowner", repo: "testrepo", issue_number: 456, title: "Updated title" }));
}),
it("should skip when no valid updates are provided", async () => {
Expand All @@ -118,9 +115,8 @@ const mockCore = {
}),
it("should validate status values", async () => {
(setAgentOutput({ items: [{ type: "update_issue", status: "invalid" }] }),
(process.env.GH_AW_UPDATE_STATUS = "true"),
(global.context.eventName = "issues"),
await eval(`(async () => { ${updateIssueScript}; await main(); })()`),
await eval(`(async () => { ${updateIssueScript}; await main({ allow_status: true }); })()`),
expect(mockCore.info).toHaveBeenCalledWith("Invalid status value: invalid. Must be 'open' or 'closed'"),
expect(mockGithub.rest.issues.update).not.toHaveBeenCalled());
}));
Expand Down