@pippit-dev/cli 1.0.21 → 1.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,155 @@
1
+ package cmd
2
+
3
+ import (
4
+ "bytes"
5
+ "io"
6
+ "net/http"
7
+ "net/http/httptest"
8
+ "os"
9
+ "path/filepath"
10
+ "strings"
11
+ "testing"
12
+
13
+ "github.com/Pippit-dev/pippit-cli/internal/config"
14
+ )
15
+
16
+ func TestUploadFileMediaContract(t *testing.T) {
17
+ for _, name := range []string{"image.png", "image.WEBP", "video.mp4", "audio.mp3", "audio.WAV"} {
18
+ t.Run(name, func(t *testing.T) {
19
+ path := filepath.Join(t.TempDir(), name)
20
+ if err := os.WriteFile(path, []byte("media-content"), 0o600); err != nil {
21
+ t.Fatal(err)
22
+ }
23
+ calls := 0
24
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
25
+ calls++
26
+ if r.Method != http.MethodPost || r.URL.Path != config.UploadFilePath {
27
+ t.Errorf("unexpected request: %s %s", r.Method, r.URL.Path)
28
+ }
29
+ if r.Header.Get("Authorization") != "Bearer test-token" {
30
+ t.Error("missing bearer authorization")
31
+ }
32
+ body, err := io.ReadAll(r.Body)
33
+ if err != nil {
34
+ t.Error(err)
35
+ return
36
+ }
37
+ if bytes.Contains(body, []byte("test-token")) || bytes.Contains(body, []byte(`name="accessKey"`)) {
38
+ t.Error("credentials must not appear in multipart body")
39
+ }
40
+ r.Body = io.NopCloser(bytes.NewReader(body))
41
+ if err := r.ParseMultipartForm(1 << 20); err != nil {
42
+ t.Error(err)
43
+ return
44
+ }
45
+ defer r.MultipartForm.RemoveAll()
46
+ files := r.MultipartForm.File["file"]
47
+ if len(files) != 1 || files[0].Filename != name {
48
+ t.Errorf("unexpected file parts: %#v", files)
49
+ return
50
+ }
51
+ contentType := files[0].Header.Get("Content-Type")
52
+ prefix := "audio/"
53
+ if strings.HasPrefix(name, "image") {
54
+ prefix = "image/"
55
+ } else if strings.HasPrefix(name, "video") {
56
+ prefix = "video/"
57
+ }
58
+ if !strings.HasPrefix(contentType, prefix) {
59
+ t.Errorf("content type = %s, want %s", contentType, prefix)
60
+ }
61
+ file, err := files[0].Open()
62
+ if err != nil {
63
+ t.Error(err)
64
+ return
65
+ }
66
+ defer file.Close()
67
+ data, err := io.ReadAll(file)
68
+ if err != nil || string(data) != "media-content" {
69
+ t.Errorf("uploaded content = %q, err = %v", data, err)
70
+ }
71
+ _, _ = w.Write([]byte(`{"ret":"0","data":{"pippit_asset_id":"asset_original"}}`))
72
+ }))
73
+ defer server.Close()
74
+ var stdout, stderr bytes.Buffer
75
+ root := newTestRootCommand(t, &stdout, &stderr, server.URL)
76
+ root.SetArgs([]string{"upload-file", "--path", path})
77
+ if err := root.Execute(); err != nil {
78
+ t.Fatal(err)
79
+ }
80
+ if stdout.String() != "{\"asset_id\":\"asset_original\"}\n" || calls != 1 {
81
+ t.Fatalf("stdout = %q, requests = %d", stdout.String(), calls)
82
+ }
83
+ })
84
+ }
85
+ }
86
+
87
+ func TestValidateMediaUpload(t *testing.T) {
88
+ dir := t.TempDir()
89
+ for _, tc := range []struct {
90
+ name string
91
+ size int64
92
+ ok bool
93
+ }{
94
+ {"below-limit.png", maxMediaUploadBytes - 1, true},
95
+ {"at-limit.png", maxMediaUploadBytes, false},
96
+ {"over-limit.png", maxMediaUploadBytes + 1, false},
97
+ {"script.docx", 1, false},
98
+ {"audio.flac", 1, false},
99
+ {"file.unknown", 1, false},
100
+ } {
101
+ path := filepath.Join(dir, tc.name)
102
+ if err := os.WriteFile(path, nil, 0o600); err != nil {
103
+ t.Fatal(err)
104
+ }
105
+ // Sparse files exercise the exact size boundary without large allocations.
106
+ if err := os.Truncate(path, tc.size); err != nil {
107
+ t.Fatal(err)
108
+ }
109
+ if err := validateMediaUpload(path); (err == nil) != tc.ok {
110
+ t.Errorf("validateMediaUpload(%s) = %v, want accepted=%t", tc.name, err, tc.ok)
111
+ }
112
+ }
113
+ for _, path := range []string{"", dir, filepath.Join(dir, "missing.png")} {
114
+ if err := validateMediaUpload(path); err == nil {
115
+ t.Errorf("validateMediaUpload(%q) should fail", path)
116
+ }
117
+ }
118
+ }
119
+
120
+ func TestUploadFileCommandHelpAndArguments(t *testing.T) {
121
+ var stdout, stderr bytes.Buffer
122
+ root := newRootCommand(&stdout, &stderr, nil)
123
+ root.SetArgs([]string{"upload-file", "--help"})
124
+ if err := root.Execute(); err != nil || !strings.Contains(stdout.String(), "--path") {
125
+ t.Fatalf("help must work without credentials: %v, %s", err, stdout.String())
126
+ }
127
+ for _, args := range [][]string{{"upload-file"}, {"upload-file", "--path", " "}, {"upload-file", "unexpected"}} {
128
+ root := newRootCommand(&stdout, &stderr, nil)
129
+ root.SetArgs(args)
130
+ if err := root.Execute(); err == nil {
131
+ t.Errorf("Execute(%v) should fail", args)
132
+ }
133
+ }
134
+ }
135
+
136
+ func TestUploadFileRejectsInvalidResponse(t *testing.T) {
137
+ path := filepath.Join(t.TempDir(), "image.png")
138
+ if err := os.WriteFile(path, []byte("media"), 0o600); err != nil {
139
+ t.Fatal(err)
140
+ }
141
+ for _, response := range []string{`{"ret":"1","errmsg":"rejected"}`, `{"ret":"0","data":{"asset_id":"wrong_field"}}`} {
142
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
143
+ _, _ = io.Copy(io.Discard, r.Body)
144
+ _, _ = w.Write([]byte(response))
145
+ }))
146
+ var stdout, stderr bytes.Buffer
147
+ root := newTestRootCommand(t, &stdout, &stderr, server.URL)
148
+ root.SetArgs([]string{"upload-file", "--path", path})
149
+ err := root.Execute()
150
+ server.Close()
151
+ if err == nil || stdout.Len() != 0 {
152
+ t.Errorf("response %s: error = %v, stdout = %s", response, err, stdout.String())
153
+ }
154
+ }
155
+ }
@@ -1,6 +1,6 @@
1
- c1657ee91f7f964dd936ecd723ff4985c12be4585f7f64dff96adba0277ec669 pippit-tool-cli-1.0.21-darwin-amd64.tar.gz
2
- ebfe75d1a8fbd6e76125b49917e97a3a81db6c4bae35ab5a1cb9625c618ea490 pippit-tool-cli-1.0.21-darwin-arm64.tar.gz
3
- 3d828780c00f985378df61072d633e84dd2bcba3b8f7b7e6619fbd9ee34bf2a2 pippit-tool-cli-1.0.21-linux-amd64.tar.gz
4
- 14dfb1412da253c62a4a52c27a40ce09c3af8480be9c4a94565952e7eed9afff pippit-tool-cli-1.0.21-linux-arm64.tar.gz
5
- 0d7b8bc575efb3928f8881cb2ba76f2583c2d4ed3f53c7ab3c98f53cf278d0c3 pippit-tool-cli-1.0.21-windows-amd64.zip
6
- 3145e59e584bfd618b06d8a4e1586d242ff8c568f7221737f2f06d8f111a2cd7 pippit-tool-cli-1.0.21-windows-arm64.zip
1
+ 259ad5fb69598b646e035e5dd70fd6c905a25128b1b9c8e9689c58e09ec0a3d9 pippit-tool-cli-1.0.23-darwin-amd64.tar.gz
2
+ 610ec13e42a53a472759daf322701e178b062ff2ca2e854382cf5a8b6b894953 pippit-tool-cli-1.0.23-darwin-arm64.tar.gz
3
+ 3d371bb915e4b6adaf29cd3b1b06a9ee6a40896f962051ce97adeb1937a1b4a1 pippit-tool-cli-1.0.23-linux-amd64.tar.gz
4
+ 541f8a8e1913a591ad98ed3835525eba8459fd12ec289f9b206f9588812311c8 pippit-tool-cli-1.0.23-linux-arm64.tar.gz
5
+ 0ded272a827aa39427c53135465c99e6e1f94c81ef1f5e0982c6726d385e03bf pippit-tool-cli-1.0.23-windows-amd64.zip
6
+ ab6fd1baeac84e4e3cdde2392462534bd2a6279ee1cab0395437f1a03b5ace55 pippit-tool-cli-1.0.23-windows-arm64.zip