From 8509004eb7f29d77372be9f4604cf03d811a0cc0 Mon Sep 17 00:00:00 2001 From: Mathias Date: Sat, 3 Oct 2026 21:05:52 +0200 Subject: [PATCH] test(store): an owner can delete a finished upload; an active or foreign one is refused (#37), red Co-Authored-By: Claude Sonnet 5.5 --- .../store/uploaded_transcripts_delete_test.go | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 internal/adapters/store/uploaded_transcripts_delete_test.go diff --git a/internal/adapters/store/uploaded_transcripts_delete_test.go b/internal/adapters/store/uploaded_transcripts_delete_test.go new file mode 100644 index 0000000..fbabf9b --- /dev/null +++ b/internal/adapters/store/uploaded_transcripts_delete_test.go @@ -0,0 +1,68 @@ +package store_test + +// Deleting one recording (#37). A finished or failed upload can be removed by its owner; +// one that is queued or transcribing is refused until it ends, because the worker would +// otherwise write its result to a row that is gone (D3 in the sprint plan). + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "git.d-ma.be/mathias/tapir/internal/adapters/store" + "git.d-ma.be/mathias/tapir/internal/domain" +) + +func TestDeleteUpload_RemovesAFinishedOrFailedUploadOfTheOwner(t *testing.T) { + for name, finish := range map[string]func(*store.Store, string) error{ + "done": func(s *store.Store, id string) error { + return s.CompleteUpload(context.Background(), userA, id, domain.Transcription{Text: "synthetic", Endpoint: "iguana/kb-whisper"}) + }, + "failed": func(s *store.Store, id string) error { + return s.FailUpload(context.Background(), userA, id, domain.UploadErrTranscriptionFailed) + }, + } { + t.Run(name, func(t *testing.T) { + s := newStore(t) + id := startedUpload(t, s) + require.NoError(t, s.StartTranscribing(context.Background(), userA, id)) + require.NoError(t, finish(s, id)) + + require.NoError(t, s.DeleteUpload(context.Background(), userA, id)) + + _, err := s.GetUpload(context.Background(), userA, id) + assert.ErrorIs(t, err, store.ErrUploadNotFound) + }) + } +} + +func TestDeleteUpload_RefusesAnUploadThatIsStillQueuedOrTranscribingAndKeepsTheRow(t *testing.T) { + s := newStore(t) + ctx := context.Background() + queued := startedUpload(t, s) + running, err := s.CreateUpload(ctx, userA, "running", false) + require.NoError(t, err) + require.NoError(t, s.StartTranscribing(ctx, userA, running)) + + for _, id := range []string{queued, running} { + assert.ErrorIs(t, s.DeleteUpload(ctx, userA, id), store.ErrUploadInProgress) + _, err := s.GetUpload(ctx, userA, id) + assert.NoError(t, err, "a refused delete must leave the row") + } +} + +func TestDeleteUpload_AnotherUsersUploadIsNotFoundAndSurvives(t *testing.T) { + s := newStore(t) + ctx := context.Background() + id := startedUpload(t, s) + require.NoError(t, s.StartTranscribing(ctx, userA, id)) + require.NoError(t, s.FailUpload(ctx, userA, id, domain.UploadErrTranscriptionFailed)) + + assert.ErrorIs(t, s.DeleteUpload(ctx, userB, id), store.ErrUploadNotFound, + "existence is not disclosed to a non-owner") + + _, err := s.GetUpload(ctx, userA, id) + assert.NoError(t, err, "B's delete must not have removed A's row") +}