package pocketbase import ( "strings" "testing" "github.com/pocketbase/pocketbase/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "git.vakhrushev.me/av/transcriber/internal/adapter/repo/pocketbase/migrations" ) // newTestStorage поднимает хранилище на пустом каталоге и накатывает схему — // тем же путём, каким это делает сервис при старте. func newTestStorage(t *testing.T) core.App { t.Helper() app, err := New(t.TempDir()) require.NoError(t, err) t.Cleanup(func() { if err := app.ResetBootstrapState(); err != nil { t.Logf("не удалось закрыть хранилище: %v", err) } }) return app } // Критерий приёмки 10. Содержимое записи закрыто во всех коллекциях, куда оно // переехало. // // Прежде содержимое лежало одной колонкой задачи, и закрывала его одна норма про // файл записи. Теперь оно живёт в шести коллекциях, и реализация, следующая // только прежней норме, завела бы поле вложения с умолчанием библиотеки: ссылка // на сырой ответ провайдера — а это полный текст речи — отдавала бы его любому, // кто её знает, без сессии. func TestRecordContentIsClosedEverywhere(t *testing.T) { app := newTestStorage(t) // Правило просмотра остаётся незаданным, то есть «только владелец панели». // Содержимое отдаёт собственный адрес сервиса, а не поверхность хранилища; // непустое правило открыло бы перечисление коллекции впрок. for _, name := range []string{ migrations.RecordsCollection, migrations.TextsCollection, migrations.StructuresCollection, migrations.RecognitionsCollection, migrations.RecordEventsCollection, migrations.TopicsCollection, } { collection, err := app.FindCollectionByNameOrId(name) require.NoError(t, err, "коллекция %s заведена шагом схемы", name) assert.Nil(t, collection.ListRule, "перечисление %s закрыто", name) assert.Nil(t, collection.ViewRule, "чтение %s закрыто", name) assert.Nil(t, collection.CreateRule, "заведение записи в %s закрыто", name) assert.Nil(t, collection.UpdateRule, "правка %s закрыта", name) assert.Nil(t, collection.DeleteRule, "удаление из %s закрыто", name) } // А поле вложения помечено защищённым: без пометки ссылка открывает // содержимое любому, кто её знает, и знание ссылки становится правом. recognitions, err := app.FindCollectionByNameOrId(migrations.RecognitionsCollection) require.NoError(t, err) field := recognitions.Fields.GetByName("payload") require.NotNil(t, field, "поле сохранённого ответа заведено") file, ok := field.(*core.FileField) require.True(t, ok, "сохранённый ответ лежит вложением, а не колонкой") assert.True(t, file.Protected, "поле вложения защищено") } // Прежняя коллекция задач уходит вместе с моделью: данных под ней не было, а // пустая копия висела бы в панели вторым домом для понятия, которого больше нет. func TestFormerJobsCollectionIsGone(t *testing.T) { app := newTestStorage(t) _, err := app.FindCollectionByNameOrId(migrations.JobsCollection) assert.Error(t, err, "прежней коллекции задач не осталось") } // Пара «запись и вид» уникальна: повтор прерванного шага не заводит второго // комплекта строк, и вопрос «какой текст отдавать человеку» не становится // вопросом порядка записи. func TestAppendicesAreUniquePerRecord(t *testing.T) { app := newTestStorage(t) indexes := map[string][]string{ migrations.TextsCollection: {"idx_texts_record_kind"}, migrations.StructuresCollection: {"idx_structures_record_version"}, migrations.TopicsCollection: {"idx_topics_owner_name"}, } for name, expected := range indexes { collection, err := app.FindCollectionByNameOrId(name) require.NoError(t, err) for _, index := range expected { var found bool for _, declared := range collection.Indexes { if strings.Contains(declared, index) && strings.Contains(declared, "UNIQUE") { found = true } } assert.Truef(t, found, "у %s есть уникальный индекс %s", name, index) } } }