redo discord mocks
This commit is contained in:
parent
f4718f979a
commit
dfbb9e2bca
19 changed files with 223 additions and 105 deletions
|
@ -1,30 +0,0 @@
|
||||||
package discord
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/mock"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DiscordClientMock struct {
|
|
||||||
mock.Mock
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *DiscordClientMock) Do(req *http.Request) (*http.Response, error) {
|
|
||||||
args := c.Called(req)
|
|
||||||
|
|
||||||
return args.Get(0).(*http.Response), args.Error(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *DiscordClientMock) MockResponse(statusCode int, data any) *http.Response {
|
|
||||||
body := bytes.Buffer{}
|
|
||||||
json.NewEncoder(&body).Encode(data)
|
|
||||||
|
|
||||||
return &http.Response{
|
|
||||||
StatusCode: statusCode,
|
|
||||||
Body: io.NopCloser(&body),
|
|
||||||
}
|
|
||||||
}
|
|
42
discord/clientmock/discord_client_mock.go
Normal file
42
discord/clientmock/discord_client_mock.go
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package clientmock
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DiscordClientMock struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *DiscordClientMock) Do(req *http.Request) (*http.Response, error) {
|
||||||
|
args := c.Called(req)
|
||||||
|
|
||||||
|
return args.Get(0).(*http.Response), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *DiscordClientMock) BotAuth(req *http.Request) {
|
||||||
|
c.Called(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *DiscordClientMock) MockResponse(method, path string, statusCode int, data any) {
|
||||||
|
body := bytes.Buffer{}
|
||||||
|
json.NewEncoder(&body).Encode(data)
|
||||||
|
|
||||||
|
r := &http.Response{
|
||||||
|
StatusCode: statusCode,
|
||||||
|
Body: io.NopCloser(&body),
|
||||||
|
}
|
||||||
|
|
||||||
|
pathMatcher := regexp.MustCompile(strings.ReplaceAll(path, "*", "[a-z0-9_-]+"))
|
||||||
|
|
||||||
|
c.On("Do", mock.MatchedBy(func(req *http.Request) bool {
|
||||||
|
return req.Method == method && pathMatcher.MatchString(req.URL.Path)
|
||||||
|
})).Return(r, nil)
|
||||||
|
}
|
|
@ -5,12 +5,15 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json"
|
||||||
)
|
)
|
||||||
|
|
||||||
const DiscordBaseUrl = "https://discord.com/api/v10"
|
const DiscordBaseUrl = "https://discord.com/api/v10"
|
||||||
|
|
||||||
type IDiscordClient interface {
|
type IDiscordClient interface {
|
||||||
Do(req *http.Request) (*http.Response, error)
|
Do(req *http.Request) (*http.Response, error)
|
||||||
|
BotAuth(req *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DiscordClient struct {
|
type DiscordClient struct {
|
||||||
|
@ -36,7 +39,11 @@ func (d *DiscordClient) Do(req *http.Request) (*http.Response, error) {
|
||||||
return d.Client.Do(req)
|
return d.Client.Do(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRequest(method string, path string, botToken string) *http.Request {
|
func (d *DiscordClient) BotAuth(req *http.Request) {
|
||||||
|
req.Header.Set("Authorization", fmt.Sprintf("Bot %s", d.BotToken))
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRequest(method string, path string) *http.Request {
|
||||||
url, err := url.Parse(fmt.Sprintf("%s%s", DiscordBaseUrl, path))
|
url, err := url.Parse(fmt.Sprintf("%s%s", DiscordBaseUrl, path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("discord/api: wtf couldnt join a string??")
|
panic("discord/api: wtf couldnt join a string??")
|
||||||
|
@ -45,13 +52,15 @@ func NewRequest(method string, path string, botToken string) *http.Request {
|
||||||
req := &http.Request{
|
req := &http.Request{
|
||||||
Method: method,
|
Method: method,
|
||||||
URL: url,
|
URL: url,
|
||||||
|
Header: http.Header{},
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Set("User-Agent", "Roleypoly (https://roleypoly.com, v4)")
|
req.Header.Set("User-Agent", "Roleypoly (https://roleypoly.com, v4)")
|
||||||
|
|
||||||
if botToken != "" {
|
|
||||||
req.Header.Set("Authorization", fmt.Sprintf("Bot %s", botToken))
|
|
||||||
}
|
|
||||||
|
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OutputResponse(resp *http.Response, dst any) error {
|
||||||
|
// TODO: more checks?
|
||||||
|
return json.NewDecoder(resp.Body).Decode(dst)
|
||||||
|
}
|
|
@ -1,12 +1,39 @@
|
||||||
package discord
|
package discord
|
||||||
|
|
||||||
import "git.sapphic.engineer/roleypoly/v4/types"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.sapphic.engineer/roleypoly/v4/types"
|
||||||
|
"git.sapphic.engineer/roleypoly/v4/utils"
|
||||||
|
)
|
||||||
|
|
||||||
type IGuild interface {
|
type IGuild interface {
|
||||||
GetMember(memberID string) (IMember, error)
|
GetMember(memberID string) (IMember, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Guild struct {
|
type Guild struct {
|
||||||
Client IDiscordClient
|
|
||||||
types.DiscordGuild
|
types.DiscordGuild
|
||||||
|
|
||||||
|
Client IDiscordClient `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Guild) GetMember(memberID string) (*Member, error) {
|
||||||
|
guildID := g.ID
|
||||||
|
req := NewRequest("GET", utils.J("guilds", guildID, "members", memberID))
|
||||||
|
g.Client.BotAuth(req)
|
||||||
|
|
||||||
|
resp, err := g.Client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Guild.GetMember: request failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
member := &Member{
|
||||||
|
Client: g.Client,
|
||||||
|
}
|
||||||
|
err = OutputResponse(resp, member)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Guild.GetMember: response decode failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return member, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package discord
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/stretchr/testify/mock"
|
|
||||||
)
|
|
||||||
|
|
||||||
type GuildMock struct {
|
|
||||||
mock.Mock
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GuildMock) GetMember(memberID string) (IMember, error) {
|
|
||||||
args := g.Called(memberID)
|
|
||||||
|
|
||||||
if args.Get(0) == nil {
|
|
||||||
return nil, args.Error(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return args.Get(0).(IMember), args.Error(1)
|
|
||||||
}
|
|
31
discord/guild_test.go
Normal file
31
discord/guild_test.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package discord_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"git.sapphic.engineer/roleypoly/v4/discord"
|
||||||
|
"git.sapphic.engineer/roleypoly/v4/types/fixtures"
|
||||||
|
"git.sapphic.engineer/roleypoly/v4/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
fixtureMember = &discord.Member{
|
||||||
|
DiscordMember: fixtures.Member,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetMember(t *testing.T) {
|
||||||
|
dc := defaultMocks(t)
|
||||||
|
g := discord.Guild{
|
||||||
|
Client: dc,
|
||||||
|
DiscordGuild: fixtures.Guild,
|
||||||
|
}
|
||||||
|
|
||||||
|
dc.MockResponse("GET", utils.J("guilds", fixtures.Guild.ID, "members", fixtureMember.User.ID), 200, fixtureMember)
|
||||||
|
|
||||||
|
m, err := g.GetMember("41666")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "Doll", m.Nick)
|
||||||
|
}
|
|
@ -1,5 +1,11 @@
|
||||||
package discord
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.sapphic.engineer/roleypoly/v4/utils"
|
||||||
|
)
|
||||||
|
|
||||||
type IGuildService interface {
|
type IGuildService interface {
|
||||||
Client() IDiscordClient
|
Client() IDiscordClient
|
||||||
GetGuild(guildID string) (IGuild, error)
|
GetGuild(guildID string) (IGuild, error)
|
||||||
|
@ -19,7 +25,23 @@ func (gs *GuildService) Client() IDiscordClient {
|
||||||
return gs.client
|
return gs.client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gs *GuildService) GetGuild(guildID string) (IGuild, error) {
|
func (gs *GuildService) GetGuild(guildID string) (*Guild, error) {
|
||||||
// gs.client
|
|
||||||
return nil, nil
|
req := NewRequest("GET", utils.J("guilds", guildID))
|
||||||
|
gs.client.BotAuth(req)
|
||||||
|
|
||||||
|
resp, err := gs.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("GuildService.GetGuild: request failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
guild := &Guild{
|
||||||
|
Client: gs.client,
|
||||||
|
}
|
||||||
|
err = OutputResponse(resp, guild)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("GuildService.GetGuild: response decode failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return guild, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
package discord
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/stretchr/testify/mock"
|
|
||||||
)
|
|
||||||
|
|
||||||
type GuildServiceMock struct {
|
|
||||||
mock.Mock
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gs *GuildServiceMock) GetGuild(guildID string) (IGuild, error) {
|
|
||||||
args := gs.Called(guildID)
|
|
||||||
|
|
||||||
if args.Get(0) == nil {
|
|
||||||
return nil, args.Error(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return args.Get(0).(IGuild), args.Error(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gs *GuildServiceMock) Client() IDiscordClient {
|
|
||||||
args := gs.Called()
|
|
||||||
return args.Get(0).(IDiscordClient)
|
|
||||||
}
|
|
27
discord/guildservice_test.go
Normal file
27
discord/guildservice_test.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package discord_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.sapphic.engineer/roleypoly/v4/discord"
|
||||||
|
"git.sapphic.engineer/roleypoly/v4/types/fixtures"
|
||||||
|
"git.sapphic.engineer/roleypoly/v4/utils"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
fixtureGuild = &discord.Guild{
|
||||||
|
DiscordGuild: fixtures.Guild,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetGuild(t *testing.T) {
|
||||||
|
dc := defaultMocks(t)
|
||||||
|
gs := discord.NewGuildService(dc)
|
||||||
|
|
||||||
|
dc.MockResponse("GET", utils.J("guilds", fixtures.Guild.ID), 200, fixtureGuild)
|
||||||
|
|
||||||
|
g, err := gs.GetGuild("1312")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "1312", g.ID)
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ type IMember interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Member struct {
|
type Member struct {
|
||||||
|
Client IDiscordClient
|
||||||
types.DiscordMember
|
types.DiscordMember
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
package discord
|
|
||||||
|
|
||||||
import "github.com/stretchr/testify/mock"
|
|
||||||
|
|
||||||
type MemberMock struct {
|
|
||||||
mock.Mock
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MemberMock) GetRoles() error {
|
|
||||||
args := m.Called()
|
|
||||||
return args.Error(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MemberMock) PatchRoles() error {
|
|
||||||
args := m.Called()
|
|
||||||
return args.Error(0)
|
|
||||||
}
|
|
1
discord/member_test.go
Normal file
1
discord/member_test.go
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package discord_test
|
16
discord/utils_test.go
Normal file
16
discord/utils_test.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package discord_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.sapphic.engineer/roleypoly/v4/discord/clientmock"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
func defaultMocks(t *testing.T) *clientmock.DiscordClientMock {
|
||||||
|
dc := &clientmock.DiscordClientMock{}
|
||||||
|
|
||||||
|
dc.On("BotAuth", mock.AnythingOfType("*http.Request"))
|
||||||
|
|
||||||
|
return dc
|
||||||
|
}
|
|
@ -56,9 +56,8 @@ func TestPostHandlerSigFail(t *testing.T) {
|
||||||
app := roleypoly.CreateFiberApp()
|
app := roleypoly.CreateFiberApp()
|
||||||
i.Routes(app)
|
i.Routes(app)
|
||||||
|
|
||||||
// TODO: make real interaction
|
body, err := json.Marshal(map[string]any{
|
||||||
body, err := json.Marshal(map[string]string{
|
"type": 1,
|
||||||
"temp": "temp",
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type TestingController struct {
|
type TestingController struct {
|
||||||
Guilds discord.IGuildService
|
Guilds *discord.GuildService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestingController) Routes(r fiber.Router) {
|
func (t *TestingController) Routes(r fiber.Router) {
|
||||||
|
|
9
types/fixtures/guild.go
Normal file
9
types/fixtures/guild.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package fixtures
|
||||||
|
|
||||||
|
import "git.sapphic.engineer/roleypoly/v4/types"
|
||||||
|
|
||||||
|
var (
|
||||||
|
Guild = types.DiscordGuild{
|
||||||
|
ID: "1312",
|
||||||
|
}
|
||||||
|
)
|
12
types/fixtures/member.go
Normal file
12
types/fixtures/member.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package fixtures
|
||||||
|
|
||||||
|
import "git.sapphic.engineer/roleypoly/v4/types"
|
||||||
|
|
||||||
|
var (
|
||||||
|
Member = types.DiscordMember{
|
||||||
|
User: User,
|
||||||
|
Nick: "Doll",
|
||||||
|
Permissions: 0,
|
||||||
|
Roles: []string{"role1", "role2"},
|
||||||
|
}
|
||||||
|
)
|
10
types/fixtures/user.go
Normal file
10
types/fixtures/user.go
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package fixtures
|
||||||
|
|
||||||
|
import "git.sapphic.engineer/roleypoly/v4/types"
|
||||||
|
|
||||||
|
var (
|
||||||
|
User = types.DiscordUser{
|
||||||
|
Username: "41666",
|
||||||
|
ID: "41666",
|
||||||
|
}
|
||||||
|
)
|
|
@ -1,3 +1,5 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
type DiscordGuild struct{}
|
type DiscordGuild struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue