88 lines
3.8 KiB
Go
88 lines
3.8 KiB
Go
package api
|
||
|
||
import (
|
||
"encoding/json"
|
||
"net/http/httptest"
|
||
"strings"
|
||
"testing"
|
||
"time"
|
||
)
|
||
|
||
func TestDecodePostRules(t *testing.T) {
|
||
cases := []struct {
|
||
name string
|
||
body string
|
||
wantCode int
|
||
wantText string
|
||
}{
|
||
{"published news", `{"title":"День открытых дверей","html":"<p>Текст</p>","published_at":"2026-09-17","published":true}`, 200, ""},
|
||
{"draft without text", `{"title":"Черновик","published":false}`, 200, ""},
|
||
{"picture-only post", `{"title":"Афиша","html":"<p><img src=\"/media/a.jpg\"></p>","published":true}`, 200, ""},
|
||
{"no title", `{"title":" ","published":false}`, 422, "заголовок"},
|
||
{"published without text", `{"title":"Пусто","html":"<p> </p>","published":true}`, 422, "добавьте текст"},
|
||
{"bad date", `{"title":"Дата","published_at":"17.09.2026"}`, 422, "ГГГГ-ММ-ДД"},
|
||
{"bad slug", `{"title":"Адрес","slug":"новость"}`, 422, "латинские"},
|
||
// адреса со старого сайта: хвостовой дефис, подчёркивание — запись должна сохраняться
|
||
{"legacy slug", `{"title":"Старая","slug":"v-klinike-dana-","published":false}`, 200, ""},
|
||
{"legacy underscore", `{"title":"Старая","slug":"lech_bol","published":false}`, 200, ""},
|
||
{"leading dash", `{"title":"Адрес","slug":"-dana"}`, 422, "латинские"},
|
||
}
|
||
for _, tc := range cases {
|
||
w := httptest.NewRecorder()
|
||
r := httptest.NewRequest("POST", "/api/v1/admin/news", strings.NewReader(tc.body))
|
||
_, valid := decodePost(w, r, "news")
|
||
code := 200
|
||
if !valid {
|
||
code = w.Code
|
||
}
|
||
if code != tc.wantCode || (tc.wantText != "" && !strings.Contains(w.Body.String(), tc.wantText)) {
|
||
t.Errorf("%s: got %d %s, want %d containing %q", tc.name, code, w.Body.String(), tc.wantCode, tc.wantText)
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestDecodePostStoresHTMLBlockAndDate(t *testing.T) {
|
||
w := httptest.NewRecorder()
|
||
r := httptest.NewRequest("POST", "/", strings.NewReader(`{"title":"Статья","html":"<h2>Раздел</h2>","published_at":"2025-05-28"}`))
|
||
in, valid := decodePost(w, r, "article")
|
||
if !valid {
|
||
t.Fatal(w.Body.String())
|
||
}
|
||
var blocks []map[string]string
|
||
if err := json.Unmarshal(in.Blocks, &blocks); err != nil || len(blocks) != 1 || blocks[0]["html"] != "<h2>Раздел</h2>" {
|
||
t.Errorf("blocks = %s", in.Blocks)
|
||
}
|
||
if in.Slug != "statya" {
|
||
t.Errorf("slug = %s", in.Slug)
|
||
}
|
||
if got := in.PublishedAt.UTC().Format(time.RFC3339); got != "2025-05-28T09:00:00Z" {
|
||
t.Errorf("published_at = %s, want midday Moscow", got)
|
||
}
|
||
|
||
// неизменённая дата возвращается полной меткой времени и сохраняется как есть
|
||
w = httptest.NewRecorder()
|
||
r = httptest.NewRequest("POST", "/", strings.NewReader(`{"title":"Статья","published_at":"2024-01-13T14:03:41+03:00"}`))
|
||
in, _ = decodePost(w, r, "article")
|
||
if got := in.PublishedAt.UTC().Format(time.RFC3339); got != "2024-01-13T11:03:41Z" {
|
||
t.Errorf("kept published_at = %s", got)
|
||
}
|
||
}
|
||
|
||
func TestDecodeVacancy(t *testing.T) {
|
||
w := httptest.NewRecorder()
|
||
r := httptest.NewRequest("POST", "/", strings.NewReader(`{"title":"Администратор","requirements":"- грамотная речь\r\n\r\n• ответственность ","published":true}`))
|
||
in, valid := decodeVacancy(w, r)
|
||
if !valid {
|
||
t.Fatal(w.Body.String())
|
||
}
|
||
if in.Requirements != "грамотная речь\nответственность" || in.Slug != "administrator" || in.Sort != 100 {
|
||
t.Errorf("got %+v", in)
|
||
}
|
||
|
||
w = httptest.NewRecorder()
|
||
r = httptest.NewRequest("POST", "/", strings.NewReader(`{"title":"Пустая","published":true}`))
|
||
if _, valid := decodeVacancy(w, r); valid || !strings.Contains(w.Body.String(), "опишите") {
|
||
t.Errorf("empty published vacancy accepted: %d %s", w.Code, w.Body.String())
|
||
}
|
||
}
|