github.com/plutov/paypal/v4@v4.7.1/unit_test.go (about)

     1  package paypal
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"testing"
    11  )
    12  
    13  var testBillingAgreementID = "BillingAgreementID"
    14  
    15  type webprofileTestServer struct {
    16  	t *testing.T
    17  }
    18  
    19  func TestNewClient(t *testing.T) {
    20  	c, err := NewClient("", "", "")
    21  	if err == nil {
    22  		t.Errorf("Expected error for NewClient('','','')")
    23  	}
    24  	if c != nil {
    25  		t.Errorf("Expected nil Client for NewClient('','',''), got %v", c)
    26  	}
    27  
    28  	c, err = NewClient("1", "2", "3")
    29  	if err != nil {
    30  		t.Errorf("Not expected error for NewClient(1, 2, 3), got %v", err)
    31  	}
    32  	if c == nil {
    33  		t.Errorf("Expected non-nil Client for NewClient(1, 2, 3)")
    34  	}
    35  }
    36  
    37  func TestTypeUserInfo(t *testing.T) {
    38  	response := `{
    39      "user_id": "https://www.paypal.com/webapps/auth/server/64ghr894040044",
    40      "name": "Peter Pepper",
    41      "given_name": "Peter",
    42      "family_name": "Pepper",
    43      "email": "ppuser@example.com"
    44      }`
    45  
    46  	u := &UserInfo{}
    47  	err := json.Unmarshal([]byte(response), u)
    48  	if err != nil {
    49  		t.Errorf("UserInfo Unmarshal failed")
    50  	}
    51  
    52  	if u.ID != "https://www.paypal.com/webapps/auth/server/64ghr894040044" ||
    53  		u.Name != "Peter Pepper" ||
    54  		u.GivenName != "Peter" ||
    55  		u.FamilyName != "Pepper" ||
    56  		u.Email != "ppuser@example.com" {
    57  		t.Errorf("UserInfo decoded result is incorrect, Given: %v", u)
    58  	}
    59  }
    60  
    61  func TestTypeItem(t *testing.T) {
    62  	response := `{
    63      "name":"Item",
    64      "quantity":"1"
    65  }`
    66  
    67  	i := &Item{}
    68  	err := json.Unmarshal([]byte(response), i)
    69  	if err != nil {
    70  		t.Errorf("Item Unmarshal failed")
    71  	}
    72  
    73  	if i.Name != "Item" ||
    74  		i.Quantity != "1" {
    75  		t.Errorf("Item decoded result is incorrect, Given: %v", i)
    76  	}
    77  }
    78  
    79  func TestTypeErrorResponseOne(t *testing.T) {
    80  	response := `{
    81  		"name":"USER_BUSINESS_ERROR",
    82  		"message":"User business error.",
    83  		"debug_id":"f05063556a338",
    84  		"information_link":"https://developer.paypal.com/docs/api/payments.payouts-batch/#errors",
    85  		"details":[
    86  			{
    87  				"field":"SENDER_BATCH_ID",
    88  				"issue":"Batch with given sender_batch_id already exists",
    89  				"link":[
    90  					{
    91  						"href":"https://api.sandbox.paypal.com/v1/payments/payouts/CR9VS2K4X4846",
    92  						"rel":"self",
    93  						"method":"GET"
    94  					}
    95  				]
    96  			}
    97  		]
    98  	}`
    99  
   100  	i := &ErrorResponse{}
   101  	err := json.Unmarshal([]byte(response), i)
   102  	if err != nil {
   103  		t.Errorf("ErrorResponse Unmarshal failed")
   104  	}
   105  
   106  	if i.Name != "USER_BUSINESS_ERROR" ||
   107  		i.Message != "User business error." ||
   108  		i.DebugID != "f05063556a338" ||
   109  		i.InformationLink != "https://developer.paypal.com/docs/api/payments.payouts-batch/#errors" ||
   110  		len(i.Details) != 1 ||
   111  		i.Details[0].Field != "SENDER_BATCH_ID" ||
   112  		i.Details[0].Issue != "Batch with given sender_batch_id already exists" ||
   113  		len(i.Details[0].Links) != 1 ||
   114  		i.Details[0].Links[0].Href != "https://api.sandbox.paypal.com/v1/payments/payouts/CR9VS2K4X4846" {
   115  		t.Errorf("ErrorResponse decoded result is incorrect, Given: %v", i)
   116  	}
   117  }
   118  
   119  func TestTypeErrorResponseTwo(t *testing.T) {
   120  	response := `{
   121  		"name":"VALIDATION_ERROR",
   122  		"message":"Invalid request - see details.",
   123  		"debug_id":"662121ee369c0",
   124  		"information_link":"https://developer.paypal.com/docs/api/payments.payouts-batch/#errors",
   125  		"details":[
   126  			{
   127  				"field":"items[0].recipient_type",
   128  				"issue":"Value is invalid (must be EMAILor PAYPAL_ID or PHONE)"
   129  			}
   130  		]
   131  	}`
   132  
   133  	i := &ErrorResponse{}
   134  	err := json.Unmarshal([]byte(response), i)
   135  	if err != nil {
   136  		t.Errorf("ErrorResponse Unmarshal failed")
   137  	}
   138  
   139  	if i.Name != "VALIDATION_ERROR" ||
   140  		i.Message != "Invalid request - see details." ||
   141  		len(i.Details) != 1 ||
   142  		i.Details[0].Field != "items[0].recipient_type" {
   143  		t.Errorf("ErrorResponse decoded result is incorrect, Given: %v", i)
   144  	}
   145  }
   146  
   147  func TestTypeErrorResponseThree(t *testing.T) {
   148  	response := `{
   149  		"name": "BUSINESS_ERROR",
   150  		"debug_id": "[REDACTED]",
   151  		"message": "Business error",
   152  		"information_link": "https://developer.paypal.com/webapps/developer/docs/api/#BUSINESS_ERROR",
   153  		"details": [
   154  			{
   155  				"name": "TOKEN_NOT_FOUND",
   156  				"message": "Not Found: Invalid BA-Token Identifier"
   157  			}
   158  		]
   159  	}`
   160  
   161  	i := &ErrorResponse{}
   162  	err := json.Unmarshal([]byte(response), i)
   163  	if err != nil {
   164  		t.Errorf("ErrorResponse Unmarshal failed")
   165  	}
   166  
   167  	if i.Name != "BUSINESS_ERROR" ||
   168  		i.Message != "Business error" ||
   169  		len(i.Details) != 1 ||
   170  		i.Details[0].Name != "TOKEN_NOT_FOUND" ||
   171  		i.Details[0].Message != "Not Found: Invalid BA-Token Identifier" {
   172  		t.Errorf("ErrorResponse decoded result is incorrect, Given: %v", i)
   173  	}
   174  }
   175  
   176  func TestTypePayoutResponse(t *testing.T) {
   177  	response := `{
   178  		"batch_header":{
   179  			"payout_batch_id":"G4E6WJE6Y4853",
   180  			"batch_status":"SUCCESS",
   181  			"time_created":"2017-11-01T23:08:25Z",
   182  			"time_completed":"2017-11-01T23:08:46Z",
   183  			"sender_batch_header":{
   184  				"sender_batch_id":"2017110109",
   185  				"email_subject":"Payment"
   186  			},
   187  			"amount":{
   188  				"currency":"USD",
   189  				"value":"6.37"
   190  			},
   191  			"fees":{
   192  				"currency":"USD",
   193  				"value":"0.25"
   194  			}
   195  		},
   196  		"items":[
   197  			{
   198  				"payout_item_id":"9T35G83YA546X",
   199  				"transaction_id":"4T328230B1D337285",
   200  				"transaction_status":"UNCLAIMED",
   201  				"payout_item_fee":{
   202  					"currency":"USD",
   203  					"value":"0.25"
   204  				},
   205  				"payout_batch_id":"G4E6WJE6Y4853",
   206  				"payout_item":{
   207  					"recipient_type":"EMAIL",
   208  					"amount":{
   209  						"currency":"USD",
   210  						"value":"6.37"
   211  					},
   212  					"note":"Optional note",
   213  					"receiver":"ppuser@example.com",
   214  					"sender_item_id":"1"
   215  				},
   216  				"time_processed":"2017-11-01T23:08:43Z",
   217  				"errors":{
   218  					"name":"RECEIVER_UNREGISTERED",
   219  					"message":"Receiver is unregistered",
   220  					"information_link":"https://developer.paypal.com/docs/api/payments.payouts-batch/#errors",
   221  					"details":[]
   222  				},
   223  				"links":[
   224  					{
   225  						"href":"https://api.sandbox.paypal.com/v1/payments/payouts-item/9T35G83YA546X",
   226  						"rel":"item",
   227  						"method":"GET",
   228  						"encType":"application/json"
   229  					}
   230  				]
   231  			}
   232  		],
   233  		"links":[
   234  			{
   235  				"href":"https://api.sandbox.paypal.com/v1/payments/payouts/G4E6WJE6Y4853?page_size=1000&page=1",
   236  				"rel":"self",
   237  				"method":"GET",
   238  				"encType":"application/json"
   239  			}
   240  		]
   241  	}`
   242  
   243  	pr := &PayoutResponse{}
   244  	err := json.Unmarshal([]byte(response), pr)
   245  	if err != nil {
   246  		t.Errorf("PayoutResponse Unmarshal failed")
   247  	}
   248  
   249  	if pr.BatchHeader.BatchStatus != "SUCCESS" ||
   250  		pr.BatchHeader.PayoutBatchID != "G4E6WJE6Y4853" ||
   251  		len(pr.Items) != 1 ||
   252  		pr.Items[0].PayoutItemID != "9T35G83YA546X" ||
   253  		pr.Items[0].TransactionID != "4T328230B1D337285" ||
   254  		pr.Items[0].TransactionStatus != "UNCLAIMED" ||
   255  		pr.Items[0].Error.Name != "RECEIVER_UNREGISTERED" {
   256  		t.Errorf("PayoutResponse decoded result is incorrect, Given: %v", pr)
   257  	}
   258  }
   259  
   260  func TestOrderUnmarshal(t *testing.T) {
   261  	response := `{
   262  		"id": "5O190127TN364715T",
   263  		"status": "CREATED",
   264  		"links": [
   265  		  {
   266  			"href": "https://api.paypal.com/v2/checkout/orders/5O190127TN364715T",
   267  			"rel": "self",
   268  			"method": "GET"
   269  		  },
   270  		  {
   271  			"href": "https://api.sandbox.paypal.com/checkoutnow?token=5O190127TN364715T",
   272  			"rel": "approve",
   273  			"method": "GET"
   274  		  },
   275  		  {
   276  			"href": "https://api.paypal.com/v2/checkout/orders/5O190127TN364715T/capture",
   277  			"rel": "capture",
   278  			"method": "POST"
   279  		  }
   280  		]
   281  	}`
   282  
   283  	order := &Order{}
   284  	err := json.Unmarshal([]byte(response), order)
   285  	if err != nil {
   286  		t.Errorf("Order Unmarshal failed")
   287  	}
   288  
   289  	if order.ID != "5O190127TN364715T" ||
   290  		order.Status != "CREATED" ||
   291  		order.Links[0].Href != "https://api.paypal.com/v2/checkout/orders/5O190127TN364715T" {
   292  		t.Errorf("Order decoded result is incorrect, Given: %+v", order)
   293  	}
   294  }
   295  
   296  func TestOrderCompletedUnmarshal(t *testing.T) {
   297  	response := `{
   298  		"id": "1K412082HD5737736",
   299  		"status": "COMPLETED",
   300  		"purchase_units": [
   301  			{
   302  				"reference_id": "default",
   303  				"amount": {
   304  					"currency_code": "EUR",
   305  					"value": "99.99"
   306  				},
   307  				"payee": {
   308  					"email_address": "payee@business.example.com",
   309  					"merchant_id": "7DVPP5Q2RZJQY"
   310  				},
   311  				"custom_id": "123456",
   312  				"soft_descriptor": "PAYPAL *TEST STORE",
   313  				"shipping": {
   314  					"name": {
   315  						"full_name": "John Doe"
   316  					},
   317  					"address": {
   318  						"address_line_1": "Address, Country",
   319  						"admin_area_2": "Area2",
   320  						"admin_area_1": "Area1",
   321  						"postal_code": "123456",
   322  						"country_code": "US"
   323  					}
   324  				},
   325  				"payments": {
   326  					"captures": [
   327  						{
   328  							"id": "6V864560EH247264J",
   329  							"status": "COMPLETED",
   330  							"amount": {
   331  								"currency_code": "EUR",
   332  								"value": "99.99"
   333  							},
   334  							"final_capture": true,
   335  							"custom_id": "123456",
   336  							"create_time": "2021-07-27T09:39:17Z",
   337  							"update_time": "2021-07-27T09:39:17Z"
   338  						}
   339  					]
   340  				}
   341  			}
   342  		],
   343  		"payer": {
   344  			"name": {
   345  				"given_name": "John",
   346  				"surname": "Doe"
   347  			},
   348  			"email_address": "payer@personal.example.com",
   349  			"payer_id": "7D36CJQ2TUEUU",
   350  			"address": {
   351  				"address_line_1": "City, Country",
   352  				"admin_area_2": "Area2",
   353  				"admin_area_1": "Area1",
   354  				"postal_code": "123456",
   355  				"country_code": "US"
   356  			}
   357  		},
   358  		"create_time": "2021-07-27T09:38:37Z",
   359  		"update_time": "2021-07-27T09:39:17Z",
   360  		"links": [
   361  			{
   362  				"href": "https://api.sandbox.paypal.com/v2/checkout/orders/1K412082HD5737736",
   363  				"rel": "self",
   364  				"method": "GET"
   365  			}
   366  		]
   367  	}`
   368  
   369  	order := &Order{}
   370  	err := json.Unmarshal([]byte(response), order)
   371  	if err != nil {
   372  		t.Errorf("Order Unmarshal failed")
   373  	}
   374  
   375  	if order.ID != "1K412082HD5737736" ||
   376  		order.Status != "COMPLETED" ||
   377  		order.PurchaseUnits[0].Payee.EmailAddress != "payee@business.example.com" ||
   378  		order.PurchaseUnits[0].CustomID != "123456" ||
   379  		order.PurchaseUnits[0].Shipping.Name.FullName != "John Doe" ||
   380  		order.PurchaseUnits[0].Shipping.Address.AdminArea1 != "Area1" ||
   381  		order.Payer.Name.GivenName != "John" ||
   382  		order.Payer.Address.AddressLine1 != "City, Country" ||
   383  		order.Links[0].Href != "https://api.sandbox.paypal.com/v2/checkout/orders/1K412082HD5737736" {
   384  		t.Errorf("Order decoded result is incorrect, Given: %+v", order)
   385  	}
   386  }
   387  
   388  func TestTypePayoutItemResponse(t *testing.T) {
   389  	response := `{
   390  		"payout_item_id":"9T35G83YA546X",
   391  		"transaction_id":"4T328230B1D337285",
   392  		"transaction_status":"UNCLAIMED",
   393  		"payout_item_fee":{
   394  			"currency":"USD",
   395  			"value":"0.25"
   396  		},
   397  		"payout_batch_id":"G4E6WJE6Y4853",
   398  		"payout_item":{
   399  			"recipient_type":"EMAIL",
   400  			"amount":{
   401  				"currency":"USD",
   402  				"value":"6.37"
   403  			},
   404  			"note":"Optional note",
   405  			"receiver":"ppuser@example.com",
   406  			"sender_item_id":"1"
   407  		},
   408  		"time_processed":"2017-11-01T23:08:43Z",
   409  		"errors":{
   410  			"name":"RECEIVER_UNREGISTERED",
   411  			"message":"Receiver is unregistered",
   412  			"information_link":"https://developer.paypal.com/docs/api/payments.payouts-batch/#errors",
   413  			"details":[]
   414  		},
   415  		"links":[
   416  			{
   417  				"href":"https://api.sandbox.paypal.com/v1/payments/payouts-item/3YA546X9T35G8",
   418  				"rel":"self",
   419  				"method":"GET",
   420  				"encType":"application/json"
   421  			},
   422  			{
   423  				"href":"https://api.sandbox.paypal.com/v1/payments/payouts/6Y4853G4E6WJE",
   424  				"rel":"batch",
   425  				"method":"GET",
   426  				"encType":"application/json"
   427  			}
   428  		]
   429  	}`
   430  
   431  	pir := &PayoutItemResponse{}
   432  	err := json.Unmarshal([]byte(response), pir)
   433  	if err != nil {
   434  		t.Errorf("PayoutItemResponse Unmarshal failed")
   435  	}
   436  
   437  	if pir.PayoutItemID != "9T35G83YA546X" ||
   438  		pir.PayoutBatchID != "G4E6WJE6Y4853" ||
   439  		pir.TransactionID != "4T328230B1D337285" ||
   440  		pir.TransactionStatus != "UNCLAIMED" ||
   441  		pir.Error.Name != "RECEIVER_UNREGISTERED" {
   442  		t.Errorf("PayoutItemResponse decoded result is incorrect, Given: %+v", pir)
   443  	}
   444  }
   445  
   446  func TestTypePaymentPatch(t *testing.T) {
   447  	// test unmarshaling
   448  	response := `{
   449  		"op": "replace",
   450  		"path": "/transactions/0/amount",
   451  		"value": "5"
   452  	}`
   453  	pp := &PaymentPatch{}
   454  	err := json.Unmarshal([]byte(response), pp)
   455  	if err != nil {
   456  		t.Errorf("TestTypePaymentPatch Unmarshal failed")
   457  	}
   458  	if pp.Operation != "replace" ||
   459  		pp.Path != "/transactions/0/amount" ||
   460  		pp.Value != "5" {
   461  		t.Errorf("PaymentPatch decoded result is incorrect, Given: %+v", pp)
   462  	}
   463  }
   464  
   465  func TestTypePaymentPatchMarshal(t *testing.T) {
   466  	// test marshalling
   467  	p2 := &PaymentPatch{
   468  		Operation: "add",
   469  		Path:      "/transactions/0/amount",
   470  		Value: map[string]interface{}{
   471  			"total":    "18.37",
   472  			"currency": "EUR",
   473  			"details": map[string]interface{}{
   474  				"subtotal": "13.37",
   475  				"shipping": "5.00",
   476  			},
   477  		},
   478  	}
   479  	p2expectedresponse := `{"op":"add","path":"/transactions/0/amount","value":{"currency":"EUR","details":{"shipping":"5.00","subtotal":"13.37"},"total":"18.37"}}`
   480  	response2, _ := json.Marshal(p2)
   481  	if string(response2) != string(p2expectedresponse) {
   482  		t.Errorf("PaymentPatch response2 is incorrect,\n Given:    %+v\n Expected: %+v", string(response2), string(p2expectedresponse))
   483  	}
   484  }
   485  
   486  // ServeHTTP implements http.Handler
   487  func (ts *webprofileTestServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   488  	ts.t.Log(r.RequestURI)
   489  	if r.RequestURI == "/v1/payment-experience/web-profiles" {
   490  		if r.Method == "POST" {
   491  			ts.create(w, r)
   492  		}
   493  		if r.Method == "GET" {
   494  			ts.list(w, r)
   495  		}
   496  	}
   497  	if r.RequestURI == "/v1/payment-experience/web-profiles/XP-CP6S-W9DY-96H8-MVN2" {
   498  		if r.Method == "GET" {
   499  			ts.getvalid(w, r)
   500  		}
   501  		if r.Method == "PUT" {
   502  			ts.updatevalid(w, r)
   503  		}
   504  		if r.Method == "DELETE" {
   505  			ts.deletevalid(w, r)
   506  		}
   507  	}
   508  	if r.RequestURI == "/v1/payment-experience/web-profiles/foobar" {
   509  		if r.Method == "GET" {
   510  			ts.getinvalid(w, r)
   511  		}
   512  		if r.Method == "PUT" {
   513  			ts.updateinvalid(w, r)
   514  		}
   515  		if r.Method == "DELETE" {
   516  			ts.deleteinvalid(w, r)
   517  		}
   518  	}
   519  	if r.RequestURI == "/v1/billing-agreements/agreement-tokens" {
   520  		if r.Method == "POST" {
   521  			ts.createWithoutName(w, r)
   522  		}
   523  	}
   524  	if r.RequestURI == "/v1/billing-agreements/agreements" {
   525  		if r.Method == "POST" {
   526  			ts.createWithoutName(w, r)
   527  		}
   528  	}
   529  	if r.RequestURI == fmt.Sprintf("/v1/billing-agreements/agreements/%s/cancel", testBillingAgreementID) {
   530  		if r.Method == "POST" {
   531  			ts.deletevalid(w, r)
   532  		}
   533  	}
   534  }
   535  
   536  func (ts *webprofileTestServer) create(w http.ResponseWriter, r *http.Request) {
   537  	var data map[string]interface{}
   538  
   539  	body, err := io.ReadAll(r.Body)
   540  
   541  	if err != nil {
   542  		http.Error(w, err.Error(), http.StatusInternalServerError)
   543  	}
   544  
   545  	err = json.Unmarshal(body, &data)
   546  
   547  	if err != nil {
   548  		http.Error(w, err.Error(), http.StatusInternalServerError)
   549  	}
   550  
   551  	var raw map[string]string
   552  
   553  	w.Header().Set("Content-Type", "application/json")
   554  
   555  	if name, ok := data["name"]; !ok || name == "" {
   556  		raw = map[string]string{
   557  			"name":    "VALIDATION_ERROR",
   558  			"message": "should have name",
   559  		}
   560  		w.WriteHeader(http.StatusBadRequest)
   561  	} else {
   562  		raw = map[string]string{
   563  			"id": "XP-CP6S-W9DY-96H8-MVN2",
   564  		}
   565  		w.WriteHeader(http.StatusCreated)
   566  	}
   567  
   568  	res, _ := json.Marshal(raw)
   569  	w.Write(res)
   570  }
   571  
   572  func (ts *webprofileTestServer) createWithoutName(w http.ResponseWriter, r *http.Request) {
   573  	var data map[string]interface{}
   574  
   575  	body, err := io.ReadAll(r.Body)
   576  
   577  	if err != nil {
   578  		http.Error(w, err.Error(), http.StatusInternalServerError)
   579  	}
   580  
   581  	err = json.Unmarshal(body, &data)
   582  
   583  	if err != nil {
   584  		http.Error(w, err.Error(), http.StatusInternalServerError)
   585  	}
   586  
   587  	var raw map[string]string
   588  
   589  	w.Header().Set("Content-Type", "application/json")
   590  
   591  	raw = map[string]string{
   592  		"id": "B-12345678901234567",
   593  	}
   594  	w.WriteHeader(http.StatusCreated)
   595  
   596  	res, _ := json.Marshal(raw)
   597  	w.Write(res)
   598  }
   599  
   600  func (ts *webprofileTestServer) updatevalid(w http.ResponseWriter, r *http.Request) {
   601  	var data map[string]interface{}
   602  
   603  	body, err := io.ReadAll(r.Body)
   604  
   605  	if err != nil {
   606  		http.Error(w, err.Error(), http.StatusInternalServerError)
   607  	}
   608  
   609  	err = json.Unmarshal(body, &data)
   610  
   611  	if err != nil {
   612  		http.Error(w, err.Error(), http.StatusInternalServerError)
   613  	}
   614  
   615  	if ID, ok := data["id"]; !ok || ID != "XP-CP6S-W9DY-96H8-MVN2" {
   616  		raw := map[string]string{
   617  			"name":    "INVALID_RESOURCE_ID",
   618  			"message": "id invalid",
   619  		}
   620  		w.Header().Set("Content-Type", "application/json")
   621  		w.WriteHeader(http.StatusBadRequest)
   622  		res, _ := json.Marshal(raw)
   623  		w.Write(res)
   624  		return
   625  	}
   626  
   627  	if name, ok := data["name"]; !ok || name == "" {
   628  		raw := map[string]string{
   629  			"name":    "VALIDATION_ERROR",
   630  			"message": "should have name",
   631  		}
   632  		w.Header().Set("Content-Type", "application/json")
   633  		w.WriteHeader(http.StatusBadRequest)
   634  		res, _ := json.Marshal(raw)
   635  		w.Write(res)
   636  		return
   637  	}
   638  
   639  	w.WriteHeader(http.StatusNoContent)
   640  
   641  }
   642  
   643  func (ts *webprofileTestServer) updateinvalid(w http.ResponseWriter, r *http.Request) {
   644  	w.Header().Set("Content-Type", "application/json")
   645  	w.WriteHeader(http.StatusNotFound)
   646  
   647  	raw := map[string]interface{}{
   648  		"name":    "INVALID_RESOURCE_ID",
   649  		"message": "foobar not found",
   650  	}
   651  
   652  	res, _ := json.Marshal(raw)
   653  	w.Write(res)
   654  }
   655  
   656  func (ts *webprofileTestServer) getvalid(w http.ResponseWriter, r *http.Request) {
   657  	w.Header().Set("Content-Type", "application/json")
   658  	w.WriteHeader(http.StatusOK)
   659  
   660  	raw := map[string]interface{}{
   661  		"id":   "XP-CP6S-W9DY-96H8-MVN2",
   662  		"name": "YeowZa! T-Shirt Shop",
   663  		"presentation": map[string]interface{}{
   664  			"brand_name":  "YeowZa! Paypal",
   665  			"logo_image":  "http://www.yeowza.com",
   666  			"locale_code": "US",
   667  		},
   668  
   669  		"input_fields": map[string]interface{}{
   670  			"allow_note":       true,
   671  			"no_shipping":      0,
   672  			"address_override": 1,
   673  		},
   674  
   675  		"flow_config": map[string]interface{}{
   676  			"landing_page_type":    "Billing",
   677  			"bank_txn_pending_url": "http://www.yeowza.com",
   678  		},
   679  	}
   680  
   681  	res, _ := json.Marshal(raw)
   682  	w.Write(res)
   683  }
   684  
   685  func (ts *webprofileTestServer) getinvalid(w http.ResponseWriter, r *http.Request) {
   686  	w.Header().Set("Content-Type", "application/json")
   687  	w.WriteHeader(http.StatusNotFound)
   688  
   689  	raw := map[string]interface{}{
   690  		"name":    "INVALID_RESOURCE_ID",
   691  		"message": "foobar not found",
   692  	}
   693  
   694  	res, _ := json.Marshal(raw)
   695  	w.Write(res)
   696  }
   697  
   698  func (ts *webprofileTestServer) list(w http.ResponseWriter, r *http.Request) {
   699  	w.Header().Set("Content-Type", "application/json")
   700  	w.WriteHeader(http.StatusOK)
   701  
   702  	raw := []interface{}{
   703  		map[string]interface{}{
   704  			"id":   "XP-CP6S-W9DY-96H8-MVN2",
   705  			"name": "YeowZa! T-Shirt Shop",
   706  		},
   707  		map[string]interface{}{
   708  			"id":   "XP-96H8-MVN2-CP6S-W9DY",
   709  			"name": "Shop T-Shirt YeowZa! ",
   710  		},
   711  	}
   712  
   713  	res, _ := json.Marshal(raw)
   714  	w.Write(res)
   715  }
   716  
   717  func (ts *webprofileTestServer) deleteinvalid(w http.ResponseWriter, r *http.Request) {
   718  	w.Header().Set("Content-Type", "application/json")
   719  	w.WriteHeader(http.StatusNotFound)
   720  
   721  	raw := map[string]interface{}{
   722  		"name":    "INVALID_RESOURCE_ID",
   723  		"message": "foobar not found",
   724  	}
   725  
   726  	res, _ := json.Marshal(raw)
   727  	w.Write(res)
   728  }
   729  
   730  func (ts *webprofileTestServer) deletevalid(w http.ResponseWriter, r *http.Request) {
   731  	w.Header().Set("Content-Type", "application/json")
   732  	w.WriteHeader(http.StatusNoContent)
   733  }
   734  
   735  func TestCreateWebProfile_valid(t *testing.T) {
   736  	ts := httptest.NewServer(&webprofileTestServer{t: t})
   737  	defer ts.Close()
   738  
   739  	c, _ := NewClient("foo", "bar", ts.URL)
   740  
   741  	wp := WebProfile{
   742  		Name: "YeowZa! T-Shirt Shop",
   743  		Presentation: Presentation{
   744  			BrandName:  "YeowZa! Paypal",
   745  			LogoImage:  "http://www.yeowza.com",
   746  			LocaleCode: "US",
   747  		},
   748  
   749  		InputFields: InputFields{
   750  			AllowNote:       true,
   751  			NoShipping:      NoShippingDisplay,
   752  			AddressOverride: AddrOverrideFromCall,
   753  		},
   754  
   755  		FlowConfig: FlowConfig{
   756  			LandingPageType:   LandingPageTypeBilling,
   757  			BankTXNPendingURL: "http://www.yeowza.com",
   758  		},
   759  	}
   760  
   761  	res, err := c.CreateWebProfile(context.Background(), wp)
   762  
   763  	if err != nil {
   764  		t.Fatal(err)
   765  	}
   766  
   767  	if res.ID != "XP-CP6S-W9DY-96H8-MVN2" {
   768  		t.Fatalf("expecting response to have ID = `XP-CP6S-W9DY-96H8-MVN2` got `%s`", res.ID)
   769  	}
   770  }
   771  
   772  func TestCreateWebProfile_invalid(t *testing.T) {
   773  	ts := httptest.NewServer(&webprofileTestServer{t: t})
   774  	defer ts.Close()
   775  
   776  	c, _ := NewClient("foo", "bar", ts.URL)
   777  
   778  	wp := WebProfile{}
   779  
   780  	_, err := c.CreateWebProfile(context.Background(), wp)
   781  
   782  	if err == nil {
   783  		t.Fatalf("expecting an error got nil")
   784  	}
   785  }
   786  
   787  func TestGetWebProfile_valid(t *testing.T) {
   788  	ts := httptest.NewServer(&webprofileTestServer{t: t})
   789  	defer ts.Close()
   790  
   791  	c, _ := NewClient("foo", "bar", ts.URL)
   792  
   793  	res, err := c.GetWebProfile(context.Background(), "XP-CP6S-W9DY-96H8-MVN2")
   794  
   795  	if err != nil {
   796  		t.Fatal(err)
   797  	}
   798  
   799  	if res.ID != "XP-CP6S-W9DY-96H8-MVN2" {
   800  		t.Fatalf("expecting res.ID to have value = `XP-CP6S-W9DY-96H8-MVN2` but got `%s`", res.ID)
   801  	}
   802  
   803  	if res.Name != "YeowZa! T-Shirt Shop" {
   804  		t.Fatalf("expecting res.Name to have value = `YeowZa! T-Shirt Shop` but got `%s`", res.Name)
   805  	}
   806  }
   807  
   808  func TestGetWebProfile_invalid(t *testing.T) {
   809  	ts := httptest.NewServer(&webprofileTestServer{t: t})
   810  	defer ts.Close()
   811  
   812  	c, _ := NewClient("foo", "bar", ts.URL)
   813  
   814  	_, err := c.GetWebProfile(context.Background(), "foobar")
   815  
   816  	if err == nil {
   817  		t.Fatalf("expecting an error got nil")
   818  	}
   819  }
   820  
   821  func TestGetWebProfiles(t *testing.T) {
   822  	ts := httptest.NewServer(&webprofileTestServer{t: t})
   823  	defer ts.Close()
   824  
   825  	c, _ := NewClient("foo", "bar", ts.URL)
   826  
   827  	res, err := c.GetWebProfiles(context.Background())
   828  
   829  	if err != nil {
   830  		t.Fatal(err)
   831  	}
   832  
   833  	if len(res) != 2 {
   834  		t.Fatalf("expecting two results got %d", len(res))
   835  	}
   836  }
   837  
   838  func TestSetWebProfile_valid(t *testing.T) {
   839  	ts := httptest.NewServer(&webprofileTestServer{t: t})
   840  	defer ts.Close()
   841  
   842  	c, _ := NewClient("foo", "bar", ts.URL)
   843  
   844  	wp := WebProfile{
   845  		ID:   "XP-CP6S-W9DY-96H8-MVN2",
   846  		Name: "Shop T-Shirt YeowZa!",
   847  	}
   848  
   849  	err := c.SetWebProfile(context.Background(), wp)
   850  
   851  	if err != nil {
   852  		t.Fatal(err)
   853  	}
   854  
   855  }
   856  
   857  func TestSetWebProfile_invalid(t *testing.T) {
   858  	ts := httptest.NewServer(&webprofileTestServer{t: t})
   859  	defer ts.Close()
   860  
   861  	c, _ := NewClient("foo", "bar", ts.URL)
   862  
   863  	wp := WebProfile{
   864  		ID: "foobar",
   865  	}
   866  
   867  	err := c.SetWebProfile(context.Background(), wp)
   868  
   869  	if err == nil {
   870  		t.Fatal(err)
   871  	}
   872  
   873  	wp = WebProfile{}
   874  
   875  	err = c.SetWebProfile(context.Background(), wp)
   876  
   877  	if err == nil {
   878  		t.Fatal(err)
   879  	}
   880  }
   881  
   882  func TestDeleteWebProfile_valid(t *testing.T) {
   883  	ts := httptest.NewServer(&webprofileTestServer{t: t})
   884  	defer ts.Close()
   885  
   886  	c, _ := NewClient("foo", "bar", ts.URL)
   887  
   888  	wp := WebProfile{
   889  		ID:   "XP-CP6S-W9DY-96H8-MVN2",
   890  		Name: "Shop T-Shirt YeowZa!",
   891  	}
   892  
   893  	err := c.SetWebProfile(context.Background(), wp)
   894  
   895  	if err != nil {
   896  		t.Fatal(err)
   897  	}
   898  
   899  }
   900  
   901  func TestDeleteWebProfile_invalid(t *testing.T) {
   902  	ts := httptest.NewServer(&webprofileTestServer{t: t})
   903  	defer ts.Close()
   904  
   905  	c, _ := NewClient("foo", "bar", ts.URL)
   906  
   907  	err := c.DeleteWebProfile(context.Background(), "foobar")
   908  
   909  	if err == nil {
   910  		t.Fatal(err)
   911  	}
   912  
   913  }
   914  
   915  func TestCreateBillingAgreementToken(t *testing.T) {
   916  
   917  	ts := httptest.NewServer(&webprofileTestServer{t: t})
   918  	defer ts.Close()
   919  
   920  	c, _ := NewClient("foo", "bar", ts.URL)
   921  	description := "name A"
   922  
   923  	_, err := c.CreateBillingAgreementToken(
   924  		context.Background(),
   925  		&description,
   926  		&ShippingAddress{RecipientName: "Name", Type: "Type", Line1: "Line1", Line2: "Line2"},
   927  		&Payer{PaymentMethod: "paypal"},
   928  		&BillingPlan{ID: "id B", Name: "name B", Description: "description B", Type: "type B"})
   929  
   930  	if err != nil {
   931  		t.Fatal(err)
   932  	}
   933  
   934  }
   935  
   936  func TestCreateBillingAgreementFromToken(t *testing.T) {
   937  
   938  	ts := httptest.NewServer(&webprofileTestServer{t: t})
   939  	defer ts.Close()
   940  
   941  	c, _ := NewClient("foo", "bar", ts.URL)
   942  
   943  	_, err := c.CreateBillingAgreementFromToken(context.Background(), "BillingAgreementToken")
   944  
   945  	if err != nil {
   946  		t.Fatal(err)
   947  	}
   948  }
   949  
   950  func TestCancelBillingAgreement(t *testing.T) {
   951  
   952  	ts := httptest.NewServer(&webprofileTestServer{t: t})
   953  	defer ts.Close()
   954  
   955  	c, _ := NewClient("foo", "bar", ts.URL)
   956  
   957  	err := c.CancelBillingAgreement(context.Background(), testBillingAgreementID)
   958  
   959  	if err != nil {
   960  		t.Fatal(err)
   961  	}
   962  }