mirror of https://github.com/statping/statping
				
				
				
			
		
			
				
	
	
		
			510 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			510 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
package handlers
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	_ "github.com/hunterlong/statping/notifiers"
 | 
						|
	"github.com/hunterlong/statping/source"
 | 
						|
	"github.com/hunterlong/statping/utils"
 | 
						|
	"github.com/stretchr/testify/assert"
 | 
						|
	"io/ioutil"
 | 
						|
	"net/http"
 | 
						|
	"net/http/httptest"
 | 
						|
	"net/url"
 | 
						|
	"strings"
 | 
						|
	"testing"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	serverDomain = "http://localhost:8080"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	dir string
 | 
						|
)
 | 
						|
 | 
						|
func init() {
 | 
						|
	source.Assets()
 | 
						|
	utils.InitLogs()
 | 
						|
	dir = utils.Directory
 | 
						|
}
 | 
						|
 | 
						|
func TestResetDatabase(t *testing.T) {
 | 
						|
	Clean()
 | 
						|
}
 | 
						|
 | 
						|
func TestFailedHTTPServer(t *testing.T) {
 | 
						|
	err := RunHTTPServer("missinghost", 0)
 | 
						|
	assert.Error(t, err)
 | 
						|
}
 | 
						|
 | 
						|
func TestSetupRoutes(t *testing.T) {
 | 
						|
 | 
						|
	form := url.Values{}
 | 
						|
	form.Add("db_host", "")
 | 
						|
	form.Add("db_user", "")
 | 
						|
	form.Add("db_password", "")
 | 
						|
	form.Add("db_database", "")
 | 
						|
	form.Add("db_connection", "sqlite")
 | 
						|
	form.Add("db_port", "")
 | 
						|
	form.Add("project", "Tester")
 | 
						|
	form.Add("username", "admin")
 | 
						|
	form.Add("password", "password123")
 | 
						|
	form.Add("sample_data", "on")
 | 
						|
	form.Add("description", "This is an awesome test")
 | 
						|
	form.Add("domain", "http://localhost:8080")
 | 
						|
	form.Add("email", "info@statping.com")
 | 
						|
 | 
						|
	tests := []HTTPTest{
 | 
						|
		{
 | 
						|
			Name:           "Statping Setup Check",
 | 
						|
			URL:            "/setup",
 | 
						|
			Method:         "GET",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:           "Statping Run Setup",
 | 
						|
			URL:            "/setup",
 | 
						|
			Method:         "POST",
 | 
						|
			Body:           form.Encode(),
 | 
						|
			ExpectedStatus: 303,
 | 
						|
			HttpHeaders:    []string{"Content-Type=application/x-www-form-urlencoded"},
 | 
						|
			ExpectedFiles:  []string{utils.Directory + "/config.yml", utils.Directory + "/statup.db"},
 | 
						|
		}}
 | 
						|
 | 
						|
	for _, v := range tests {
 | 
						|
		t.Run(v.Name, func(t *testing.T) {
 | 
						|
			_, t, err := RunHTTPTest(v, t)
 | 
						|
			assert.Nil(t, err)
 | 
						|
			if err != nil {
 | 
						|
				t.FailNow()
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestMainApiRoutes(t *testing.T) {
 | 
						|
	tests := []HTTPTest{
 | 
						|
		{
 | 
						|
			Name:             "Statping Details",
 | 
						|
			URL:              "/api",
 | 
						|
			Method:           "GET",
 | 
						|
			ExpectedStatus:   200,
 | 
						|
			ExpectedContains: []string{`"name":"Tester","description":"This is an awesome test"`},
 | 
						|
		}}
 | 
						|
 | 
						|
	for _, v := range tests {
 | 
						|
		t.Run(v.Name, func(t *testing.T) {
 | 
						|
			_, t, err := RunHTTPTest(v, t)
 | 
						|
			assert.Nil(t, err)
 | 
						|
			if err != nil {
 | 
						|
				t.FailNow()
 | 
						|
			}
 | 
						|
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestApiServiceRoutes(t *testing.T) {
 | 
						|
	tests := []HTTPTest{
 | 
						|
		{
 | 
						|
			Name:             "Statping All Services",
 | 
						|
			URL:              "/api/services",
 | 
						|
			Method:           "GET",
 | 
						|
			ExpectedStatus:   200,
 | 
						|
			ExpectedContains: []string{`"id":1,"name":"Google","domain":"https://google.com"`},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:             "Statping Service 1",
 | 
						|
			URL:              "/api/services/1",
 | 
						|
			Method:           "GET",
 | 
						|
			ExpectedContains: []string{`"id":1,"name":"Google","domain":"https://google.com"`},
 | 
						|
			ExpectedStatus:   200,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:           "Statping Service 1 Data",
 | 
						|
			URL:            "/api/services/1/data",
 | 
						|
			Method:         "GET",
 | 
						|
			Body:           "",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:           "Statping Service 1 Failures",
 | 
						|
			URL:            "/api/services/1/failures",
 | 
						|
			Method:         "GET",
 | 
						|
			Body:           "",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:           "Statping Reorder Services",
 | 
						|
			URL:            "/api/services/reorder",
 | 
						|
			Method:         "POST",
 | 
						|
			Body:           `[{"service":1,"order":1},{"service":5,"order":2},{"service":2,"order":3},{"service":3,"order":4},{"service":4,"order":5}]`,
 | 
						|
			ExpectedStatus: 200,
 | 
						|
			HttpHeaders:    []string{"Content-Type=application/json"},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:        "Statping Create Service",
 | 
						|
			URL:         "/api/services",
 | 
						|
			HttpHeaders: []string{"Content-Type=application/json"},
 | 
						|
			Method:      "POST",
 | 
						|
			Body: `{
 | 
						|
    "name": "New Service",
 | 
						|
    "domain": "https://statping.com",
 | 
						|
    "expected": "",
 | 
						|
    "expected_status": 200,
 | 
						|
    "check_interval": 30,
 | 
						|
    "type": "http",
 | 
						|
    "method": "GET",
 | 
						|
    "post_data": "",
 | 
						|
    "port": 0,
 | 
						|
    "timeout": 30,
 | 
						|
    "order_id": 0
 | 
						|
}`,
 | 
						|
			ExpectedStatus:   200,
 | 
						|
			ExpectedContains: []string{`"status":"success","type":"service","method":"create"`},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:        "Statping Update Service",
 | 
						|
			URL:         "/api/services/1",
 | 
						|
			HttpHeaders: []string{"Content-Type=application/json"},
 | 
						|
			Method:      "POST",
 | 
						|
			Body: `{
 | 
						|
    "name": "Updated New Service",
 | 
						|
    "domain": "https://google.com",
 | 
						|
    "expected": "",
 | 
						|
    "expected_status": 200,
 | 
						|
    "check_interval": 60,
 | 
						|
    "type": "http",
 | 
						|
    "method": "GET",
 | 
						|
    "post_data": "",
 | 
						|
    "port": 0,
 | 
						|
    "timeout": 10,
 | 
						|
    "order_id": 0
 | 
						|
}`,
 | 
						|
			ExpectedStatus:   200,
 | 
						|
			ExpectedContains: []string{`"status":"success","type":"service","method":"update"`},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:             "Statping Delete Service",
 | 
						|
			URL:              "/api/services/1",
 | 
						|
			Method:           "DELETE",
 | 
						|
			ExpectedStatus:   200,
 | 
						|
			ExpectedContains: []string{`"status":"success","type":"service","method":"delete"`},
 | 
						|
		}}
 | 
						|
 | 
						|
	for _, v := range tests {
 | 
						|
		t.Run(v.Name, func(t *testing.T) {
 | 
						|
			_, t, err := RunHTTPTest(v, t)
 | 
						|
			assert.Nil(t, err)
 | 
						|
			if err != nil {
 | 
						|
				t.FailNow()
 | 
						|
			}
 | 
						|
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestGroupAPIRoutes(t *testing.T) {
 | 
						|
	tests := []HTTPTest{
 | 
						|
		{
 | 
						|
			Name:           "Statping Groups",
 | 
						|
			URL:            "/api/groups",
 | 
						|
			Method:         "GET",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:           "Statping View Group",
 | 
						|
			URL:            "/api/groups/1",
 | 
						|
			Method:         "GET",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:        "Statping Create Group",
 | 
						|
			URL:         "/api/groups",
 | 
						|
			HttpHeaders: []string{"Content-Type=application/json"},
 | 
						|
			Body: `{
 | 
						|
    "name": "New Group",
 | 
						|
    "public": true
 | 
						|
}`,
 | 
						|
			Method:         "POST",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:           "Statping Delete Group",
 | 
						|
			URL:            "/api/groups/1",
 | 
						|
			Method:         "DELETE",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		}}
 | 
						|
 | 
						|
	for _, v := range tests {
 | 
						|
		t.Run(v.Name, func(t *testing.T) {
 | 
						|
			_, t, err := RunHTTPTest(v, t)
 | 
						|
			assert.Nil(t, err)
 | 
						|
			if err != nil {
 | 
						|
				t.FailNow()
 | 
						|
			}
 | 
						|
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestApiUsersRoutes(t *testing.T) {
 | 
						|
	tests := []HTTPTest{
 | 
						|
		{
 | 
						|
			Name:           "Statping All Users",
 | 
						|
			URL:            "/api/users",
 | 
						|
			Method:         "GET",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		}, {
 | 
						|
			Name:        "Statping Create User",
 | 
						|
			URL:         "/api/users",
 | 
						|
			HttpHeaders: []string{"Content-Type=application/json"},
 | 
						|
			Method:      "POST",
 | 
						|
			Body: `{
 | 
						|
    "username": "adminuser2",
 | 
						|
    "email": "info@adminemail.com",
 | 
						|
    "password": "passsword123",
 | 
						|
    "admin": true
 | 
						|
}`,
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		}, {
 | 
						|
			Name:           "Statping View User",
 | 
						|
			URL:            "/api/users/1",
 | 
						|
			Method:         "GET",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		}, {
 | 
						|
			Name:   "Statping Update User",
 | 
						|
			URL:    "/api/users/1",
 | 
						|
			Method: "POST",
 | 
						|
			Body: `{
 | 
						|
    "username": "adminupdated",
 | 
						|
    "email": "info@email.com",
 | 
						|
    "password": "password12345",
 | 
						|
    "admin": true
 | 
						|
}`,
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		}, {
 | 
						|
			Name:           "Statping Delete User",
 | 
						|
			URL:            "/api/users/1",
 | 
						|
			Method:         "DELETE",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		}}
 | 
						|
 | 
						|
	for _, v := range tests {
 | 
						|
		t.Run(v.Name, func(t *testing.T) {
 | 
						|
			_, t, err := RunHTTPTest(v, t)
 | 
						|
			assert.Nil(t, err)
 | 
						|
			if err != nil {
 | 
						|
				t.FailNow()
 | 
						|
			}
 | 
						|
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestApiNotifiersRoutes(t *testing.T) {
 | 
						|
	tests := []HTTPTest{
 | 
						|
		{
 | 
						|
			Name:           "Statping Notifiers",
 | 
						|
			URL:            "/api/notifiers",
 | 
						|
			Method:         "GET",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		}, {
 | 
						|
			Name:           "Statping Mobile Notifier",
 | 
						|
			URL:            "/api/notifier/mobile",
 | 
						|
			Method:         "GET",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		}, {
 | 
						|
			Name:   "Statping Update Notifier",
 | 
						|
			URL:    "/api/notifier/mobile",
 | 
						|
			Method: "POST",
 | 
						|
			Body: `{
 | 
						|
    "method": "mobile",
 | 
						|
    "var1": "ExponentPushToken[ToBadIWillError123456]",
 | 
						|
    "enabled": true,
 | 
						|
    "limits": 55
 | 
						|
}`,
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		}}
 | 
						|
 | 
						|
	for _, v := range tests {
 | 
						|
		t.Run(v.Name, func(t *testing.T) {
 | 
						|
			_, t, err := RunHTTPTest(v, t)
 | 
						|
			assert.Nil(t, err)
 | 
						|
			if err != nil {
 | 
						|
				t.FailNow()
 | 
						|
			}
 | 
						|
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestMessagesApiRoutes(t *testing.T) {
 | 
						|
	tests := []HTTPTest{
 | 
						|
		{
 | 
						|
			Name:             "Statping Messages",
 | 
						|
			URL:              "/api/messages",
 | 
						|
			Method:           "GET",
 | 
						|
			ExpectedStatus:   200,
 | 
						|
			ExpectedContains: []string{`"id":1,"title":"Routine Downtime"`},
 | 
						|
		}, {
 | 
						|
			Name:   "Statping Create Message",
 | 
						|
			URL:    "/api/messages",
 | 
						|
			Method: "POST",
 | 
						|
			Body: `{
 | 
						|
    "title": "API Message",
 | 
						|
    "description": "This is an example a upcoming message for a service!",
 | 
						|
    "start_on": "2022-11-17T03:28:16.323797-08:00",
 | 
						|
    "end_on": "2022-11-17T05:13:16.323798-08:00",
 | 
						|
    "service": 1,
 | 
						|
    "notify_users": true,
 | 
						|
    "notify_method": "email",
 | 
						|
    "notify_before": 6,
 | 
						|
    "notify_before_scale": "hour"
 | 
						|
}`,
 | 
						|
			ExpectedStatus:   200,
 | 
						|
			ExpectedContains: []string{`"status":"success","type":"message","method":"create"`},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:             "Statping View Message",
 | 
						|
			URL:              "/api/messages/1",
 | 
						|
			Method:           "GET",
 | 
						|
			ExpectedStatus:   200,
 | 
						|
			ExpectedContains: []string{`"id":1,"title":"Routine Downtime"`},
 | 
						|
		}, {
 | 
						|
			Name:   "Statping Update Message",
 | 
						|
			URL:    "/api/messages/1",
 | 
						|
			Method: "POST",
 | 
						|
			Body: `{
 | 
						|
    "title": "Updated Message",
 | 
						|
    "description": "This message was updated",
 | 
						|
    "start_on": "2022-11-17T03:28:16.323797-08:00",
 | 
						|
    "end_on": "2022-11-17T05:13:16.323798-08:00",
 | 
						|
    "service": 1,
 | 
						|
    "notify_users": true,
 | 
						|
    "notify_method": "email",
 | 
						|
    "notify_before": 3,
 | 
						|
    "notify_before_scale": "hour"
 | 
						|
}`,
 | 
						|
			ExpectedStatus:   200,
 | 
						|
			ExpectedContains: []string{`"status":"success","type":"message","method":"update"`},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:             "Statping Delete Message",
 | 
						|
			URL:              "/api/messages/1",
 | 
						|
			Method:           "DELETE",
 | 
						|
			ExpectedStatus:   200,
 | 
						|
			ExpectedContains: []string{`"status":"success","type":"message","method":"delete"`},
 | 
						|
		}}
 | 
						|
 | 
						|
	for _, v := range tests {
 | 
						|
		t.Run(v.Name, func(t *testing.T) {
 | 
						|
			_, t, err := RunHTTPTest(v, t)
 | 
						|
			assert.Nil(t, err)
 | 
						|
			if err != nil {
 | 
						|
				t.FailNow()
 | 
						|
			}
 | 
						|
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestApiCheckinRoutes(t *testing.T) {
 | 
						|
	tests := []HTTPTest{
 | 
						|
		{
 | 
						|
			Name:           "Statping Checkins",
 | 
						|
			URL:            "/api/checkins",
 | 
						|
			Method:         "GET",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		}, {
 | 
						|
			Name:   "Statping Create Checkin",
 | 
						|
			URL:    "/api/checkin",
 | 
						|
			Method: "POST",
 | 
						|
			Body: `{
 | 
						|
    "service_id": 2,
 | 
						|
    "name": "Server Checkin",
 | 
						|
    "interval": 900,
 | 
						|
    "grace": 60
 | 
						|
}`,
 | 
						|
			ExpectedStatus:   200,
 | 
						|
			ExpectedContains: []string{`"status":"success","type":"checkin","method":"create"`},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Name:           "Statping Checkins",
 | 
						|
			URL:            "/api/checkins",
 | 
						|
			Method:         "GET",
 | 
						|
			ExpectedStatus: 200,
 | 
						|
		}}
 | 
						|
 | 
						|
	for _, v := range tests {
 | 
						|
		t.Run(v.Name, func(t *testing.T) {
 | 
						|
			_, t, err := RunHTTPTest(v, t)
 | 
						|
			assert.Nil(t, err)
 | 
						|
			if err != nil {
 | 
						|
				t.FailNow()
 | 
						|
			}
 | 
						|
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// HTTPTest contains all the parameters for a HTTP Unit Test
 | 
						|
type HTTPTest struct {
 | 
						|
	Name             string
 | 
						|
	URL              string
 | 
						|
	Method           string
 | 
						|
	Body             string
 | 
						|
	ExpectedStatus   int
 | 
						|
	ExpectedContains []string
 | 
						|
	HttpHeaders      []string
 | 
						|
	ExpectedFiles    []string
 | 
						|
}
 | 
						|
 | 
						|
// RunHTTPTest accepts a HTTPTest type to execute the HTTP request
 | 
						|
func RunHTTPTest(test HTTPTest, t *testing.T) (string, *testing.T, error) {
 | 
						|
	req, err := http.NewRequest(test.Method, serverDomain+test.URL, strings.NewReader(test.Body))
 | 
						|
	if err != nil {
 | 
						|
		assert.Nil(t, err)
 | 
						|
		return "", t, err
 | 
						|
	}
 | 
						|
	if len(test.HttpHeaders) != 0 {
 | 
						|
		for _, v := range test.HttpHeaders {
 | 
						|
			splits := strings.Split(v, "=")
 | 
						|
			req.Header.Set(splits[0], splits[1])
 | 
						|
		}
 | 
						|
	}
 | 
						|
	rr := httptest.NewRecorder()
 | 
						|
	Router().ServeHTTP(rr, req)
 | 
						|
	if err != nil {
 | 
						|
		assert.Nil(t, err)
 | 
						|
		return "", t, err
 | 
						|
	}
 | 
						|
	body, err := ioutil.ReadAll(rr.Result().Body)
 | 
						|
	if err != nil {
 | 
						|
		assert.Nil(t, err)
 | 
						|
		return "", t, err
 | 
						|
	}
 | 
						|
	stringBody := string(body)
 | 
						|
	if test.ExpectedStatus != rr.Result().StatusCode {
 | 
						|
		assert.Equal(t, test.ExpectedStatus, rr.Result().StatusCode)
 | 
						|
		return stringBody, t, fmt.Errorf("status code %v does not match %v", rr.Result().StatusCode, test.ExpectedStatus)
 | 
						|
	}
 | 
						|
	if len(test.ExpectedContains) != 0 {
 | 
						|
		for _, v := range test.ExpectedContains {
 | 
						|
			assert.Contains(t, stringBody, v)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if len(test.ExpectedFiles) != 0 {
 | 
						|
		for _, v := range test.ExpectedFiles {
 | 
						|
			assert.FileExists(t, v)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return stringBody, t, err
 | 
						|
}
 | 
						|
 | 
						|
func Clean() {
 | 
						|
	utils.DeleteFile(dir + "/config.yml")
 | 
						|
	utils.DeleteFile(dir + "/statup.db")
 | 
						|
	utils.DeleteDirectory(dir + "/logs")
 | 
						|
}
 |