layout: непомещающееся целевое имя уводит задачу в review вместо failed

- предел длины компонента (255 байт) проверяется в BuildLinks до первой
  операции с ФС: ни каталога, ни ссылки при отказе не создаётся
- причина пустого предпросмотра считается на показе (ReviewData.PreviewError)
  и печатается в панели действий и в карточке Telegram: у задачи без
  записанной причины взять её больше неоткуда
This commit is contained in:
av
2026-08-10 12:16:44 +03:00
parent 1710e5a9d5
commit b9f0929d0c
31 changed files with 1511 additions and 17 deletions
+23 -1
View File
@@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"errors"
"fmt"
"log/slog"
"strings"
"testing"
@@ -78,6 +79,7 @@ type fakeReviewer struct {
deleted []string
dismissed []string
chosen map[string]string // downloadID → выбранный candidateID
applyErr error // чем отвечает Apply (nil — успехом)
}
func (f *fakeReviewer) ReviewData(context.Context, string) (*worker.ReviewData, error) {
@@ -85,7 +87,7 @@ func (f *fakeReviewer) ReviewData(context.Context, string) (*worker.ReviewData,
}
func (f *fakeReviewer) Apply(_ context.Context, id string) error {
f.applied = append(f.applied, id)
return nil
return f.applyErr
}
func (f *fakeReviewer) Refine(_ context.Context, id string, hint string) error {
if f.refined == nil {
@@ -614,3 +616,23 @@ func TestBot_IngestErrorPromisesNoDownloadID(t *testing.T) {
t.Errorf("в отказе обещан идентификатор загрузки: %q", got)
}
}
// Непомещающееся целевое имя — штатный отказ, чинимый на ревью: бот отвечает
// конкретно и обновляет карточку (в ней теперь причина), как для коллизии, а не
// падает в общее «Не удалось выполнить действие».
func TestBot_CallbackApplyNameTooLong(t *testing.T) {
b, api, _, rev := newTestBot(t, []int64{7})
rev.applyErr = fmt.Errorf("apply: %w", layout.ErrNameTooLong)
b.handleCallback(context.Background(), cbFrom(7, "apply:"+tid))
if len(api.answers) != 1 || !strings.Contains(api.answers[0], "не помещается") {
t.Errorf("answers = %+v, ожидался конкретный ответ", api.answers)
}
if len(api.sent) != 1 || !strings.Contains(api.sent[0].text, "слишком длинное") {
t.Errorf("sent = %+v, ожидалось конкретное сообщение", api.sent)
}
if len(api.edits) != 1 {
t.Errorf("edits = %v, карточка должна обновиться причиной", api.edits)
}
}