zip_test.go raw

   1  package bridge
   2  
   3  import (
   4  	"archive/zip"
   5  	"bytes"
   6  	crand "crypto/rand"
   7  	"strings"
   8  	"testing"
   9  
  10  	bridgesmtp "next.orly.dev/pkg/bridge/smtp"
  11  )
  12  
  13  func TestZipParts_HTMLOnly(t *testing.T) {
  14  	data, err := ZipParts("<html><body>Hello</body></html>", nil)
  15  	if err != nil {
  16  		t.Fatalf("ZipParts: %v", err)
  17  	}
  18  
  19  	// Verify it's a valid zip
  20  	r, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
  21  	if err != nil {
  22  		t.Fatalf("read zip: %v", err)
  23  	}
  24  
  25  	if len(r.File) != 1 {
  26  		t.Fatalf("expected 1 file, got %d", len(r.File))
  27  	}
  28  	if r.File[0].Name != "body.html" {
  29  		t.Errorf("file name = %q, want body.html", r.File[0].Name)
  30  	}
  31  }
  32  
  33  func TestZipParts_WithAttachments(t *testing.T) {
  34  	attachments := []bridgesmtp.Attachment{
  35  		{Filename: "test.pdf", ContentType: "application/pdf", Data: []byte("pdf-content")},
  36  		{Filename: "image.png", ContentType: "image/png", Data: []byte("png-content")},
  37  	}
  38  
  39  	data, err := ZipParts("", attachments)
  40  	if err != nil {
  41  		t.Fatalf("ZipParts: %v", err)
  42  	}
  43  
  44  	r, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
  45  	if err != nil {
  46  		t.Fatalf("read zip: %v", err)
  47  	}
  48  
  49  	if len(r.File) != 2 {
  50  		t.Fatalf("expected 2 files, got %d", len(r.File))
  51  	}
  52  
  53  	names := map[string]bool{}
  54  	for _, f := range r.File {
  55  		names[f.Name] = true
  56  	}
  57  
  58  	if !names["test.pdf"] {
  59  		t.Error("missing test.pdf in zip")
  60  	}
  61  	if !names["image.png"] {
  62  		t.Error("missing image.png in zip")
  63  	}
  64  }
  65  
  66  func TestZipParts_HTMLAndAttachments(t *testing.T) {
  67  	attachments := []bridgesmtp.Attachment{
  68  		{Filename: "doc.txt", ContentType: "text/plain", Data: []byte("content")},
  69  	}
  70  
  71  	data, err := ZipParts("<p>HTML</p>", attachments)
  72  	if err != nil {
  73  		t.Fatalf("ZipParts: %v", err)
  74  	}
  75  
  76  	r, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
  77  	if err != nil {
  78  		t.Fatalf("read zip: %v", err)
  79  	}
  80  
  81  	if len(r.File) != 2 { // body.html + doc.txt
  82  		t.Errorf("expected 2 files, got %d", len(r.File))
  83  	}
  84  }
  85  
  86  func TestZipParts_Empty(t *testing.T) {
  87  	// Both empty — should produce a valid (empty) zip
  88  	data, err := ZipParts("", nil)
  89  	if err != nil {
  90  		t.Fatalf("ZipParts: %v", err)
  91  	}
  92  
  93  	r, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
  94  	if err != nil {
  95  		t.Fatalf("read zip: %v", err)
  96  	}
  97  	if len(r.File) != 0 {
  98  		t.Errorf("expected 0 files, got %d", len(r.File))
  99  	}
 100  }
 101  
 102  func TestZipParts_ExceedsSizeLimit(t *testing.T) {
 103  	// crypto/rand data is incompressible — zip output will be >= input size
 104  	bigData := make([]byte, 26*1024*1024) // 26MB
 105  	crand.Read(bigData)
 106  
 107  	attachments := []bridgesmtp.Attachment{
 108  		{Filename: "huge.bin", ContentType: "application/octet-stream", Data: bigData},
 109  	}
 110  
 111  	_, err := ZipParts("", attachments)
 112  	if err == nil {
 113  		t.Fatal("expected error for exceeding zip size limit")
 114  	}
 115  	if !strings.Contains(err.Error(), "limit") {
 116  		t.Errorf("error should mention limit, got: %v", err)
 117  	}
 118  }
 119  
 120  func TestZipParts_EmptyFilename(t *testing.T) {
 121  	attachments := []bridgesmtp.Attachment{
 122  		{Filename: "", ContentType: "application/octet-stream", Data: []byte("data")},
 123  	}
 124  
 125  	data, err := ZipParts("", attachments)
 126  	if err != nil {
 127  		t.Fatalf("ZipParts: %v", err)
 128  	}
 129  
 130  	r, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
 131  	if err != nil {
 132  		t.Fatalf("read zip: %v", err)
 133  	}
 134  
 135  	if r.File[0].Name != "attachment" {
 136  		t.Errorf("fallback name = %q, want 'attachment'", r.File[0].Name)
 137  	}
 138  }
 139