1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-05-04 22:17:59 +08:00
Mainflux.mainflux/manager/api/transport_test.go
Aleksandar Novaković 2dace5564f MF-170 - Add manager API unit tests (#211)
* Fix connection request validation and EOF error handling

Fix validation of connection and client id in connection request.
Fix EOF error handling by returning HTTP status Bad Request.

Signed-off-by: Aleksandar Novakovic <anovakovic01@gmail.com>

* Add manager API tests and update swagger

Implement unit tests for every manager API endpoint. Update client
and connection mock implementations by switching to UUIDs. Update
swagger file with correct status codes.

Signed-off-by: Aleksandar Novakovic <anovakovic01@gmail.com>

* Add content type check and update documentation

Add content type check in implementation and update documentation
accordingly. Refactor tests and add empty content type test cases.
Add code coverage badge to readme.

Signed-off-by: Aleksandar Novakovic <anovakovic01@gmail.com>
2018-04-08 22:57:56 +02:00

738 lines
24 KiB
Go

package api_test
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/mainflux/mainflux/manager"
"github.com/mainflux/mainflux/manager/api"
"github.com/mainflux/mainflux/manager/mocks"
"github.com/stretchr/testify/assert"
)
const (
contentType = "application/json; charset=utf-8"
invalidEmail = "userexample.com"
wrongID = "123e4567-e89b-12d3-a456-000000000042"
)
var (
user = manager.User{"user@example.com", "password"}
client = manager.Client{Type: "app", Name: "test_app", Payload: "test_payload"}
channel = manager.Channel{Name: "test"}
)
type testRequest struct {
client *http.Client
method string
url string
contentType string
token string
body io.Reader
}
func (tr testRequest) make() (*http.Response, error) {
req, err := http.NewRequest(tr.method, tr.url, tr.body)
if err != nil {
return nil, err
}
if tr.token != "" {
req.Header.Set("Authorization", tr.token)
}
if tr.contentType != "" {
req.Header.Set("Content-Type", tr.contentType)
}
return tr.client.Do(req)
}
func newService() manager.Service {
users := mocks.NewUserRepository()
clients := mocks.NewClientRepository()
channels := mocks.NewChannelRepository(clients)
hasher := mocks.NewHasher()
idp := mocks.NewIdentityProvider()
return manager.New(users, clients, channels, hasher, idp)
}
func newServer(svc manager.Service) *httptest.Server {
mux := api.MakeHandler(svc)
return httptest.NewServer(mux)
}
func toJSON(data interface{}) string {
jsonData, _ := json.Marshal(data)
return string(jsonData)
}
func TestRegister(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
client := ts.Client()
data := toJSON(user)
invalidData := toJSON(manager.User{Email: invalidEmail, Password: "password"})
cases := []struct {
desc string
req string
contentType string
status int
}{
{"register new user", data, contentType, http.StatusCreated},
{"register existing user", data, contentType, http.StatusConflict},
{"register user with invalid email address", invalidData, contentType, http.StatusBadRequest},
{"register user with invalid request format", "{", contentType, http.StatusBadRequest},
{"register user with empty JSON request", "{}", contentType, http.StatusBadRequest},
{"register user with empty request", "", contentType, http.StatusBadRequest},
{"register user with missing content type", data, "", http.StatusUnsupportedMediaType},
}
for _, tc := range cases {
req := testRequest{
client: client,
method: http.MethodPost,
url: fmt.Sprintf("%s/users", ts.URL),
contentType: tc.contentType,
body: strings.NewReader(tc.req),
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
}
}
func TestLogin(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
client := ts.Client()
tokenData := toJSON(map[string]string{"token": user.Email})
data := toJSON(user)
invalidEmailData := toJSON(manager.User{Email: invalidEmail, Password: "password"})
invalidData := toJSON(manager.User{"user@example.com", "invalid_password"})
nonexistentData := toJSON(manager.User{"non-existentuser@example.com", "pass"})
svc.Register(user)
cases := []struct {
desc string
req string
contentType string
status int
res string
}{
{"login with valid credentials", data, contentType, http.StatusCreated, tokenData},
{"login with invalid credentials", invalidData, contentType, http.StatusForbidden, ""},
{"login with invalid email address", invalidEmailData, contentType, http.StatusBadRequest, ""},
{"login non-existent user", nonexistentData, contentType, http.StatusForbidden, ""},
{"login with invalid request format", "{", contentType, http.StatusBadRequest, ""},
{"login with empty JSON request", "{}", contentType, http.StatusBadRequest, ""},
{"login with empty request", "", contentType, http.StatusBadRequest, ""},
{"login with missing content type", data, "", http.StatusUnsupportedMediaType, ""},
}
for _, tc := range cases {
req := testRequest{
client: client,
method: http.MethodPost,
url: fmt.Sprintf("%s/tokens", ts.URL),
contentType: tc.contentType,
body: strings.NewReader(tc.req),
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
body, err := ioutil.ReadAll(res.Body)
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
token := strings.Trim(string(body), "\n")
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
assert.Equal(t, tc.res, token, fmt.Sprintf("%s: expected body %s got %s", tc.desc, tc.res, token))
}
}
func TestAddClient(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
cli := ts.Client()
data := toJSON(client)
invalidData := toJSON(manager.Client{
Type: "foo",
Name: "invalid_client",
Payload: "some_payload",
})
svc.Register(user)
cases := []struct {
desc string
req string
contentType string
auth string
status int
}{
{"add valid client", data, contentType, user.Email, http.StatusCreated},
{"add client with invalid data", invalidData, contentType, user.Email, http.StatusBadRequest},
{"add client with invalid auth token", data, contentType, "invalid_token", http.StatusForbidden},
{"add client with invalid request format", "}", contentType, user.Email, http.StatusBadRequest},
{"add client with empty JSON request", "{}", contentType, user.Email, http.StatusBadRequest},
{"add client with empty request", "", contentType, user.Email, http.StatusBadRequest},
{"add client with missing content type", data, "", user.Email, http.StatusUnsupportedMediaType},
}
for _, tc := range cases {
req := testRequest{
client: cli,
method: http.MethodPost,
url: fmt.Sprintf("%s/clients", ts.URL),
contentType: tc.contentType,
token: tc.auth,
body: strings.NewReader(tc.req),
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
}
}
func TestUpdateClient(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
cli := ts.Client()
data := toJSON(client)
invalidData := toJSON(manager.Client{
Type: "foo",
Name: client.Name,
Payload: client.Payload,
})
svc.Register(user)
id, _ := svc.AddClient(user.Email, client)
cases := []struct {
desc string
req string
id string
contentType string
auth string
status int
}{
{"update existing client", data, id, contentType, user.Email, http.StatusOK},
{"update non-existent client", data, wrongID, contentType, user.Email, http.StatusNotFound},
{"update client with invalid id", data, "1", contentType, user.Email, http.StatusNotFound},
{"update client with invalid data", invalidData, id, contentType, user.Email, http.StatusBadRequest},
{"update client with invalid user token", data, id, contentType, invalidEmail, http.StatusForbidden},
{"update client with invalid data format", "{", id, contentType, user.Email, http.StatusBadRequest},
{"update client with empty JSON request", "{}", id, contentType, user.Email, http.StatusBadRequest},
{"update client with empty request", "", id, contentType, user.Email, http.StatusBadRequest},
{"update client with missing content type", data, id, "", user.Email, http.StatusUnsupportedMediaType},
}
for _, tc := range cases {
req := testRequest{
client: cli,
method: http.MethodPut,
url: fmt.Sprintf("%s/clients/%s", ts.URL, tc.id),
contentType: tc.contentType,
token: tc.auth,
body: strings.NewReader(tc.req),
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
}
}
func TestViewClient(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
cli := ts.Client()
svc.Register(user)
id, _ := svc.AddClient(user.Email, client)
client.ID = id
client.Key = id
data := toJSON(client)
cases := []struct {
desc string
id string
auth string
status int
res string
}{
{"view existing client", id, user.Email, http.StatusOK, data},
{"view non-existent client", wrongID, user.Email, http.StatusNotFound, ""},
{"view client by passing invalid id", "1", user.Email, http.StatusNotFound, ""},
{"view client by passing invalid token", id, invalidEmail, http.StatusForbidden, ""},
}
for _, tc := range cases {
req := testRequest{
client: cli,
method: http.MethodGet,
url: fmt.Sprintf("%s/clients/%s", ts.URL, tc.id),
token: tc.auth,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
body, err := ioutil.ReadAll(res.Body)
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
data := strings.Trim(string(body), "\n")
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
assert.Equal(t, tc.res, data, fmt.Sprintf("%s: expected body %s got %s", tc.desc, tc.res, data))
}
}
func TestListClients(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
cli := ts.Client()
svc.Register(user)
noClientsUser := manager.User{Email: "no_clients_user@example.com", Password: user.Password}
svc.Register(noClientsUser)
clients := []manager.Client{}
for i := 0; i < 10; i++ {
id, _ := svc.AddClient(user.Email, client)
client.ID = id
client.Key = id
clients = append(clients, client)
}
cases := []struct {
desc string
auth string
status int
res []manager.Client
}{
{"fetch list of clients", user.Email, http.StatusOK, clients},
{"fetch empty list of clients", noClientsUser.Email, http.StatusOK, []manager.Client{}},
{"fetch list of clients with invalid token", invalidEmail, http.StatusForbidden, nil},
}
for _, tc := range cases {
req := testRequest{
client: cli,
method: http.MethodGet,
url: fmt.Sprintf("%s/clients", ts.URL),
token: tc.auth,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
var data map[string][]manager.Client
json.NewDecoder(res.Body).Decode(&data)
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
assert.ElementsMatch(t, tc.res, data["clients"], fmt.Sprintf("%s: expected body %s got %s", tc.desc, tc.res, data["clients"]))
}
}
func TestRemoveClient(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
cli := ts.Client()
svc.Register(user)
id, _ := svc.AddClient(user.Email, client)
cases := []struct {
desc string
id string
auth string
status int
}{
{"delete existing client", id, user.Email, http.StatusNoContent},
{"delete non-existent client", wrongID, user.Email, http.StatusNoContent},
{"delete client with invalid id", "1", user.Email, http.StatusNoContent},
{"delete client with invalid token", id, invalidEmail, http.StatusForbidden},
}
for _, tc := range cases {
req := testRequest{
client: cli,
method: http.MethodDelete,
url: fmt.Sprintf("%s/clients/%s", ts.URL, tc.id),
token: tc.auth,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
}
}
func TestCreateChannel(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
client := ts.Client()
data := toJSON(channel)
svc.Register(user)
cases := []struct {
desc string
req string
contentType string
auth string
status int
}{
{"create new channel", data, contentType, user.Email, http.StatusCreated},
{"create new channel with invalid token", data, contentType, invalidEmail, http.StatusForbidden},
{"create new channel with invalid data format", "{", contentType, user.Email, http.StatusBadRequest},
{"create new channel with empty JSON request", "{}", contentType, user.Email, http.StatusCreated},
{"create new channel with empty request", "", contentType, user.Email, http.StatusBadRequest},
{"create new channel with missing content type", data, "", user.Email, http.StatusUnsupportedMediaType},
}
for _, tc := range cases {
req := testRequest{
client: client,
method: http.MethodPost,
url: fmt.Sprintf("%s/channels", ts.URL),
contentType: tc.contentType,
token: tc.auth,
body: strings.NewReader(tc.req),
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
}
}
func TestUpdateChannel(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
client := ts.Client()
updateData := toJSON(map[string]string{
"name": "updated_channel",
})
svc.Register(user)
id, _ := svc.CreateChannel(user.Email, channel)
cases := []struct {
desc string
req string
id string
contentType string
auth string
status int
}{
{"update existing channel", updateData, id, contentType, user.Email, http.StatusOK},
{"update non-existing channel", updateData, wrongID, contentType, user.Email, http.StatusNotFound},
{"update channel with invalid token", updateData, id, contentType, invalidEmail, http.StatusForbidden},
{"update channel with invalid id", updateData, "1", contentType, user.Email, http.StatusNotFound},
{"update channel with invalid data format", "}", id, contentType, user.Email, http.StatusBadRequest},
{"update channel with empty JSON object", "{}", id, contentType, user.Email, http.StatusOK},
{"update channel with empty request", "", id, contentType, user.Email, http.StatusBadRequest},
{"update channel with missing content type", updateData, id, "", user.Email, http.StatusUnsupportedMediaType},
}
for _, tc := range cases {
req := testRequest{
client: client,
method: http.MethodPut,
url: fmt.Sprintf("%s/channels/%s", ts.URL, tc.id),
contentType: tc.contentType,
token: tc.auth,
body: strings.NewReader(tc.req),
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
}
}
func TestViewChannel(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
client := ts.Client()
svc.Register(user)
id, _ := svc.CreateChannel(user.Email, channel)
channel.ID = id
data := toJSON(channel)
cases := []struct {
desc string
id string
auth string
status int
res string
}{
{"view existing channel", id, user.Email, http.StatusOK, data},
{"view non-existent channel", wrongID, user.Email, http.StatusNotFound, ""},
{"view channel with invalid id", "1", user.Email, http.StatusNotFound, ""},
{"view channel with invalid token", id, invalidEmail, http.StatusForbidden, ""},
}
for _, tc := range cases {
req := testRequest{
client: client,
method: http.MethodGet,
url: fmt.Sprintf("%s/channels/%s", ts.URL, tc.id),
token: tc.auth,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
data, err := ioutil.ReadAll(res.Body)
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
body := strings.Trim(string(data), "\n")
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
assert.Equal(t, tc.res, body, fmt.Sprintf("%s: expected body %s got %s", tc.desc, tc.res, body))
}
}
func TestListChannels(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
client := ts.Client()
svc.Register(user)
channels := []manager.Channel{}
for i := 0; i < 10; i++ {
id, _ := svc.CreateChannel(user.Email, channel)
channel.ID = id
channels = append(channels, channel)
}
cases := []struct {
desc string
auth string
status int
res []manager.Channel
}{
{"get a list of channels", user.Email, http.StatusOK, channels},
{"get a list of channels with invalid token", invalidEmail, http.StatusForbidden, nil},
}
for _, tc := range cases {
req := testRequest{
client: client,
method: http.MethodGet,
url: fmt.Sprintf("%s/channels", ts.URL),
token: tc.auth,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
var body map[string][]manager.Channel
json.NewDecoder(res.Body).Decode(&body)
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
assert.ElementsMatch(t, tc.res, body["channels"], fmt.Sprintf("%s: expected body %s got %s", tc.desc, tc.res, body["channels"]))
}
}
func TestRemoveChannel(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
client := ts.Client()
svc.Register(user)
id, _ := svc.CreateChannel(user.Email, channel)
channel.ID = id
cases := []struct {
desc string
id string
auth string
status int
}{
{"remove existing channel", channel.ID, user.Email, http.StatusNoContent},
{"remove non-existent channel", channel.ID, user.Email, http.StatusNoContent},
{"remove channel with invalid id", wrongID, user.Email, http.StatusNoContent},
{"remove channel with invalid token", channel.ID, invalidEmail, http.StatusForbidden},
}
for _, tc := range cases {
req := testRequest{
client: client,
method: http.MethodDelete,
url: fmt.Sprintf("%s/channels/%s", ts.URL, tc.id),
token: tc.auth,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
}
}
func TestConnect(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
cli := ts.Client()
svc.Register(user)
clientID, _ := svc.AddClient(user.Email, client)
chanID, _ := svc.CreateChannel(user.Email, channel)
otherUser := manager.User{Email: "other_user@example.com", Password: "password"}
svc.Register(otherUser)
otherClientID, _ := svc.AddClient(otherUser.Email, client)
otherChanID, _ := svc.CreateChannel(otherUser.Email, channel)
cases := []struct {
desc string
chanID string
clientID string
auth string
status int
}{
{"connect existing client to existing channel", chanID, clientID, user.Email, http.StatusOK},
{"connect existing client to non-existent channel", wrongID, clientID, user.Email, http.StatusNotFound},
{"connect client with invalid id to channel", chanID, "1", user.Email, http.StatusNotFound},
{"connect client to channel with invalid id", "1", clientID, user.Email, http.StatusNotFound},
{"connect existing client to existing channel with invalid token", chanID, clientID, invalidEmail, http.StatusForbidden},
{"connect client from owner to channel of other user", otherChanID, clientID, user.Email, http.StatusNotFound},
{"connect client from other user to owner's channel", chanID, otherClientID, user.Email, http.StatusNotFound},
}
for _, tc := range cases {
req := testRequest{
client: cli,
method: http.MethodPut,
url: fmt.Sprintf("%s/channels/%s/clients/%s", ts.URL, tc.chanID, tc.clientID),
token: tc.auth,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
}
}
func TestDisconnnect(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
cli := ts.Client()
svc.Register(user)
clientID, _ := svc.AddClient(user.Email, client)
chanID, _ := svc.CreateChannel(user.Email, channel)
svc.Connect(user.Email, chanID, clientID)
otherUser := manager.User{Email: "other_user@example.com", Password: "password"}
svc.Register(otherUser)
otherClientID, _ := svc.AddClient(otherUser.Email, client)
otherChanID, _ := svc.CreateChannel(otherUser.Email, channel)
svc.Connect(otherUser.Email, otherChanID, otherClientID)
cases := []struct {
desc string
chanID string
clientID string
auth string
status int
}{
{"disconnect connected client from channel", chanID, clientID, user.Email, http.StatusNoContent},
{"disconnect non-connected client from channel", chanID, clientID, user.Email, http.StatusNotFound},
{"disconnect non-existent client from channel", chanID, "1", user.Email, http.StatusNotFound},
{"disconnect client from non-existent channel", "1", clientID, user.Email, http.StatusNotFound},
{"disconnect client from channel with invalid token", chanID, clientID, invalidEmail, http.StatusForbidden},
{"disconnect owner's client from someone elses channel", otherChanID, clientID, user.Email, http.StatusNotFound},
{"disconnect other's client from owner's channel", chanID, otherClientID, user.Email, http.StatusNotFound},
}
for _, tc := range cases {
req := testRequest{
client: cli,
method: http.MethodDelete,
url: fmt.Sprintf("%s/channels/%s/clients/%s", ts.URL, tc.chanID, tc.clientID),
token: tc.auth,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
}
}
func TestIdentity(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
cli := ts.Client()
svc.Register(user)
clientID, _ := svc.AddClient(user.Email, client)
cases := []struct {
desc string
key string
status int
clientID string
}{
{"get client id using existing client key", clientID, http.StatusOK, clientID},
{"get client id using non-existent client key", "", http.StatusForbidden, ""},
}
for _, tc := range cases {
req := testRequest{
client: cli,
method: http.MethodGet,
url: fmt.Sprintf("%s/access-grant", ts.URL),
token: tc.key,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
clientID := res.Header.Get("X-client-id")
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
assert.Equal(t, tc.clientID, clientID, fmt.Sprintf("%s: expected %s got %s", tc.desc, tc.clientID, clientID))
}
}
func TestCanAccess(t *testing.T) {
svc := newService()
ts := newServer(svc)
defer ts.Close()
cli := ts.Client()
svc.Register(user)
clientID, _ := svc.AddClient(user.Email, client)
notConnectedClientID, _ := svc.AddClient(user.Email, client)
chanID, _ := svc.CreateChannel(user.Email, channel)
svc.Connect(user.Email, chanID, clientID)
cases := []struct {
desc string
chanID string
clientKey string
status int
clientID string
}{
{"check access to existing channel given connected client", chanID, clientID, http.StatusOK, clientID},
{"check access to existing channel given not connected client", chanID, notConnectedClientID, http.StatusForbidden, ""},
{"check access to existing channel given non-existent client", chanID, "invalid_token", http.StatusForbidden, ""},
{"check access to non-existent channel given existing client", "invalid_token", clientID, http.StatusForbidden, ""},
}
for _, tc := range cases {
req := testRequest{
client: cli,
method: http.MethodGet,
url: fmt.Sprintf("%s/channels/%s/access-grant", ts.URL, tc.chanID),
token: tc.clientKey,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
clientID := res.Header.Get("X-client-id")
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
assert.Equal(t, tc.clientID, clientID, fmt.Sprintf("%s: expected %s got %s", tc.desc, tc.clientID, clientID))
}
}