Documentation
¶
Overview ¶
Package testutil provides testing utilities for galigo.
This package is intended for internal testing only and should not be imported by external packages.
Mock Telegram Server ¶
MockTelegramServer provides a mock Telegram Bot API server for testing:
server := testutil.NewMockServer(t)
server.OnMethod("POST", "/bot"+testutil.TestToken+"/sendMessage", func(w http.ResponseWriter, r *http.Request) {
testutil.ReplyMessage(w, 123)
})
// Use server.BaseURL() as the API base URL
Request Capture ¶
All requests are automatically captured and can be inspected:
cap := server.LastCapture() cap.AssertMethod(t, "POST") cap.AssertJSONField(t, "chat_id", float64(123))
Fake Sleeper ¶
FakeSleeper records sleep calls without actually sleeping:
sleeper := &testutil.FakeSleeper{}
// Pass to client via WithSleeper option
assert.Equal(t, 2*time.Second, sleeper.LastCall())
Test Fixtures ¶
Common test data is available:
testutil.TestToken // Valid bot token format testutil.TestChatID // Test chat ID testutil.TestUser() // Test user fixture testutil.TestMessage(1, "Hello") // Test message fixture
Index ¶
- Constants
- func CircuitBreakerAggressiveTrip() sender.CircuitBreakerSettings
- func CircuitBreakerNeverTrip() sender.CircuitBreakerSettings
- func NewBreakerTestClient(t *testing.T, baseURL string, opts ...sender.Option) *sender.Client
- func NewRetryTestClient(t *testing.T, baseURL string, sleeper *FakeSleeper, opts ...sender.Option) *sender.Client
- func NewTestClient(t *testing.T, baseURL string, opts ...sender.Option) *sender.Client
- func ReplyBadRequest(w http.ResponseWriter, description string)
- func ReplyBool(w http.ResponseWriter, result bool)
- func ReplyEmptyUpdates(w http.ResponseWriter)
- func ReplyError(w http.ResponseWriter, code int, description string, params *Parameters)
- func ReplyForbidden(w http.ResponseWriter, description string)
- func ReplyMessage(w http.ResponseWriter, messageID int)
- func ReplyMessageID(w http.ResponseWriter, messageID int)
- func ReplyMessageWithChat(w http.ResponseWriter, messageID int, chatID int64)
- func ReplyNotFound(w http.ResponseWriter, description string)
- func ReplyOK(w http.ResponseWriter, result any)
- func ReplyRateLimit(w http.ResponseWriter, retryAfter int)
- func ReplyRateLimitHeaderOnly(w http.ResponseWriter, retryAfter int)
- func ReplyServerError(w http.ResponseWriter, code int, description string)
- func ReplyUpdates(w http.ResponseWriter, updates []map[string]any)
- func ReplyUser(w http.ResponseWriter)
- func ReplyWebhookInfo(w http.ResponseWriter, url string, pendingCount int)
- func TestBot() *tg.User
- func TestCallbackQuery(id, data string) *tg.CallbackQuery
- func TestCallbackQueryWithMessage(id, data string, msg *tg.Message) *tg.CallbackQuery
- func TestChannelChat(id int64, title, username string) *tg.Chat
- func TestChat() *tg.Chat
- func TestGroupChat(id int64, title string) *tg.Chat
- func TestInlineButton(text, callbackData string) tg.InlineKeyboardButton
- func TestInlineKeyboard(buttons ...[]tg.InlineKeyboardButton) *tg.InlineKeyboardMarkup
- func TestMessage(messageID int, text string) *tg.Message
- func TestMessageInChat(messageID int, chatID int64, text string) *tg.Message
- func TestSuperGroupChat(id int64, title, username string) *tg.Chat
- func TestURLButton(text, url string) tg.InlineKeyboardButton
- func TestUpdate(updateID int, text string) tg.Update
- func TestUpdateWithCallback(updateID int, cbID, cbData string) tg.Update
- func TestUpdateWithMessage(updateID int, msg *tg.Message) tg.Update
- func TestUser() *tg.User
- type Capture
- func (c *Capture) AssertContentType(t *testing.T, expected string)
- func (c *Capture) AssertHeader(t *testing.T, key, expected string)
- func (c *Capture) AssertHeaderExists(t *testing.T, key string)
- func (c *Capture) AssertJSONField(t *testing.T, field string, expected any)
- func (c *Capture) AssertJSONFieldAbsent(t *testing.T, field string)
- func (c *Capture) AssertJSONFieldExists(t *testing.T, field string)
- func (c *Capture) AssertJSONFieldNested(t *testing.T, path string, expected any)
- func (c *Capture) AssertMethod(t *testing.T, expected string)
- func (c *Capture) AssertPath(t *testing.T, expected string)
- func (c *Capture) AssertQuery(t *testing.T, key, expected string)
- func (c *Capture) BodyJSON(t *testing.T, target any)
- func (c *Capture) BodyMap(t *testing.T) map[string]any
- func (c *Capture) BodyString() string
- func (c *Capture) GetQuery(key string) string
- func (c *Capture) HasQuery(key string) bool
- type FakeSleeper
- func (f *FakeSleeper) CallAt(index int) time.Duration
- func (f *FakeSleeper) CallCount() int
- func (f *FakeSleeper) Calls() []time.Duration
- func (f *FakeSleeper) LastCall() time.Duration
- func (f *FakeSleeper) Reset()
- func (f *FakeSleeper) Sleep(ctx context.Context, d time.Duration) error
- func (f *FakeSleeper) TotalDuration() time.Duration
- type MockTelegramServer
- func (m *MockTelegramServer) BaseURL() string
- func (m *MockTelegramServer) BotURL(token string) string
- func (m *MockTelegramServer) CaptureAt(index int) *Capture
- func (m *MockTelegramServer) CaptureCount() int
- func (m *MockTelegramServer) Captures() []Capture
- func (m *MockTelegramServer) LastCapture() *Capture
- func (m *MockTelegramServer) On(path string, handler http.HandlerFunc)
- func (m *MockTelegramServer) OnMethod(method, path string, handler http.HandlerFunc)
- func (m *MockTelegramServer) Reset()
- func (m *MockTelegramServer) ResetCaptures()
- func (m *MockTelegramServer) TimeBetweenCaptures(i, j int) time.Duration
- type Parameters
- type RealSleeper
- type Sleeper
- type TelegramEnvelope
Constants ¶
const ( // TestToken is a valid-format bot token for testing. TestToken = "123456789:ABCdefGHIjklMNOpqrsTUVwxyz" // TestChatID is a test chat ID. TestChatID = int64(123456789) // TestUserID is a test user ID. TestUserID = int64(987654321) // TestBotID is a test bot ID. TestBotID = int64(123456789) // TestUsername is a test username. TestUsername = "testuser" // TestBotUsername is a test bot username. TestBotUsername = "testbot" )
Test constants for consistent test data.
Variables ¶
This section is empty.
Functions ¶
func CircuitBreakerAggressiveTrip ¶
func CircuitBreakerAggressiveTrip() sender.CircuitBreakerSettings
CircuitBreakerAggressiveTrip returns settings for testing breaker behavior. Trips after just 2 consecutive failures.
func CircuitBreakerNeverTrip ¶
func CircuitBreakerNeverTrip() sender.CircuitBreakerSettings
CircuitBreakerNeverTrip returns settings where breaker never opens. Use for retry tests that need to verify retry behavior without breaker interference.
func NewBreakerTestClient ¶
NewBreakerTestClient creates a client for testing circuit breaker behavior. Circuit breaker trips aggressively for fast testing.
func NewRetryTestClient ¶
func NewRetryTestClient(t *testing.T, baseURL string, sleeper *FakeSleeper, opts ...sender.Option) *sender.Client
NewRetryTestClient creates a client for testing retry behavior. Circuit breaker is configured to never trip.
func NewTestClient ¶
NewTestClient creates a standard test client with sensible defaults.
func ReplyBadRequest ¶
func ReplyBadRequest(w http.ResponseWriter, description string)
ReplyBadRequest writes a 400 bad request error.
func ReplyBool ¶
func ReplyBool(w http.ResponseWriter, result bool)
ReplyBool writes a successful boolean response (for deleteMessage, etc.).
func ReplyEmptyUpdates ¶
func ReplyEmptyUpdates(w http.ResponseWriter)
ReplyEmptyUpdates writes an empty getUpdates response.
func ReplyError ¶
func ReplyError(w http.ResponseWriter, code int, description string, params *Parameters)
ReplyError writes a Telegram API error response.
func ReplyForbidden ¶
func ReplyForbidden(w http.ResponseWriter, description string)
ReplyForbidden writes a 403 forbidden error (e.g., bot blocked).
func ReplyMessage ¶
func ReplyMessage(w http.ResponseWriter, messageID int)
ReplyMessage writes a successful message response.
func ReplyMessageID ¶
func ReplyMessageID(w http.ResponseWriter, messageID int)
ReplyMessageID writes a successful MessageId response (for copyMessage).
func ReplyMessageWithChat ¶
func ReplyMessageWithChat(w http.ResponseWriter, messageID int, chatID int64)
ReplyMessageWithChat writes a successful message response for a specific chat.
func ReplyNotFound ¶
func ReplyNotFound(w http.ResponseWriter, description string)
ReplyNotFound writes a 404 not found error.
func ReplyOK ¶
func ReplyOK(w http.ResponseWriter, result any)
ReplyOK writes a successful Telegram API response.
func ReplyRateLimit ¶
func ReplyRateLimit(w http.ResponseWriter, retryAfter int)
ReplyRateLimit writes a 429 rate limit response with retry_after in both JSON and HTTP header.
func ReplyRateLimitHeaderOnly ¶
func ReplyRateLimitHeaderOnly(w http.ResponseWriter, retryAfter int)
ReplyRateLimitHeaderOnly writes a 429 rate limit response with retry_after ONLY in HTTP header. Useful for testing HTTP header fallback parsing.
func ReplyServerError ¶
func ReplyServerError(w http.ResponseWriter, code int, description string)
ReplyServerError writes a 5xx server error response.
func ReplyUpdates ¶
func ReplyUpdates(w http.ResponseWriter, updates []map[string]any)
ReplyUpdates writes a successful getUpdates response.
func ReplyUser ¶
func ReplyUser(w http.ResponseWriter)
ReplyUser writes a successful getMe response.
func ReplyWebhookInfo ¶
func ReplyWebhookInfo(w http.ResponseWriter, url string, pendingCount int)
ReplyWebhookInfo writes a successful getWebhookInfo response.
func TestCallbackQuery ¶
func TestCallbackQuery(id, data string) *tg.CallbackQuery
TestCallbackQuery returns a test callback query fixture.
func TestCallbackQueryWithMessage ¶
func TestCallbackQueryWithMessage(id, data string, msg *tg.Message) *tg.CallbackQuery
TestCallbackQueryWithMessage returns a test callback query with a custom message.
func TestChannelChat ¶
TestChannelChat returns a test channel chat fixture.
func TestGroupChat ¶
TestGroupChat returns a test group chat fixture.
func TestInlineButton ¶
func TestInlineButton(text, callbackData string) tg.InlineKeyboardButton
TestInlineButton returns a test inline keyboard button with callback data.
func TestInlineKeyboard ¶
func TestInlineKeyboard(buttons ...[]tg.InlineKeyboardButton) *tg.InlineKeyboardMarkup
TestInlineKeyboard returns a test inline keyboard fixture.
func TestMessage ¶
TestMessage returns a test message fixture.
func TestMessageInChat ¶
TestMessageInChat returns a test message fixture for a specific chat.
func TestSuperGroupChat ¶
TestSuperGroupChat returns a test supergroup chat fixture.
func TestURLButton ¶
func TestURLButton(text, url string) tg.InlineKeyboardButton
TestURLButton returns a test inline keyboard button with URL.
func TestUpdate ¶
TestUpdate returns a test update fixture with a message.
func TestUpdateWithCallback ¶
TestUpdateWithCallback returns a test update fixture with a callback query.
func TestUpdateWithMessage ¶
TestUpdateWithMessage returns a test update fixture with a custom message.
Types ¶
type Capture ¶
type Capture struct {
Method string
Path string
Query map[string][]string
Headers http.Header
Body []byte
ContentType string
Timestamp time.Time
}
Capture represents a captured HTTP request with timestamp.
func (*Capture) AssertContentType ¶
AssertContentType verifies the Content-Type header contains expected value.
func (*Capture) AssertHeader ¶
AssertHeader verifies a specific header value.
func (*Capture) AssertHeaderExists ¶
AssertHeaderExists verifies a header exists (with any value).
func (*Capture) AssertJSONField ¶
AssertJSONField verifies a field in the JSON body.
func (*Capture) AssertJSONFieldAbsent ¶
AssertJSONFieldAbsent verifies a field does NOT exist in the JSON body.
func (*Capture) AssertJSONFieldExists ¶
AssertJSONFieldExists verifies a field exists in the JSON body.
func (*Capture) AssertJSONFieldNested ¶
AssertJSONFieldNested verifies a nested field in the JSON body. Use dot notation: "chat.id", "reply_markup.inline_keyboard"
func (*Capture) AssertMethod ¶
AssertMethod verifies the HTTP method.
func (*Capture) AssertPath ¶
AssertPath verifies the request path.
func (*Capture) AssertQuery ¶
AssertQuery verifies a query parameter value.
func (*Capture) BodyString ¶
BodyString returns the body as a string.
type FakeSleeper ¶
type FakeSleeper struct {
// contains filtered or unexported fields
}
FakeSleeper records sleep calls without actually sleeping. Use this in tests to verify retry timing without real delays.
func (*FakeSleeper) CallAt ¶
func (f *FakeSleeper) CallAt(index int) time.Duration
CallAt returns the sleep duration at the given index. Returns 0 if index is out of bounds.
func (*FakeSleeper) CallCount ¶
func (f *FakeSleeper) CallCount() int
CallCount returns the number of sleep calls.
func (*FakeSleeper) Calls ¶
func (f *FakeSleeper) Calls() []time.Duration
Calls returns all recorded sleep durations.
func (*FakeSleeper) LastCall ¶
func (f *FakeSleeper) LastCall() time.Duration
LastCall returns the most recent sleep duration. Returns 0 if no calls have been made.
func (*FakeSleeper) Sleep ¶
Sleep records the duration without actually sleeping. Returns ctx.Err() if the context is already cancelled.
func (*FakeSleeper) TotalDuration ¶
func (f *FakeSleeper) TotalDuration() time.Duration
TotalDuration returns the sum of all sleep durations.
type MockTelegramServer ¶
MockTelegramServer provides a mock Telegram Bot API server for testing.
func NewMockServer ¶
func NewMockServer(t *testing.T) *MockTelegramServer
NewMockServer creates a mock Telegram API server. The server is automatically closed when the test completes.
func (*MockTelegramServer) BaseURL ¶
func (m *MockTelegramServer) BaseURL() string
BaseURL returns the server's base URL. Use this as the API base URL when creating clients.
func (*MockTelegramServer) BotURL ¶
func (m *MockTelegramServer) BotURL(token string) string
BotURL returns the full bot API URL for a given token. Example: server.BotURL(testutil.TestToken) returns "http://127.0.0.1:port/bot123:ABC"
func (*MockTelegramServer) CaptureAt ¶
func (m *MockTelegramServer) CaptureAt(index int) *Capture
CaptureAt returns the capture at the given index.
func (*MockTelegramServer) CaptureCount ¶
func (m *MockTelegramServer) CaptureCount() int
CaptureCount returns the total number of captured requests.
func (*MockTelegramServer) Captures ¶
func (m *MockTelegramServer) Captures() []Capture
Captures returns all captured requests.
func (*MockTelegramServer) LastCapture ¶
func (m *MockTelegramServer) LastCapture() *Capture
LastCapture returns the most recent captured request.
func (*MockTelegramServer) On ¶
func (m *MockTelegramServer) On(path string, handler http.HandlerFunc)
On registers a handler for a POST request (most common case).
func (*MockTelegramServer) OnMethod ¶
func (m *MockTelegramServer) OnMethod(method, path string, handler http.HandlerFunc)
OnMethod registers a handler for a specific HTTP method and path.
Example:
server.OnMethod("POST", "/bot123:ABC/sendMessage", func(w http.ResponseWriter, r *http.Request) {
testutil.ReplyMessage(w, 123)
})
func (*MockTelegramServer) Reset ¶
func (m *MockTelegramServer) Reset()
Reset clears all captures and handlers.
func (*MockTelegramServer) ResetCaptures ¶
func (m *MockTelegramServer) ResetCaptures()
ResetCaptures clears only captures, keeping handlers.
func (*MockTelegramServer) TimeBetweenCaptures ¶
func (m *MockTelegramServer) TimeBetweenCaptures(i, j int) time.Duration
TimeBetweenCaptures returns the duration between two captures. Useful for rate-limit testing.
type Parameters ¶
type Parameters struct {
RetryAfter int `json:"retry_after,omitempty"`
MigrateToChatID int64 `json:"migrate_to_chat_id,omitempty"`
}
Parameters contains optional error parameters (e.g., retry_after).
type TelegramEnvelope ¶
type TelegramEnvelope struct {
OK bool `json:"ok"`
Result any `json:"result,omitempty"`
ErrorCode int `json:"error_code,omitempty"`
Description string `json:"description,omitempty"`
Parameters *Parameters `json:"parameters,omitempty"`
}
TelegramEnvelope is the standard Telegram API response format.