Example #1
0
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)
}
Example #2
0
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")
}
Example #3
0
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
}
Example #4
0
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)
}
Example #5
0
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
}
Example #6
0
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)
}
Example #7
0
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
}
Example #8
0
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
}
Example #9
0
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
}
Example #10
0
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)
}
Example #11
0
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
}
Example #12
0
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"))
}
Example #13
0
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
}
Example #14
0
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")
}
Example #15
0
// 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
		}
	}
}
Example #16
0
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(&params)
			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
}
Example #18
0
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(&params)
			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
}