diff --git a/client/product.go b/client/product.go index 0b20a47..32eb789 100644 --- a/client/product.go +++ b/client/product.go @@ -8,8 +8,14 @@ import ( ) const ( - productListResourceEndpoint = "/admin/api/services.json" - productResourceEndpoint = "/admin/api/services/%d.json" + productListResourceEndpoint = "/admin/api/services.json" + productResourceEndpoint = "/admin/api/services/%d.json" + productMethodListResourceEndpoint = "/admin/api/services/%d/metrics/%d/methods.json" + productMethodResourceEndpoint = "/admin/api/services/%d/metrics/%d/methods/%d.json" + productMetricListResourceEndpoint = "/admin/api/services/%d/metrics.json" + productMetricResourceEndpoint = "/admin/api/services/%d/metrics/%d.json" + productMappingRuleListResourceEndpoint = "/admin/api/services/%d/proxy/mapping_rules.json" + productMappingRuleResourceEndpoint = "/admin/api/services/%d/proxy/mapping_rules/%d.json" ) // CreateProduct Create 3scale Product @@ -99,3 +105,327 @@ func (c *ThreeScaleClient) ListProducts() (*ProductList, error) { err = handleJsonResp(resp, http.StatusOK, productList) return productList, err } + +// ListProductMethods List existing product methods +func (c *ThreeScaleClient) ListProductMethods(productID, hitsID int64) (*MethodList, error) { + endpoint := fmt.Sprintf(productMethodListResourceEndpoint, productID, hitsID) + req, err := c.buildGetReq(endpoint) + if err != nil { + return nil, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + list := &MethodList{} + err = handleJsonResp(resp, http.StatusOK, list) + return list, err +} + +// CreateProductMethod Create 3scale product method +func (c *ThreeScaleClient) CreateProductMethod(productID, hitsID int64, params Params) (*Method, error) { + endpoint := fmt.Sprintf(productMethodListResourceEndpoint, productID, hitsID) + + values := url.Values{} + for k, v := range params { + values.Add(k, v) + } + + body := strings.NewReader(values.Encode()) + req, err := c.buildPostReq(endpoint, body) + if err != nil { + return nil, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + item := &Method{} + err = handleJsonResp(resp, http.StatusCreated, item) + return item, err +} + +// DeleteProductMethod Delete 3scale product method +func (c *ThreeScaleClient) DeleteProductMethod(productID, hitsID, methodID int64) error { + endpoint := fmt.Sprintf(productMethodResourceEndpoint, productID, hitsID, methodID) + + req, err := c.buildDeleteReq(endpoint, nil) + if err != nil { + return err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + return handleJsonResp(resp, http.StatusOK, nil) +} + +// ProductMethod Read 3scale product method +func (c *ThreeScaleClient) ProductMethod(productID, hitsID, methodID int64) (*Method, error) { + endpoint := fmt.Sprintf(productMethodResourceEndpoint, productID, hitsID, methodID) + + req, err := c.buildGetReq(endpoint) + if err != nil { + return nil, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + item := &Method{} + err = handleJsonResp(resp, http.StatusOK, item) + return item, err +} + +// UpdateProductMethod Update 3scale product method +func (c *ThreeScaleClient) UpdateProductMethod(productID, hitsID, methodID int64, params Params) (*Method, error) { + endpoint := fmt.Sprintf(productMethodResourceEndpoint, productID, hitsID, methodID) + + values := url.Values{} + for k, v := range params { + values.Add(k, v) + } + body := strings.NewReader(values.Encode()) + req, err := c.buildUpdateReq(endpoint, body) + if err != nil { + return nil, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + item := &Method{} + err = handleJsonResp(resp, http.StatusOK, item) + return item, err +} + +// ListProductMetrics List existing product metrics +func (c *ThreeScaleClient) ListProductMetrics(productID int64) (*MetricJSONList, error) { + endpoint := fmt.Sprintf(productMetricListResourceEndpoint, productID) + req, err := c.buildGetReq(endpoint) + if err != nil { + return nil, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + list := &MetricJSONList{} + err = handleJsonResp(resp, http.StatusOK, list) + return list, err +} + +// CreateProductMetric Create 3scale product metric +func (c *ThreeScaleClient) CreateProductMetric(productID int64, params Params) (*MetricJSON, error) { + endpoint := fmt.Sprintf(productMetricListResourceEndpoint, productID) + + values := url.Values{} + for k, v := range params { + values.Add(k, v) + } + + body := strings.NewReader(values.Encode()) + req, err := c.buildPostReq(endpoint, body) + if err != nil { + return nil, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + item := &MetricJSON{} + err = handleJsonResp(resp, http.StatusCreated, item) + return item, err +} + +// DeleteProductMetric Delete 3scale product metric +func (c *ThreeScaleClient) DeleteProductMetric(productID, metricID int64) error { + endpoint := fmt.Sprintf(productMetricResourceEndpoint, productID, metricID) + + req, err := c.buildDeleteReq(endpoint, nil) + if err != nil { + return err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + return handleJsonResp(resp, http.StatusOK, nil) +} + +// ProductMetric Read 3scale product metric +func (c *ThreeScaleClient) ProductMetric(productID, metricID int64) (*MetricJSON, error) { + endpoint := fmt.Sprintf(productMetricResourceEndpoint, productID, metricID) + + req, err := c.buildGetReq(endpoint) + if err != nil { + return nil, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + item := &MetricJSON{} + err = handleJsonResp(resp, http.StatusOK, item) + return item, err +} + +// UpdateProductMetric Update 3scale product metric +func (c *ThreeScaleClient) UpdateProductMetric(productID, metricID int64, params Params) (*MetricJSON, error) { + endpoint := fmt.Sprintf(productMetricResourceEndpoint, productID, metricID) + + values := url.Values{} + for k, v := range params { + values.Add(k, v) + } + body := strings.NewReader(values.Encode()) + req, err := c.buildUpdateReq(endpoint, body) + if err != nil { + return nil, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + item := &MetricJSON{} + err = handleJsonResp(resp, http.StatusOK, item) + return item, err +} + +// ListProductMappingRules List existing product mappingrules +func (c *ThreeScaleClient) ListProductMappingRules(productID int64) (*MappingRuleJSONList, error) { + endpoint := fmt.Sprintf(productMappingRuleListResourceEndpoint, productID) + req, err := c.buildGetReq(endpoint) + if err != nil { + return nil, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + list := &MappingRuleJSONList{} + err = handleJsonResp(resp, http.StatusOK, list) + return list, err +} + +// CreateProductMappingRule Create 3scale product mappingrule +func (c *ThreeScaleClient) CreateProductMappingRule(productID int64, params Params) (*MappingRuleJSON, error) { + endpoint := fmt.Sprintf(productMappingRuleListResourceEndpoint, productID) + + values := url.Values{} + for k, v := range params { + values.Add(k, v) + } + + body := strings.NewReader(values.Encode()) + req, err := c.buildPostReq(endpoint, body) + if err != nil { + return nil, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + item := &MappingRuleJSON{} + err = handleJsonResp(resp, http.StatusCreated, item) + return item, err +} + +// DeleteProductMappingRule Delete 3scale product mappingrule +func (c *ThreeScaleClient) DeleteProductMappingRule(productID, itemID int64) error { + endpoint := fmt.Sprintf(productMappingRuleResourceEndpoint, productID, itemID) + + req, err := c.buildDeleteReq(endpoint, nil) + if err != nil { + return err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + return handleJsonResp(resp, http.StatusOK, nil) +} + +// ProductMappingRule Read 3scale product mappingrule +func (c *ThreeScaleClient) ProductMappingRule(productID, itemID int64) (*MappingRuleJSON, error) { + endpoint := fmt.Sprintf(productMappingRuleResourceEndpoint, productID, itemID) + + req, err := c.buildGetReq(endpoint) + if err != nil { + return nil, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + item := &MappingRuleJSON{} + err = handleJsonResp(resp, http.StatusOK, item) + return item, err +} + +// UpdateProductMappingRule Update 3scale product mappingrule +func (c *ThreeScaleClient) UpdateProductMappingRule(productID, itemID int64, params Params) (*MappingRuleJSON, error) { + endpoint := fmt.Sprintf(productMappingRuleResourceEndpoint, productID, itemID) + + values := url.Values{} + for k, v := range params { + values.Add(k, v) + } + body := strings.NewReader(values.Encode()) + req, err := c.buildUpdateReq(endpoint, body) + if err != nil { + return nil, err + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + item := &MappingRuleJSON{} + err = handleJsonResp(resp, http.StatusOK, item) + return item, err +} diff --git a/client/product_test.go b/client/product_test.go new file mode 100644 index 0000000..1b51a44 --- /dev/null +++ b/client/product_test.go @@ -0,0 +1,802 @@ +package client + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strings" + "testing" +) + +func TestListProductMethods(t *testing.T) { + var ( + productID int64 = 97 + hitsID int64 = 98 + endpoint = fmt.Sprintf(productMethodListResourceEndpoint, productID, hitsID) + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodGet { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodGet, req.Method) + } + + list := MethodList{ + Methods: []Method{ + { + Element: MethodItem{ + ID: 1, + Name: "method01", + SystemName: "desc01", + }, + }, + { + Element: MethodItem{ + ID: 2, + Name: "method02", + SystemName: "desc02", + }, + }, + }, + } + + responseBodyBytes, err := json.Marshal(list) + if err != nil { + t.Fatal(err) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer(responseBodyBytes)), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + list, err := c.ListProductMethods(productID, hitsID) + if err != nil { + t.Fatal(err) + } + + if list == nil { + t.Fatal("list returned nil") + } + + if len(list.Methods) != 2 { + t.Fatalf("Then number of list items does not match. Expected [%d]; got [%d]", 2, len(list.Methods)) + } +} + +func TestCreateProductMethod(t *testing.T) { + var ( + productID int64 = 97 + hitsID int64 = 98 + params = Params{"friendly_name": "method5"} + endpoint = fmt.Sprintf(productMethodListResourceEndpoint, productID, hitsID) + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodPost { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodPost, req.Method) + } + + item := &Method{ + Element: MethodItem{ + ID: 10, + Name: params["friendly_name"], + SystemName: params["friendly_name"], + }, + } + + responseBodyBytes, err := json.Marshal(item) + if err != nil { + t.Fatal(err) + } + + return &http.Response{ + StatusCode: http.StatusCreated, + Body: ioutil.NopCloser(bytes.NewBuffer(responseBodyBytes)), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + obj, err := c.CreateProductMethod(productID, hitsID, params) + if err != nil { + t.Fatal(err) + } + + if obj == nil { + t.Fatal("returned nil") + } + + if obj.Element.ID != 10 { + t.Fatalf("method ID does not match. Expected [%d]; got [%d]", 10, obj.Element.ID) + } + + if obj.Element.Name != params["friendly_name"] { + t.Fatalf("method name does not match. Expected [%s]; got [%s]", params["friendly_name"], obj.Element.Name) + } +} + +func TestDeleteProductMethod(t *testing.T) { + var ( + productID int64 = 97 + hitsID int64 = 98 + methodID int64 = 123325 + endpoint = fmt.Sprintf(productMethodResourceEndpoint, productID, hitsID, methodID) + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodDelete { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodDelete, req.Method) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(strings.NewReader("")), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + err := c.DeleteProductMethod(productID, hitsID, methodID) + if err != nil { + t.Fatal(err) + } +} + +func TestReadProductMethod(t *testing.T) { + var ( + productID int64 = 97 + hitsID int64 = 98 + methodID int64 = 123325 + endpoint = fmt.Sprintf(productMethodResourceEndpoint, productID, hitsID, methodID) + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodGet { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodGet, req.Method) + } + + item := &Method{ + Element: MethodItem{ + ID: methodID, + Name: "someName", + SystemName: "someName2", + }, + } + + responseBodyBytes, err := json.Marshal(item) + if err != nil { + t.Fatal(err) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer(responseBodyBytes)), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + obj, err := c.ProductMethod(productID, hitsID, methodID) + if err != nil { + t.Fatal(err) + } + + if obj == nil { + t.Fatal("method returned nil") + } + + if obj.Element.ID != methodID { + t.Fatalf("ID does not match. Expected [%d]; got [%d]", methodID, obj.Element.ID) + } +} + +func TestUpdateProductMethod(t *testing.T) { + var ( + productID int64 = 98765 + hitsID int64 = 1 + methodID int64 = 123325 + endpoint = fmt.Sprintf(productMethodResourceEndpoint, productID, hitsID, methodID) + params = Params{"description": "newDescr"} + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodPut { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodPut, req.Method) + } + + method := &Method{ + Element: MethodItem{ + ID: methodID, + Name: "someName", + SystemName: "someName2", + Description: params["description"], + }, + } + + responseBodyBytes, err := json.Marshal(method) + if err != nil { + t.Fatal(err) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer(responseBodyBytes)), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + obj, err := c.UpdateProductMethod(productID, hitsID, methodID, params) + if err != nil { + t.Fatal(err) + } + + if obj == nil { + t.Fatal("method returned nil") + } + + if obj.Element.ID != methodID { + t.Fatalf("method ID does not match. Expected [%d]; got [%d]", methodID, obj.Element.ID) + } + + if obj.Element.Description != params["description"] { + t.Fatalf("method description does not match. Expected [%s]; got [%s]", params["description"], obj.Element.Description) + } +} + +func TestListProductMetrics(t *testing.T) { + var ( + productID int64 = 97 + endpoint = fmt.Sprintf(productMetricListResourceEndpoint, productID) + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodGet { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodGet, req.Method) + } + + list := MetricJSONList{ + Metrics: []MetricJSON{ + { + Element: MetricItem{ + ID: 1, + Name: "hits", + SystemName: "hits", + Unit: "hit", + }, + }, + { + Element: MetricItem{ + ID: 2, + Name: "method02", + SystemName: "desc02", + Unit: "1", + }, + }, + }, + } + + responseBodyBytes, err := json.Marshal(list) + if err != nil { + t.Fatal(err) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer(responseBodyBytes)), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + list, err := c.ListProductMetrics(productID) + if err != nil { + t.Fatal(err) + } + + if list == nil { + t.Fatal("list returned nil") + } + + if len(list.Metrics) != 2 { + t.Fatalf("Then number of list items does not match. Expected [%d]; got [%d]", 2, len(list.Metrics)) + } +} + +func TestCreateProductMetric(t *testing.T) { + var ( + productID int64 = 97 + params = Params{"friendly_name": "metric02"} + endpoint = fmt.Sprintf(productMetricListResourceEndpoint, productID) + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodPost { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodPost, req.Method) + } + + item := &MetricJSON{ + Element: MetricItem{ + ID: 10, + Name: params["friendly_name"], + SystemName: params["friendly_name"], + Unit: "1", + }, + } + + responseBodyBytes, err := json.Marshal(item) + if err != nil { + t.Fatal(err) + } + + return &http.Response{ + StatusCode: http.StatusCreated, + Body: ioutil.NopCloser(bytes.NewBuffer(responseBodyBytes)), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + obj, err := c.CreateProductMetric(productID, params) + if err != nil { + t.Fatal(err) + } + + if obj == nil { + t.Fatal("returned nil") + } + + if obj.Element.ID != 10 { + t.Fatalf("ID does not match. Expected [%d]; got [%d]", 10, obj.Element.ID) + } + + if obj.Element.Name != params["friendly_name"] { + t.Fatalf("name does not match. Expected [%s]; got [%s]", params["friendly_name"], obj.Element.Name) + } +} + +func TestDeleteProductMetric(t *testing.T) { + var ( + productID int64 = 97 + itemID int64 = 123325 + endpoint = fmt.Sprintf(productMetricResourceEndpoint, productID, itemID) + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodDelete { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodDelete, req.Method) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(strings.NewReader("")), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + err := c.DeleteProductMetric(productID, itemID) + if err != nil { + t.Fatal(err) + } +} + +func TestReadProductMetric(t *testing.T) { + var ( + productID int64 = 97 + itemID int64 = 123325 + endpoint = fmt.Sprintf(productMetricResourceEndpoint, productID, itemID) + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodGet { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodGet, req.Method) + } + + item := &MetricJSON{ + Element: MetricItem{ + ID: itemID, + Name: "someName", + SystemName: "someName2", + Unit: "1", + }, + } + + responseBodyBytes, err := json.Marshal(item) + if err != nil { + t.Fatal(err) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer(responseBodyBytes)), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + obj, err := c.ProductMetric(productID, itemID) + if err != nil { + t.Fatal(err) + } + + if obj == nil { + t.Fatal("returned nil") + } + + if obj.Element.ID != itemID { + t.Fatalf("ID does not match. Expected [%d]; got [%d]", itemID, obj.Element.ID) + } +} + +func TestUpdateProductMetric(t *testing.T) { + var ( + productID int64 = 98765 + itemID int64 = 123325 + endpoint = fmt.Sprintf(productMetricResourceEndpoint, productID, itemID) + params = Params{"description": "newDescr"} + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodPut { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodPut, req.Method) + } + + item := &MetricJSON{ + Element: MetricItem{ + ID: itemID, + Name: "someName", + SystemName: "someName2", + Description: params["description"], + Unit: "1", + }, + } + + responseBodyBytes, err := json.Marshal(item) + if err != nil { + t.Fatal(err) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer(responseBodyBytes)), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + obj, err := c.UpdateProductMetric(productID, itemID, params) + if err != nil { + t.Fatal(err) + } + + if obj == nil { + t.Fatal("returned nil") + } + + if obj.Element.ID != itemID { + t.Fatalf("ID does not match. Expected [%d]; got [%d]", itemID, obj.Element.ID) + } + + if obj.Element.Description != params["description"] { + t.Fatalf("description does not match. Expected [%s]; got [%s]", params["description"], obj.Element.Description) + } +} + +func TestListProductMappingRules(t *testing.T) { + var ( + productID int64 = 97 + endpoint = fmt.Sprintf(productMappingRuleListResourceEndpoint, productID) + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodGet { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodGet, req.Method) + } + + list := MappingRuleJSONList{ + MappingRules: []MappingRuleJSON{ + { + Element: MappingRuleItem{ + ID: 1, + MetricID: 2, + Pattern: "/v1", + HTTPMethod: "GET", + }, + }, + { + Element: MappingRuleItem{ + ID: 2, + MetricID: 2, + Pattern: "/v2", + HTTPMethod: "GET", + }, + }, + }, + } + + responseBodyBytes, err := json.Marshal(list) + if err != nil { + t.Fatal(err) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer(responseBodyBytes)), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + list, err := c.ListProductMappingRules(productID) + if err != nil { + t.Fatal(err) + } + + if list == nil { + t.Fatal("list returned nil") + } + + if len(list.MappingRules) != 2 { + t.Fatalf("Then number of list items does not match. Expected [%d]; got [%d]", 2, len(list.MappingRules)) + } +} + +func TestCreateProductMappingRule(t *testing.T) { + var ( + productID int64 = 97 + params = Params{"pattern": "/somePath"} + endpoint = fmt.Sprintf(productMappingRuleListResourceEndpoint, productID) + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodPost { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodPost, req.Method) + } + + item := &MappingRuleJSON{ + Element: MappingRuleItem{ + ID: 10, + MetricID: 2, + Pattern: params["pattern"], + HTTPMethod: "GET", + }, + } + + responseBodyBytes, err := json.Marshal(item) + if err != nil { + t.Fatal(err) + } + + return &http.Response{ + StatusCode: http.StatusCreated, + Body: ioutil.NopCloser(bytes.NewBuffer(responseBodyBytes)), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + obj, err := c.CreateProductMappingRule(productID, params) + if err != nil { + t.Fatal(err) + } + + if obj == nil { + t.Fatal("returned nil") + } + + if obj.Element.ID != 10 { + t.Fatalf("ID does not match. Expected [%d]; got [%d]", 10, obj.Element.ID) + } + + if obj.Element.Pattern != params["pattern"] { + t.Fatalf("name does not match. Expected [%s]; got [%s]", params["pattern"], obj.Element.Pattern) + } +} + +func TestDeleteProductMappingRule(t *testing.T) { + var ( + productID int64 = 97 + itemID int64 = 123325 + endpoint = fmt.Sprintf(productMappingRuleResourceEndpoint, productID, itemID) + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodDelete { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodDelete, req.Method) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(strings.NewReader("")), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + err := c.DeleteProductMappingRule(productID, itemID) + if err != nil { + t.Fatal(err) + } +} + +func TestReadProductMappingRule(t *testing.T) { + var ( + productID int64 = 97 + itemID int64 = 123325 + endpoint = fmt.Sprintf(productMappingRuleResourceEndpoint, productID, itemID) + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodGet { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodGet, req.Method) + } + + item := &MappingRuleJSON{ + Element: MappingRuleItem{ + ID: itemID, + MetricID: 2, + Pattern: "/v1", + HTTPMethod: "GET", + }, + } + + responseBodyBytes, err := json.Marshal(item) + if err != nil { + t.Fatal(err) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer(responseBodyBytes)), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + obj, err := c.ProductMappingRule(productID, itemID) + if err != nil { + t.Fatal(err) + } + + if obj == nil { + t.Fatal("returned nil") + } + + if obj.Element.ID != itemID { + t.Fatalf("ID does not match. Expected [%d]; got [%d]", itemID, obj.Element.ID) + } +} + +func TestUpdateProductMappingRule(t *testing.T) { + var ( + productID int64 = 98765 + itemID int64 = 123325 + endpoint = fmt.Sprintf(productMappingRuleResourceEndpoint, productID, itemID) + params = Params{"pattern": "/newPath"} + ) + + httpClient := NewTestClient(func(req *http.Request) *http.Response { + if req.URL.Path != endpoint { + t.Fatalf("Path does not match. Expected [%s]; got [%s]", endpoint, req.URL.Path) + } + + if req.Method != http.MethodPut { + t.Fatalf("Method does not match. Expected [%s]; got [%s]", http.MethodPut, req.Method) + } + + item := &MappingRuleJSON{ + Element: MappingRuleItem{ + ID: itemID, + MetricID: 2, + Pattern: params["pattern"], + HTTPMethod: "GET", + }, + } + + responseBodyBytes, err := json.Marshal(item) + if err != nil { + t.Fatal(err) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer(responseBodyBytes)), + Header: make(http.Header), + } + }) + + credential := "someAccessToken" + c := NewThreeScale(NewTestAdminPortal(t), credential, httpClient) + obj, err := c.UpdateProductMappingRule(productID, itemID, params) + if err != nil { + t.Fatal(err) + } + + if obj == nil { + t.Fatal("returned nil") + } + + if obj.Element.ID != itemID { + t.Fatalf("ID does not match. Expected [%d]; got [%d]", itemID, obj.Element.ID) + } + + if obj.Element.Pattern != params["pattern"] { + t.Fatalf("description does not match. Expected [%s]; got [%s]", params["pattern"], obj.Element.Pattern) + } +}