summaryrefslogtreecommitdiffstats
path: root/internal/formatter/buckets_test.go
diff options
context:
space:
mode:
authors <[email protected]>2025-11-13 14:43:15 -0500
committers <[email protected]>2025-11-13 14:43:15 -0500
commit344a6f6415c3c1b593677adec3b8844e0839971b (patch)
treeb05291ecdf21917b27e9e234eeb997c2706966d5 /internal/formatter/buckets_test.go
parenta5fc01a03753c9a18ddeaf13610dd99b4b311b80 (diff)
downloaddborg-344a6f6415c3c1b593677adec3b8844e0839971b.tar.gz
dborg-344a6f6415c3c1b593677adec3b8844e0839971b.zip
created pretty printing for all commandsv1.0.0
Diffstat (limited to 'internal/formatter/buckets_test.go')
-rw-r--r--internal/formatter/buckets_test.go509
1 files changed, 509 insertions, 0 deletions
diff --git a/internal/formatter/buckets_test.go b/internal/formatter/buckets_test.go
new file mode 100644
index 0000000..eabddf0
--- /dev/null
+++ b/internal/formatter/buckets_test.go
@@ -0,0 +1,509 @@
+package formatter
+
+import (
+ "bytes"
+ "os"
+ "testing"
+
+ "git.db.org.ai/dborg/internal/models"
+)
+
+func TestFormatBucketsResults(t *testing.T) {
+ tests := []struct {
+ name string
+ response *models.BucketsSearchResponse
+ asJSON bool
+ wantErr bool
+ }{
+ {
+ name: "format_buckets_with_multiple_types",
+ response: &models.BucketsSearchResponse{
+ Credits: models.CreditsInfo{
+ Unlimited: true,
+ },
+ Results: map[string]any{
+ "buckets": []any{
+ map[string]any{
+ "bucket": "test-bucket.s3.amazonaws.com",
+ "fileCount": float64(1500),
+ "id": float64(1),
+ "type": "aws",
+ },
+ map[string]any{
+ "bucket": "another.s3-eu-west-1.amazonaws.com",
+ "fileCount": float64(250),
+ "id": float64(2),
+ "type": "aws",
+ },
+ map[string]any{
+ "bucket": "storage.googleapis.com",
+ "fileCount": float64(10000),
+ "id": float64(3),
+ "type": "gcp",
+ },
+ map[string]any{
+ "bucket": "spaces.digitaloceanspaces.com",
+ "fileCount": float64(0),
+ "id": float64(4),
+ "type": "dos",
+ },
+ },
+ },
+ },
+ asJSON: false,
+ wantErr: false,
+ },
+ {
+ name: "format_empty_buckets",
+ response: &models.BucketsSearchResponse{
+ Credits: models.CreditsInfo{
+ Remaining: 100,
+ Unlimited: false,
+ },
+ Results: nil,
+ },
+ asJSON: false,
+ wantErr: false,
+ },
+ {
+ name: "format_json_output",
+ response: &models.BucketsSearchResponse{
+ Credits: models.CreditsInfo{
+ Unlimited: true,
+ },
+ Results: map[string]any{
+ "buckets": []any{
+ map[string]any{
+ "bucket": "test.s3.amazonaws.com",
+ "type": "aws",
+ },
+ },
+ },
+ },
+ asJSON: true,
+ wantErr: false,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ oldStdout := os.Stdout
+ r, w, _ := os.Pipe()
+ os.Stdout = w
+
+ err := FormatBucketsResults(tt.response, tt.asJSON)
+
+ w.Close()
+ var buf bytes.Buffer
+ buf.ReadFrom(r)
+ os.Stdout = oldStdout
+
+ if (err != nil) != tt.wantErr {
+ t.Errorf("FormatBucketsResults() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+
+ output := buf.String()
+ if !tt.asJSON && tt.response.Results != nil {
+ if output == "" {
+ t.Error("Expected non-empty output for non-JSON formatting")
+ }
+ }
+ })
+ }
+}
+
+func TestFormatBucketFilesResults(t *testing.T) {
+ tests := []struct {
+ name string
+ response *models.BucketsFilesSearchResponse
+ asJSON bool
+ wantErr bool
+ }{
+ {
+ name: "format_files_grouped_by_bucket",
+ response: &models.BucketsFilesSearchResponse{
+ Credits: models.CreditsInfo{
+ Unlimited: true,
+ },
+ Results: map[string]any{
+ "files": []any{
+ map[string]any{
+ "bucket": "test-bucket.s3.amazonaws.com",
+ "file": "documents/report.pdf",
+ "url": "https://test-bucket.s3.amazonaws.com/documents/report.pdf",
+ "size": float64(1024000),
+ "lastModified": "2024-01-01T00:00:00Z",
+ },
+ map[string]any{
+ "bucket": "test-bucket.s3.amazonaws.com",
+ "file": "images/logo.png",
+ "url": "https://test-bucket.s3.amazonaws.com/images/logo.png",
+ "size": float64(50000),
+ },
+ map[string]any{
+ "bucket": "another-bucket.s3.amazonaws.com",
+ "file": "data.json",
+ "url": "https://another-bucket.s3.amazonaws.com/data.json",
+ },
+ },
+ },
+ },
+ asJSON: false,
+ wantErr: false,
+ },
+ {
+ name: "format_empty_files",
+ response: &models.BucketsFilesSearchResponse{
+ Credits: models.CreditsInfo{
+ Remaining: 50,
+ Unlimited: false,
+ },
+ Results: map[string]any{
+ "files": []any{},
+ },
+ },
+ asJSON: false,
+ wantErr: false,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ oldStdout := os.Stdout
+ r, w, _ := os.Pipe()
+ os.Stdout = w
+
+ err := FormatBucketFilesResults(tt.response, tt.asJSON)
+
+ w.Close()
+ var buf bytes.Buffer
+ buf.ReadFrom(r)
+ os.Stdout = oldStdout
+
+ if (err != nil) != tt.wantErr {
+ t.Errorf("FormatBucketFilesResults() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ })
+ }
+}
+
+func TestGetBucketTypeHeader(t *testing.T) {
+ tests := []struct {
+ name string
+ bucketType string
+ wantNonEmpty bool
+ }{
+ {
+ name: "aws_header",
+ bucketType: "aws",
+ wantNonEmpty: true,
+ },
+ {
+ name: "gcp_header",
+ bucketType: "gcp",
+ wantNonEmpty: true,
+ },
+ {
+ name: "dos_header",
+ bucketType: "dos",
+ wantNonEmpty: true,
+ },
+ {
+ name: "unknown_header",
+ bucketType: "custom",
+ wantNonEmpty: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := getBucketTypeHeader(tt.bucketType)
+ if tt.wantNonEmpty && got == "" {
+ t.Errorf("getBucketTypeHeader() returned empty string for %s", tt.bucketType)
+ }
+ })
+ }
+}
+
+func TestFormatFileCount(t *testing.T) {
+ tests := []struct {
+ name string
+ count int
+ want bool
+ }{
+ {
+ name: "small_count",
+ count: 10,
+ want: true,
+ },
+ {
+ name: "medium_count",
+ count: 500,
+ want: true,
+ },
+ {
+ name: "large_count",
+ count: 5000,
+ want: true,
+ },
+ {
+ name: "very_large_count",
+ count: 50000,
+ want: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := formatFileCount(tt.count)
+ if tt.want && got == "" {
+ t.Errorf("formatFileCount() returned empty for count %d", tt.count)
+ }
+ })
+ }
+}
+
+func TestFormatNumber(t *testing.T) {
+ tests := []struct {
+ name string
+ n int
+ want string
+ }{
+ {
+ name: "small_number",
+ n: 999,
+ want: "999",
+ },
+ {
+ name: "thousand",
+ n: 1000,
+ want: "1,000",
+ },
+ {
+ name: "million",
+ n: 1000000,
+ want: "1,000,000",
+ },
+ {
+ name: "random_large",
+ n: 12345678,
+ want: "12,345,678",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := formatNumber(tt.n)
+ if got != tt.want {
+ t.Errorf("formatNumber() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestGetExtensionColor(t *testing.T) {
+ tests := []struct {
+ name string
+ ext string
+ want string
+ }{
+ {
+ name: "pdf_extension",
+ ext: "pdf",
+ want: ColorBlue,
+ },
+ {
+ name: "image_extension",
+ ext: "png",
+ want: ColorGreen,
+ },
+ {
+ name: "video_extension",
+ ext: "mp4",
+ want: ColorMagenta,
+ },
+ {
+ name: "archive_extension",
+ ext: "zip",
+ want: ColorYellow,
+ },
+ {
+ name: "database_extension",
+ ext: "sql",
+ want: ColorRed,
+ },
+ {
+ name: "config_extension",
+ ext: "json",
+ want: ColorCyan,
+ },
+ {
+ name: "unknown_extension",
+ ext: "xyz",
+ want: ColorWhite,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := getExtensionColor(tt.ext)
+ if got != tt.want {
+ t.Errorf("getExtensionColor() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestTruncateBucketName(t *testing.T) {
+ tests := []struct {
+ name string
+ bucket string
+ wantLen int
+ }{
+ {
+ name: "short_name",
+ bucket: "test-bucket",
+ wantLen: 50,
+ },
+ {
+ name: "long_aws_bucket",
+ bucket: "very-long-bucket-name-that-exceeds-the-limit.s3.amazonaws.com",
+ wantLen: 60,
+ },
+ {
+ name: "long_gcp_bucket",
+ bucket: "extremely-long-google-cloud-storage-bucket-name.storage.googleapis.com",
+ wantLen: 80,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := truncateBucketName(tt.bucket)
+ if len(got) > tt.wantLen {
+ t.Errorf("truncateBucketName() length = %d, want <= %d", len(got), tt.wantLen)
+ }
+ })
+ }
+}
+
+func TestExtractFileNameFromURL(t *testing.T) {
+ tests := []struct {
+ name string
+ url string
+ want string
+ }{
+ {
+ name: "simple_filename",
+ url: "https://bucket.s3.amazonaws.com/file.pdf",
+ want: "file.pdf",
+ },
+ {
+ name: "filename_with_path",
+ url: "https://bucket.s3.amazonaws.com/path/to/document.docx",
+ want: "document.docx",
+ },
+ {
+ name: "filename_with_query",
+ url: "https://bucket.s3.amazonaws.com/image.jpg?version=123",
+ want: "image.jpg",
+ },
+ {
+ name: "encoded_filename",
+ url: "https://bucket.s3.amazonaws.com/my%20file%20name.pdf",
+ want: "my%20file%20name.pdf",
+ },
+ {
+ name: "no_filename",
+ url: "https://bucket.s3.amazonaws.com/",
+ want: "index",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := extractFileNameFromURL(tt.url)
+ if got != tt.want {
+ t.Errorf("extractFileNameFromURL() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestExtractBucketFromURL(t *testing.T) {
+ tests := []struct {
+ name string
+ url string
+ want string
+ }{
+ {
+ name: "aws_s3_url",
+ url: "https://my-bucket.s3.amazonaws.com/file.pdf",
+ want: "my-bucket.s3.amazonaws.com",
+ },
+ {
+ name: "digitalocean_spaces",
+ url: "https://space.nyc3.digitaloceanspaces.com/path/file.jpg",
+ want: "space.nyc3.digitaloceanspaces.com",
+ },
+ {
+ name: "gcp_storage",
+ url: "https://bucket.storage.googleapis.com/data.json",
+ want: "bucket.storage.googleapis.com",
+ },
+ {
+ name: "http_url",
+ url: "http://bucket.example.com/file.txt",
+ want: "bucket.example.com",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := extractBucketFromURL(tt.url)
+ if got != tt.want {
+ t.Errorf("extractBucketFromURL() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestDecodeURLEncoding(t *testing.T) {
+ tests := []struct {
+ name string
+ s string
+ want string
+ }{
+ {
+ name: "spaces",
+ s: "my%20file%20name.pdf",
+ want: "my file name.pdf",
+ },
+ {
+ name: "parentheses",
+ s: "document%28final%29.docx",
+ want: "document(final).docx",
+ },
+ {
+ name: "underscores",
+ s: "test_file_name.jpg",
+ want: "test file name.jpg",
+ },
+ {
+ name: "mixed",
+ s: "WhatsApp%20Image_2021%2810%29.jpeg",
+ want: "WhatsApp Image 2021(10).jpeg",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := decodeURLEncoding(tt.s)
+ if got != tt.want {
+ t.Errorf("decodeURLEncoding() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}