mirror of https://github.com/statping/statping
notifier on success after failure - service downtime readable
parent
8dbf573667
commit
e3c572da75
2
Makefile
2
Makefile
|
@ -1,4 +1,4 @@
|
|||
VERSION=0.64
|
||||
VERSION=0.65
|
||||
BINARY_NAME=statup
|
||||
GOPATH:=$(GOPATH)
|
||||
GOCMD=go
|
||||
|
|
|
@ -58,6 +58,7 @@ type Notification struct {
|
|||
Queue []interface{} `gorm:"-" json:"-"`
|
||||
Running chan bool `gorm:"-" json:"-"`
|
||||
CanTest bool `gorm:"-" json:"-"`
|
||||
Online bool `gorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
type NotificationForm struct {
|
||||
|
|
|
@ -232,9 +232,7 @@ func TestRunAllQueueAndStop(t *testing.T) {
|
|||
assert.Equal(t, 16, len(example.Queue))
|
||||
go Queue(example)
|
||||
assert.Equal(t, 16, len(example.Queue))
|
||||
time.Sleep(13 * time.Second)
|
||||
assert.Equal(t, 6, len(example.Queue))
|
||||
time.Sleep(1 * time.Second)
|
||||
time.Sleep(15 * time.Second)
|
||||
assert.Equal(t, 6, len(example.Queue))
|
||||
example.close()
|
||||
assert.False(t, example.IsRunning())
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*
|
||||
* Statup
|
||||
* Copyright (C) 2018. Hunter Long and the project contributors
|
||||
* Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
*
|
||||
* https://github.com/hunterlong/statup
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
context('Setup Process', () => {
|
||||
|
||||
// it('should go to setup Statup with Postgres', () => {
|
||||
|
@ -45,4 +62,4 @@ context('Setup Process', () => {
|
|||
cy.get('.card').should('have.length', 5)
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*
|
||||
* Statup
|
||||
* Copyright (C) 2018. Hunter Long and the project contributors
|
||||
* Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
*
|
||||
* https://github.com/hunterlong/statup
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
context('Asset Tests', () => {
|
||||
|
||||
beforeEach(function () {
|
||||
|
@ -36,4 +53,4 @@ context('Asset Tests', () => {
|
|||
cy.request('http://localhost:8080/css/base.css').its('body').should('contain', 'BODY')
|
||||
})
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*
|
||||
* Statup
|
||||
* Copyright (C) 2018. Hunter Long and the project contributors
|
||||
* Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
*
|
||||
* https://github.com/hunterlong/statup
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
context('Dashboard Tests', () => {
|
||||
|
||||
beforeEach(function() {
|
||||
|
@ -21,4 +38,4 @@ context('Dashboard Tests', () => {
|
|||
cy.get('.col-12 > :nth-child(1)').should('contain', 'Statup')
|
||||
})
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*
|
||||
* Statup
|
||||
* Copyright (C) 2018. Hunter Long and the project contributors
|
||||
* Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
*
|
||||
* https://github.com/hunterlong/statup
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
context('Service Tests', () => {
|
||||
|
||||
beforeEach(function () {
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*
|
||||
* Statup
|
||||
* Copyright (C) 2018. Hunter Long and the project contributors
|
||||
* Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
*
|
||||
* https://github.com/hunterlong/statup
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
context('Settings Forms', () => {
|
||||
|
||||
beforeEach(function() {
|
||||
|
@ -28,4 +45,4 @@ context('Settings Forms', () => {
|
|||
// cy.get('.header-desc').should('contain', 'This is an awesome page')
|
||||
// })
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*
|
||||
* Statup
|
||||
* Copyright (C) 2018. Hunter Long and the project contributors
|
||||
* Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
*
|
||||
* https://github.com/hunterlong/statup
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
context('User Testing', () => {
|
||||
|
||||
beforeEach(function () {
|
||||
|
@ -49,4 +66,4 @@ context('User Testing', () => {
|
|||
cy.get('tr').should('have.length', 2)
|
||||
})
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*
|
||||
* Statup
|
||||
* Copyright (C) 2018. Hunter Long and the project contributors
|
||||
* Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
*
|
||||
* https://github.com/hunterlong/statup
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*
|
||||
* Statup
|
||||
* Copyright (C) 2018. Hunter Long and the project contributors
|
||||
* Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
*
|
||||
* https://github.com/hunterlong/statup
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*
|
||||
* Statup
|
||||
* Copyright (C) 2018. Hunter Long and the project contributors
|
||||
* Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
*
|
||||
* https://github.com/hunterlong/statup
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
|
|
|
@ -32,32 +32,27 @@ type Service struct {
|
|||
}
|
||||
|
||||
func renderServiceChartHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !IsAuthenticated(r) {
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
vars := mux.Vars(r)
|
||||
fields := parseGet(r)
|
||||
w.Header().Set("Content-Type", "text/javascript")
|
||||
w.Header().Set("Cache-Control", "max-age=30")
|
||||
|
||||
startField := fields.Get("start")
|
||||
endField := fields.Get("end")
|
||||
var start time.Time
|
||||
var end time.Time
|
||||
if startField == "" {
|
||||
start = time.Now().Add(-24 * time.Hour)
|
||||
start = time.Now().Add(-24 * time.Hour).UTC()
|
||||
} else {
|
||||
start = time.Unix(utils.StringInt(startField), 0)
|
||||
start = time.Unix(utils.StringInt(startField), 0).UTC()
|
||||
}
|
||||
if endField == "" {
|
||||
end = time.Now()
|
||||
end = time.Now().UTC()
|
||||
} else {
|
||||
end = time.Unix(utils.StringInt(endField), 0)
|
||||
end = time.Unix(utils.StringInt(endField), 0).UTC()
|
||||
}
|
||||
|
||||
service := core.SelectService(utils.StringInt(vars["id"]))
|
||||
w.Header().Set("Content-Type", "text/javascript")
|
||||
w.Header().Set("Cache-Control", "max-age=60")
|
||||
|
||||
data := core.GraphDataRaw(service, start, end).ToString()
|
||||
|
||||
out := struct {
|
||||
|
|
|
@ -54,8 +54,8 @@ func init() {
|
|||
|
||||
// Send will send a HTTP Post to the Discord API. It accepts type: []byte
|
||||
func (u *Discord) Send(msg interface{}) error {
|
||||
message := msg.([]byte)
|
||||
req, _ := http.NewRequest("POST", discorder.GetValue("host"), bytes.NewBuffer(message))
|
||||
message := msg.(string)
|
||||
req, _ := http.NewRequest("POST", discorder.GetValue("host"), bytes.NewBuffer([]byte(message)))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
|
@ -73,11 +73,16 @@ func (u *Discord) Select() *notifier.Notification {
|
|||
func (u *Discord) OnFailure(s *types.Service, f *types.Failure) {
|
||||
msg := fmt.Sprintf(`{"content": "Your service '%v' is currently failing! Reason: %v"}`, s.Name, f.Issue)
|
||||
u.AddQueue(msg)
|
||||
u.Online = false
|
||||
}
|
||||
|
||||
// OnSuccess will trigger successful service
|
||||
func (u *Discord) OnSuccess(s *types.Service) {
|
||||
|
||||
if !u.Online {
|
||||
msg := fmt.Sprintf(`{"content": "Your service '%v' is back online!"}`, s.Name)
|
||||
u.AddQueue(msg)
|
||||
}
|
||||
u.Online = true
|
||||
}
|
||||
|
||||
// OnSave triggers when this notifier has been saved
|
||||
|
|
|
@ -60,8 +60,31 @@ func TestDiscordNotifier(t *testing.T) {
|
|||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("Discord OnFailure", func(t *testing.T) {
|
||||
discorder.OnFailure(TestService, TestFailure)
|
||||
assert.Len(t, discorder.Queue, 1)
|
||||
})
|
||||
|
||||
t.Run("Discord Check Offline", func(t *testing.T) {
|
||||
assert.False(t, discorder.Online)
|
||||
})
|
||||
|
||||
t.Run("Discord OnSuccess", func(t *testing.T) {
|
||||
discorder.OnSuccess(TestService)
|
||||
assert.Len(t, discorder.Queue, 2)
|
||||
})
|
||||
|
||||
t.Run("Discord Check Back Online", func(t *testing.T) {
|
||||
assert.True(t, discorder.Online)
|
||||
})
|
||||
|
||||
t.Run("Discord OnSuccess Again", func(t *testing.T) {
|
||||
discorder.OnSuccess(TestService)
|
||||
assert.Len(t, discorder.Queue, 2)
|
||||
})
|
||||
|
||||
t.Run("Discord Send", func(t *testing.T) {
|
||||
err := discorder.Send([]byte(discordMessage))
|
||||
err := discorder.Send(discordMessage)
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -97,11 +97,34 @@ func TestEmailNotifier(t *testing.T) {
|
|||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("Emailer Test Source", func(t *testing.T) {
|
||||
t.Run("Email Test Source", func(t *testing.T) {
|
||||
emailSource(testEmail)
|
||||
assert.NotEmpty(t, testEmail.Source)
|
||||
})
|
||||
|
||||
t.Run("Email OnFailure", func(t *testing.T) {
|
||||
emailer.OnFailure(TestService, TestFailure)
|
||||
assert.Len(t, emailer.Queue, 1)
|
||||
})
|
||||
|
||||
t.Run("Email Check Offline", func(t *testing.T) {
|
||||
assert.False(t, emailer.Online)
|
||||
})
|
||||
|
||||
t.Run("Email OnSuccess", func(t *testing.T) {
|
||||
emailer.OnSuccess(TestService)
|
||||
assert.Len(t, emailer.Queue, 2)
|
||||
})
|
||||
|
||||
t.Run("Email Check Back Online", func(t *testing.T) {
|
||||
assert.True(t, emailer.Online)
|
||||
})
|
||||
|
||||
t.Run("Email OnSuccess Again", func(t *testing.T) {
|
||||
emailer.OnSuccess(TestService)
|
||||
assert.Len(t, emailer.Queue, 2)
|
||||
})
|
||||
|
||||
t.Run("Email Send", func(t *testing.T) {
|
||||
err := emailer.Send(testEmail)
|
||||
assert.Nil(t, err)
|
||||
|
|
|
@ -80,11 +80,16 @@ func (u *LineNotify) Select() *notifier.Notification {
|
|||
func (u *LineNotify) OnFailure(s *types.Service, f *types.Failure) {
|
||||
msg := fmt.Sprintf("Your service '%v' is currently offline!", s.Name)
|
||||
u.AddQueue(msg)
|
||||
u.Online = false
|
||||
}
|
||||
|
||||
// OnSuccess will trigger successful service
|
||||
func (u *LineNotify) OnSuccess(s *types.Service) {
|
||||
|
||||
if !u.Online {
|
||||
msg := fmt.Sprintf("Your service '%v' is back online!", s.Name)
|
||||
u.AddQueue(msg)
|
||||
}
|
||||
u.Online = true
|
||||
}
|
||||
|
||||
// OnSave triggers when this notifier has been saved
|
||||
|
|
|
@ -27,11 +27,10 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
SLACK_ID = 2
|
||||
SLACK_METHOD = "slack"
|
||||
FAILING_TEMPLATE = `{ "attachments": [ { "fallback": "Service {{.Service.Name}} - is currently failing", "text": "<{{.Service.Domain}}|{{.Service.Name}}> - Your Statup service '{{.Service.Name}}' has just received a Failure notification with a HTTP Status code of {{.Service.LastStatusCode}}.", "fields": [ { "title": "Expected", "value": "{{.Service.Expected}}", "short": true }, { "title": "Status Code", "value": "{{.Service.LastStatusCode}}", "short": true } ], "color": "#FF0000", "thumb_url": "https://statup.io", "footer": "Statup", "footer_icon": "https://img.cjx.io/statuplogo32.png" } ] }`
|
||||
SUCCESS_TEMPLATE = `{ "attachments": [ { "fallback": "Service {{.Service.Name}} - is now back online", "text": "<{{.Service.Domain}}|{{.Service.Name}}> - Your Statup service '{{.Service.Name}}' has just received a Failure notification.", "fields": [ { "title": "Issue", "value": "Awesome Project", "short": true }, { "title": "Status Code", "value": "{{.Service.LastStatusCode}}", "short": true } ], "color": "#00FF00", "thumb_url": "https://statup.io", "footer": "Statup", "footer_icon": "https://img.cjx.io/statuplogo32.png" } ] }`
|
||||
TEST_TEMPLATE = `{"text":"{{.}}"}`
|
||||
SLACK_TEXT = `{"text":"{{.}}"}`
|
||||
)
|
||||
|
||||
type Slack struct {
|
||||
|
@ -91,7 +90,6 @@ func (u *Slack) Send(msg interface{}) error {
|
|||
}
|
||||
defer res.Body.Close()
|
||||
//contents, _ := ioutil.ReadAll(res.Body)
|
||||
//fmt.Println(string(contents))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -102,7 +100,7 @@ func (u *Slack) Select() *notifier.Notification {
|
|||
func (u *Slack) OnTest(n notifier.Notification) (bool, error) {
|
||||
utils.Log(1, "Slack notifier loaded")
|
||||
msg := fmt.Sprintf("You're Statup Slack Notifier is working correctly!")
|
||||
err := parseSlackMessage(TEST_TEMPLATE, msg)
|
||||
err := parseSlackMessage(SLACK_TEXT, msg)
|
||||
return true, err
|
||||
}
|
||||
|
||||
|
@ -110,15 +108,24 @@ func (u *Slack) OnTest(n notifier.Notification) (bool, error) {
|
|||
func (u *Slack) OnFailure(s *types.Service, f *types.Failure) {
|
||||
message := SlackMessage{
|
||||
Service: s,
|
||||
Template: FAILURE,
|
||||
Template: FAILING_TEMPLATE,
|
||||
Time: time.Now().Unix(),
|
||||
}
|
||||
parseSlackMessage(FAILING_TEMPLATE, message)
|
||||
u.Online = false
|
||||
}
|
||||
|
||||
// OnSuccess will trigger successful service
|
||||
func (u *Slack) OnSuccess(s *types.Service) {
|
||||
|
||||
if !u.Online {
|
||||
message := SlackMessage{
|
||||
Service: s,
|
||||
Template: SUCCESS_TEMPLATE,
|
||||
Time: time.Now().Unix(),
|
||||
}
|
||||
parseSlackMessage(SUCCESS_TEMPLATE, message)
|
||||
}
|
||||
u.Online = true
|
||||
}
|
||||
|
||||
// OnSave triggers when this notifier has been saved
|
||||
|
|
|
@ -40,6 +40,8 @@ func init() {
|
|||
|
||||
func TestSlackNotifier(t *testing.T) {
|
||||
t.Parallel()
|
||||
SLACK_URL = os.Getenv("SLACK_URL")
|
||||
slacker.Host = SLACK_URL
|
||||
if SLACK_URL == "" {
|
||||
t.Log("Slack notifier testing skipped, missing SLACK_URL environment variable")
|
||||
t.SkipNow()
|
||||
|
@ -60,7 +62,7 @@ func TestSlackNotifier(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Slack parse message", func(t *testing.T) {
|
||||
err := parseSlackMessage("this is a test message!", slackTestMessage)
|
||||
err := parseSlackMessage(SLACK_TEXT, "this is a test!")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 1, len(slacker.Queue))
|
||||
})
|
||||
|
@ -71,14 +73,38 @@ func TestSlackNotifier(t *testing.T) {
|
|||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("Slack OnFailure", func(t *testing.T) {
|
||||
slacker.OnFailure(TestService, TestFailure)
|
||||
assert.Len(t, slacker.Queue, 2)
|
||||
})
|
||||
|
||||
t.Run("Slack Check Offline", func(t *testing.T) {
|
||||
assert.False(t, slacker.Online)
|
||||
})
|
||||
|
||||
t.Run("Slack OnSuccess", func(t *testing.T) {
|
||||
slacker.OnSuccess(TestService)
|
||||
assert.Len(t, slacker.Queue, 3)
|
||||
})
|
||||
|
||||
t.Run("Slack Check Back Online", func(t *testing.T) {
|
||||
assert.True(t, slacker.Online)
|
||||
})
|
||||
|
||||
t.Run("Slack OnSuccess Again", func(t *testing.T) {
|
||||
slacker.OnSuccess(TestService)
|
||||
assert.Len(t, slacker.Queue, 3)
|
||||
})
|
||||
|
||||
t.Run("Slack Send", func(t *testing.T) {
|
||||
err := slacker.Send(slackMessage)
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, slacker.Queue, 3)
|
||||
})
|
||||
|
||||
t.Run("Slack Queue", func(t *testing.T) {
|
||||
go notifier.Queue(slacker)
|
||||
time.Sleep(1 * time.Second)
|
||||
time.Sleep(2 * time.Second)
|
||||
assert.Equal(t, SLACK_URL, slacker.Host)
|
||||
assert.Equal(t, 0, len(slacker.Queue))
|
||||
})
|
||||
|
|
|
@ -28,7 +28,7 @@ var (
|
|||
TWILIO_SECRET = os.Getenv("TWILIO_SECRET")
|
||||
TWILIO_FROM = os.Getenv("TWILIO_FROM")
|
||||
TWILIO_TO = os.Getenv("TWILIO_TO")
|
||||
twilioMessage = "The twilioNotifier notifier on Statup has been tested!"
|
||||
twilioMessage = "The Twilio notifier on Statup has been tested!"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -70,6 +70,29 @@ func TestTwilioNotifier(t *testing.T) {
|
|||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("Twilio OnFailure", func(t *testing.T) {
|
||||
twilioNotifier.OnFailure(TestService, TestFailure)
|
||||
assert.Len(t, twilioNotifier.Queue, 2)
|
||||
})
|
||||
|
||||
t.Run("Twilio Check Offline", func(t *testing.T) {
|
||||
assert.False(t, twilioNotifier.Online)
|
||||
})
|
||||
|
||||
t.Run("Twilio OnSuccess", func(t *testing.T) {
|
||||
twilioNotifier.OnSuccess(TestService)
|
||||
assert.Len(t, twilioNotifier.Queue, 3)
|
||||
})
|
||||
|
||||
t.Run("Twilio Check Back Online", func(t *testing.T) {
|
||||
assert.True(t, twilioNotifier.Online)
|
||||
})
|
||||
|
||||
t.Run("Twilio OnSuccess Again", func(t *testing.T) {
|
||||
twilioNotifier.OnSuccess(TestService)
|
||||
assert.Len(t, twilioNotifier.Queue, 3)
|
||||
})
|
||||
|
||||
t.Run("Twilio Send", func(t *testing.T) {
|
||||
err := twilioNotifier.Send(twilioMessage)
|
||||
assert.Nil(t, err)
|
||||
|
|
|
@ -193,7 +193,7 @@ func copyAndCapture(w io.Writer, r io.Reader) ([]byte, error) {
|
|||
|
||||
func DurationReadable(d time.Duration) string {
|
||||
if d.Hours() >= 1 {
|
||||
return fmt.Sprintf("%0.0f hours and %0.0f minutes", d.Hours(), d.Minutes())
|
||||
return fmt.Sprintf("%0.0f hours", d.Hours())
|
||||
} else if d.Minutes() >= 1 {
|
||||
return fmt.Sprintf("%0.0f minutes", d.Minutes())
|
||||
} else if d.Seconds() >= 1 {
|
||||
|
|
Loading…
Reference in New Issue