generated from NdoleStudio/go-http-client
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
40456ee
commit 6e8bbe7
Showing
8 changed files
with
338 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
package stubs | ||
|
||
// ProductGetResponse is a dummy response to the GET /v1/products/:id endpoint | ||
func ProductGetResponse() []byte { | ||
return []byte(` | ||
{ | ||
"jsonapi": { | ||
"version": "1.0" | ||
}, | ||
"links": { | ||
"self": "https://api.lemonsqueezy.com/v1/products/1" | ||
}, | ||
"data": { | ||
"type": "products", | ||
"id": "1", | ||
"attributes": { | ||
"store_id": 1, | ||
"name": "Example Product", | ||
"slug": "example-product", | ||
"description": "<p>Lorem ipsum...</p>", | ||
"status": "published", | ||
"status_formatted": "Published", | ||
"thumb_url": "https://app.lemonsqueezy.com/storage/media/1/1c40f227-aed5-4321-9ffc-62f37a06c9a0.jpg", | ||
"large_thumb_url": "https://app.lemonsqueezy.com/storage/media/1/1c40f227-aed5-4321-9ffc-62f37a06c9a0.jpg", | ||
"price": 999, | ||
"pay_what_you_want": false, | ||
"from_price": null, | ||
"to_price": null, | ||
"buy_now_url": "https://my-store.lemonsqueezy.com/checkout/buy/0a841cf5-4cc2-4bbb-ae5d-9529d97deec6", | ||
"price_formatted": "$9.99", | ||
"created_at": "2021-05-27T12:54:47.000000Z", | ||
"updated_at": "2021-07-14T11:25:24.000000Z" | ||
}, | ||
"relationships": { | ||
"store": { | ||
"links": { | ||
"related": "https://api.lemonsqueezy.com/v1/products/1/store", | ||
"self": "https://api.lemonsqueezy.com/v1/products/1/relationships/store" | ||
} | ||
}, | ||
"variants": { | ||
"links": { | ||
"related": "https://api.lemonsqueezy.com/v1/products/1/variants", | ||
"self": "https://api.lemonsqueezy.com/v1/products/1/relationships/variants" | ||
} | ||
} | ||
}, | ||
"links": { | ||
"self": "https://api.lemonsqueezy.com/v1/products/1" | ||
} | ||
} | ||
} | ||
`) | ||
} | ||
|
||
// ProductsListResponse is a dummy response to GET /v1/products | ||
func ProductsListResponse() []byte { | ||
return []byte(` | ||
{ | ||
"meta": { | ||
"page": { | ||
"currentPage": 1, | ||
"from": 1, | ||
"lastPage": 1, | ||
"perPage": 10, | ||
"to": 10, | ||
"total": 10 | ||
} | ||
}, | ||
"jsonapi": { | ||
"version": "1.0" | ||
}, | ||
"links": { | ||
"first": "https://api.lemonsqueezy.com/v1/products?page%5Bnumber%5D=1&page%5Bsize%5D=10&sort=name", | ||
"last": "https://api.lemonsqueezy.com/v1/products?page%5Bnumber%5D=1&page%5Bsize%5D=10&sort=name" | ||
}, | ||
"data": [ | ||
{ | ||
"type": "products", | ||
"id": "1", | ||
"attributes": { | ||
"store_id": 1, | ||
"name": "Example Product", | ||
"slug": "example-product", | ||
"description": "<p>Lorem ipsum...</p>", | ||
"status": "published", | ||
"status_formatted": "Published", | ||
"thumb_url": "https://app.lemonsqueezy.com/storage/media/1/1c40f227-aed5-4321-9ffc-62f37a06c9a0.jpg", | ||
"large_thumb_url": "https://app.lemonsqueezy.com/storage/media/1/1c40f227-aed5-4321-9ffc-62f37a06c9a0.jpg", | ||
"price": 999, | ||
"pay_what_you_want": false, | ||
"from_price": null, | ||
"to_price": null, | ||
"buy_now_url": "https://my-store.lemonsqueezy.com/checkout/buy/0a841cf5-4cc2-4bbb-ae5d-9529d97deec6", | ||
"price_formatted": "$9.99", | ||
"created_at": "2021-05-27T12:54:47.000000Z", | ||
"updated_at": "2021-07-14T11:25:24.000000Z" | ||
}, | ||
"relationships": { | ||
"store": { | ||
"links": { | ||
"related": "https://api.lemonsqueezy.com/v1/products/1/store", | ||
"self": "https://api.lemonsqueezy.com/v1/products/1/relationships/store" | ||
} | ||
}, | ||
"variants": { | ||
"links": { | ||
"related": "https://api.lemonsqueezy.com/v1/products/1/variants", | ||
"self": "https://api.lemonsqueezy.com/v1/products/1/relationships/variants" | ||
} | ||
} | ||
}, | ||
"links": { | ||
"self": "https://api.lemonsqueezy.com/v1/products/1" | ||
} | ||
}, | ||
{ | ||
"type": "products", | ||
"id": "2", | ||
"attributes": { | ||
"store_id": 2, | ||
"name": "Example Product", | ||
"slug": "example-product", | ||
"description": "<p>Lorem ipsum...</p>", | ||
"status": "published", | ||
"status_formatted": "Published", | ||
"thumb_url": "https://app.lemonsqueezy.com/storage/media/1/1c40f227-aed5-4321-9ffc-62f37a06c9a0.jpg", | ||
"large_thumb_url": "https://app.lemonsqueezy.com/storage/media/1/1c40f227-aed5-4321-9ffc-62f37a06c9a0.jpg", | ||
"price": 999, | ||
"pay_what_you_want": false, | ||
"from_price": null, | ||
"to_price": null, | ||
"buy_now_url": "https://my-store.lemonsqueezy.com/checkout/buy/0a841cf5-4cc2-4bbb-ae5d-9529d97deec6", | ||
"price_formatted": "$9.99", | ||
"created_at": "2021-05-27T12:54:47.000000Z", | ||
"updated_at": "2021-07-14T11:25:24.000000Z" | ||
}, | ||
"relationships": { | ||
"store": { | ||
"links": { | ||
"related": "https://api.lemonsqueezy.com/v1/products/1/store", | ||
"self": "https://api.lemonsqueezy.com/v1/products/1/relationships/store" | ||
} | ||
}, | ||
"variants": { | ||
"links": { | ||
"related": "https://api.lemonsqueezy.com/v1/products/1/variants", | ||
"self": "https://api.lemonsqueezy.com/v1/products/1/relationships/variants" | ||
} | ||
} | ||
}, | ||
"links": { | ||
"self": "https://api.lemonsqueezy.com/v1/products/1" | ||
} | ||
} | ||
] | ||
} | ||
`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package client | ||
|
||
import "time" | ||
|
||
// ProductAttributes are the attributes of a lemonsqueezy product | ||
type ProductAttributes struct { | ||
StoreID int `json:"store_id"` | ||
Name string `json:"name"` | ||
Slug string `json:"slug"` | ||
Description string `json:"description"` | ||
Status string `json:"status"` | ||
StatusFormatted string `json:"status_formatted"` | ||
ThumbURL string `json:"thumb_url"` | ||
LargeThumbURL string `json:"large_thumb_url"` | ||
Price int `json:"price"` | ||
PayWhatYouWant bool `json:"pay_what_you_want"` | ||
FromPrice *int `json:"from_price"` | ||
ToPrice *int `json:"to_price"` | ||
BuyNowURL string `json:"buy_now_url"` | ||
PriceFormatted string `json:"price_formatted"` | ||
CreatedAt time.Time `json:"created_at"` | ||
UpdatedAt time.Time `json:"updated_at"` | ||
} | ||
|
||
// ApiResponseRelationshipsProduct relationships of a product | ||
type ApiResponseRelationshipsProduct struct { | ||
Store ApiResponseLinks `json:"store"` | ||
Variants ApiResponseLinks `json:"variants"` | ||
} | ||
|
||
// ProductApiResponse represents a product api response | ||
type ProductApiResponse = ApiResponse[ProductAttributes, ApiResponseRelationshipsProduct] | ||
|
||
// ProductsApiResponse represents a list of products api responses. | ||
type ProductsApiResponse = ApiResponseList[ProductAttributes, ApiResponseRelationshipsProduct] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"net/http" | ||
) | ||
|
||
// ProductsService is the API client for the `/v1/products` endpoint | ||
type ProductsService service | ||
|
||
// Get returns the product with the given ID. | ||
// https://docs.lemonsqueezy.com/api/products#retrieve-a-product | ||
func (service *ProductsService) Get(ctx context.Context, productID string) (*ProductApiResponse, *Response, error) { | ||
response, err := service.client.do(ctx, http.MethodGet, "/v1/products/"+productID) | ||
if err != nil { | ||
return nil, response, err | ||
} | ||
|
||
product := new(ProductApiResponse) | ||
if err = json.Unmarshal(*response.Body, product); err != nil { | ||
return nil, response, err | ||
} | ||
|
||
return product, response, nil | ||
} | ||
|
||
// List returns a paginated list of products. | ||
// https://docs.lemonsqueezy.com/api/products#list-all-products | ||
func (service *ProductsService) List(ctx context.Context) (*ProductsApiResponse, *Response, error) { | ||
response, err := service.client.do(ctx, http.MethodGet, "/v1/products") | ||
if err != nil { | ||
return nil, response, err | ||
} | ||
|
||
products := new(ProductsApiResponse) | ||
if err = json.Unmarshal(*response.Body, products); err != nil { | ||
return nil, response, err | ||
} | ||
|
||
return products, response, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/NdoleStudio/lemonsqueezy-go/internal/helpers" | ||
"github.com/NdoleStudio/lemonsqueezy-go/internal/stubs" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestProductsService_Get(t *testing.T) { | ||
// Setup | ||
t.Parallel() | ||
|
||
// Arrange | ||
server := helpers.MakeTestServer(http.StatusOK, stubs.ProductGetResponse()) | ||
client := New(WithBaseURL(server.URL)) | ||
|
||
// Act | ||
product, response, err := client.Products.Get(context.Background(), "1") | ||
|
||
// Assert | ||
assert.Nil(t, err) | ||
|
||
assert.Equal(t, http.StatusOK, response.HTTPResponse.StatusCode) | ||
assert.Equal(t, stubs.ProductGetResponse(), *response.Body) | ||
assert.Equal(t, "1", product.Data.ID) | ||
|
||
// Teardown | ||
server.Close() | ||
} | ||
|
||
func TestProductsService_GetWithError(t *testing.T) { | ||
// Setup | ||
t.Parallel() | ||
|
||
// Arrange | ||
server := helpers.MakeTestServer(http.StatusInternalServerError, nil) | ||
client := New(WithBaseURL(server.URL)) | ||
|
||
// Act | ||
_, response, err := client.Products.Get(context.Background(), "1") | ||
|
||
// Assert | ||
assert.NotNil(t, err) | ||
|
||
assert.Equal(t, http.StatusInternalServerError, response.HTTPResponse.StatusCode) | ||
|
||
// Teardown | ||
server.Close() | ||
} | ||
|
||
func TestProductsService_List(t *testing.T) { | ||
// Setup | ||
t.Parallel() | ||
|
||
// Arrange | ||
server := helpers.MakeTestServer(http.StatusOK, stubs.ProductsListResponse()) | ||
client := New(WithBaseURL(server.URL)) | ||
|
||
// Act | ||
products, response, err := client.Products.List(context.Background()) | ||
|
||
// Assert | ||
assert.Nil(t, err) | ||
|
||
assert.Equal(t, http.StatusOK, response.HTTPResponse.StatusCode) | ||
assert.Equal(t, stubs.ProductsListResponse(), *response.Body) | ||
assert.Equal(t, 2, len(products.Data)) | ||
|
||
// Teardown | ||
server.Close() | ||
} | ||
|
||
func TestProductsService_ListWithError(t *testing.T) { | ||
// Setup | ||
t.Parallel() | ||
|
||
// Arrange | ||
server := helpers.MakeTestServer(http.StatusInternalServerError, nil) | ||
client := New(WithBaseURL(server.URL)) | ||
|
||
// Act | ||
_, response, err := client.Products.List(context.Background()) | ||
|
||
// Assert | ||
assert.NotNil(t, err) | ||
|
||
assert.Equal(t, http.StatusInternalServerError, response.HTTPResponse.StatusCode) | ||
|
||
// Teardown | ||
server.Close() | ||
} |