Adds a client and tests for the handlers
This commit is contained in:
parent
eaca9c1691
commit
3335cfe795
4 changed files with 139 additions and 0 deletions
91
client/client.go
Normal file
91
client/client.go
Normal file
|
@ -0,0 +1,91 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"git.ctrlz.es/mgdelacroix/birthdaybot/model"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrEmptyURL = errors.New("URL cannot be empty")
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
url string
|
||||
httpClient *http.Client
|
||||
headers map[string]string
|
||||
}
|
||||
|
||||
func New(opts ...Option) (*Client, error) {
|
||||
client := &Client{
|
||||
httpClient: &http.Client{},
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
client = opt(client)
|
||||
}
|
||||
|
||||
if client.url == "" {
|
||||
return nil, ErrEmptyURL
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (c *Client) Do(ctx context.Context, method, path, data string, headers map[string]string) (*http.Response, error) {
|
||||
url, err := url.JoinPath(c.url, path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot build request url: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, method, url, strings.NewReader(data))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create request: %w", err)
|
||||
}
|
||||
|
||||
for k, v := range c.headers {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot do request: %w", err)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *Client) Health(ctx context.Context) (bool, error) {
|
||||
resp, err := c.Do(ctx, http.MethodGet, "/health", "", nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return resp.StatusCode == 200, nil
|
||||
}
|
||||
|
||||
func (c *Client) NextBirthdays(ctx context.Context) ([]*model.Birthday, error) {
|
||||
resp, err := c.Do(ctx, http.MethodGet, "/next_birthdays", "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var birthdays []*model.Birthday
|
||||
if err := json.NewDecoder(resp.Body).Decode(&birthdays); err != nil {
|
||||
return nil, fmt.Errorf("cannot decode birthdays: %w", err)
|
||||
}
|
||||
|
||||
return birthdays, nil
|
||||
}
|
17
client/options.go
Normal file
17
client/options.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package client
|
||||
|
||||
type Option func(*Client) *Client
|
||||
|
||||
func WithURL(url string) Option {
|
||||
return func(client *Client) *Client {
|
||||
client.url = url
|
||||
return client
|
||||
}
|
||||
}
|
||||
|
||||
func WithHeaders(headers map[string]string) Option {
|
||||
return func(client *Client) *Client {
|
||||
client.headers = headers
|
||||
return client
|
||||
}
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.ctrlz.es/mgdelacroix/birthdaybot/client"
|
||||
"git.ctrlz.es/mgdelacroix/birthdaybot/model"
|
||||
"git.ctrlz.es/mgdelacroix/birthdaybot/notification"
|
||||
notification_mocks "git.ctrlz.es/mgdelacroix/birthdaybot/notification/mocks"
|
||||
|
@ -20,6 +22,7 @@ type TestHelper struct {
|
|||
mockNotificationService *notification_mocks.MockNotificationService
|
||||
mockWorker *server_mocks.MockWorker
|
||||
srv *Server
|
||||
client *client.Client
|
||||
}
|
||||
|
||||
func testConfig(t *testing.T) *model.Config {
|
||||
|
@ -71,6 +74,10 @@ func SetupTestHelper(t *testing.T, opts ...Option) *TestHelper {
|
|||
|
||||
th.srv.Start()
|
||||
|
||||
client, err := client.New(client.WithURL(fmt.Sprintf("http://127.0.0.1:%d", th.srv.WebServer.Port())))
|
||||
require.NoError(t, err)
|
||||
th.client = client
|
||||
|
||||
return th
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -13,3 +14,26 @@ func TestPort(t *testing.T) {
|
|||
port := th.srv.WebServer.Port()
|
||||
require.NotEmpty(t, port)
|
||||
}
|
||||
|
||||
func TestHealthHandler(t *testing.T) {
|
||||
th := SetupTestHelper(t)
|
||||
defer th.TearDown()
|
||||
|
||||
t.Run("should return ok if the server is up and running", func(t *testing.T) {
|
||||
health, err := th.client.Health(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.True(t, health)
|
||||
})
|
||||
}
|
||||
|
||||
func TestNextBirthdaysHandler(t *testing.T) {
|
||||
th := SetupTestHelper(t)
|
||||
defer th.TearDown()
|
||||
|
||||
t.Run("should return a list if the server is up and running", func(t *testing.T) {
|
||||
birthdays, err := th.client.NextBirthdays(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.Len(t, birthdays, 1)
|
||||
require.Equal(t, "john@doe.com", birthdays[0].Email)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue