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
7 changes: 4 additions & 3 deletions .github/workflows/pr-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ jobs:
--owner "${{ github.event.pull_request.head.repo.owner.login || github.repository_owner }}" \
--repo "${{ github.event.pull_request.head.repo.name || github.event.repository.name }}" \
--pr "${{ github.event.pull_request.number }}" \
--language ja \
--post-comment
env:
AISettings__Endpoint: ${{ vars.AI_ENDPOINT || 'https://api.openai.com/v1' }}
AISettings__ApiKey: ${{ secrets.AI_API_KEY }}
AISettings__ModelId: ${{ vars.AI_MODEL_ID || 'gpt-4o-mini' }}
AISettings__Endpoint: ${{ vars.AISETTINGS__ENDPOINT }}
AISettings__ApiKey: ${{ secrets.AISETTINGS__APIKEY }}
AISettings__ModelId: ${{ vars.AISETTINGS__MODELID || 'gpt-4o-mini' }}
PRSettings__GitHubToken: ${{ secrets.GITHUB_TOKEN }}
18 changes: 1 addition & 17 deletions .github/workflows/pragent-native.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,9 @@
# PRAgent - Native .NET CLI Version
# PR作成/更新時に自動実行、または他のリポジトリから参照して使用
# 他のリポジトリから参照して使用

name: PRAgent (Native)

on:
pull_request:
types: [opened, synchronize]
workflow_dispatch:
inputs:
pr_number:
description: 'PR number'
required: true
type: number
command:
description: 'Command (review/summary/approve)'
required: true
type: choice
options:
- review
- summary
- approve
workflow_call:
inputs:
pr_number:
Expand Down
320 changes: 320 additions & 0 deletions PRAgent.Tests/CommentCommandTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
using PRAgent.Models;
using Xunit;

namespace PRAgent.Tests;

public class CommentCommandTests
{
[Fact]
public void Parse_CommentCommandWithSingleComment_ReturnsCorrectOptions()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123", "@150", "Test comment" };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
Assert.Equal("testowner", options.Owner);
Assert.Equal("testrepo", options.Repo);
Assert.Equal(123, options.PrNumber);
Assert.Single(options.Comments);
Assert.Equal(150, options.Comments[0].LineNumber);
Assert.Equal("src/index.cs", options.Comments[0].FilePath);
Assert.Equal("Test comment", options.Comments[0].CommentText);
Assert.Null(options.Comments[0].SuggestionText);
}

[Fact]
public void Parse_CommentCommandWithMultipleComments_ReturnsCorrectOptions()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123", "@100", "Comment1", "@200", "Comment2" };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
Assert.Equal("testowner", options.Owner);
Assert.Equal("testrepo", options.Repo);
Assert.Equal(123, options.PrNumber);
Assert.Equal(2, options.Comments.Count);
Assert.Equal(100, options.Comments[0].LineNumber);
Assert.Equal("Comment1", options.Comments[0].CommentText);
Assert.Equal(200, options.Comments[1].LineNumber);
Assert.Equal("Comment2", options.Comments[1].CommentText);
}

[Fact]
public void Parse_CommentCommandWithSuggestion_ReturnsCorrectOptions()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123", "@200", "Test comment", "--suggestion", "Suggested code" };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
Assert.Equal("testowner", options.Owner);
Assert.Equal("testrepo", options.Repo);
Assert.Equal(123, options.PrNumber);
Assert.Single(options.Comments);
Assert.Equal(200, options.Comments[0].LineNumber);
Assert.Equal("src/index.cs", options.Comments[0].FilePath);
Assert.Equal("Test comment", options.Comments[0].CommentText);
Assert.Equal("Suggested code", options.Comments[0].SuggestionText);
}

[Fact]
public void Parse_CommentCommandWithShortOptions_ReturnsCorrectOptions()
{
// Arrange
string[] args = { "comment", "-o", "testowner", "-r", "testrepo", "-p", "123", "@150", "Test comment" };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
Assert.Equal("testowner", options.Owner);
Assert.Equal("testrepo", options.Repo);
Assert.Equal(123, options.PrNumber);
Assert.Single(options.Comments);
Assert.Equal(150, options.Comments[0].LineNumber);
Assert.Equal("Test comment", options.Comments[0].CommentText);
}

[Fact]
public void Parse_CommentCommandWithoutOwner_ReturnsError()
{
// Arrange
string[] args = { "comment", "--repo", "testrepo", "--pr", "123", "@150", "Test comment" };

// Act
var options = CommentCommandOptions.Parse(args);
var isValid = options.IsValid(out var errors);

// Assert
Assert.False(isValid);
Assert.Contains("--owner is required", errors);
}

[Fact]
public void Parse_CommentCommandWithoutRepo_ReturnsError()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--pr", "123", "@150", "Test comment" };

// Act
var options = CommentCommandOptions.Parse(args);
var isValid = options.IsValid(out var errors);

// Assert
Assert.False(isValid);
Assert.Contains("--repo is required", errors);
}

[Fact]
public void Parse_CommentCommandWithoutPrNumber_ReturnsError()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "@150", "Test comment" };

// Act
var options = CommentCommandOptions.Parse(args);
var isValid = options.IsValid(out var errors);

// Assert
Assert.False(isValid);
Assert.Contains("--pr is required and must be a positive number", errors);
}

[Fact]
public void Parse_CommentCommandWithoutComments_ReturnsError()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123" };

// Act
var options = CommentCommandOptions.Parse(args);
var isValid = options.IsValid(out var errors);

// Assert
Assert.False(isValid);
// コメントが指定されていない場合はエラー
Assert.Contains("No valid comments specified", errors);
}

[Fact]
public void Parse_CommentCommandWithInvalidLineNumber_IsIgnored()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123", "@-1", "Test comment" };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
// 無効な行番号のコメントはパース段階で除外される
Assert.Empty(options.Comments);
}

[Fact]
public void Parse_CommentCommandWithEmptyCommentText_IsIgnored()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123", "@150", "" };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
// 空のコメントはパース段階で除外される
Assert.Empty(options.Comments);
}

[Fact]
public void Parse_CommentCommandWithWhitespaceOnlyCommentText_IsIgnored()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123", "@150", " \t\n " };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
// 空白のみのコメントはパース段階で除外される
Assert.Empty(options.Comments);
}

[Fact]
public void Parse_CommentCommandWithEmptySuggestion_IgnoresSuggestion()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123", "@200", "Test comment", "--suggestion", "" };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
Assert.Single(options.Comments);
Assert.Equal(200, options.Comments[0].LineNumber);
Assert.Equal("Test comment", options.Comments[0].CommentText);
Assert.Null(options.Comments[0].SuggestionText);
}

[Fact]
public void Parse_CommentCommandWithWhitespaceOnlySuggestion_IgnoresSuggestion()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123", "@200", "Test comment", "--suggestion", " \t\n " };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
Assert.Single(options.Comments);
Assert.Equal(200, options.Comments[0].LineNumber);
Assert.Equal("Test comment", options.Comments[0].CommentText);
Assert.Null(options.Comments[0].SuggestionText);
}

[Fact]
public void Parse_CommentCommandWithFilePath_ReturnsCorrectOptions()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123", "src/file.cs@123", "Test comment" };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
Assert.Equal("testowner", options.Owner);
Assert.Equal("testrepo", options.Repo);
Assert.Equal(123, options.PrNumber);
Assert.Single(options.Comments);
Assert.Equal(123, options.Comments[0].LineNumber);
Assert.Equal("src/file.cs", options.Comments[0].FilePath);
Assert.Equal("Test comment", options.Comments[0].CommentText);
Assert.Null(options.Comments[0].SuggestionText);
}

[Fact]
public void Parse_CommentCommandWithApprove_ReturnsCorrectOptions()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123", "@150", "Test comment", "--approve" };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
Assert.Equal("testowner", options.Owner);
Assert.Equal("testrepo", options.Repo);
Assert.Equal(123, options.PrNumber);
Assert.Single(options.Comments);
Assert.Equal(150, options.Comments[0].LineNumber);
Assert.Equal("Test comment", options.Comments[0].CommentText);
Assert.True(options.Approve);
Assert.Null(options.Comments[0].SuggestionText);
}

[Fact]
public void Parse_CommentCommandWithApproveAndSuggestion_ReturnsCorrectOptions()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123", "@200", "Test comment", "--suggestion", "Fixed code", "--approve" };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
Assert.Equal("testowner", options.Owner);
Assert.Equal("testrepo", options.Repo);
Assert.Equal(123, options.PrNumber);
Assert.Single(options.Comments);
Assert.Equal(200, options.Comments[0].LineNumber);
Assert.Equal("Test comment", options.Comments[0].CommentText);
Assert.Equal("Fixed code", options.Comments[0].SuggestionText);
Assert.True(options.Approve);
}

[Fact]
public void Parse_CommentCommandWithMultipleCommentsAndApprove_ReturnsCorrectOptions()
{
// Arrange
string[] args = { "comment", "--owner", "testowner", "--repo", "testrepo", "--pr", "123", "@100", "Comment1", "@200", "Comment2", "--approve" };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
Assert.Equal("testowner", options.Owner);
Assert.Equal("testrepo", options.Repo);
Assert.Equal(123, options.PrNumber);
Assert.Equal(2, options.Comments.Count);
Assert.Equal(100, options.Comments[0].LineNumber);
Assert.Equal("Comment1", options.Comments[0].CommentText);
Assert.Equal(200, options.Comments[1].LineNumber);
Assert.Equal("Comment2", options.Comments[1].CommentText);
Assert.True(options.Approve);
}

[Fact]
public void Parse_CommentCommandWithShortApprove_ReturnsCorrectOptions()
{
// Arrange
string[] args = { "comment", "-o", "testowner", "-r", "testrepo", "-p", "123", "@150", "Test comment", "--approve" };

// Act
var options = CommentCommandOptions.Parse(args);

// Assert
Assert.Equal("testowner", options.Owner);
Assert.Equal("testrepo", options.Repo);
Assert.Equal(123, options.PrNumber);
Assert.Single(options.Comments);
Assert.Equal(150, options.Comments[0].LineNumber);
Assert.Equal("Test comment", options.Comments[0].CommentText);
Assert.True(options.Approve);
}
}
Loading
Loading