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
10 changes: 2 additions & 8 deletions lib/algora/integrations/github/command.ex
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,12 @@ defmodule Algora.Github.Command do

defparsec(:parse_raw, Helper.commands())

def parse(nil), do: {:ok, %{}}
def parse(nil), do: {:ok, []}

def parse(input) when is_binary(input) do
case parse_raw(input) do
{:ok, [], _, _, _, _} ->
{:ok, %{}}

{:ok, parsed, _, _, _, _} ->
{:ok,
parsed
|> Enum.reject(&is_nil/1)
|> Map.new()}
{:ok, Enum.reject(parsed, &is_nil/1)}

{:error, reason, _, _, _, _} ->
{:error, reason}
Expand Down
61 changes: 25 additions & 36 deletions test/algora/github/command_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,145 +7,134 @@ defmodule Algora.Github.CommandTest do

describe "parse/1 with bounty command" do
test "parses simple bounty amount" do
assert {:ok, %{bounty: [{:amount, ~M[1000]usd}]}} ==
assert {:ok, [bounty: [{:amount, ~M[1000]usd}]]} ==
Command.parse("/bounty 1000")
end

test "parses bounty with EN thousand separators and decimal points" do
assert {:ok, %{bounty: [{:amount, ~M[1000.5]usd}]}} ==
assert {:ok, [bounty: [{:amount, ~M[1000.5]usd}]]} ==
Command.parse("/bounty 1,000.5")
end

test "parses bounty with EN thousand separators" do
assert {:ok, %{bounty: [{:amount, ~M[1_000_000]usd}]}} ==
assert {:ok, [bounty: [{:amount, ~M[1_000_000]usd}]]} ==
Command.parse("/bounty 1,000,000")
end

test "parses bounty with EN decimal points" do
assert {:ok, %{bounty: [{:amount, ~M[1000.50]usd}]}} ==
assert {:ok, [bounty: [{:amount, ~M[1000.50]usd}]]} ==
Command.parse("/bounty 1000.50")
end

test "parses bounty with DE thousand separators and decimal points" do
assert {:ok, %{bounty: [{:amount, ~M[1000.5]usd}]}} ==
assert {:ok, [bounty: [{:amount, ~M[1000.5]usd}]]} ==
Command.parse("/bounty 1.000,5")
end

test "parses bounty with DE thousand separators" do
assert {:ok, %{bounty: [{:amount, ~M[1_000_000]usd}]}} ==
assert {:ok, [bounty: [{:amount, ~M[1_000_000]usd}]]} ==
Command.parse("/bounty 1.000.000")
end

test "parses bounty with DE decimal points" do
assert {:ok, %{bounty: [{:amount, ~M[1000.50]usd}]}} ==
assert {:ok, [bounty: [{:amount, ~M[1000.50]usd}]]} ==
Command.parse("/bounty 1000,50")
end

test "parses bounty with dollar sign" do
assert {:ok, %{bounty: [{:amount, ~M[50]usd}]}} ==
assert {:ok, [bounty: [{:amount, ~M[50]usd}]]} ==
Command.parse("/bounty $50")
end
end

describe "parse/1 with tip command" do
test "parses tip with amount first" do
assert {:ok, %{tip: [{:amount, ~M[100]usd}, {:recipient, "user"}]}} ==
assert {:ok, [tip: [{:amount, ~M[100]usd}, {:recipient, "user"}]]} ==
Command.parse("/tip 100 @user")
end

test "parses tip with recipient first" do
assert {:ok, %{tip: [{:recipient, "user"}, {:amount, ~M[100]usd}]}} ==
assert {:ok, [tip: [{:recipient, "user"}, {:amount, ~M[100]usd}]]} ==
Command.parse("/tip @user 100")
end

test "parses tip with only amount" do
assert {:ok, %{tip: [{:amount, ~M[100]usd}]}} ==
assert {:ok, [tip: [{:amount, ~M[100]usd}]]} ==
Command.parse("/tip 100")
end

test "parses tip with only recipient" do
assert {:ok, %{tip: [{:recipient, "user"}]}} ==
assert {:ok, [tip: [{:recipient, "user"}]]} ==
Command.parse("/tip @user")
end
end

describe "parse/1 with claim command" do
test "parses simple issue number" do
assert {:ok, %{claim: [{:ticket_ref, [number: 123]}]}} ==
assert {:ok, [claim: [{:ticket_ref, [number: 123]}]]} ==
Command.parse("/claim 123")
end

test "parses issue with hash" do
assert {:ok, %{claim: [{:ticket_ref, [number: 123]}]}} ==
assert {:ok, [claim: [{:ticket_ref, [number: 123]}]]} ==
Command.parse("/claim #123")
end

test "parses repo issue reference" do
assert {:ok, %{claim: [{:ticket_ref, [repo: "repo", number: 123]}]}} ==
assert {:ok, [claim: [{:ticket_ref, [repo: "repo", number: 123]}]]} ==
Command.parse("/claim repo#123")
end

test "parses full repo path" do
assert {:ok, %{claim: [{:ticket_ref, [owner: "owner", repo: "repo", number: 123]}]}} ==
assert {:ok, [claim: [{:ticket_ref, [owner: "owner", repo: "repo", number: 123]}]]} ==
Command.parse("/claim owner/repo#123")
end

test "parses full GitHub URL for issues" do
expected =
{:ok,
%{
claim: [{:ticket_ref, [owner: "owner", repo: "repo", type: "issues", number: 123]}]
}}
{:ok, [claim: [{:ticket_ref, [owner: "owner", repo: "repo", type: "issues", number: 123]}]]}

assert expected == Command.parse("/claim github.com/owner/repo/issues/123")
assert expected == Command.parse("/claim http://github.com/owner/repo/issues/123")
assert expected == Command.parse("/claim https://github.com/owner/repo/issues/123")
end

test "parses full GitHub URL for pull requests" do
assert {:ok,
%{
claim: [{:ticket_ref, [owner: "owner", repo: "repo", type: "pull", number: 123]}]
}} ==
assert {:ok, [claim: [{:ticket_ref, [owner: "owner", repo: "repo", type: "pull", number: 123]}]]} ==
Command.parse("/claim https://github.com/owner/repo/pull/123")
end

test "parses full GitHub URL for discussions" do
assert {:ok,
%{
claim: [
{:ticket_ref, [owner: "owner", repo: "repo", type: "discussions", number: 123]}
]
}} ==
assert {:ok, [claim: [{:ticket_ref, [owner: "owner", repo: "repo", type: "discussions", number: 123]}]]} ==
Command.parse("/claim https://github.com/owner/repo/discussions/123")
end
end

describe "parse/1 with multiple commands" do
test "parses multiple commands in sequence" do
assert {:ok,
%{
[
bounty: [{:amount, Money.new!(100, :USD)}],
tip: [{:amount, Money.new!(50, :USD)}, {:recipient, "user"}]
}} == Command.parse("/bounty 100 /tip 50 @user")
]} == Command.parse("/bounty 100 /tip 50 @user")
end

test "handles text between commands" do
assert {:ok,
%{
[
bounty: [{:amount, Money.new!(100, :USD)}],
tip: [{:recipient, "user"}, {:amount, Money.new!(50, :USD)}]
}} == Command.parse("Hello /bounty 100 world /tip @user 50")
]} == Command.parse("Hello /bounty 100 world /tip @user 50")
end
end

describe "parse/1 with invalid input" do
test "returns empty list for invalid commands" do
assert {:ok, %{}} == Command.parse("/invalid")
assert {:ok, []} == Command.parse("/invalid")
end

test "returns empty list for no commands" do
assert {:ok, %{}} == Command.parse("just some text")
assert {:ok, []} == Command.parse("just some text")
end

test "returns error for malformed amounts" do
Expand Down
Loading