package statuscake import ( "bytes" "encoding/json" "io/ioutil" "log" "net/http" "net/url" "os" "path/filepath" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestTest_Validate(t *testing.T) { assert := assert.New(t) require := require.New(t) test := &Test{ Timeout: 200, Confirmation: 100, Public: 200, Virus: 200, TestType: "FTP", RealBrowser: 100, TriggerRate: 100, CheckRate: 100000, CustomHeader: "here be dragons", WebsiteName: "", WebsiteURL: "", } err := test.Validate() require.NotNil(err) message := err.Error() assert.Contains(message, "WebsiteName is required") assert.Contains(message, "WebsiteURL is required") assert.Contains(message, "Timeout must be 0 or between 6 and 99") assert.Contains(message, "Confirmation must be between 0 and 9") assert.Contains(message, "CheckRate must be between 0 and 23999") assert.Contains(message, "Public must be 0 or 1") assert.Contains(message, "Virus must be 0 or 1") assert.Contains(message, "TestType must be HTTP, TCP, or PING") assert.Contains(message, "RealBrowser must be 0 or 1") assert.Contains(message, "TriggerRate must be between 0 and 59") assert.Contains(message, "CustomHeader must be provided as json string") test.Timeout = 10 test.Confirmation = 2 test.Public = 1 test.Virus = 1 test.TestType = "HTTP" test.RealBrowser = 1 test.TriggerRate = 50 test.CheckRate = 10 test.WebsiteName = "Foo" test.WebsiteURL = "http://example.com" test.CustomHeader = `{"test": 15}` test.NodeLocations = []string{"foo", "bar"} err = test.Validate() assert.Nil(err) } func TestTest_ToURLValues(t *testing.T) { assert := assert.New(t) test := &Test{ TestID: 123, Paused: true, WebsiteName: "Foo Bar", CustomHeader: `{"some":{"json": ["value"]}}`, WebsiteURL: "http://example.com", Port: 3000, NodeLocations: []string{"foo", "bar"}, Timeout: 11, PingURL: "http://example.com/ping", Confirmation: 1, CheckRate: 500, BasicUser: "myuser", BasicPass: "mypass", Public: 1, LogoImage: "http://example.com/logo.jpg", Branding: 1, WebsiteHost: "hoster", Virus: 1, FindString: "hello", DoNotFind: true, TestType: "HTTP", RealBrowser: 1, TriggerRate: 50, TestTags: []string{"tag1", "tag2"}, StatusCodes: "500", EnableSSLAlert: false, FollowRedirect: false, } expected := url.Values{ "TestID": {"123"}, "Paused": {"1"}, "WebsiteName": {"Foo Bar"}, "WebsiteURL": {"http://example.com"}, "CustomHeader": {`{"some":{"json": ["value"]}}`}, "Port": {"3000"}, "NodeLocations": {"foo,bar"}, "Timeout": {"11"}, "PingURL": {"http://example.com/ping"}, "ContactGroup": {""}, "Confirmation": {"1"}, "CheckRate": {"500"}, "BasicUser": {"myuser"}, "BasicPass": {"mypass"}, "Public": {"1"}, "LogoImage": {"http://example.com/logo.jpg"}, "Branding": {"1"}, "WebsiteHost": {"hoster"}, "Virus": {"1"}, "FindString": {"hello"}, "DoNotFind": {"1"}, "TestType": {"HTTP"}, "RealBrowser": {"1"}, "TriggerRate": {"50"}, "TestTags": {"tag1,tag2"}, "StatusCodes": {"500"}, "UseJar": {"0"}, "PostRaw": {""}, "FinalEndpoint": {""}, "EnableSSLAlert": {"0"}, "FollowRedirect": {"0"}, } assert.Equal(expected, test.ToURLValues()) test.TestID = 0 delete(expected, "TestID") assert.Equal(expected.Encode(), test.ToURLValues().Encode()) } func TestTests_All(t *testing.T) { assert := assert.New(t) require := require.New(t) c := &fakeAPIClient{ fixture: "tests_all_ok.json", } tt := newTests(c) tests, err := tt.All() require.Nil(err) assert.Equal("/Tests", c.sentRequestPath) assert.Equal("GET", c.sentRequestMethod) assert.Nil(c.sentRequestValues) assert.Len(tests, 2) expectedTest := &Test{ TestID: 100, Paused: false, TestType: "HTTP", WebsiteName: "www 1", ContactGroup: []string{"1"}, Status: "Up", Uptime: 100, NodeLocations: []string{"foo", "bar"}, } assert.Equal(expectedTest, tests[0]) expectedTest = &Test{ TestID: 101, Paused: true, TestType: "HTTP", WebsiteName: "www 2", ContactGroup: []string{"2"}, Status: "Down", Uptime: 0, NodeLocations: []string{"foo"}, TestTags: []string{"test1", "test2"}, } assert.Equal(expectedTest, tests[1]) } func TestTests_AllWithFilter(t *testing.T) { assert := assert.New(t) require := require.New(t) c := &fakeAPIClient{ fixture: "tests_all_ok.json", } v := url.Values{} v.Set("tags", "test1,test2") tt := newTests(c) tests, err := tt.AllWithFilter(v) require.Nil(err) assert.Equal("/Tests", c.sentRequestPath) assert.Equal("GET", c.sentRequestMethod) assert.NotNil(c.sentRequestValues) assert.Len(tests, 1) expectedTest := &Test{ TestID: 101, Paused: true, TestType: "HTTP", WebsiteName: "www 2", ContactGroup: []string{"2"}, Status: "Down", Uptime: 0, NodeLocations: []string{"foo"}, TestTags: []string{"test1", "test2"}, } assert.Equal(expectedTest, tests[0]) } func TestTests_Update_OK(t *testing.T) { assert := assert.New(t) require := require.New(t) c := &fakeAPIClient{ fixture: "tests_update_ok.json", } tt := newTests(c) test1 := &Test{ WebsiteName: "foo", } test2, err := tt.Update(test1) require.Nil(err) assert.Equal("/Tests/Update", c.sentRequestPath) assert.Equal("PUT", c.sentRequestMethod) assert.NotNil(c.sentRequestValues) assert.NotNil(test2) assert.Equal(1234, test2.TestID) } func TestTests_Update_Error(t *testing.T) { assert := assert.New(t) require := require.New(t) c := &fakeAPIClient{ fixture: "tests_update_error.json", } tt := newTests(c) test1 := &Test{ WebsiteName: "foo", } test2, err := tt.Update(test1) assert.Nil(test2) require.NotNil(err) assert.IsType(&updateError{}, err) assert.Contains(err.Error(), "issue a") } func TestTests_Update_ErrorWithSliceOfIssues(t *testing.T) { assert := assert.New(t) require := require.New(t) c := &fakeAPIClient{ fixture: "tests_update_error_slice_of_issues.json", } tt := newTests(c) test1 := &Test{ WebsiteName: "foo", } test2, err := tt.Update(test1) assert.Nil(test2) require.NotNil(err) assert.IsType(&updateError{}, err) assert.Equal("Required Data is Missing., hello, world", err.Error()) } func TestTests_Delete_OK(t *testing.T) { assert := assert.New(t) require := require.New(t) c := &fakeAPIClient{ fixture: "tests_delete_ok.json", } tt := newTests(c) err := tt.Delete(1234) require.Nil(err) assert.Equal("/Tests/Details", c.sentRequestPath) assert.Equal("DELETE", c.sentRequestMethod) assert.Equal(url.Values{"TestID": {"1234"}}, c.sentRequestValues) } func TestTests_Delete_Error(t *testing.T) { assert := assert.New(t) require := require.New(t) c := &fakeAPIClient{ fixture: "tests_delete_error.json", } tt := newTests(c) err := tt.Delete(1234) require.NotNil(err) assert.Equal("this is an error", err.Error()) } func TestTests_Detail_OK(t *testing.T) { assert := assert.New(t) require := require.New(t) c := &fakeAPIClient{ fixture: "tests_detail_ok.json", } tt := newTests(c) test, err := tt.Detail(1234) require.Nil(err) assert.Equal("/Tests/Details", c.sentRequestPath) assert.Equal("GET", c.sentRequestMethod) assert.Equal(url.Values{"TestID": {"1234"}}, c.sentRequestValues) assert.Equal(test.TestID, 6735) assert.Equal(test.TestType, "HTTP") assert.Equal(test.Paused, false) assert.Equal(test.WebsiteName, "NL") assert.Equal(test.CustomHeader, `{"some":{"json": ["value"]}}`) assert.Equal(test.UserAgent, "product/version (comment)") assert.Equal(test.ContactGroup, []string{"536"}) assert.Equal(test.Status, "Up") assert.Equal(test.Uptime, 0.0) assert.Equal(test.CheckRate, 60) assert.Equal(test.Timeout, 40) assert.Equal(test.LogoImage, "") assert.Equal(test.WebsiteHost, "Various") assert.Equal(test.FindString, "") assert.Equal(test.DoNotFind, false) assert.Equal(test.NodeLocations, []string{"foo", "bar"}) } type fakeAPIClient struct { sentRequestPath string sentRequestMethod string sentRequestValues url.Values fixture string } func (c *fakeAPIClient) put(path string, v url.Values) (*http.Response, error) { return c.all("PUT", path, v) } func (c *fakeAPIClient) delete(path string, v url.Values) (*http.Response, error) { return c.all("DELETE", path, v) } func (c *fakeAPIClient) get(path string, v url.Values) (*http.Response, error) { return c.all("GET", path, v) } func (c *fakeAPIClient) all(method string, path string, v url.Values) (*http.Response, error) { c.sentRequestMethod = method c.sentRequestPath = path c.sentRequestValues = v p := filepath.Join("fixtures", c.fixture) f, err := os.Open(p) if err != nil { log.Fatal(err) } var resp *http.Response if len(c.sentRequestValues.Get("tags")) > 0 { var storedResponses []Test var returnResponses []Test byteValue, _ := ioutil.ReadAll(f) json.Unmarshal(byteValue, &storedResponses) requestedTags := strings.Split(c.sentRequestValues.Get("tags"), ",") for _, storedResponse := range storedResponses { if len(requestedTags) > len(storedResponse.TestTags) { // if we are requesting more tags than whats stored then there are no matches continue } match := true for i, tag := range requestedTags { if tag != storedResponse.TestTags[i] { match = false } } if match { // we can add it to the response now returnResponses = append(returnResponses, storedResponse) } } if len(returnResponses) == 0 { return nil, nil } newByteValue, _ := json.Marshal(&returnResponses) resp = &http.Response{ Body: ioutil.NopCloser(bytes.NewBuffer(newByteValue)), } } else { resp = &http.Response{ Body: f, } } return resp, nil }