1
1
package client_test
2
2
3
3
import (
4
+ "bytes"
4
5
"context"
5
6
"encoding/base64"
6
7
"encoding/json"
@@ -16,6 +17,7 @@ import (
16
17
"github.com/kardolus/chatgpt-cli/history"
17
18
"github.com/kardolus/chatgpt-cli/internal"
18
19
"github.com/kardolus/chatgpt-cli/test"
20
+ "io"
19
21
"os"
20
22
"strings"
21
23
"testing"
@@ -1060,7 +1062,7 @@ func testClient(t *testing.T, when spec.G, it spec.S) {
1060
1062
})
1061
1063
it ("throws an error when the http call fails" , func () {
1062
1064
mockCaller .EXPECT ().
1063
- Post (subject .Config .URL + subject .Config .DrawPath , body , false ).
1065
+ Post (subject .Config .URL + subject .Config .ImageGenerationsPath , body , false ).
1064
1066
Return (nil , errors .New (errorText ))
1065
1067
1066
1068
err := subject .GenerateImage (inputText , outputFile )
@@ -1069,7 +1071,7 @@ func testClient(t *testing.T, when spec.G, it spec.S) {
1069
1071
})
1070
1072
it ("throws an error when no image data is returned" , func () {
1071
1073
mockCaller .EXPECT ().
1072
- Post (subject .Config .URL + subject .Config .DrawPath , body , false ).
1074
+ Post (subject .Config .URL + subject .Config .ImageGenerationsPath , body , false ).
1073
1075
Return ([]byte (`{"data":[]}` ), nil )
1074
1076
1075
1077
err := subject .GenerateImage (inputText , outputFile )
@@ -1078,7 +1080,7 @@ func testClient(t *testing.T, when spec.G, it spec.S) {
1078
1080
})
1079
1081
it ("throws an error when base64 is invalid" , func () {
1080
1082
mockCaller .EXPECT ().
1081
- Post (subject .Config .URL + subject .Config .DrawPath , body , false ).
1083
+ Post (subject .Config .URL + subject .Config .ImageGenerationsPath , body , false ).
1082
1084
Return ([]byte (`{"data":[{"b64_json":"!!notbase64!!"}]}` ), nil )
1083
1085
1084
1086
err := subject .GenerateImage (inputText , outputFile )
@@ -1089,7 +1091,7 @@ func testClient(t *testing.T, when spec.G, it spec.S) {
1089
1091
valid := base64 .StdEncoding .EncodeToString ([]byte ("image-bytes" ))
1090
1092
1091
1093
mockCaller .EXPECT ().
1092
- Post (subject .Config .URL + subject .Config .DrawPath , body , false ).
1094
+ Post (subject .Config .URL + subject .Config .ImageGenerationsPath , body , false ).
1093
1095
Return ([]byte (fmt .Sprintf (`{"data":[{"b64_json":"%s"}]}` , valid )), nil )
1094
1096
1095
1097
mockWriter .EXPECT ().Create (outputFile ).Return (nil , errors .New (errorText ))
@@ -1105,7 +1107,7 @@ func testClient(t *testing.T, when spec.G, it spec.S) {
1105
1107
defer file .Close ()
1106
1108
1107
1109
mockCaller .EXPECT ().
1108
- Post (subject .Config .URL + subject .Config .DrawPath , body , false ).
1110
+ Post (subject .Config .URL + subject .Config .ImageGenerationsPath , body , false ).
1109
1111
Return ([]byte (fmt .Sprintf (`{"data":[{"b64_json":"%s"}]}` , valid )), nil )
1110
1112
1111
1113
mockWriter .EXPECT ().Create (outputFile ).Return (file , nil )
@@ -1122,7 +1124,7 @@ func testClient(t *testing.T, when spec.G, it spec.S) {
1122
1124
defer file .Close ()
1123
1125
1124
1126
mockCaller .EXPECT ().
1125
- Post (subject .Config .URL + subject .Config .DrawPath , body , false ).
1127
+ Post (subject .Config .URL + subject .Config .ImageGenerationsPath , body , false ).
1126
1128
Return ([]byte (fmt .Sprintf (`{"data":[{"b64_json":"%s"}]}` , valid )), nil )
1127
1129
1128
1130
mockWriter .EXPECT ().Create (outputFile ).Return (file , nil )
@@ -1132,6 +1134,100 @@ func testClient(t *testing.T, when spec.G, it spec.S) {
1132
1134
Expect (err ).NotTo (HaveOccurred ())
1133
1135
})
1134
1136
})
1137
+ when ("EditImage()" , func () {
1138
+ const (
1139
+ inputText = "give the dog sunglasses"
1140
+ inputFile = "dog.png"
1141
+ outputFile = "dog_cool.png"
1142
+ errorText = "mock error occurred"
1143
+ )
1144
+
1145
+ var (
1146
+ subject * client.Client
1147
+ validB64 string
1148
+ imageBytes = []byte ("image-bytes" )
1149
+ respBytes []byte
1150
+ )
1151
+
1152
+ it .Before (func () {
1153
+ subject = factory .buildClientWithoutConfig ()
1154
+ validB64 = base64 .StdEncoding .EncodeToString (imageBytes )
1155
+ respBytes = []byte (fmt .Sprintf (`{"data":[{"b64_json":"%s"}]}` , validB64 ))
1156
+ })
1157
+
1158
+ it ("returns error when input file can't be opened" , func () {
1159
+ mockReader .EXPECT ().Open (inputFile ).Return (nil , errors .New (errorText ))
1160
+
1161
+ err := subject .EditImage (inputText , inputFile , outputFile )
1162
+ Expect (err ).To (HaveOccurred ())
1163
+ Expect (err .Error ()).To (ContainSubstring ("failed to open input image" ))
1164
+ })
1165
+ it ("returns error on invalid mime type" , func () {
1166
+ file := openDummy ()
1167
+ mockReader .EXPECT ().Open (inputFile ).Return (file , nil ).Times (2 )
1168
+ mockReader .EXPECT ().ReadBufferFromFile (file ).Return ([]byte ("not an image" ), nil )
1169
+
1170
+ err := subject .EditImage (inputText , inputFile , outputFile )
1171
+ Expect (err ).To (HaveOccurred ())
1172
+ Expect (err .Error ()).To (ContainSubstring ("unsupported MIME type" ))
1173
+ })
1174
+ it ("returns error when HTTP call fails" , func () {
1175
+ mockReader .EXPECT ().Open (inputFile ).DoAndReturn (func (string ) (* os.File , error ) {
1176
+ return openDummy (), nil
1177
+ }).Times (2 )
1178
+
1179
+ mockReader .EXPECT ().
1180
+ ReadBufferFromFile (gomock .AssignableToTypeOf (& os.File {})).
1181
+ Return ([]byte ("\x89 PNG\r \n \x1a \n " ), nil )
1182
+
1183
+ mockCaller .EXPECT ().
1184
+ PostWithHeaders (gomock .Any (), gomock .Any (), gomock .Any ()).
1185
+ Return (nil , errors .New (errorText ))
1186
+
1187
+ err := subject .EditImage (inputText , inputFile , outputFile )
1188
+ Expect (err ).To (HaveOccurred ())
1189
+ Expect (err .Error ()).To (ContainSubstring ("failed to edit image" ))
1190
+ })
1191
+ it ("returns error when base64 is invalid" , func () {
1192
+ invalidResp := []byte (`{"data":[{"b64_json":"!notbase64"}]}` )
1193
+
1194
+ mockReader .EXPECT ().Open (inputFile ).DoAndReturn (func (string ) (* os.File , error ) {
1195
+ return openDummy (), nil
1196
+ }).Times (2 )
1197
+
1198
+ mockReader .EXPECT ().
1199
+ ReadBufferFromFile (gomock .AssignableToTypeOf (& os.File {})).
1200
+ Return ([]byte ("\x89 PNG\r \n \x1a \n " ), nil )
1201
+
1202
+ mockCaller .EXPECT ().
1203
+ PostWithHeaders (gomock .Any (), gomock .Any (), gomock .Any ()).
1204
+ Return (invalidResp , nil )
1205
+
1206
+ err := subject .EditImage (inputText , inputFile , outputFile )
1207
+ Expect (err ).To (HaveOccurred ())
1208
+ Expect (err .Error ()).To (ContainSubstring ("failed to decode base64 image" ))
1209
+ })
1210
+ it ("writes image when all steps succeed" , func () {
1211
+ file := openDummy ()
1212
+ mockReader .EXPECT ().Open (inputFile ).DoAndReturn (func (string ) (* os.File , error ) {
1213
+ return openDummy (), nil
1214
+ }).Times (2 )
1215
+
1216
+ mockReader .EXPECT ().
1217
+ ReadBufferFromFile (gomock .AssignableToTypeOf (& os.File {})).
1218
+ Return ([]byte ("\x89 PNG\r \n \x1a \n " ), nil )
1219
+
1220
+ mockCaller .EXPECT ().
1221
+ PostWithHeaders (gomock .Any (), gomock .Any (), gomock .Any ()).
1222
+ Return (respBytes , nil )
1223
+
1224
+ mockWriter .EXPECT ().Create (outputFile ).Return (file , nil )
1225
+ mockWriter .EXPECT ().Write (file , imageBytes ).Return (nil )
1226
+
1227
+ err := subject .EditImage (inputText , inputFile , outputFile )
1228
+ Expect (err ).NotTo (HaveOccurred ())
1229
+ })
1230
+ })
1135
1231
when ("Transcribe()" , func () {
1136
1232
const audioPath = "path/to/audio.wav"
1137
1233
const transcribedText = "Hello, this is a test."
@@ -1535,6 +1631,16 @@ func testClient(t *testing.T, when spec.G, it spec.S) {
1535
1631
})
1536
1632
}
1537
1633
1634
+ func openDummy () * os.File {
1635
+ // Use os.Pipe to get an *os.File without needing a real disk file.
1636
+ r , w , _ := os .Pipe ()
1637
+ go func () {
1638
+ _ , _ = io .Copy (w , bytes .NewBuffer ([]byte ("\x89 PNG\r \n \x1a \n " )))
1639
+ _ = w .Close ()
1640
+ }()
1641
+ return r
1642
+ }
1643
+
1538
1644
func createBody (messages []api.Message , stream bool ) ([]byte , error ) {
1539
1645
req := api.CompletionsRequest {
1540
1646
Model : config .Model ,
0 commit comments