mirror of https://github.com/statping/statping
http table testing - source JS files
parent
6e45bfdaea
commit
34c3964749
|
@ -0,0 +1,510 @@
|
|||
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) {
|
||||
body, t, err := RunHTTPTest(v, t)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("Test %v got: %v\n", v.Name, string(body))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
body, t, err := RunHTTPTest(v, t)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("Test %v got: %v\n", v.Name, string(body))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
body, t, err := RunHTTPTest(v, t)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("Test %v got: %v\n", v.Name, string(body))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
body, t, err := RunHTTPTest(v, t)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("Test %v got: %v\n", v.Name, string(body))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
body, t, err := RunHTTPTest(v, t)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("Test %v got: %v\n", v.Name, string(body))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
body, t, err := RunHTTPTest(v, t)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("Test %v got: %v\n", v.Name, string(body))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
body, t, err := RunHTTPTest(v, t)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("Test %v got: %v\n", v.Name, string(body))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
body, t, err := RunHTTPTest(v, t)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("Test %v got: %v\n", v.Name, string(body))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGenericRoutes(t *testing.T) {
|
||||
|
||||
form := url.Values{}
|
||||
form.Add("username", "admin")
|
||||
form.Add("password", "password123")
|
||||
|
||||
form2 := url.Values{}
|
||||
form2.Add("username", "admin")
|
||||
form2.Add("password", "wrongpassword")
|
||||
|
||||
tests := []HTTPTest{
|
||||
{
|
||||
Name: "Statping Index",
|
||||
URL: "/",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{
|
||||
`<title>Tester Status</title>`,
|
||||
`<footer>`,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Statping Incorrect Login",
|
||||
URL: "/dashboard",
|
||||
Method: "POST",
|
||||
Body: form.Encode(),
|
||||
HttpHeaders: []string{"Content-Type=application/x-www-form-urlencoded"},
|
||||
ExpectedContains: []string{"Incorrect login information submitted, try again."},
|
||||
ExpectedStatus: 200,
|
||||
},
|
||||
{
|
||||
Name: "Dashboard Routes",
|
||||
URL: "/dashboard",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{"<title>Statping | Dashboard</title>"},
|
||||
},
|
||||
{
|
||||
Name: "Services Routes",
|
||||
URL: "/services",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{"<title>Statping | Services</title>"},
|
||||
},
|
||||
{
|
||||
Name: "Users Routes",
|
||||
URL: "/users",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{"<title>Statping | Users</title>"},
|
||||
},
|
||||
{
|
||||
Name: "Messages Routes",
|
||||
URL: "/messages",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{"<title>Statping Messages</title>"},
|
||||
},
|
||||
{
|
||||
Name: "Settings Routes",
|
||||
URL: "/settings",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{"<title>Statping | Settings</title>"},
|
||||
},
|
||||
{
|
||||
Name: "Logs Routes",
|
||||
URL: "/logs",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{"<title>Statping | Logs</title>"},
|
||||
},
|
||||
{
|
||||
Name: "Help Routes",
|
||||
URL: "/help",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{"<title>Statping | Help</title>"},
|
||||
},
|
||||
{
|
||||
Name: "Logout",
|
||||
URL: "/logout",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 303,
|
||||
},
|
||||
{
|
||||
Name: "Prometheus Metrics Routes",
|
||||
URL: "/metrics",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{"statping_total_services 5"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, v := range tests {
|
||||
t.Run(v.Name, func(t *testing.T) {
|
||||
body, t, err := RunHTTPTest(v, t)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("Test %v got: %v\n", v.Name, string(body))
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,493 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// The licenses for most software and other practical works are designed
|
||||
// to take away your freedom to share and change the works. By contrast,
|
||||
// the GNU General Public License is intended to guarantee your freedom to
|
||||
// share and change all versions of a program--to make sure it remains free
|
||||
// software for all its users.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/core"
|
||||
_ "github.com/hunterlong/statping/notifiers"
|
||||
"github.com/hunterlong/statping/source"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestResetHandlerDatabase(t *testing.T) {
|
||||
Clean()
|
||||
//loadDatabase()
|
||||
//createDatabase()
|
||||
}
|
||||
|
||||
func TestFailedHTTPServer(t *testing.T) {
|
||||
err := RunHTTPServer("missinghost", 0)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestSetupHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/setup", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Statping | Setup</title>")
|
||||
}
|
||||
|
||||
func TestProcessSetupHandler(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")
|
||||
req, err := http.NewRequest("POST", "/setup", strings.NewReader(form.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
assert.FileExists(t, dir+"/config.yml")
|
||||
assert.FileExists(t, dir+"/statup.db")
|
||||
}
|
||||
|
||||
func TestCheckSetupHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/setup", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
}
|
||||
|
||||
func TestCheckIndexHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
}
|
||||
|
||||
func TestServicesViewHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/service/1", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Google Status</title>")
|
||||
assert.Contains(t, body, "</footer>")
|
||||
}
|
||||
|
||||
func TestMissingServiceViewHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/service/99999999", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 404, rr.Code)
|
||||
}
|
||||
|
||||
func TestServiceChartHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/charts.js", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "var ctx_1")
|
||||
assert.Contains(t, body, "var ctx_2")
|
||||
assert.Contains(t, body, "var ctx_3")
|
||||
assert.Contains(t, body, "var ctx_4")
|
||||
assert.Contains(t, body, "var ctx_5")
|
||||
}
|
||||
|
||||
func TestDashboardHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/dashboard", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Statping | Dashboard</title>")
|
||||
assert.Contains(t, body, "</footer>")
|
||||
}
|
||||
|
||||
func TestLoginHandler(t *testing.T) {
|
||||
form := url.Values{}
|
||||
form.Add("username", "admin")
|
||||
form.Add("password", "password123")
|
||||
req, err := http.NewRequest("POST", "/dashboard", strings.NewReader(form.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
}
|
||||
|
||||
func TestBadLoginHandler(t *testing.T) {
|
||||
form := url.Values{}
|
||||
form.Add("username", "admin")
|
||||
form.Add("password", "wrongpassword")
|
||||
req, err := http.NewRequest("POST", "/dashboard", strings.NewReader(form.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Contains(t, body, "Incorrect login information submitted, try again.")
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
}
|
||||
|
||||
func TestServicesHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/services", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Statping | Services</title>")
|
||||
//assert.Contains(t, body, "</footer>️")
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestUsersHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/users", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Statping | Users</title>")
|
||||
assert.Contains(t, body, "<td>admin</td>")
|
||||
assert.NotContains(t, body, "<td>changedusername</td>")
|
||||
assert.Contains(t, body, "</footer>")
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestUsersEditHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/user/1", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Statping | admin</title>")
|
||||
assert.Contains(t, body, "<h3>User admin</h3>")
|
||||
assert.Contains(t, body, "value=\"info@statping.com\"")
|
||||
//assert.Contains(t, body, "</footer>️")
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestSettingsHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/settings", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Statping | Settings</title>")
|
||||
//assert.Contains(t, body, "</footer>️")
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestHelpHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/help", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Statping | Help</title>")
|
||||
//assert.Contains(t, body, "</footer>️")
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestServicesHandler2(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/services", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Statping | Services</title>")
|
||||
assert.Contains(t, body, "JSON Users Test")
|
||||
assert.Contains(t, body, "JSON API Tester")
|
||||
//assert.Contains(t, body, "</footer>️")
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestViewHTTPServicesHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/service/5", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Google DNS Status</title>")
|
||||
//assert.Contains(t, body, "</footer>️")
|
||||
}
|
||||
|
||||
func TestViewTCPServicesHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/service/5", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Google DNS Status</title>")
|
||||
//assert.Contains(t, body, "</footer>️")
|
||||
}
|
||||
|
||||
func TestServicesDeleteFailuresHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/service/5/delete_failures", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestFailingServicesDeleteFailuresHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/service/5/delete_failures", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestLogsHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/logs", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Statping | Logs</title>")
|
||||
//assert.Contains(t, body, "</footer>️")
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestLogsLineHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/logs/line", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.NotEmpty(t, body)
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestSaveSettingsHandler(t *testing.T) {
|
||||
form := url.Values{}
|
||||
form.Add("project", "Awesome Status")
|
||||
form.Add("description", "These tests can probably be better")
|
||||
req, err := http.NewRequest("POST", "/settings", strings.NewReader(form.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestViewSettingsHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/settings", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Statping | Settings</title>")
|
||||
assert.Contains(t, body, "Awesome Status")
|
||||
//assert.Contains(t, body, "</footer>️")
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestSaveAssetsHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/settings/build", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
assert.FileExists(t, utils.Directory+"/assets/css/base.css")
|
||||
assert.DirExists(t, utils.Directory+"/assets")
|
||||
assert.True(t, source.UsingAssets(dir))
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestDeleteAssetsHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/settings/delete_assets", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
assert.False(t, source.UsingAssets(dir))
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestPrometheusHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/metrics", nil)
|
||||
req.Header.Set("Authorization", core.CoreApp.ApiSecret)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "statping_total_services 5")
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestUpdateNotificationHandler(t *testing.T) {
|
||||
t.SkipNow()
|
||||
data := `{"limits": 7, "enabled": true, "method": "email", "host": "smtp.emailserver.com", "username": "exampleuser", "password": "password123", "port": 543, "var1": "info@betatude.com", "var2": "sendto@gmail.com"}`
|
||||
rr, err := httpRequestAPI(t, "POST", "/api/notifier/email", strings.NewReader(data))
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj apiResponse
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Equal(t, "success", obj.Status)
|
||||
}
|
||||
|
||||
func TestViewNotificationSettingsHandler(t *testing.T) {
|
||||
t.SkipNow()
|
||||
req, err := http.NewRequest("GET", "/settings", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "<title>Statping | Settings</title>")
|
||||
assert.Contains(t, body, `value="exampleuser" id="smtp_username"`)
|
||||
assert.Contains(t, body, `value="587" id="smtp_port"`)
|
||||
assert.Contains(t, body, `value="info@betatude.com" id="outgoing_email_address"`)
|
||||
assert.Contains(t, body, `value="sendto@gmail.com" id="send_alerts_to"`)
|
||||
assert.Contains(t, body, `id="limits_per_hour_email" value="7"`)
|
||||
assert.Contains(t, body, `id="switch-email" checked`)
|
||||
//assert.Contains(t, body, "</footer>️")
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestSaveFooterHandler(t *testing.T) {
|
||||
form := url.Values{}
|
||||
form.Add("footer", "Created by Hunter Long")
|
||||
req, err := http.NewRequest("POST", "/settings", strings.NewReader(form.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
|
||||
req, err = http.NewRequest("GET", "/", nil)
|
||||
assert.Nil(t, err)
|
||||
rr = httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, body, "Created by Hunter Long")
|
||||
}
|
||||
|
||||
func TestError404Handler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/404me", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 404, rr.Code)
|
||||
}
|
||||
|
||||
func TestLogoutHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/logout", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
}
|
||||
|
||||
func TestBuildAssetsHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/settings/build", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
assert.FileExists(t, "../assets/scss/base.scss")
|
||||
}
|
||||
|
||||
func TestSaveSassHandler(t *testing.T) {
|
||||
base := source.OpenAsset(utils.Directory, "scss/base.scss")
|
||||
vars := source.OpenAsset(utils.Directory, "scss/variables.scss")
|
||||
|
||||
form := url.Values{}
|
||||
form.Add("theme", base+"\n .test_design { color: $test-design; }")
|
||||
form.Add("variables", vars+"\n $test-design: #ffffff; ")
|
||||
req, err := http.NewRequest("POST", "/settings/css", strings.NewReader(form.Encode()))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
|
||||
newBase := source.OpenAsset(utils.Directory, "css/base.css")
|
||||
assert.Contains(t, newBase, ".test_design {")
|
||||
}
|
||||
|
||||
func TestReorderServiceHandler(t *testing.T) {
|
||||
data := `[{id: 1, order: 3},{id: 2, order: 2},{id: 3, order: 1}]"`
|
||||
req, err := http.NewRequest("POST", "/api/services/reorder", strings.NewReader(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func TestExportHandler(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/settings/export", nil)
|
||||
assert.Nil(t, err)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.True(t, isRouteAuthenticated(req))
|
||||
}
|
||||
|
||||
func isRouteAuthenticated(req *http.Request) bool {
|
||||
os.Setenv("GO_ENV", "production")
|
||||
rr := httptest.NewRecorder()
|
||||
req.Header.Set("Authorization", "badkey")
|
||||
Router().ServeHTTP(rr, req)
|
||||
code := rr.Code
|
||||
if code == 200 {
|
||||
os.Setenv("GO_ENV", "test")
|
||||
return false
|
||||
}
|
||||
os.Setenv("GO_ENV", "test")
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMessageRoutes(t *testing.T) {
|
||||
tests := []HTTPTest{
|
||||
{
|
||||
Name: "Messages",
|
||||
URL: "/messages",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{`<title>Statping Messages</title>`},
|
||||
},
|
||||
{
|
||||
Name: "Message 2",
|
||||
URL: "/message/2",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{`<title>Statping | Server Reboot</title>`},
|
||||
}}
|
||||
|
||||
for _, v := range tests {
|
||||
t.Run(v.Name, func(t *testing.T) {
|
||||
body, t, err := RunHTTPTest(v, t)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("Test %v got: %v\n", v.Name, string(body))
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,327 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// The licenses for most software and other practical works are designed
|
||||
// to take away your freedom to share and change the works. By contrast,
|
||||
// the GNU General Public License is intended to guarantee your freedom to
|
||||
// share and change all versions of a program--to make sure it remains free
|
||||
// software for all its users.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/hunterlong/statping/core"
|
||||
"github.com/hunterlong/statping/source"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
NEW_HTTP_SERVICE = `{"name": "Google Website", "domain": "https://google.com", "expected_status": 200, "check_interval": 10, "type": "http", "method": "GET"}`
|
||||
)
|
||||
|
||||
var (
|
||||
dir string
|
||||
)
|
||||
|
||||
func init() {
|
||||
dir = utils.Directory
|
||||
utils.InitLogs()
|
||||
source.Assets()
|
||||
}
|
||||
|
||||
func loadDatabase() {
|
||||
core.NewCore()
|
||||
core.LoadConfigFile(dir)
|
||||
core.Configs = &core.DbConfig{
|
||||
DbConn: "sqlite",
|
||||
Location: dir,
|
||||
}
|
||||
core.CoreApp.DbConnection = "sqlite"
|
||||
core.Configs.Connect(false, utils.Directory)
|
||||
core.CoreApp.Version = "DEV"
|
||||
core.Configs.Save()
|
||||
}
|
||||
|
||||
func createDatabase() {
|
||||
core.Configs.DropDatabase()
|
||||
core.Configs.CreateDatabase()
|
||||
}
|
||||
|
||||
func resetDatabase() {
|
||||
core.Configs.DropDatabase()
|
||||
core.Configs.CreateDatabase()
|
||||
core.InsertLargeSampleData()
|
||||
}
|
||||
|
||||
func Clean() {
|
||||
utils.DeleteFile(dir + "/config.yml")
|
||||
utils.DeleteFile(dir + "/statup.db")
|
||||
utils.DeleteDirectory(dir + "/assets")
|
||||
utils.DeleteDirectory(dir + "/logs")
|
||||
}
|
||||
|
||||
func TestInit(t *testing.T) {
|
||||
//Clean()
|
||||
//loadDatabase()
|
||||
//resetDatabase()
|
||||
//loadDatabase()
|
||||
//core.SelectCore()
|
||||
//core.InsertNotifierDB()
|
||||
//core.CoreApp.SelectAllServices(false)
|
||||
//core.CoreApp.Notifications = notifier.Load()
|
||||
}
|
||||
|
||||
func formatJSON(res string, out interface{}) {
|
||||
json.Unmarshal([]byte(res), &out)
|
||||
}
|
||||
|
||||
func TestApiIndexHandler(t *testing.T) {
|
||||
rr, err := httpRequestAPI(t, "GET", "/api", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj types.Core
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Equal(t, "Awesome Status", obj.Name)
|
||||
assert.Equal(t, "sqlite", obj.DbConnection)
|
||||
}
|
||||
|
||||
func TestApiAllServicesHandlerHandler(t *testing.T) {
|
||||
rr, err := httpRequestAPI(t, "GET", "/api/services", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj []types.Service
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Equal(t, "Google", obj[0].Name)
|
||||
assert.Equal(t, "https://google.com", obj[0].Domain)
|
||||
}
|
||||
|
||||
func TestApiServiceHandler(t *testing.T) {
|
||||
rr, err := httpRequestAPI(t, "GET", "/api/services/1", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj types.Service
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Equal(t, "Google", obj.Name)
|
||||
assert.Equal(t, "https://google.com", obj.Domain)
|
||||
}
|
||||
|
||||
func TestApiCreateServiceHandler(t *testing.T) {
|
||||
rr, err := httpRequestAPI(t, "POST", "/api/services", strings.NewReader(NEW_HTTP_SERVICE))
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
var obj apiResponse
|
||||
formatJSON(body, &obj)
|
||||
t.Log(body)
|
||||
object := obj.Output.(map[string]interface{})
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Equal(t, "Google Website", object["name"])
|
||||
assert.Equal(t, "https://google.com", object["domain"])
|
||||
}
|
||||
|
||||
func TestApiUpdateServiceHandler(t *testing.T) {
|
||||
data := `{
|
||||
"name": "Updated 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}`
|
||||
rr, err := httpRequestAPI(t, "POST", "/api/services/1", strings.NewReader(data))
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
t.Log(body)
|
||||
var obj apiResponse
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Equal(t, "success", obj.Status)
|
||||
assert.Equal(t, "update", obj.Method)
|
||||
assert.Equal(t, int64(1), obj.Id)
|
||||
}
|
||||
|
||||
func TestApiDeleteServiceHandler(t *testing.T) {
|
||||
rr, err := httpRequestAPI(t, "DELETE", "/api/services/2", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj apiResponse
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Equal(t, "delete", obj.Method)
|
||||
assert.Equal(t, "success", obj.Status)
|
||||
}
|
||||
|
||||
func TestApiAllUsersHandler(t *testing.T) {
|
||||
rr, err := httpRequestAPI(t, "GET", "/api/users", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
var obj []types.User
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, true, obj[0].Admin.Bool)
|
||||
assert.Equal(t, "admin", obj[0].Username)
|
||||
}
|
||||
|
||||
func TestApiCreateUserHandler(t *testing.T) {
|
||||
data := `{
|
||||
"username": "admin2",
|
||||
"email": "info@email.com",
|
||||
"password": "password123",
|
||||
"admin": true}`
|
||||
rr, err := httpRequestAPI(t, "POST", "/api/users", strings.NewReader(data))
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj apiResponse
|
||||
formatJSON(body, &obj)
|
||||
t.Log(body)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Contains(t, "create", obj.Method)
|
||||
assert.Contains(t, "success", obj.Status)
|
||||
}
|
||||
|
||||
func TestApiViewUserHandler(t *testing.T) {
|
||||
rr, err := httpRequestAPI(t, "GET", "/api/users/1", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
var obj types.User
|
||||
formatJSON(body, &obj)
|
||||
t.Log(body)
|
||||
assert.Equal(t, "admin", obj.Username)
|
||||
assert.Equal(t, true, obj.Admin.Bool)
|
||||
}
|
||||
|
||||
func TestApiUpdateUserHandler(t *testing.T) {
|
||||
data := `{
|
||||
"username": "adminupdated",
|
||||
"password": "password123",
|
||||
"admin": true}`
|
||||
rr, err := httpRequestAPI(t, "POST", "/api/users/1", strings.NewReader(data))
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj apiResponse
|
||||
formatJSON(body, &obj)
|
||||
t.Log(body)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Equal(t, "update", obj.Method)
|
||||
assert.Equal(t, "success", obj.Status)
|
||||
assert.Equal(t, int64(1), obj.Id)
|
||||
}
|
||||
|
||||
func TestApiDeleteUserHandler(t *testing.T) {
|
||||
rr, err := httpRequestAPI(t, "DELETE", "/api/users/1", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj apiResponse
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Equal(t, "delete", obj.Method)
|
||||
assert.Equal(t, "success", obj.Status)
|
||||
}
|
||||
|
||||
func TestApiServiceDataHandler(t *testing.T) {
|
||||
grouping := []string{"minute", "hour", "day", "week"}
|
||||
for _, g := range grouping {
|
||||
params := "?start=0&end=999999999999&group=" + g
|
||||
rr, err := httpRequestAPI(t, "GET", "/api/services/5/data"+params, nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj core.DateScanObj
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.NotZero(t, len(obj.Array))
|
||||
}
|
||||
}
|
||||
|
||||
func TestApiRenewHandler(t *testing.T) {
|
||||
api := core.CoreApp.ApiKey
|
||||
secret := core.CoreApp.ApiSecret
|
||||
rr, err := httpRequestAPI(t, "GET", "/api/renew", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj apiResponse
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 303, rr.Code)
|
||||
assert.NotEqual(t, api, core.CoreApp.ApiKey)
|
||||
assert.NotEqual(t, secret, core.CoreApp.ApiSecret)
|
||||
}
|
||||
|
||||
func TestApiCheckinHandler(t *testing.T) {
|
||||
t.SkipNow()
|
||||
service := core.SelectService(1)
|
||||
checkin := service.AllCheckins()
|
||||
rr, err := httpRequestAPI(t, "GET", "/api/checkin/"+checkin[0].ApiKey, nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj apiResponse
|
||||
formatJSON(body, &obj)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
}
|
||||
|
||||
func TestApiCreateCheckinHandler(t *testing.T) {
|
||||
data := `{
|
||||
"service_id": 1,
|
||||
"name": "New API Checkin",
|
||||
"interval": 60,
|
||||
"grace": 30}`
|
||||
rr, err := httpRequestAPI(t, "POST", "/api/checkin", strings.NewReader(data))
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
var obj apiResponse
|
||||
formatJSON(body, &obj)
|
||||
t.Log(body)
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
assert.Equal(t, "create", obj.Method)
|
||||
assert.Equal(t, "success", obj.Status)
|
||||
assert.Equal(t, int64(1), obj.Id)
|
||||
}
|
||||
|
||||
func TestApiAllCheckinsHandler(t *testing.T) {
|
||||
rr, err := httpRequestAPI(t, "GET", "/api/checkins", nil)
|
||||
assert.Nil(t, err)
|
||||
body := rr.Body.String()
|
||||
assert.Equal(t, 200, rr.Code)
|
||||
var obj []types.Checkin
|
||||
formatJSON(body, &obj)
|
||||
t.Log(body)
|
||||
assert.Equal(t, int(1), len(obj))
|
||||
assert.Equal(t, int64(1), obj[0].Id)
|
||||
assert.Equal(t, int64(1), obj[0].ServiceId)
|
||||
assert.Equal(t, "New API Checkin", obj[0].Name)
|
||||
}
|
||||
|
||||
func httpRequestAPI(t *testing.T, method, url string, body io.Reader) (*httptest.ResponseRecorder, error) {
|
||||
req, err := http.NewRequest(method, url, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if body != nil {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
req.Header.Set("Authorization", core.CoreApp.ApiSecret)
|
||||
rr := httptest.NewRecorder()
|
||||
Router().ServeHTTP(rr, req)
|
||||
assert.Nil(t, err)
|
||||
return rr, err
|
||||
}
|
|
@ -40,17 +40,18 @@ func Router() *mux.Router {
|
|||
indexHandler := http.FileServer(http.Dir(dir + "/assets/"))
|
||||
r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir(dir+"/assets/css"))))
|
||||
r.PathPrefix("/font/").Handler(http.StripPrefix("/font/", http.FileServer(http.Dir(dir+"/assets/font"))))
|
||||
r.PathPrefix("/js/").Handler(http.StripPrefix("/js/", http.FileServer(http.Dir(dir+"/assets/js"))))
|
||||
r.PathPrefix("/robots.txt").Handler(indexHandler)
|
||||
r.PathPrefix("/favicon.ico").Handler(indexHandler)
|
||||
r.PathPrefix("/banner.png").Handler(indexHandler)
|
||||
} else {
|
||||
r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(source.CssBox.HTTPBox())))
|
||||
r.PathPrefix("/font/").Handler(http.StripPrefix("/font/", http.FileServer(source.FontBox.HTTPBox())))
|
||||
r.PathPrefix("/js/").Handler(http.StripPrefix("/js/", http.FileServer(source.JsBox.HTTPBox())))
|
||||
r.PathPrefix("/robots.txt").Handler(http.FileServer(source.TmplBox.HTTPBox()))
|
||||
r.PathPrefix("/favicon.ico").Handler(http.FileServer(source.TmplBox.HTTPBox()))
|
||||
r.PathPrefix("/banner.png").Handler(http.FileServer(source.TmplBox.HTTPBox()))
|
||||
}
|
||||
r.PathPrefix("/js/").Handler(http.StripPrefix("/js/", http.FileServer(source.JsBox.HTTPBox())))
|
||||
r.Handle("/charts.js", http.HandlerFunc(renderServiceChartsHandler))
|
||||
r.Handle("/setup", http.HandlerFunc(setupHandler)).Methods("GET")
|
||||
r.Handle("/setup", http.HandlerFunc(processSetupHandler)).Methods("POST")
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestServiceRoutes(t *testing.T) {
|
||||
tests := []HTTPTest{
|
||||
{
|
||||
Name: "Services",
|
||||
URL: "/services",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{`<title>Statping | Services</title>`},
|
||||
},
|
||||
{
|
||||
Name: "Services 2",
|
||||
URL: "/service/2",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{`<title>Statping Github Status</title>`},
|
||||
}}
|
||||
|
||||
for _, v := range tests {
|
||||
t.Run(v.Name, func(t *testing.T) {
|
||||
body, t, err := RunHTTPTest(v, t)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("Test %v got: %v\n", v.Name, string(body))
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUserRoutes(t *testing.T) {
|
||||
tests := []HTTPTest{
|
||||
{
|
||||
Name: "Users",
|
||||
URL: "/users",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{`<title>Statping | Users</title>`},
|
||||
},
|
||||
{
|
||||
Name: "User 2",
|
||||
URL: "/user/2",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 200,
|
||||
ExpectedContains: []string{`<title>Statping | adminuser2</title>`},
|
||||
}}
|
||||
|
||||
for _, v := range tests {
|
||||
t.Run(v.Name, func(t *testing.T) {
|
||||
body, t, err := RunHTTPTest(v, t)
|
||||
assert.Nil(t, err)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
t.Logf("Test %v got: %v\n", v.Name, string(body))
|
||||
})
|
||||
}
|
||||
}
|
|
@ -7,54 +7,66 @@
|
|||
/* Mobile Service Container */
|
||||
HTML, BODY {
|
||||
background-color: #fcfcfc;
|
||||
padding-bottom: 10px; }
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 25px;
|
||||
max-width: 860px;
|
||||
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; }
|
||||
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
color: #464646; }
|
||||
color: #464646;
|
||||
}
|
||||
|
||||
.header-desc {
|
||||
color: #939393; }
|
||||
color: #939393;
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 0.2rem; }
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.online_list .badge {
|
||||
margin-top: 0.2rem; }
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
margin-bottom: 30px; }
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
line-height: 1.3;
|
||||
font-size: 0.75rem; }
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.view_service_btn {
|
||||
position: absolute;
|
||||
bottom: -40px;
|
||||
right: 40px; }
|
||||
right: 40px;
|
||||
}
|
||||
|
||||
.service_lower_info {
|
||||
position: absolute;
|
||||
bottom: -40px;
|
||||
left: 40px;
|
||||
color: #d1ffca;
|
||||
font-size: 0.85rem; }
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.lg_number {
|
||||
font-size: 2.3rem;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
color: #4f4f4f; }
|
||||
color: #4f4f4f;
|
||||
}
|
||||
|
||||
.stats_area {
|
||||
text-align: center;
|
||||
color: #a5a5a5; }
|
||||
color: #a5a5a5;
|
||||
}
|
||||
|
||||
.lower_canvas {
|
||||
height: 3.4rem;
|
||||
|
@ -62,112 +74,144 @@ HTML, BODY {
|
|||
background-color: #48d338;
|
||||
padding: 15px 10px;
|
||||
margin-left: 0px !important;
|
||||
margin-right: 0px !important; }
|
||||
margin-right: 0px !important;
|
||||
}
|
||||
|
||||
.lower_canvas SPAN {
|
||||
font-size: 1rem;
|
||||
color: #fff; }
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-decoration: none;
|
||||
margin-top: 20px; }
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.footer A {
|
||||
color: #8d8d8d;
|
||||
text-decoration: none; }
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer A:HOVER {
|
||||
color: #6d6d6d; }
|
||||
color: #6d6d6d;
|
||||
}
|
||||
|
||||
.badge {
|
||||
color: white;
|
||||
border-radius: 0.2rem; }
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
height: 25px; }
|
||||
.btn-group A {
|
||||
padding: 0.1rem .75rem;
|
||||
font-size: 0.8rem; }
|
||||
height: 25px;
|
||||
}
|
||||
.btn-group A {
|
||||
padding: 0.1rem 0.75rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.card-body .badge {
|
||||
color: #fff; }
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.nav-pills .nav-link {
|
||||
border-radius: 0.2rem; }
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border-radius: 0.2rem; }
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #ffffff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.125); }
|
||||
border: 1px solid rgba(0, 0, 0, 0.125);
|
||||
}
|
||||
|
||||
.card-body {
|
||||
overflow: hidden; }
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-body H4 A {
|
||||
color: #444444;
|
||||
text-decoration: none; }
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
position: relative;
|
||||
height: 170px;
|
||||
width: 100%; }
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.service-chart-container {
|
||||
position: relative;
|
||||
height: 400px;
|
||||
width: 100%; }
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #3e9bff;
|
||||
border-color: #006fe6;
|
||||
color: white; }
|
||||
.btn-primary.dyn-dark {
|
||||
background-color: #32a825 !important;
|
||||
border-color: #2c9320 !important; }
|
||||
.btn-primary.dyn-light {
|
||||
background-color: #75de69 !important;
|
||||
border-color: #88e37e !important; }
|
||||
color: white;
|
||||
}
|
||||
.btn-primary.dyn-dark {
|
||||
background-color: #32a825 !important;
|
||||
border-color: #2c9320 !important;
|
||||
}
|
||||
.btn-primary.dyn-light {
|
||||
background-color: #75de69 !important;
|
||||
border-color: #88e37e !important;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background-color: #47d337; }
|
||||
.btn-success.dyn-dark {
|
||||
background-color: #32a825 !important;
|
||||
border-color: #2c9320 !important; }
|
||||
.btn-success.dyn-light {
|
||||
background-color: #75de69 !important;
|
||||
border-color: #88e37e !important; }
|
||||
background-color: #47d337;
|
||||
}
|
||||
.btn-success.dyn-dark {
|
||||
background-color: #32a825 !important;
|
||||
border-color: #2c9320 !important;
|
||||
}
|
||||
.btn-success.dyn-light {
|
||||
background-color: #75de69 !important;
|
||||
border-color: #88e37e !important;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background-color: #dd3545; }
|
||||
.btn-danger.dyn-dark {
|
||||
background-color: #b61f2d !important;
|
||||
border-color: #a01b28 !important; }
|
||||
.btn-danger.dyn-light {
|
||||
background-color: #e66975 !important;
|
||||
border-color: #e97f89 !important; }
|
||||
background-color: #dd3545;
|
||||
}
|
||||
.btn-danger.dyn-dark {
|
||||
background-color: #b61f2d !important;
|
||||
border-color: #a01b28 !important;
|
||||
}
|
||||
.btn-danger.dyn-light {
|
||||
background-color: #e66975 !important;
|
||||
border-color: #e97f89 !important;
|
||||
}
|
||||
|
||||
.bg-success {
|
||||
background-color: #47d337 !important; }
|
||||
background-color: #47d337 !important;
|
||||
}
|
||||
|
||||
.bg-danger {
|
||||
background-color: #dd3545 !important; }
|
||||
background-color: #dd3545 !important;
|
||||
}
|
||||
|
||||
.bg-success .dyn-dark {
|
||||
background-color: #35b027 !important; }
|
||||
background-color: #35b027 !important;
|
||||
}
|
||||
|
||||
.bg-danger .dyn-dark {
|
||||
background-color: #bf202f !important; }
|
||||
background-color: #bf202f !important;
|
||||
}
|
||||
|
||||
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
|
||||
background-color: #13a00d; }
|
||||
background-color: #13a00d;
|
||||
}
|
||||
|
||||
.nav-pills A {
|
||||
color: #424242; }
|
||||
color: #424242;
|
||||
}
|
||||
|
||||
.nav-pills I {
|
||||
margin-right: 10px; }
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
/* Bootstrap Settings */
|
||||
|
@ -187,23 +231,26 @@ HTML, BODY {
|
|||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
|
||||
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
|
||||
/* Code Mirror Settings */
|
||||
font-family: monospace;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 80vh; }
|
||||
height: 80vh;
|
||||
}
|
||||
|
||||
.CodeMirror-focused {
|
||||
/* Bootstrap Settings */
|
||||
border-color: #66afe9;
|
||||
outline: 0;
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; }
|
||||
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.switch {
|
||||
font-size: 1rem;
|
||||
position: relative; }
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.switch input {
|
||||
position: absolute;
|
||||
|
@ -214,7 +261,8 @@ HTML, BODY {
|
|||
clip: rect(0 0 0 0);
|
||||
clip-path: inset(50%);
|
||||
overflow: hidden;
|
||||
padding: 0; }
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.switch input + label {
|
||||
position: relative;
|
||||
|
@ -227,23 +275,26 @@ HTML, BODY {
|
|||
outline: none;
|
||||
user-select: none;
|
||||
vertical-align: middle;
|
||||
text-indent: calc(calc(calc(2.375rem * .8) * 2) + .5rem); }
|
||||
text-indent: calc(calc(calc(2.375rem * .8) * 2) + .5rem);
|
||||
}
|
||||
|
||||
.switch input + label::before,
|
||||
.switch input + label::after {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: calc(calc(2.375rem * .8) * 2);
|
||||
bottom: 0;
|
||||
display: block; }
|
||||
display: block;
|
||||
}
|
||||
|
||||
.switch input + label::before {
|
||||
right: 0;
|
||||
background-color: #dee2e6;
|
||||
border-radius: calc(2.375rem * .8);
|
||||
transition: 0.2s all; }
|
||||
transition: 0.2s all;
|
||||
}
|
||||
|
||||
.switch input + label::after {
|
||||
top: 2px;
|
||||
|
@ -252,120 +303,154 @@ HTML, BODY {
|
|||
height: calc(calc(2.375rem * .8) - calc(2px * 2));
|
||||
border-radius: 50%;
|
||||
background-color: white;
|
||||
transition: 0.2s all; }
|
||||
transition: 0.2s all;
|
||||
}
|
||||
|
||||
.switch input:checked + label::before {
|
||||
background-color: #08d; }
|
||||
background-color: #08d;
|
||||
}
|
||||
|
||||
.switch input:checked + label::after {
|
||||
margin-left: calc(2.375rem * .8); }
|
||||
margin-left: calc(2.375rem * .8);
|
||||
}
|
||||
|
||||
.switch input:focus + label::before {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 136, 221, 0.25); }
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 136, 221, 0.25);
|
||||
}
|
||||
|
||||
.switch input:disabled + label {
|
||||
color: #868e96;
|
||||
cursor: not-allowed; }
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.switch input:disabled + label::before {
|
||||
background-color: #e9ecef; }
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.switch.switch-sm {
|
||||
font-size: 0.875rem; }
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.switch.switch-sm input + label {
|
||||
min-width: calc(calc(1.9375rem * .8) * 2);
|
||||
height: calc(1.9375rem * .8);
|
||||
line-height: calc(1.9375rem * .8);
|
||||
text-indent: calc(calc(calc(1.9375rem * .8) * 2) + .5rem); }
|
||||
text-indent: calc(calc(calc(1.9375rem * .8) * 2) + .5rem);
|
||||
}
|
||||
|
||||
.switch.switch-sm input + label::before {
|
||||
width: calc(calc(1.9375rem * .8) * 2); }
|
||||
width: calc(calc(1.9375rem * .8) * 2);
|
||||
}
|
||||
|
||||
.switch.switch-sm input + label::after {
|
||||
width: calc(calc(1.9375rem * .8) - calc(2px * 2));
|
||||
height: calc(calc(1.9375rem * .8) - calc(2px * 2)); }
|
||||
height: calc(calc(1.9375rem * .8) - calc(2px * 2));
|
||||
}
|
||||
|
||||
.switch.switch-sm input:checked + label::after {
|
||||
margin-left: calc(1.9375rem * .8); }
|
||||
margin-left: calc(1.9375rem * .8);
|
||||
}
|
||||
|
||||
.switch.switch-lg {
|
||||
font-size: 1.25rem; }
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.switch.switch-lg input + label {
|
||||
min-width: calc(calc(3rem * .8) * 2);
|
||||
height: calc(3rem * .8);
|
||||
line-height: calc(3rem * .8);
|
||||
text-indent: calc(calc(calc(3rem * .8) * 2) + .5rem); }
|
||||
text-indent: calc(calc(calc(3rem * .8) * 2) + .5rem);
|
||||
}
|
||||
|
||||
.switch.switch-lg input + label::before {
|
||||
width: calc(calc(3rem * .8) * 2); }
|
||||
width: calc(calc(3rem * .8) * 2);
|
||||
}
|
||||
|
||||
.switch.switch-lg input + label::after {
|
||||
width: calc(calc(3rem * .8) - calc(2px * 2));
|
||||
height: calc(calc(3rem * .8) - calc(2px * 2)); }
|
||||
height: calc(calc(3rem * .8) - calc(2px * 2));
|
||||
}
|
||||
|
||||
.switch.switch-lg input:checked + label::after {
|
||||
margin-left: calc(3rem * .8); }
|
||||
margin-left: calc(3rem * .8);
|
||||
}
|
||||
|
||||
.switch + .switch {
|
||||
margin-left: 1rem; }
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
@keyframes pulse_animation {
|
||||
0% {
|
||||
transform: scale(1); }
|
||||
transform: scale(1);
|
||||
}
|
||||
30% {
|
||||
transform: scale(1); }
|
||||
transform: scale(1);
|
||||
}
|
||||
40% {
|
||||
transform: scale(1.02); }
|
||||
transform: scale(1.02);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1); }
|
||||
transform: scale(1);
|
||||
}
|
||||
60% {
|
||||
transform: scale(1); }
|
||||
transform: scale(1);
|
||||
}
|
||||
70% {
|
||||
transform: scale(1.05); }
|
||||
transform: scale(1.05);
|
||||
}
|
||||
80% {
|
||||
transform: scale(1); }
|
||||
transform: scale(1);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1); } }
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
.pulse {
|
||||
animation-name: pulse_animation;
|
||||
animation-duration: 1500ms;
|
||||
transform-origin: 70% 70%;
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: linear; }
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
@keyframes glow-grow {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(1); }
|
||||
transform: scale(1);
|
||||
}
|
||||
80% {
|
||||
opacity: 1; }
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(2);
|
||||
opacity: 0; } }
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.pulse-glow {
|
||||
animation-name: glow-grown;
|
||||
animation-duration: 100ms;
|
||||
transform-origin: 70% 30%;
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: linear; }
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
.pulse-glow:before,
|
||||
.pulse-glow:after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
content: "";
|
||||
height: 0.5rem;
|
||||
width: 1.75rem;
|
||||
top: 1.2rem;
|
||||
right: 2.15rem;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 7px #47d337;
|
||||
animation: glow-grow 2s ease-out infinite; }
|
||||
animation: glow-grow 2s ease-out infinite;
|
||||
}
|
||||
|
||||
.sortable_drag {
|
||||
background-color: #0000000f; }
|
||||
background-color: #0000000f;
|
||||
}
|
||||
|
||||
.drag_icon {
|
||||
cursor: move;
|
||||
|
@ -379,106 +464,132 @@ HTML, BODY {
|
|||
margin-right: 5px;
|
||||
margin-left: -10px;
|
||||
text-align: center;
|
||||
color: #b1b1b1; }
|
||||
color: #b1b1b1;
|
||||
}
|
||||
|
||||
/* (Optional) Apply a "closed-hand" cursor during drag operation. */
|
||||
.drag_icon:active {
|
||||
cursor: grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
cursor: -webkit-grabbing; }
|
||||
cursor: -webkit-grabbing;
|
||||
}
|
||||
|
||||
.switch_btn {
|
||||
float: right;
|
||||
margin: -1px 0px 0px 0px;
|
||||
display: block; }
|
||||
display: block;
|
||||
}
|
||||
|
||||
#start_container {
|
||||
position: absolute;
|
||||
z-index: 99999;
|
||||
margin-top: 20px; }
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#end_container {
|
||||
position: absolute;
|
||||
z-index: 99999;
|
||||
margin-top: 20px;
|
||||
right: 0; }
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer; }
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.jumbotron {
|
||||
background-color: white; }
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
HTML, BODY {
|
||||
background-color: #fcfcfc; }
|
||||
background-color: #fcfcfc;
|
||||
}
|
||||
|
||||
.sm-container {
|
||||
margin-top: 0px !important;
|
||||
padding: 0 !important; }
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.list-group-item H5 {
|
||||
font-size: 0.9rem; }
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 0px !important;
|
||||
padding-top: 15px !important; }
|
||||
padding-top: 15px !important;
|
||||
}
|
||||
|
||||
.group_header {
|
||||
margin-left: 15px; }
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
margin-left: 0px;
|
||||
margin-top: 0px;
|
||||
width: 100%;
|
||||
margin-bottom: 0; }
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
line-height: 0.9rem;
|
||||
font-size: 0.65rem; }
|
||||
font-size: 0.65rem;
|
||||
}
|
||||
|
||||
.full-col-12 {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px; }
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.card {
|
||||
border: 0;
|
||||
border-radius: 0rem;
|
||||
padding: 0;
|
||||
background-color: #ffffff; }
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
font-size: 10pt;
|
||||
padding: 0px 10px; }
|
||||
padding: 0px 10px;
|
||||
}
|
||||
|
||||
.lg_number {
|
||||
font-size: 7.8vw; }
|
||||
font-size: 7.8vw;
|
||||
}
|
||||
|
||||
.stats_area {
|
||||
margin-top: 1.5rem !important;
|
||||
margin-bottom: 1.5rem !important; }
|
||||
margin-bottom: 1.5rem !important;
|
||||
}
|
||||
|
||||
.stats_area .col-4 {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
font-size: 0.6rem; }
|
||||
font-size: 0.6rem;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
border-top: 1px solid #e4e4e4;
|
||||
border: 0px; }
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.list-group-item:first-child {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-item:last-child {
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 0; }
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-item P {
|
||||
font-size: 0.7rem; }
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.service-chart-container {
|
||||
height: 200px; } }
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=base.css.map */
|
||||
|
|
|
@ -40,8 +40,8 @@ func TestCore_UsingAssets(t *testing.T) {
|
|||
func TestCreateAssets(t *testing.T) {
|
||||
assert.Nil(t, CreateAllAssets(dir))
|
||||
assert.True(t, UsingAssets(dir))
|
||||
assert.FileExists(t, "../assets/css/base.css")
|
||||
assert.FileExists(t, "../assets/scss/base.scss")
|
||||
assert.FileExists(t, "./assets/css/base.css")
|
||||
assert.FileExists(t, "./assets/scss/base.scss")
|
||||
}
|
||||
|
||||
func TestCompileSASS(t *testing.T) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2019-01-10 12:48:42.676069 -0800 PST m=+0.785435129
|
||||
// 2019-01-14 17:21:53.045328 -0800 PST m=+0.787121391
|
||||
//
|
||||
// This contains the most recently Markdown source for the Statping Wiki.
|
||||
package source
|
||||
|
|
|
@ -31,11 +31,7 @@ func TestCreateLog(t *testing.T) {
|
|||
|
||||
func TestInitLogs(t *testing.T) {
|
||||
assert.Nil(t, InitLogs())
|
||||
assert.FileExists(t, "../logs/statup.log")
|
||||
}
|
||||
|
||||
func TestFileExists(t *testing.T) {
|
||||
assert.True(t, FileExists("../logs/statup.log"))
|
||||
assert.FileExists(t, "./logs/statup.log")
|
||||
}
|
||||
|
||||
func TestDir(t *testing.T) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.80.36
|
||||
0.80.37
|
||||
|
|
Loading…
Reference in New Issue