-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add some unit tests #92
Merged
negasus
merged 3 commits into
go-telegram:main
from
renatosaksanni:feature/add-some-unit-tests
Jul 18, 2024
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package bot | ||
|
||
import ( | ||
"errors" | ||
"testing" | ||
) | ||
|
||
func TestTooManyRequestsError(t *testing.T) { | ||
err := &TooManyRequestsError{ | ||
Message: "rate limit exceeded", | ||
RetryAfter: 30, | ||
} | ||
|
||
expectedErrorMsg := "rate limit exceeded: retry_after 30" | ||
if err.Error() != expectedErrorMsg { | ||
t.Errorf("expected %s, got %s", expectedErrorMsg, err.Error()) | ||
} | ||
|
||
if !IsTooManyRequestsError(err) { | ||
t.Errorf("expected IsTooManyRequestsError to return true") | ||
} | ||
|
||
var genericError error = err | ||
if !IsTooManyRequestsError(genericError) { | ||
t.Errorf("expected IsTooManyRequestsError to return true for generic error type") | ||
} | ||
} | ||
|
||
func TestMigrateError(t *testing.T) { | ||
err := &MigrateError{ | ||
Message: "chat migrated", | ||
MigrateToChatID: 12345, | ||
} | ||
|
||
expectedErrorMsg := "chat migrated: migrate_to_chat_id 12345" | ||
if err.Error() != expectedErrorMsg { | ||
t.Errorf("expected %s, got %s", expectedErrorMsg, err.Error()) | ||
} | ||
|
||
if !IsMigrateError(err) { | ||
t.Errorf("expected IsMigrateError to return true") | ||
} | ||
|
||
var genericError error = err | ||
if !IsMigrateError(genericError) { | ||
t.Errorf("expected IsMigrateError to return true for generic error type") | ||
} | ||
} | ||
|
||
func TestStandardErrors(t *testing.T) { | ||
tests := []struct { | ||
err error | ||
expected string | ||
}{ | ||
{ErrorForbidden, "forbidden"}, | ||
{ErrorBadRequest, "bad request"}, | ||
{ErrorUnauthorized, "unauthorized"}, | ||
{ErrorTooManyRequests, "too many requests"}, | ||
{ErrorNotFound, "not found"}, | ||
{ErrorConflict, "conflict"}, | ||
} | ||
|
||
for _, tt := range tests { | ||
if tt.err.Error() != tt.expected { | ||
t.Errorf("expected %s, got %s", tt.expected, tt.err.Error()) | ||
} | ||
} | ||
} | ||
|
||
func TestIsTooManyRequestsErrorFalse(t *testing.T) { | ||
err := errors.New("some other error") | ||
if IsTooManyRequestsError(err) { | ||
t.Errorf("expected IsTooManyRequestsError to return false") | ||
} | ||
} | ||
|
||
func TestIsMigrateErrorFalse(t *testing.T) { | ||
err := errors.New("some other error") | ||
if IsMigrateError(err) { | ||
t.Errorf("expected IsMigrateError to return false") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package bot | ||
|
||
import ( | ||
"context" | ||
"sync" | ||
"testing" | ||
|
||
"github.com/go-telegram/bot/models" | ||
) | ||
|
||
func Test_applyMiddlewares(t *testing.T) { | ||
h := func(ctx context.Context, bot *Bot, update *models.Update) {} | ||
|
||
middleware1 := func(next HandlerFunc) HandlerFunc { | ||
return func(ctx context.Context, bot *Bot, update *models.Update) { | ||
next(ctx, bot, update) | ||
} | ||
} | ||
|
||
middleware2 := func(next HandlerFunc) HandlerFunc { | ||
return func(ctx context.Context, bot *Bot, update *models.Update) { | ||
next(ctx, bot, update) | ||
} | ||
} | ||
|
||
wrapped := applyMiddlewares(h, middleware1, middleware2) | ||
if wrapped == nil { | ||
t.Fatal("Expected wrapped handler to be non-nil") | ||
} | ||
} | ||
|
||
func TestProcessUpdate(t *testing.T) { | ||
var called bool | ||
h := func(ctx context.Context, bot *Bot, update *models.Update) { | ||
called = true | ||
} | ||
|
||
bot := &Bot{ | ||
defaultHandlerFunc: h, | ||
middlewares: []Middleware{}, | ||
handlersMx: &sync.RWMutex{}, | ||
handlers: map[string]handler{}, | ||
} | ||
|
||
ctx := context.Background() | ||
upd := &models.Update{Message: &models.Message{Text: "test"}} | ||
|
||
bot.ProcessUpdate(ctx, upd) | ||
if !called { | ||
t.Fatal("Expected default handler to be called") | ||
} | ||
} | ||
|
||
func TestProcessUpdate_WithMiddlewares(t *testing.T) { | ||
var called bool | ||
h := func(ctx context.Context, bot *Bot, update *models.Update) { | ||
called = true | ||
} | ||
|
||
middleware := func(next HandlerFunc) HandlerFunc { | ||
return func(ctx context.Context, bot *Bot, update *models.Update) { | ||
next(ctx, bot, update) | ||
} | ||
} | ||
|
||
bot := &Bot{ | ||
defaultHandlerFunc: h, | ||
middlewares: []Middleware{middleware}, | ||
handlersMx: &sync.RWMutex{}, | ||
handlers: map[string]handler{}, | ||
} | ||
|
||
ctx := context.Background() | ||
upd := &models.Update{Message: &models.Message{Text: "test"}} | ||
|
||
bot.ProcessUpdate(ctx, upd) | ||
if !called { | ||
t.Fatal("Expected default handler to be called") | ||
} | ||
} | ||
|
||
func Test_findHandler(t *testing.T) { | ||
var called bool | ||
h := func(ctx context.Context, bot *Bot, update *models.Update) { | ||
called = true | ||
} | ||
|
||
bot := &Bot{ | ||
defaultHandlerFunc: h, | ||
handlersMx: &sync.RWMutex{}, | ||
handlers: map[string]handler{}, | ||
} | ||
|
||
// Register a handler | ||
bot.handlers["test"] = handler{ | ||
handlerType: HandlerTypeMessageText, | ||
matchType: MatchTypeExact, | ||
pattern: "test", | ||
handler: h, | ||
} | ||
|
||
ctx := context.Background() | ||
upd := &models.Update{Message: &models.Message{Text: "test"}} | ||
|
||
handler := bot.findHandler(HandlerTypeMessageText, upd) | ||
handler(ctx, bot, upd) | ||
|
||
if !called { | ||
t.Fatal("Expected registered handler to be called") | ||
} | ||
} | ||
|
||
func Test_findHandler_Default(t *testing.T) { | ||
var called bool | ||
h := func(ctx context.Context, bot *Bot, update *models.Update) { | ||
called = true | ||
} | ||
|
||
bot := &Bot{ | ||
defaultHandlerFunc: h, | ||
handlersMx: &sync.RWMutex{}, | ||
handlers: map[string]handler{}, | ||
} | ||
|
||
ctx := context.Background() | ||
upd := &models.Update{Message: &models.Message{Text: "test"}} | ||
|
||
handler := bot.findHandler(HandlerTypeCallbackQueryData, upd) | ||
handler(ctx, bot, upd) | ||
|
||
if !called { | ||
t.Fatal("Expected default handler to be called") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code confuses me. What is the essence of his change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@negasus
In the first select block,
default:
is used to ensure that if the context has been canceled, it will immediately exit the select block and execute the error handling logic without waiting. This helps avoid sending the update if the context is already invalid.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With
default:
The code checks for context cancellation non-blockingly, allowing it to proceed immediately if the context is not canceled. And if withoutdefault:
then code will block until the context is canceled, potentially causing delays and inefficiencies.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in summary the first
select
block will checks if the context is canceled. If it is, it logs an error and returns without sending the update to the channel.And the second
select
block will sends the update to thebot.updates
channel, or logs an error if the context is canceled during the send operation.@negasus just to give you some context to the line changes, due to I ran into this error while creating and running the webhook_handler unit test:
FAIL: TestWebhookHandler_ContextDone (0.00s)
webhook_handler_test.go:171: Received update despite context cancellation