Skip to content

Commit f232b8c

Browse files
committed
Add tests for command interpreter
Update go.mod and go.sum to add goconvey
1 parent 57196b3 commit f232b8c

3 files changed

Lines changed: 180 additions & 4 deletions

File tree

go.mod

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/google/go-github/v45 v45.1.0
1010
github.com/gorilla/mux v1.8.0
1111
github.com/slack-go/slack v0.11.0
12+
github.com/smartystreets/goconvey v1.8.1
1213
go.uber.org/zap v1.21.0
1314
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2
1415
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
@@ -22,7 +23,9 @@ require (
2223
github.com/beorn7/perks v1.0.1 // indirect
2324
github.com/cespare/xxhash/v2 v2.1.2 // indirect
2425
github.com/fsnotify/fsnotify v1.5.4 // indirect
26+
github.com/gopherjs/gopherjs v1.17.2 // indirect
2527
github.com/hashicorp/hcl v1.0.0 // indirect
28+
github.com/jtolds/gls v4.20.0+incompatible // indirect
2629
github.com/magiconair/properties v1.8.6 // indirect
2730
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
2831
github.com/mitchellh/mapstructure v1.5.0 // indirect
@@ -31,6 +34,7 @@ require (
3134
github.com/prometheus/client_model v0.2.0 // indirect
3235
github.com/prometheus/common v0.32.1 // indirect
3336
github.com/prometheus/procfs v0.7.3 // indirect
37+
github.com/smarty/assertions v1.15.0 // indirect
3438
github.com/spf13/afero v1.8.2 // indirect
3539
github.com/spf13/jwalterweatherman v1.1.0 // indirect
3640
github.com/subosito/gotenv v1.3.0 // indirect
@@ -81,7 +85,7 @@ require (
8185
go.uber.org/multierr v1.6.0 // indirect
8286
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
8387
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect
84-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
88+
golang.org/x/sys v0.6.0 // indirect
8589
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
8690
golang.org/x/text v0.3.7 // indirect
8791
google.golang.org/appengine v1.6.7 // indirect
@@ -91,7 +95,7 @@ require (
9195
gopkg.in/yaml.v3 v3.0.0 // indirect
9296
k8s.io/klog/v2 v2.60.1 // indirect
9397
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect
94-
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
98+
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
9599
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
96100
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
97101
sigs.k8s.io/yaml v1.2.0 // indirect

go.sum

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
230230
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
231231
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
232232
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
233+
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
234+
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
233235
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
234236
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
235237
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
@@ -259,6 +261,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
259261
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
260262
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
261263
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
264+
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
265+
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
262266
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
263267
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
264268
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@@ -365,6 +369,10 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
365369
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
366370
github.com/slack-go/slack v0.11.0 h1:sBBjQz8LY++6eeWhGJNZpRm5jvLRNnWBFZ/cAq58a6k=
367371
github.com/slack-go/slack v0.11.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
372+
github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
373+
github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
374+
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
375+
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
368376
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
369377
github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
370378
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
@@ -590,8 +598,8 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
590598
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
591599
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
592600
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
593-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
594-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
601+
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
602+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
595603
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
596604
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
597605
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

pkg/slack/command_test.go

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package slack
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/oursky/github-actions-manager/pkg/kv"
8+
"github.com/slack-go/slack"
9+
. "github.com/smartystreets/goconvey/convey"
10+
11+
"go.uber.org/zap"
12+
)
13+
14+
func commandChan1(command string) slack.SlashCommand {
15+
return slack.SlashCommand{
16+
ChannelID: "TestChannelID1",
17+
Command: "/test-gha",
18+
Text: command,
19+
}
20+
}
21+
func commandChan2(command string) slack.SlashCommand {
22+
return slack.SlashCommand{
23+
ChannelID: "TestChannelID2",
24+
Command: "/test-gha",
25+
Text: command,
26+
}
27+
}
28+
29+
func TestSpec(t *testing.T) {
30+
31+
Convey("When receiving commands, the bot", t, func() {
32+
ctx, cancel := context.WithCancel(context.Background())
33+
defer cancel()
34+
35+
testApp := &App{
36+
logger: zap.NewNop(),
37+
store: kv.NewInMemoryStore(),
38+
commandName: "test-gha",
39+
}
40+
41+
cli := NewCLI(testApp.logger)
42+
cli.SetContext(ctx, testApp)
43+
44+
Convey("responds", func() {
45+
response := cli.Parse(commandChan1("meow"))
46+
So(response["text"], ShouldEqual, "meow")
47+
})
48+
Convey("rejects unrecognised commmands", func() {
49+
response := cli.Parse(commandChan1("fhqwhgads"))
50+
So(response["response_type"], ShouldBeNil)
51+
So(response["text"], ShouldContainSubstring, "fhqwhgads")
52+
})
53+
Convey("When asked to subscribe", func() {
54+
Convey("rejects an insufficient number of arguments", func() {
55+
response := cli.Parse(commandChan1("subscribe"))
56+
So(response["printToChannel"], ShouldBeNil)
57+
So(response["text"], ShouldContainSubstring, "repo")
58+
})
59+
Convey("rejects an unrecognised conclusion", func() {
60+
response := cli.Parse(commandChan1("subscribe owner/repo foo"))
61+
So(response["printToChannel"], ShouldBeNil)
62+
So(response["text"], ShouldContainSubstring, "conclusion")
63+
})
64+
Convey("rejects a malformed filter", func() {
65+
response := cli.Parse(commandChan1("subscribe owner/repo foo:bar"))
66+
So(response["printToChannel"], ShouldBeNil)
67+
So(response["text"], ShouldContainSubstring, "filter")
68+
69+
response = cli.Parse(commandChan1("subscribe owner/repo foo:bar:success"))
70+
So(response["printToChannel"], ShouldBeNil)
71+
So(response["text"], ShouldContainSubstring, "filter")
72+
})
73+
Convey("rejects a duplicated filter", func() {
74+
response := cli.Parse(commandChan1("subscribe owner/repo success failure"))
75+
So(response["printToChannel"], ShouldBeNil)
76+
So(response["text"], ShouldContainSubstring, "duplicated")
77+
78+
response = cli.Parse(commandChan1("subscribe owner/repo workflows:bar:success workflows:bar:failure"))
79+
So(response["printToChannel"], ShouldBeNil)
80+
So(response["text"], ShouldContainSubstring, "duplicated")
81+
})
82+
Convey("accepts a well-formed filter", func() {
83+
response := cli.Parse(commandChan1("subscribe owner/repo workflows:workflow1:success failure"))
84+
So(response["response_type"], ShouldEqual, "in_channel")
85+
So(response["text"], ShouldContainSubstring, "Subscribed")
86+
So(response["text"], ShouldContainSubstring, "workflow1")
87+
})
88+
Convey("overrides an existing subscription", func() {
89+
response := cli.Parse(commandChan1("subscribe owner/repo workflows:workflow2:success failure"))
90+
So(response["response_type"], ShouldEqual, "in_channel")
91+
So(response["text"], ShouldContainSubstring, "Subscribed")
92+
So(response["text"], ShouldContainSubstring, "workflow2")
93+
94+
// Anachronistic usage of list command, this needs to be fixed
95+
response = cli.Parse(commandChan1("list owner/repo"))
96+
So(response["response_type"], ShouldEqual, "in_channel")
97+
So(response["text"], ShouldNotContainSubstring, "workflow1")
98+
})
99+
})
100+
Convey("When asked to list", func() {
101+
Convey("rejects an insufficient number of arguments", func() {
102+
response := cli.Parse(commandChan1("list"))
103+
So(response["response_type"], ShouldBeNil)
104+
So(response["text"], ShouldContainSubstring, "repo")
105+
})
106+
Convey("correct lists subscribed channels", func() {
107+
cli.Parse(commandChan1("subscribe owner/repo"))
108+
cli.Parse(commandChan2("subscribe owner/repo workflows:workflow1 failure"))
109+
response := cli.Parse(commandChan1("list owner/repo"))
110+
So(response["response_type"], ShouldEqual, "in_channel")
111+
So(response["text"], ShouldContainSubstring, "TestChannelID1")
112+
So(response["text"], ShouldContainSubstring, "TestChannelID2")
113+
So(response["text"], ShouldContainSubstring, "workflow1")
114+
So(response["text"], ShouldContainSubstring, "failure")
115+
})
116+
Convey("responds correctly if no channels are subscribed", func() {
117+
response := cli.Parse(commandChan1("list owner/repo"))
118+
So(response["response_type"], ShouldEqual, "in_channel")
119+
So(response["text"], ShouldContainSubstring, " no")
120+
})
121+
})
122+
Convey("When asked to unsubscribe", func() {
123+
Convey("rejects an insufficient number of arguments", func() {
124+
response := cli.Parse(commandChan1("unsubscribe"))
125+
So(response["response_type"], ShouldBeNil)
126+
So(response["text"], ShouldContainSubstring, "repo")
127+
})
128+
Convey("notifies if the channel is not subscribed to the repo", func() {
129+
response := cli.Parse(commandChan1("unsubscribe owner/repo"))
130+
So(response["response_type"], ShouldBeNil)
131+
So(response["text"], ShouldContainSubstring, "subscribed")
132+
})
133+
Convey("correctly unsubscribes from a channel", func() {
134+
cli.Parse(commandChan1("subscribe owner/repo"))
135+
cli.Parse(commandChan1("unsubscribe owner/repo"))
136+
response := cli.Parse(commandChan1("list owner/repo"))
137+
So(response["response_type"], ShouldEqual, "in_channel")
138+
So(response["text"], ShouldContainSubstring, " no")
139+
})
140+
Convey("correctly unsubscribes from only the requested channel", func() {
141+
cli.Parse(commandChan1("subscribe owner/repo"))
142+
cli.Parse(commandChan2("subscribe owner/repo workflows:workflow1 failure"))
143+
cli.Parse(commandChan1("unsubscribe owner/repo"))
144+
response := cli.Parse(commandChan1("list owner/repo"))
145+
So(response["response_type"], ShouldEqual, "in_channel")
146+
So(response["text"], ShouldContainSubstring, "TestChannelID2")
147+
So(response["text"], ShouldContainSubstring, "workflow1")
148+
So(response["text"], ShouldContainSubstring, "failure")
149+
})
150+
Convey("is able to resubscribe", func() {
151+
cli.Parse(commandChan1("subscribe owner/repo"))
152+
cli.Parse(commandChan1("unsubscribe owner/repo"))
153+
cli.Parse(commandChan1("subscribe owner/repo"))
154+
response := cli.Parse(commandChan1("list owner/repo"))
155+
So(response["response_type"], ShouldEqual, "in_channel")
156+
So(response["text"], ShouldContainSubstring, "TestChannelID1")
157+
})
158+
})
159+
})
160+
Convey("When receiving webhooks, the bot", t, func() {
161+
Convey("has no tests at the moment", func() {
162+
})
163+
})
164+
}

0 commit comments

Comments
 (0)