testutil

package
v0.0.0-...-cc41f30 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 9, 2026 License: MIT Imports: 15 Imported by: 0

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

View Source
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

func NewBreakerTestClient(t *testing.T, baseURL string, opts ...sender.Option) *sender.Client

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

func NewTestClient(t *testing.T, baseURL string, opts ...sender.Option) *sender.Client

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 TestBot

func TestBot() *tg.User

TestBot returns a test bot user fixture.

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

func TestChannelChat(id int64, title, username string) *tg.Chat

TestChannelChat returns a test channel chat fixture.

func TestChat

func TestChat() *tg.Chat

TestChat returns a test private chat fixture.

func TestGroupChat

func TestGroupChat(id int64, title string) *tg.Chat

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

func TestMessage(messageID int, text string) *tg.Message

TestMessage returns a test message fixture.

func TestMessageInChat

func TestMessageInChat(messageID int, chatID int64, text string) *tg.Message

TestMessageInChat returns a test message fixture for a specific chat.

func TestSuperGroupChat

func TestSuperGroupChat(id int64, title, username string) *tg.Chat

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

func TestUpdate(updateID int, text string) tg.Update

TestUpdate returns a test update fixture with a message.

func TestUpdateWithCallback

func TestUpdateWithCallback(updateID int, cbID, cbData string) tg.Update

TestUpdateWithCallback returns a test update fixture with a callback query.

func TestUpdateWithMessage

func TestUpdateWithMessage(updateID int, msg *tg.Message) tg.Update

TestUpdateWithMessage returns a test update fixture with a custom message.

func TestUser

func TestUser() *tg.User

TestUser returns a test user fixture.

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

func (c *Capture) AssertContentType(t *testing.T, expected string)

AssertContentType verifies the Content-Type header contains expected value.

func (*Capture) AssertHeader

func (c *Capture) AssertHeader(t *testing.T, key, expected string)

AssertHeader verifies a specific header value.

func (*Capture) AssertHeaderExists

func (c *Capture) AssertHeaderExists(t *testing.T, key string)

AssertHeaderExists verifies a header exists (with any value).

func (*Capture) AssertJSONField

func (c *Capture) AssertJSONField(t *testing.T, field string, expected any)

AssertJSONField verifies a field in the JSON body.

func (*Capture) AssertJSONFieldAbsent

func (c *Capture) AssertJSONFieldAbsent(t *testing.T, field string)

AssertJSONFieldAbsent verifies a field does NOT exist in the JSON body.

func (*Capture) AssertJSONFieldExists

func (c *Capture) AssertJSONFieldExists(t *testing.T, field string)

AssertJSONFieldExists verifies a field exists in the JSON body.

func (*Capture) AssertJSONFieldNested

func (c *Capture) AssertJSONFieldNested(t *testing.T, path string, expected any)

AssertJSONFieldNested verifies a nested field in the JSON body. Use dot notation: "chat.id", "reply_markup.inline_keyboard"

func (*Capture) AssertMethod

func (c *Capture) AssertMethod(t *testing.T, expected string)

AssertMethod verifies the HTTP method.

func (*Capture) AssertPath

func (c *Capture) AssertPath(t *testing.T, expected string)

AssertPath verifies the request path.

func (*Capture) AssertQuery

func (c *Capture) AssertQuery(t *testing.T, key, expected string)

AssertQuery verifies a query parameter value.

func (*Capture) BodyJSON

func (c *Capture) BodyJSON(t *testing.T, target any)

BodyJSON decodes the body as JSON into target.

func (*Capture) BodyMap

func (c *Capture) BodyMap(t *testing.T) map[string]any

BodyMap returns the body as a map.

func (*Capture) BodyString

func (c *Capture) BodyString() string

BodyString returns the body as a string.

func (*Capture) GetQuery

func (c *Capture) GetQuery(key string) string

GetQuery returns the first value of a query parameter.

func (*Capture) HasQuery

func (c *Capture) HasQuery(key string) bool

HasQuery checks if a query parameter exists.

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) Reset

func (f *FakeSleeper) Reset()

Reset clears all recorded calls.

func (*FakeSleeper) Sleep

func (f *FakeSleeper) Sleep(ctx context.Context, d time.Duration) error

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

type MockTelegramServer struct {
	*httptest.Server
	// contains filtered or unexported fields
}

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 RealSleeper

type RealSleeper struct{}

RealSleeper uses actual time (production).

func (RealSleeper) Sleep

func (RealSleeper) Sleep(ctx context.Context, d time.Duration) error

Sleep waits for the specified duration or until context is cancelled.

type Sleeper

type Sleeper interface {
	Sleep(ctx context.Context, d time.Duration) error
}

Sleeper abstracts time-based waiting for deterministic testing.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL