func TestBatchDo(t *testing.T) { const ( method = "GET" relativeURL = "/me" accessToken = "at" appID = 42 ) given := []*Response{{Code: 42}} br := &Request{ Method: method, RelativeURL: relativeURL, } b := &Batch{ AccessToken: accessToken, AppID: appID, Request: []*Request{br}, } c := &fbapi.Client{ Transport: fTransport(func(r *http.Request) (*http.Response, error) { ensure.Nil(t, r.ParseForm()) ensure.DeepEqual(t, r.URL.String(), "https://graph.facebook.com/") ensure.DeepEqual(t, r.Method, "POST") ensure.DeepEqual(t, r.PostFormValue("access_token"), accessToken) ensure.DeepEqual(t, r.PostFormValue("batch_app_id"), fmt.Sprint(appID)) return &http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser(jsonpipe.Encode(given)), }, nil }), } actual, err := BatchDo(c, b) ensure.Nil(t, err) ensure.DeepEqual(t, actual, given) }
func TestLatestVersion(t *testing.T) { t.Parallel() h := parsecli.NewHarness(t) defer h.Stop() ht := parsecli.TransportFunc(func(r *http.Request) (*http.Response, error) { ensure.DeepEqual(t, r.URL.Path, "/1/supported") return &http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser( jsonpipe.Encode( map[string]string{"version": "2.0.2"}, ), ), }, nil }) h.Env.ParseAPIClient = &parsecli.ParseAPIClient{APIClient: &parse.Client{Transport: ht}} u := new(updateCmd) latestVersion, err := u.latestVersion(h.Env) ensure.Nil(t, err) ensure.DeepEqual(t, latestVersion, "2.0.2") downloadURL, err := u.getDownloadURL(h.Env) ensure.StringContains(t, downloadURL, "https://github.com/ParsePlatform/parse-cli/releases/download/release_2.0.2") }
func (l *Login) AuthToken(e *Env, token string) (string, error) { req := &http.Request{ Method: "POST", URL: &url.URL{Path: "accountkey"}, Body: ioutil.NopCloser( jsonpipe.Encode( map[string]string{ "accountKey": token, }, ), ), } res := &struct { Email string `json:"email"` }{} if response, err := e.ParseAPIClient.Do(req, nil, res); err != nil { if response != nil && response.StatusCode == http.StatusUnauthorized { return "", stackerr.Newf(tokenErrMsgf, Last4(token), keysURL) } return "", stackerr.Wrap(err) } if e.ParserEmail != "" && res.Email != e.ParserEmail { return "", stackerr.Newf("Account key %q does not belong to %q", Last4(token), e.ParserEmail) } return res.Email, nil }
func TestClientDo(t *testing.T) { given := map[string]string{"answer": "42"} givenJSON, err := json.Marshal(given) ensure.Nil(t, err) wrapped := []map[string]interface{}{ { "code": http.StatusOK, "body": string(givenJSON), }, } c := &Client{ Client: &fbapi.Client{ Transport: fTransport(func(r *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser(jsonpipe.Encode(wrapped)), }, nil }), }, } var actual map[string]string _, err = c.Do(&http.Request{ Method: "GET", URL: &url.URL{}, }, &actual) ensure.Nil(t, err) ensure.DeepEqual(t, actual, given) }
func (b *batch) fire() error { if b.Client.Debug { log.Printf("stathat: sending batch with %d items", len(b.Data)) } const url = "http://api.stathat.com/ez" req, err := http.NewRequest("POST", url, jsonpipe.Encode(b)) if err != nil { return fmt.Errorf("stathat: error creating http request: %s", err) } req.Header.Add("Content-Type", "application/json") resp, err := b.Client.Transport.RoundTrip(req) if err != nil { return fmt.Errorf("stathat: %s", err) } defer resp.Body.Close() var br batchResponse err = json.NewDecoder(resp.Body).Decode(&br) if err != nil { return fmt.Errorf("stathat: error decoding response: %s", err) } if br.Status != 200 { return fmt.Errorf("stathat: api error: %+v", &br) } else if b.Client.Debug { log.Printf("stathat: api response: %+v", &br) } return nil }
func TestValidResponse(t *testing.T) { t.Parallel() given := map[string]string{"answer": "42"} c := &fbapi.Client{ Transport: fTransport(func(r *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser(jsonpipe.Encode(given)), }, nil }), } var actual map[string]string _, err := c.Do(&http.Request{Method: "GET"}, &actual) ensure.Nil(t, err) ensure.DeepEqual(t, actual, given) }
func (a *apps) restCreateApp(e *env, appName string) (*app, error) { req := &http.Request{ Method: "POST", URL: &url.URL{Path: "apps"}, Header: getAuthHeaders(&a.login.credentials, nil), Body: ioutil.NopCloser(jsonpipe.Encode(map[string]string{"appName": appName})), } var res app if response, err := e.ParseAPIClient.Do(req, nil, &res); err != nil { if response != nil && response.StatusCode == http.StatusUnauthorized { return nil, errAuth } return nil, err } return &res, nil }
func (h *herokuLink) createNewLink(e *parsecli.Env, herokuAppName string) (string, error) { var l parsecli.Login _, err := l.AuthUserWithToken(e, true) if err != nil { return "", stackerr.Wrap(err) } req, err := http.NewRequest( "POST", "herokuLink", ioutil.NopCloser( jsonpipe.Encode( map[string]string{"herokuAppName": herokuAppName}, ), ), ) if err != nil { return "", stackerr.Wrap(err) } req.Header = make(http.Header) req.Header.Set("X-Parse-Application-Id", h.parseAppID) req.Header.Set("X-Parse-Account-Key", l.Credentials.Token) resp, err := e.ParseAPIClient.RoundTrip(req) if err != nil { if herokuAppNameTaken(err) { fmt.Fprintln(e.Err, ` Please provide a unique name that might not already be taken on Heroku. `) } return "", stackerr.Wrap(err) } result := &struct { Name string `json:"name"` ID string `json:"id"` }{} if err := json.NewDecoder(resp.Body).Decode(result); err != nil { return "", stackerr.Wrap(err) } if result.Name != herokuAppName || result.ID == "" { return "", stackerr.New("could not create heroku app link") } return result.ID, nil }
func (d *deployCmd) uploadFile(filename, endpoint string, e *parsecli.Env, normalizeName func(string) string) (string, error) { content, err := ioutil.ReadFile(filename) if err != nil { return "", err } req, err := http.NewRequest( "POST", endpoint, ioutil.NopCloser( jsonpipe.Encode( map[string]interface{}{ "name": normalizeName(filename), "content": content, }, ), ), ) if err != nil { return "", stackerr.Wrap(err) } mimeType := mime.TypeByExtension(filepath.Ext(filename)) if mimeType == "" { mimeType = "application/octet-stream" } req.Header.Add("Content-Type", mimeType) var res struct { Version string `json:"version"` } if _, err := e.ParseAPIClient.Do(req, nil, &res); err != nil { return "", stackerr.Wrap(err) } if res.Version == "" { return "", stackerr.Newf("Malformed response when trying to upload %s", filename) } return res.Version, nil }
func TestErrorResponse(t *testing.T) { t.Parallel() givenErr := &fbapi.Error{ Message: "message42", Type: "type42", Code: 42, } given := map[string]interface{}{"error": givenErr} c := &fbapi.Client{ Transport: fTransport(func(r *http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusBadRequest, Body: ioutil.NopCloser(jsonpipe.Encode(given)), }, nil }), } var actual map[string]string _, err := c.Do(&http.Request{Method: "GET"}, &actual) ensure.DeepEqual(t, err, givenErr) }
func (c *HerokuAppConfig) GetApplicationAuth(e *Env) (string, error) { if c.herokuAccessToken != "" { return c.herokuAccessToken, nil } var l Login _, err := l.AuthUserWithToken(e, true) if err != nil { return "", err } req, err := http.NewRequest( "POST", "herokuToken", ioutil.NopCloser( jsonpipe.Encode( map[string]string{ "id": c.HerokuAppID, }, ), ), ) if err != nil { return "", stackerr.Wrap(err) } req.Header = make(http.Header) req.Header.Set("X-Parse-Application-Id", c.ParseAppID) req.Header.Set("X-Parse-Account-Key", l.Credentials.Token) resp, err := e.ParseAPIClient.RoundTrip(req) if err != nil { return "", stackerr.Wrap(err) } result := &struct { Token string `json:"token"` }{} if err := json.NewDecoder(resp.Body).Decode(result); err != nil { return "", stackerr.Wrap(err) } c.herokuAccessToken = result.Token return result.Token, nil }
func TestIsSupportedError(t *testing.T) { t.Parallel() h := parsecli.NewHarness(t) defer h.Stop() ht := parsecli.TransportFunc(func(r *http.Request) (*http.Response, error) { ensure.DeepEqual(t, r.URL.Path, "/1/supported") return &http.Response{ StatusCode: http.StatusBadRequest, Body: ioutil.NopCloser( jsonpipe.Encode( map[string]string{"error": "not supported"}, ), ), }, nil }) h.Env.ParseAPIClient = &parsecli.ParseAPIClient{APIClient: &parse.Client{Transport: ht}} _, err := checkIfSupported(h.Env, "2.0.2", "parse") ensure.Err(t, err, regexp.MustCompile("not supported")) }
func (a *apps) restCreateApp(e *env, appName string) (*app, error) { req := &http.Request{ Method: "POST", URL: &url.URL{Path: "apps"}, Header: make(http.Header), Body: ioutil.NopCloser(jsonpipe.Encode(map[string]string{"appName": appName})), } req.Header.Add("X-Parse-Email", a.login.credentials.email) req.Header.Add("X-Parse-Password", a.login.credentials.password) var res app if response, err := e.Client.Do(req, nil, &res); err != nil { if response != nil && response.StatusCode == http.StatusUnauthorized { return nil, errAuth } return nil, err } return &res, nil }
func TestIsSupportedWarning(t *testing.T) { t.Parallel() h := parsecli.NewHarness(t) defer h.Stop() ht := parsecli.TransportFunc(func(r *http.Request) (*http.Response, error) { ensure.DeepEqual(t, r.URL.Path, "/1/supported") return &http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser( jsonpipe.Encode( map[string]string{"warning": "please update"}, ), ), }, nil }) h.Env.ParseAPIClient = &parsecli.ParseAPIClient{APIClient: &parse.Client{Transport: ht}} message, err := checkIfSupported(h.Env, "2.0.2", "parse") ensure.Nil(t, err) ensure.DeepEqual(t, message, "please update") }
// removeStaleLinks tries to best effort delete stale links // where corresponding heroku app was deleted func (h *herokuLink) removeStaleLinks(e *parsecli.Env, token string, removeLinks []string) { for _, removeLink := range removeLinks { req, err := http.NewRequest( "DELETE", "herokuLink", jsonpipe.Encode( map[string]string{"herokuAppId": removeLink}, ), ) if err != nil { continue } req.Header = make(http.Header) req.Header.Set("X-Parse-Application-Id", h.parseAppID) req.Header.Set("X-Parse-Account-Key", token) _, err = e.ParseAPIClient.RoundTrip(req) if err != nil { continue } } }
func TestLatestVersion(t *testing.T) { t.Parallel() h := newHarness(t) defer h.Stop() ht := transportFunc(func(r *http.Request) (*http.Response, error) { ensure.DeepEqual(t, r.URL.Path, "/1/supported") return &http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser( jsonpipe.Encode( map[string]string{"version": "2.0.2"}, ), ), }, nil }) h.env.ParseAPIClient = &ParseAPIClient{apiClient: &parse.Client{Transport: ht}} u := new(updateCmd) latestVersion, err := u.latestVersion(h.env) ensure.Nil(t, err) ensure.DeepEqual(t, latestVersion, "2.0.2") }
func newTriggersHarness(t testing.TB) *Harness { h := newHarness(t) defer h.Stop() ht := transportFunc(func(r *http.Request) (*http.Response, error) { var body interface{} var params map[string]interface{} if r.Body != nil { err := json.NewDecoder(r.Body).Decode(¶ms) if err != nil { return &http.Response{StatusCode: http.StatusInternalServerError}, err } } switch r.Method { case "GET": if r.URL.Path == "/1/hooks/triggers/foo/beforeSave" { body = map[string]interface{}{ "results": []map[string]interface{}{ {"className": "foo", "triggerName": "beforeSave"}, {"className": "foo", "triggerName": "beforeSave", "url": "https://api.example.com/foo/beforeSave"}, }, } } else { ensure.DeepEqual(t, r.URL.Path, defaultTriggersURL) body = map[string]interface{}{ "results": []map[string]interface{}{ {"className": "foo", "triggerName": "beforeSave"}, {"className": "foo", "triggerName": "beforeSave", "url": "https://api.example.com/foo/beforeSave"}, {"className": "bar", "triggerName": "afterSave", "url": "https://api.example.com/bar/afterSave"}, }, } } case "POST": ensure.DeepEqual(t, r.URL.Path, defaultTriggersURL) switch fmt.Sprintf("%v:%v", params["className"], params["triggerName"]) { case "foo:beforeSave": body = map[string]interface{}{ "className": "foo", "triggerName": "beforeSave", "url": "https://api.example.com/foo/beforeSave", "warning": "beforeSave trigger already exists for class: foo", } case "bar:afterSave": body = map[string]interface{}{ "className": "bar", "triggerName": "afterSave", "url": "https://api.example.com/bar/afterSave", } default: return &http.Response{StatusCode: http.StatusInternalServerError}, errors.New("invalid params") } case "PUT": if params["__op"] == "Delete" && strings.HasPrefix(r.URL.Path, "/foo/beforeSave") { ensure.DeepEqual(t, r.URL.Path, "/1/hooks/triggers/foo/beforeSave") body = map[string]interface{}{"className": "foo", "triggerName": "beforeSave"} } else { switch strings.Replace(r.URL.Path, defaultTriggersURL, "", 1) { case "/foo/beforeSave": ensure.DeepEqual(t, r.URL.Path, "/1/hooks/triggers/foo/beforeSave") body = map[string]interface{}{ "className": "foo", "triggerName": "beforeSave", "url": "https://api.example.com/_foo/beforeSave", "warning": "beforeSave trigger already exists for class: foo", } case "/bar/afterSave": ensure.DeepEqual(t, r.URL.Path, "/1/hooks/triggers/bar/afterSave") body = map[string]interface{}{ "className": "bar", "triggerName": "afterSave", "url": "https://api.example.com/_bar/afterSave", } default: return &http.Response{StatusCode: http.StatusInternalServerError}, errors.New("invalid params") } } } return &http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser(jsonpipe.Encode(body)), }, nil }) h.env.Client = &Client{client: &parse.Client{Transport: ht}} return h }
func newFunctionsHarness(t testing.TB) *parsecli.Harness { h := parsecli.NewHarness(t) defer h.Stop() ht := parsecli.TransportFunc(func(r *http.Request) (*http.Response, error) { var body interface{} var params map[string]interface{} if r.Body != nil { err := json.NewDecoder(r.Body).Decode(¶ms) if err != nil { return &http.Response{StatusCode: http.StatusInternalServerError}, err } } switch r.Method { case "GET": if r.URL.Path == "/1/hooks/functions/foo" { body = map[string]interface{}{ "results": []map[string]interface{}{ {"functionName": "foo"}, {"functionName": "foo", "url": "https://api.example.com/foo"}, }, } } else if r.URL.Path == defaultFunctionsURL { body = map[string]interface{}{ "results": []map[string]interface{}{ {"functionName": "foo"}, {"functionName": "foo", "url": "https://api.example.com/foo"}, {"functionName": "bar", "url": "https://api.example.com/bar"}, }, } } else { return &http.Response{StatusCode: http.StatusBadRequest}, errors.New("no such function hook is defined") } case "POST": ensure.DeepEqual(t, r.URL.Path, defaultFunctionsURL) switch params["functionName"] { case "foo": body = map[string]interface{}{ "functionName": "foo", "url": "https://api.example.com/foo", "warning": "function foo already exists", } case "bar": body = map[string]interface{}{ "functionName": "bar", "url": "https://api.example.com/bar", } default: return &http.Response{StatusCode: http.StatusInternalServerError}, errors.New("invalid function name") } case "PUT": if params["__op"] == "Delete" && strings.HasPrefix(r.URL.Path, "/foo") { ensure.DeepEqual(t, r.URL.Path, "/1/hooks/functions/foo") body = map[string]interface{}{"functionName": "foo"} } else { switch strings.Replace(r.URL.Path, "/1/hooks/functions/", "", 1) { case "foo": ensure.DeepEqual(t, r.URL.Path, "/1/hooks/functions/foo") body = map[string]interface{}{ "functionName": "foo", "url": "https://api.example.com/_foo", "warning": "function foo already exists", } case "bar": ensure.DeepEqual(t, r.URL.Path, "/1/hooks/functions/bar") body = map[string]interface{}{ "functionName": "bar", "url": "https://api.example.com/_bar", } default: return &http.Response{StatusCode: http.StatusInternalServerError}, errors.New("invalid function name") } } } return &http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser(jsonpipe.Encode(body)), }, nil }) h.Env.ParseAPIClient = &parsecli.ParseAPIClient{APIClient: &parse.Client{Transport: ht}} return h }