Some checks failed
CI / test (push) Failing after 4s
Watches issue/PR comments and pushes for flagged phrases; warns commenters via reply and opens a redacted correction PR for flagged file content, never rewriting history or deleting content directly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
157 lines
5 KiB
Go
157 lines
5 KiB
Go
package bot
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.folja.dev/awayatan/yaju-is-always-watching-you/internal/detector"
|
|
"git.folja.dev/awayatan/yaju-is-always-watching-you/internal/forgejo"
|
|
)
|
|
|
|
type fakeClient struct {
|
|
comments []string
|
|
corrections []string
|
|
prs int
|
|
fileContent map[string]string
|
|
}
|
|
|
|
func (f *fakeClient) ReplyToIssue(owner, repo string, index int64, body string) error {
|
|
f.comments = append(f.comments, body)
|
|
return nil
|
|
}
|
|
|
|
func (f *fakeClient) FileContent(owner, repo, ref, path string) (string, string, error) {
|
|
return f.fileContent[path], "sha-" + path, nil
|
|
}
|
|
|
|
func (f *fakeClient) CommitCorrection(owner, repo, baseBranch, newBranch, path, sha, newContent, message string) error {
|
|
f.corrections = append(f.corrections, path)
|
|
return nil
|
|
}
|
|
|
|
func (f *fakeClient) OpenCorrectionPR(owner, repo, head, base, title, body string) error {
|
|
f.prs++
|
|
return nil
|
|
}
|
|
|
|
func newTestBot(fc *fakeClient) *Bot {
|
|
det := detector.New([]string{"しょうもな"})
|
|
return New(fc, det, "yaju-keisatsu-bot", "bot/goroku-fix/", nil)
|
|
}
|
|
|
|
func TestHandleIssueComment_Flagged(t *testing.T) {
|
|
fc := &fakeClient{}
|
|
b := newTestBot(fc)
|
|
|
|
err := b.HandleIssueComment(forgejo.IssueCommentPayload{
|
|
Action: "created",
|
|
Issue: forgejo.WebhookIssue{Number: 1},
|
|
Comment: forgejo.WebhookComment{Body: "それはしょうもな", User: forgejo.WebhookUser{Login: "alice"}},
|
|
Repository: forgejo.WebhookRepository{Name: "repo", Owner: forgejo.WebhookUser{Login: "owner"}},
|
|
Sender: forgejo.WebhookUser{Login: "alice"},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("HandleIssueComment() error = %v", err)
|
|
}
|
|
if len(fc.comments) != 1 {
|
|
t.Fatalf("expected 1 warning comment, got %d", len(fc.comments))
|
|
}
|
|
}
|
|
|
|
func TestHandleIssueComment_IgnoresSelf(t *testing.T) {
|
|
fc := &fakeClient{}
|
|
b := newTestBot(fc)
|
|
|
|
err := b.HandleIssueComment(forgejo.IssueCommentPayload{
|
|
Action: "created",
|
|
Comment: forgejo.WebhookComment{Body: "それはしょうもな", User: forgejo.WebhookUser{Login: "yaju-keisatsu-bot"}},
|
|
Repository: forgejo.WebhookRepository{Name: "repo", Owner: forgejo.WebhookUser{Login: "owner"}},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("HandleIssueComment() error = %v", err)
|
|
}
|
|
if len(fc.comments) != 0 {
|
|
t.Fatalf("bot must not reply to its own comments, got %d replies", len(fc.comments))
|
|
}
|
|
}
|
|
|
|
func TestHandleIssueComment_Clean(t *testing.T) {
|
|
fc := &fakeClient{}
|
|
b := newTestBot(fc)
|
|
|
|
err := b.HandleIssueComment(forgejo.IssueCommentPayload{
|
|
Action: "created",
|
|
Comment: forgejo.WebhookComment{Body: "普通のコメントです", User: forgejo.WebhookUser{Login: "alice"}},
|
|
Repository: forgejo.WebhookRepository{Name: "repo", Owner: forgejo.WebhookUser{Login: "owner"}},
|
|
Sender: forgejo.WebhookUser{Login: "alice"},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("HandleIssueComment() error = %v", err)
|
|
}
|
|
if len(fc.comments) != 0 {
|
|
t.Fatalf("expected no reply for clean comment, got %d", len(fc.comments))
|
|
}
|
|
}
|
|
|
|
func TestHandlePush_OpensCorrectionPR(t *testing.T) {
|
|
fc := &fakeClient{fileContent: map[string]string{
|
|
"README.md": "これはしょうもな話だ",
|
|
}}
|
|
b := newTestBot(fc)
|
|
|
|
err := b.HandlePush(forgejo.PushPayload{
|
|
Ref: "refs/heads/main",
|
|
After: "abcdef1234567890",
|
|
Commits: []forgejo.WebhookCommit{
|
|
{ID: "abcdef1234567890", Modified: []string{"README.md"}},
|
|
},
|
|
Repository: forgejo.WebhookRepository{Name: "repo", Owner: forgejo.WebhookUser{Login: "owner"}},
|
|
Pusher: forgejo.WebhookUser{Login: "alice"},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("HandlePush() error = %v", err)
|
|
}
|
|
if len(fc.corrections) != 1 || fc.corrections[0] != "README.md" {
|
|
t.Fatalf("expected a correction commit for README.md, got %v", fc.corrections)
|
|
}
|
|
if fc.prs != 1 {
|
|
t.Fatalf("expected 1 correction PR, got %d", fc.prs)
|
|
}
|
|
}
|
|
|
|
func TestHandlePush_IgnoresSelf(t *testing.T) {
|
|
fc := &fakeClient{fileContent: map[string]string{"README.md": "しょうもな"}}
|
|
b := newTestBot(fc)
|
|
|
|
err := b.HandlePush(forgejo.PushPayload{
|
|
Ref: "refs/heads/main",
|
|
After: "abc",
|
|
Commits: []forgejo.WebhookCommit{{ID: "abc", Modified: []string{"README.md"}}},
|
|
Repository: forgejo.WebhookRepository{Name: "repo", Owner: forgejo.WebhookUser{Login: "owner"}},
|
|
Pusher: forgejo.WebhookUser{Login: "yaju-keisatsu-bot"},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("HandlePush() error = %v", err)
|
|
}
|
|
if fc.prs != 0 {
|
|
t.Fatalf("bot must not react to its own pushes, got %d PRs", fc.prs)
|
|
}
|
|
}
|
|
|
|
func TestHandlePush_CleanFileNoOp(t *testing.T) {
|
|
fc := &fakeClient{fileContent: map[string]string{"README.md": "普通のREADMEです"}}
|
|
b := newTestBot(fc)
|
|
|
|
err := b.HandlePush(forgejo.PushPayload{
|
|
Ref: "refs/heads/main",
|
|
After: "abc",
|
|
Commits: []forgejo.WebhookCommit{{ID: "abc", Modified: []string{"README.md"}}},
|
|
Repository: forgejo.WebhookRepository{Name: "repo", Owner: forgejo.WebhookUser{Login: "owner"}},
|
|
Pusher: forgejo.WebhookUser{Login: "alice"},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("HandlePush() error = %v", err)
|
|
}
|
|
if fc.prs != 0 || len(fc.corrections) != 0 {
|
|
t.Fatalf("expected no correction for clean file, got prs=%d corrections=%v", fc.prs, fc.corrections)
|
|
}
|
|
}
|