diff --git a/handlers_test.go b/handlers_test.go index ec17eb9..f9290a1 100644 --- a/handlers_test.go +++ b/handlers_test.go @@ -64,22 +64,24 @@ func TestHandleUpdate_NewChat(t *testing.T) { assert.NoError(t, err) testCases := []struct { - name string - userID int64 - isOwner bool - wantResp string + name string + // userID 123 is the configured owner; any other ID is a regular user. + userID int64 + // wantSubstr must appear in both the Telegram-sent text and the DB-stored + // response. Owners (model:set scope) see the raw API error; regular users + // get the generic fallback. Substring (not exact) so the test stays robust + // against the SDK's evolving error wording for non-API errors. + wantSubstr string }{ { - name: "Owner First Message", - userID: 123, // owner's ID - isOwner: true, - wantResp: "I'm sorry, I'm having trouble processing your request right now.", + name: "Owner First Message", + userID: 123, + wantSubstr: "Anthropic call failed:", }, { - name: "Regular User First Message", - userID: 456, - isOwner: false, - wantResp: "I'm sorry, I'm having trouble processing your request right now.", + name: "Regular User First Message", + userID: 456, + wantSubstr: "I'm sorry, I'm having trouble processing your request right now.", }, } @@ -88,7 +90,7 @@ func TestHandleUpdate_NewChat(t *testing.T) { // Setup mock response expectations for error case to test fallback messages mockTgClient.SendMessageFunc = func(ctx context.Context, params *bot.SendMessageParams) (*models.Message, error) { assert.Equal(t, tc.userID, params.ChatID) - assert.Equal(t, tc.wantResp, params.Text) + assert.Contains(t, params.Text, tc.wantSubstr) return &models.Message{}, nil } @@ -112,10 +114,13 @@ func TestHandleUpdate_NewChat(t *testing.T) { err := db.Where("chat_id = ? AND user_id = ? AND text = ?", tc.userID, tc.userID, "Hello").First(&storedMsg).Error assert.NoError(t, err) - // Verify response was stored + // Verify response was stored (most recent assistant message in this chat). var respMsg Message - err = db.Where("chat_id = ? AND is_user = ? AND text = ?", tc.userID, false, tc.wantResp).First(&respMsg).Error + err = db.Where("chat_id = ? AND is_user = ?", tc.userID, false). + Order("timestamp DESC"). + First(&respMsg).Error assert.NoError(t, err) + assert.Contains(t, respMsg.Text, tc.wantSubstr) }) } } @@ -720,11 +725,22 @@ func TestAnthropicErrorResponse(t *testing.T) { //NOSONAR go:S100 -- underscore wantMissing: "/set_model", }, { - name: "owner receives generic message for non-model error", + // Non-model errors (network, plain errors, API errors other than 404) + // surface to anyone with model:set scope so admins/owners can diagnose. + name: "owner receives elevated detail for non-API error", err: otherErr, userID: 123, + wantSubstr: "Anthropic call failed:", + wantMissing: "I'm sorry", + }, + { + // Regular users keep getting the generic fallback for any non-model error + // to avoid leaking internal details. + name: "regular user receives generic message for non-model error", + err: otherErr, + userID: 789, wantSubstr: "I'm sorry", - wantMissing: "/set_model", + wantMissing: "Anthropic call failed", }, }