1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-04-24 13:48:49 +08:00
Mainflux.mainflux/twins/api/http/endpoint_states_test.go
b1ackd0t 1f21541a27
NOISSUE - Fix Twins Tests (#1931)
* feat(twins/mocks): Add new service constructor with mock dependencies

This commit adds a new service constructor to the `twins/mocks/service.go` file. The new constructor, `NewService`, takes no arguments and returns an instance of `twins.Service` along with a mock instance of `authmocks.Service`. This allows for the creation of a real twins service using mock dependencies.

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>

* feat(api): Add tests for endpoint states

This commit adds tests for the endpoint states API in the `endpoint_states_test.go` file. The tests cover the functionality of the `GET` and `POST` methods for retrieving and updating the states of endpoints respectively. The tests use the `mainflux` and `authmocks` packages for mocking and testing the API endpoints. Additionally, the `testsutil` package is imported for utility functions used in the tests.

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>

---------

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>
2023-10-20 23:06:03 +02:00

218 lines
6.0 KiB
Go

// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0
package http_test
import (
"context"
"encoding/json"
"fmt"
"net/http"
"testing"
"github.com/mainflux/mainflux"
authmocks "github.com/mainflux/mainflux/auth/mocks"
"github.com/mainflux/mainflux/internal/testsutil"
"github.com/mainflux/mainflux/twins"
"github.com/mainflux/mainflux/twins/mocks"
"github.com/mainflux/senml"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
const numRecs = 100
var (
subtopics = []string{"engine", "chassis", "wheel_2"}
channels = []string{"01ec3c3e-0e66-4e69-9751-a0545b44e08f", "48061e4f-7c23-4f5c-9012-0f9b7cd9d18d", "5b2180e4-e96b-4469-9dc1-b6745078d0b6"}
)
type stateRes struct {
TwinID string `json:"twin_id"`
ID int64 `json:"id"`
Definition int `json:"definition"`
Payload map[string]interface{} `json:"payload"`
}
type statesPageRes struct {
pageRes
States []stateRes `json:"states"`
}
func TestListStates(t *testing.T) {
svc, auth := mocks.NewService()
ts := newServer(svc)
defer ts.Close()
twin := twins.Twin{
Owner: email,
}
def := mocks.CreateDefinition(channels[0:2], subtopics[0:2])
repoCall := auth.On("Identify", mock.Anything, &mainflux.IdentityReq{Token: token}).Return(&mainflux.IdentityRes{Id: testsutil.GenerateUUID(t)}, nil)
tw, err := svc.AddTwin(context.Background(), token, twin, def)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
repoCall.Unset()
attr := def.Attributes[0]
recs := make([]senml.Record, numRecs)
mocks.CreateSenML(recs)
message, err := mocks.CreateMessage(attr, recs)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
err = svc.SaveStates(context.Background(), message)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
var data []stateRes
for i := 0; i < len(recs); i++ {
res := createStateResponse(i, tw, recs[i])
data = append(data, res)
}
baseURL := fmt.Sprintf("%s/states/%s", ts.URL, tw.ID)
queryFmt := "%s?offset=%d&limit=%d"
cases := []struct {
desc string
auth string
status int
url string
res []stateRes
}{
{
desc: "get a list of states",
auth: token,
status: http.StatusOK,
url: baseURL,
res: data[0:10],
},
{
desc: "get a list of states with valid offset and limit",
auth: token,
status: http.StatusOK,
url: fmt.Sprintf(queryFmt, baseURL, 20, 15),
res: data[20:35],
},
{
desc: "get a list of states with invalid token",
auth: authmocks.InvalidValue,
status: http.StatusUnauthorized,
url: fmt.Sprintf(queryFmt, baseURL, 0, 5),
res: nil,
},
{
desc: "get a list of states with empty token",
auth: "",
status: http.StatusUnauthorized,
url: fmt.Sprintf(queryFmt, baseURL, 0, 5),
res: nil,
},
{
desc: "get a list of states with + limit > total",
auth: token,
status: http.StatusOK,
url: fmt.Sprintf(queryFmt, baseURL, 91, 20),
res: data[91:],
},
{
desc: "get a list of states with negative offset",
auth: token,
status: http.StatusBadRequest,
url: fmt.Sprintf(queryFmt, baseURL, -1, 5),
res: nil,
},
{
desc: "get a list of states with negative limit",
auth: token,
status: http.StatusBadRequest,
url: fmt.Sprintf(queryFmt, baseURL, 0, -5),
res: nil,
},
{
desc: "get a list of states with zero limit",
auth: token,
status: http.StatusBadRequest,
url: fmt.Sprintf(queryFmt, baseURL, 0, 0),
res: nil,
},
{
desc: "get a list of states with limit greater than max",
auth: token,
status: http.StatusBadRequest,
url: fmt.Sprintf(queryFmt, baseURL, 0, 110),
res: nil,
},
{
desc: "get a list of states with invalid offset",
auth: token,
status: http.StatusBadRequest,
url: fmt.Sprintf("%s?offset=invalid&limit=%d", baseURL, 15),
res: nil,
},
{
desc: "get a list of states with invalid limit",
auth: token,
status: http.StatusBadRequest,
url: fmt.Sprintf("%s?offset=%d&limit=invalid", baseURL, 0),
res: nil,
},
{
desc: "get a list of states without offset",
auth: token,
status: http.StatusOK,
url: fmt.Sprintf("%s?limit=%d", baseURL, 15),
res: data[0:15],
},
{
desc: "get a list of states without limit",
auth: token,
status: http.StatusOK,
url: fmt.Sprintf("%s?offset=%d", baseURL, 14),
res: data[14:24],
},
{
desc: "get a list of states with invalid number of parameters",
auth: token,
status: http.StatusBadRequest,
url: fmt.Sprintf("%s%s", baseURL, "?offset=4&limit=4&limit=5&offset=5"),
res: nil,
},
{
desc: "get a list of states with redundant query parameters",
auth: token,
status: http.StatusOK,
url: fmt.Sprintf("%s?offset=%d&limit=%d&value=something", baseURL, 0, 5),
res: data[0:5],
},
}
for _, tc := range cases {
repoCall := auth.On("Identify", mock.Anything, mock.Anything).Return(&mainflux.IdentityRes{Id: testsutil.GenerateUUID(t)}, nil)
req := testRequest{
client: ts.Client(),
method: http.MethodGet,
url: tc.url,
token: tc.auth,
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
var resData statesPageRes
if tc.res != nil {
err = json.NewDecoder(res.Body).Decode(&resData)
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))
assert.ElementsMatch(t, tc.res, resData.States, fmt.Sprintf("%s: got incorrect body from response", tc.desc))
repoCall.Unset()
}
}
func createStateResponse(id int, tw twins.Twin, rec senml.Record) stateRes {
return stateRes{
TwinID: tw.ID,
ID: int64(id),
Definition: tw.Definitions[len(tw.Definitions)-1].ID,
Payload: map[string]interface{}{rec.BaseName: nil},
}
}