package archiver import ( "bytes" "context" "fmt" "io" "net/http" "net/http/httptest" "testing" "git.nakama.town/fmartingr/hako/internal/model" "github.com/google/uuid" ) // MockStorage implements storage.Storage for testing type MockStorage struct { files map[string][]byte } func NewMockStorage() *MockStorage { return &MockStorage{ files: make(map[string][]byte), } } func (m *MockStorage) Save(ctx context.Context, linkID string, filename string, reader io.Reader) (string, error) { data, err := io.ReadAll(reader) if err != nil { return "", err } path := fmt.Sprintf("%s/%s", linkID, filename) m.files[path] = data return path, nil } func (m *MockStorage) Get(ctx context.Context, path string) (io.ReadCloser, error) { data, ok := m.files[path] if !ok { return nil, fmt.Errorf("file not found") } return io.NopCloser(bytes.NewReader(data)), nil } func (m *MockStorage) Delete(ctx context.Context, path string) error { delete(m.files, path) return nil } func (m *MockStorage) Exists(ctx context.Context, path string) (bool, error) { _, ok := m.files[path] return ok, nil } func (m *MockStorage) DeleteDirectory(ctx context.Context, linkID string) error { // Delete all files that start with linkID/ prefix := linkID + "/" for path := range m.files { if len(path) > len(prefix) && path[:len(prefix)] == prefix { delete(m.files, path) } } return nil } func TestDirectDownloadArchiver_Success(t *testing.T) { // Create a test HTTP server testContent := "This is test content" server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") w.WriteHeader(http.StatusOK) _, _ = fmt.Fprint(w, testContent) })) defer server.Close() // Create archiver and mock storage archiver := NewDirectDownloadExtractor() stor := NewMockStorage() // Create test link link := &model.Link{ ID: uuid.New().String(), URL: server.URL, } // Test archival ctx := context.Background() result, err := archiver.Archive(ctx, link, stor) if err != nil { t.Fatalf("Archive failed: %v", err) } if len(result.Files) != 1 { t.Fatalf("Expected 1 file, got %d", len(result.Files)) } file := result.Files[0] if file.MimeType != "text/plain" { t.Errorf("Expected mime type text/plain, got %s", file.MimeType) } if file.Filename == "" { t.Error("Expected non-empty filename") } if file.FileSize == 0 { t.Error("Expected non-zero file size") } if file.HashSha256 == "" { t.Error("Expected non-empty hash") } } func TestDirectDownloadArchiver_HTTPError(t *testing.T) { // Create a test HTTP server that returns 404 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) })) defer server.Close() // Create archiver and mock storage archiver := NewDirectDownloadExtractor() stor := NewMockStorage() // Create test link link := &model.Link{ ID: uuid.New().String(), URL: server.URL, } // Test archival ctx := context.Background() _, err := archiver.Archive(ctx, link, stor) if err == nil { t.Fatal("Expected error for 404 response") } } func TestDirectDownloadArchiver_IsEnabled(t *testing.T) { archiver := NewDirectDownloadExtractor() ctx := context.Background() if !archiver.IsEnabled(ctx) { t.Error("Direct download archiver should always be enabled") } } func TestDirectDownloadArchiver_Key(t *testing.T) { archiver := NewDirectDownloadExtractor() if archiver.Key() != "direct_download" { t.Errorf("Expected key 'direct_download', got %s", archiver.Key()) } }