github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/api/parse_request_test.go (about) 1 package api 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "mime/multipart" 7 "net/http" 8 "net/http/httptest" 9 "testing" 10 11 "github.com/google/go-cmp/cmp" 12 "github.com/google/go-cmp/cmp/cmpopts" 13 "github.com/gorilla/mux" 14 "github.com/qri-io/dataset" 15 "github.com/qri-io/qri/base/params" 16 "github.com/qri-io/qri/lib" 17 ) 18 19 func TestParseGetParamsFromRequest(t *testing.T) { 20 cases := []struct { 21 description string 22 url string 23 expectParams *lib.GetParams 24 muxVars map[string]string 25 }{ 26 { 27 "basic get", 28 "/get/peer/my_ds", 29 &lib.GetParams{ 30 Ref: "peer/my_ds", 31 All: true, 32 }, 33 map[string]string{"username": "peer", "name": "my_ds"}, 34 }, 35 { 36 "get request with ref", 37 "/get/peer/my_ds", 38 &lib.GetParams{ 39 Ref: "peer/my_ds", 40 All: true, 41 }, 42 map[string]string{"ref": "peer/my_ds"}, 43 }, 44 { 45 "meta component", 46 "/get/peer/my_ds/meta", 47 &lib.GetParams{ 48 Ref: "peer/my_ds", 49 Selector: "meta", 50 All: true, 51 }, 52 map[string]string{"username": "peer", "name": "my_ds", "selector": "meta"}, 53 }, 54 { 55 "get request with limit and offset", 56 "/get/peer/my_ds/body", 57 &lib.GetParams{ 58 Ref: "peer/my_ds", 59 Selector: "body", 60 List: params.List{ 61 Offset: 10, 62 Limit: 0, 63 }, 64 }, 65 map[string]string{"ref": "peer/my_ds", "selector": "body", "limit": "0", "offset": "10"}, 66 }, 67 { 68 "get request with 'all'", 69 "/get/peer/my_ds/body", 70 &lib.GetParams{ 71 Ref: "peer/my_ds", 72 Selector: "body", 73 All: true, 74 }, 75 map[string]string{"ref": "peer/my_ds", "selector": "body", "all": "true"}, 76 }, 77 } 78 for _, c := range cases { 79 t.Run(c.description, func(t *testing.T) { 80 r, _ := http.NewRequest("GET", c.url, nil) 81 if c.muxVars != nil { 82 r = mux.SetURLVars(r, c.muxVars) 83 } 84 r = mustSetMuxVarsOnRequest(t, r, c.muxVars) 85 gotParams := &lib.GetParams{} 86 if err := parseGetParamsFromRequest(r, gotParams); err != nil { 87 t.Error(err) 88 return 89 } 90 if diff := cmp.Diff(c.expectParams, gotParams); diff != "" { 91 t.Errorf("output mismatch (-want +got):\n%s", diff) 92 } 93 }) 94 } 95 96 badCases := []struct { 97 description string 98 url string 99 expectErr string 100 muxVars map[string]string 101 }{ 102 { 103 "get me", 104 "/get/me/my_ds", 105 `username "me" not allowed`, 106 map[string]string{"ref": "me/my_ds"}, 107 }, 108 { 109 "bad parse", 110 "/get/peer/my+ds", 111 `unexpected character at position 7: '+'`, 112 map[string]string{"ref": "peer/my+ds"}, 113 }, 114 } 115 for i, c := range badCases { 116 t.Run(c.description, func(t *testing.T) { 117 r := httptest.NewRequest("GET", c.url, nil) 118 r = mustSetMuxVarsOnRequest(t, r, c.muxVars) 119 gotParams := &lib.GetParams{} 120 err := parseGetParamsFromRequest(r, gotParams) 121 if err == nil { 122 t.Errorf("case %d: expected error, but did not get one", i) 123 return 124 } 125 if diff := cmp.Diff(c.expectErr, err.Error()); diff != "" { 126 t.Errorf("output mismatch (-want +got):\n%s", diff) 127 } 128 }) 129 } 130 } 131 132 func TestParseSaveParamsFromRequest(t *testing.T) { 133 expect := &lib.SaveParams{ 134 Ref: "test/ref", 135 Title: "test title", 136 Message: "test message", 137 Apply: true, 138 Replace: true, 139 ConvertFormatToPrev: true, 140 Drop: "drop", 141 Force: true, 142 NewName: true, 143 Dataset: &dataset.Dataset{ 144 Name: "dataset name", 145 Peername: "test peername", 146 Meta: &dataset.Meta{ 147 Title: "test meta title", 148 Qri: "md:0", 149 }, 150 }, 151 } 152 153 dsBytes, err := json.Marshal(expect.Dataset) 154 if err != nil { 155 t.Fatalf("error marshaling dataset: %s", err) 156 } 157 158 body := new(bytes.Buffer) 159 writer := multipart.NewWriter(body) 160 writer.WriteField("ref", expect.Ref) 161 writer.WriteField("title", expect.Title) 162 writer.WriteField("message", expect.Message) 163 writer.WriteField("apply", "true") 164 writer.WriteField("replace", "true") 165 writer.WriteField("convertFormatToPrev", "true") 166 writer.WriteField("drop", "drop") 167 writer.WriteField("force", "true") 168 writer.WriteField("newName", "true") 169 writer.WriteField("dataset", string(dsBytes)) 170 writer.Close() 171 172 r, err := http.NewRequest(http.MethodPost, "save", body) 173 if err != nil { 174 t.Fatalf("error creating new request: %s", err) 175 } 176 r.Header.Add("Content-Type", writer.FormDataContentType()) 177 got := &lib.SaveParams{} 178 err = parseSaveParamsFromRequest(r, got) 179 if err != nil { 180 t.Fatalf("error saving params from request: %s", err) 181 } 182 if diff := cmp.Diff(expect, got, cmpopts.IgnoreUnexported(dataset.Dataset{}), cmpopts.IgnoreUnexported(dataset.Meta{})); diff != "" { 183 t.Errorf("SaveParams mismatch (-want +got):%s\n", diff) 184 } 185 } 186 187 func TestParseDatasetFromRequest(t *testing.T) { 188 r := newFormFileRequest(t, "/", nil, nil) 189 dsp := &dataset.Dataset{} 190 if err := parseDatasetFromRequest(r, dsp); err != nil { 191 t.Error("expected 'empty' request to be ok") 192 } 193 194 r = newFormFileRequest(t, "/", map[string]string{ 195 "file": dstestTestdataFile("cities/init_dataset.json"), 196 "viz": dstestTestdataFile("cities/template.html"), 197 "transform": dstestTestdataFile("cities/transform.star"), 198 "readme": dstestTestdataFile("cities/readme.md"), 199 "body": dstestTestdataFile("cities/data.csv"), 200 }, nil) 201 if err := parseDatasetFromRequest(r, dsp); err != nil { 202 t.Error(err) 203 } 204 205 r = newFormFileRequest(t, "/", map[string]string{ 206 "file": "testdata/cities/dataset.yml", 207 "body": dstestTestdataFile("cities/data.csv"), 208 }, nil) 209 if err := parseDatasetFromRequest(r, dsp); err != nil { 210 t.Error(err) 211 } 212 }