Skip to content

Commit 1ab272c

Browse files
committed
fix: parse commands into keyword list to allow multiple commands with same name (#33)
1 parent e4efd81 commit 1ab272c

File tree

2 files changed

+27
-44
lines changed

2 files changed

+27
-44
lines changed

lib/algora/integrations/github/command.ex

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,12 @@ defmodule Algora.Github.Command do
7171

7272
defparsec(:parse_raw, Helper.commands())
7373

74-
def parse(nil), do: {:ok, %{}}
74+
def parse(nil), do: {:ok, []}
7575

7676
def parse(input) when is_binary(input) do
7777
case parse_raw(input) do
78-
{:ok, [], _, _, _, _} ->
79-
{:ok, %{}}
80-
8178
{:ok, parsed, _, _, _, _} ->
82-
{:ok,
83-
parsed
84-
|> Enum.reject(&is_nil/1)
85-
|> Map.new()}
79+
{:ok, Enum.reject(parsed, &is_nil/1)}
8680

8781
{:error, reason, _, _, _, _} ->
8882
{:error, reason}

test/algora/github/command_test.exs

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,145 +7,134 @@ defmodule Algora.Github.CommandTest do
77

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

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

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

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

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

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

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

4444
test "parses bounty with dollar sign" do
45-
assert {:ok, %{bounty: [{:amount, ~M[50]usd}]}} ==
45+
assert {:ok, [bounty: [{:amount, ~M[50]usd}]]} ==
4646
Command.parse("/bounty $50")
4747
end
4848
end
4949

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

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

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

6666
test "parses tip with only recipient" do
67-
assert {:ok, %{tip: [{:recipient, "user"}]}} ==
67+
assert {:ok, [tip: [{:recipient, "user"}]]} ==
6868
Command.parse("/tip @user")
6969
end
7070
end
7171

7272
describe "parse/1 with claim command" do
7373
test "parses simple issue number" do
74-
assert {:ok, %{claim: [{:ticket_ref, [number: 123]}]}} ==
74+
assert {:ok, [claim: [{:ticket_ref, [number: 123]}]]} ==
7575
Command.parse("/claim 123")
7676
end
7777

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

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

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

9393
test "parses full GitHub URL for issues" do
9494
expected =
95-
{:ok,
96-
%{
97-
claim: [{:ticket_ref, [owner: "owner", repo: "repo", type: "issues", number: 123]}]
98-
}}
95+
{:ok, [claim: [{:ticket_ref, [owner: "owner", repo: "repo", type: "issues", number: 123]}]]}
9996

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

105102
test "parses full GitHub URL for pull requests" do
106-
assert {:ok,
107-
%{
108-
claim: [{:ticket_ref, [owner: "owner", repo: "repo", type: "pull", number: 123]}]
109-
}} ==
103+
assert {:ok, [claim: [{:ticket_ref, [owner: "owner", repo: "repo", type: "pull", number: 123]}]]} ==
110104
Command.parse("/claim https://github.com/owner/repo/pull/123")
111105
end
112106

113107
test "parses full GitHub URL for discussions" do
114-
assert {:ok,
115-
%{
116-
claim: [
117-
{:ticket_ref, [owner: "owner", repo: "repo", type: "discussions", number: 123]}
118-
]
119-
}} ==
108+
assert {:ok, [claim: [{:ticket_ref, [owner: "owner", repo: "repo", type: "discussions", number: 123]}]]} ==
120109
Command.parse("/claim https://github.com/owner/repo/discussions/123")
121110
end
122111
end
123112

124113
describe "parse/1 with multiple commands" do
125114
test "parses multiple commands in sequence" do
126115
assert {:ok,
127-
%{
116+
[
128117
bounty: [{:amount, Money.new!(100, :USD)}],
129118
tip: [{:amount, Money.new!(50, :USD)}, {:recipient, "user"}]
130-
}} == Command.parse("/bounty 100 /tip 50 @user")
119+
]} == Command.parse("/bounty 100 /tip 50 @user")
131120
end
132121

133122
test "handles text between commands" do
134123
assert {:ok,
135-
%{
124+
[
136125
bounty: [{:amount, Money.new!(100, :USD)}],
137126
tip: [{:recipient, "user"}, {:amount, Money.new!(50, :USD)}]
138-
}} == Command.parse("Hello /bounty 100 world /tip @user 50")
127+
]} == Command.parse("Hello /bounty 100 world /tip @user 50")
139128
end
140129
end
141130

142131
describe "parse/1 with invalid input" do
143132
test "returns empty list for invalid commands" do
144-
assert {:ok, %{}} == Command.parse("/invalid")
133+
assert {:ok, []} == Command.parse("/invalid")
145134
end
146135

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

151140
test "returns error for malformed amounts" do

0 commit comments

Comments
 (0)