Merge pull request #1 from StevanFreeborn/stevanfreeborn/feat/implement-ping-endpoint
feat: implement ping endpoint
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
name: Pull Request
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
test-and-lint:
|
||||
name: Test, Format & Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.25"
|
||||
cache: true
|
||||
- name: Check formatting
|
||||
run: |
|
||||
# Fails if any files are not formatted correctly
|
||||
if [ -n "$(gofmt -l .)" ]; then
|
||||
echo "Go code is not formatted:"
|
||||
gofmt -d .
|
||||
exit 1
|
||||
fi
|
||||
- name: Run go vet
|
||||
run: go vet ./...
|
||||
- name: Run linter
|
||||
uses: golangci/golangci-lint-action@v9
|
||||
with:
|
||||
version: latest
|
||||
- name: Run tests
|
||||
run: go test -v ./... -coverprofile=coverage.out
|
||||
- name: Generate coverage report
|
||||
run: go tool cover -html=coverage.out -o coverage.html
|
||||
- name: Upload test coverage
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: coverage-report
|
||||
path: coverage.html
|
||||
@@ -7,3 +7,85 @@ The Go SDK for the Onspring API is meant to simplify development in Go for Onspr
|
||||
Note: This is an unofficial SDK for the Onspring API. It was not built in consultation with Onspring Technologies LLC or a member of their development team.
|
||||
|
||||
This SDK was developed independently using Onspring's existing C# SDK, the Onspring API's swagger page, and api documentation as the starting point with the intention of making development of integrations done in Javascript with an Onspring instance quicker and more convenient.
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Go
|
||||
|
||||
Requires use of [Go](https://golang.org/dl/) version 1.18 or higher.
|
||||
|
||||
## Installation
|
||||
|
||||
To install the Onspring API Go SDK, use the following command:
|
||||
|
||||
```pwsh
|
||||
go get github.com/StevanFreeborn/onspring-api-sdk-go
|
||||
```
|
||||
|
||||
## API Key
|
||||
|
||||
In order to successfully interact with the Onspring Api you will need an API key. API keys are obtained by an Onspring user with permissions to at least **Read** API Keys for your instance via the following steps:
|
||||
|
||||
1. Login to the Onspring instance.
|
||||
2. Navigate to **Administration** > **Security** > **API Keys**
|
||||
3. On the list page, add a new API Key - this will require **Create** permissions - or click an existing API key to view its details.
|
||||
4. Click on the **Developer Information** tab.
|
||||
5. Copy the **X-ApiKey Header** value from this tab.
|
||||
|
||||
**Important:**
|
||||
|
||||
- An API Key must have a status of `Enabled` in order to make authorized requests.
|
||||
- Each API Key must have an assigned Role. This role controls the permissions for requests made. If the API Key used does not have sufficient permissions the requests made won't be successful.
|
||||
|
||||
### 🔒 Permission Considerations
|
||||
|
||||
You can think of any API Key as another user in your Onspring instance and therefore it is subject to all the same permission considerations as any other user when it comes to its ability to access data in your instance. The API Key you use needs to have all the correct permissions within your instance to access the data requested. Things to think about in this context are `role security`, `content security`, and `field security`.
|
||||
|
||||
## Start Coding
|
||||
|
||||
### `Client`
|
||||
|
||||
The most common way to use the SDK is to create a `Client` instance and call its methods to interact with the Onspring API. Here is an example of how to create a `Client` instance. You will need to provide your API key when creating the client. It is best practice to store your API key securely and not hard-code it in your source code.
|
||||
|
||||
```go
|
||||
import "github.com/StevanFreeborn/onspring-api-sdk-go/onspring"
|
||||
|
||||
client := onspring.NewClient("your-api-key")
|
||||
```
|
||||
|
||||
The `Client` instance can be further configured by providing optional configuration settings via the `ClientConfig` struct. For example, you can set a custom base URL for the Onspring API if needed:
|
||||
|
||||
```go
|
||||
import "github.com/StevanFreeborn/onspring-api-sdk-go/onspring"
|
||||
|
||||
client := onspring.NewClient(
|
||||
"your-api-key",
|
||||
onspring.WithBaseURL(customURL),
|
||||
)
|
||||
```
|
||||
|
||||
### Full API Documentation
|
||||
|
||||
You may wish to refer to the full [Onspring API documentation](https://software.onspring.com/hubfs/Training/Admin%20Guide%20-%20v2%20API.pdf) when determining which values to pass as parameters to some of the `OnspringClient` methods. There is also a [swagger page](https://api.onspring.com/swagger/index.html) that you can use for making exploratory requests.
|
||||
|
||||
## Examples
|
||||
|
||||
### Connectivity
|
||||
|
||||
#### Verify connectivity
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/StevanFreeborn/onspring-api-sdk-go/onspring"
|
||||
)
|
||||
|
||||
client := onspring.NewClient("your-api-key")
|
||||
|
||||
err := client.Ping.Get(context.TODO())
|
||||
|
||||
if err == nil {
|
||||
fmt.Println("Connection successful!")
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
// Package onspring provides a Go SDK for interacting with the Onspring API.
|
||||
// It offers a type-safe, idiomatic Go interface for making API requests
|
||||
// to the Onspring platform.
|
||||
package onspring
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// defaultBaseURL is the default base URL for the Onspring API.
|
||||
defaultBaseURL = "https://api.onspring.com"
|
||||
// defaultTimeout is the default HTTP client timeout duration.
|
||||
defaultTimeout = 120 * time.Second
|
||||
// defaultAPIKeyHeader is the HTTP header name used for API key authentication.
|
||||
defaultAPIKeyHeader = "x-api-key"
|
||||
// defaultAPIVersionHeader is the HTTP header name used to specify the API version.
|
||||
defaultAPIVersionHeader = "x-api-version"
|
||||
// defaultAPIVersion is the default Onspring API version to use.
|
||||
defaultAPIVersion = "2.0"
|
||||
)
|
||||
|
||||
// Client is the main client for interacting with the Onspring API.
|
||||
// It manages HTTP communication, authentication, and API versioning.
|
||||
// All API endpoints are accessed through this client.
|
||||
type Client struct {
|
||||
// httpClient is the underlying HTTP client used to make requests.
|
||||
httpClient *http.Client
|
||||
// baseURL is the base URL for the Onspring API.
|
||||
baseURL string
|
||||
// apiKey is the API key used for authentication.
|
||||
apiKey string
|
||||
// apiVersion is the API version to use for requests.
|
||||
apiVersion string
|
||||
|
||||
// Ping provides access to the ping endpoint for health checks.
|
||||
Ping *PingEndpoint
|
||||
}
|
||||
|
||||
// NewClient creates a new Onspring API client with the provided API key.
|
||||
// It initializes the client with default settings including a 100-second timeout,
|
||||
// the production API base URL, and API version 2.0.
|
||||
//
|
||||
// Optional configuration can be provided using Option functions such as
|
||||
// WithHTTPClient, WithBaseURL, and WithAPIVersion.
|
||||
//
|
||||
// Parameters:
|
||||
// - apiKey: The API key for authenticating with the Onspring API
|
||||
// - opts: Optional configuration functions to customize the client
|
||||
//
|
||||
// Returns:
|
||||
// - *Client: A configured Onspring API client ready to make requests
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// client := onspring.NewClient("your-api-key")
|
||||
// client := onspring.NewClient("your-api-key", onspring.WithHTTPClient(customHTTPClient))
|
||||
func NewClient(apiKey string, opts ...Option) *Client {
|
||||
c := &Client{
|
||||
httpClient: &http.Client{Timeout: defaultTimeout},
|
||||
baseURL: defaultBaseURL,
|
||||
apiKey: apiKey,
|
||||
apiVersion: defaultAPIVersion,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(c)
|
||||
}
|
||||
|
||||
c.Ping = &PingEndpoint{client: c}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// do executes an HTTP request and handles the response.
|
||||
// It performs the actual HTTP call using the configured HTTP client,
|
||||
// checks the response status code, and handles any API errors.
|
||||
//
|
||||
// Parameters:
|
||||
// - req: The HTTP request to execute
|
||||
//
|
||||
// Returns:
|
||||
// - error: nil if the request succeeds, or an error if the request fails
|
||||
// or returns a non-2xx status code
|
||||
func (c *Client) do(req *http.Request) error {
|
||||
resp, err := c.httpClient.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = resp.Body.Close()
|
||||
}()
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return c.handleAPIError(resp)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// handleAPIError processes error responses from the Onspring API.
|
||||
// It attempts to decode the error message from the response body.
|
||||
// If decoding fails, it falls back to using the HTTP status text.
|
||||
//
|
||||
// Parameters:
|
||||
// - resp: The HTTP response containing the error
|
||||
//
|
||||
// Returns:
|
||||
// - error: An OnspringAPIError with the status code and error message
|
||||
func (c *Client) handleAPIError(resp *http.Response) error {
|
||||
var errBody struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
decodeErr := json.NewDecoder(resp.Body).Decode(&errBody)
|
||||
|
||||
if decodeErr != nil {
|
||||
errBody.Message = http.StatusText(resp.StatusCode)
|
||||
}
|
||||
|
||||
return &OnspringAPIError{
|
||||
StatusCode: resp.StatusCode,
|
||||
Message: errBody.Message,
|
||||
}
|
||||
}
|
||||
|
||||
// newRequest creates a new HTTP request for the Onspring API.
|
||||
// It constructs the full URL, sets required authentication headers,
|
||||
// and prepares the request with the provided context.
|
||||
//
|
||||
// Parameters:
|
||||
// - ctx: The context for the request
|
||||
// - method: The HTTP method
|
||||
// - path: The API endpoint path
|
||||
// - body: The request body
|
||||
//
|
||||
// Returns:
|
||||
// - *http.Request: The prepared HTTP request
|
||||
// - error: An error if the context is nil or request creation fails
|
||||
func (c *Client) newRequest(ctx context.Context, method, path string, _ any) (*http.Request, error) {
|
||||
if ctx == nil {
|
||||
return nil, fmt.Errorf("context must not be nil")
|
||||
}
|
||||
|
||||
fullURL := fmt.Sprintf("%s/%s", strings.TrimRight(c.baseURL, "/"), strings.TrimLeft(path, "/"))
|
||||
|
||||
var bodyReader io.Reader
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, method, fullURL, bodyReader)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set(defaultAPIKeyHeader, c.apiKey)
|
||||
req.Header.Set(defaultAPIVersionHeader, c.apiVersion)
|
||||
|
||||
return req, nil
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package onspring
|
||||
|
||||
import "net/http"
|
||||
|
||||
func (c *Client) HTTPClient() *http.Client {
|
||||
return c.httpClient
|
||||
}
|
||||
|
||||
func (c *Client) BaseURL() string {
|
||||
return c.baseURL
|
||||
}
|
||||
|
||||
func (c *Client) APIKey() string {
|
||||
return c.apiKey
|
||||
}
|
||||
|
||||
func (c *Client) APIVersion() string {
|
||||
return c.apiVersion
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package onspring_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/StevanFreeborn/onspring-api-sdk-go"
|
||||
)
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
t.Run("it should create client with default settings", func(t *testing.T) {
|
||||
apiKey := "test-api-key"
|
||||
client := onspring.NewClient(apiKey)
|
||||
|
||||
if client.APIKey() != apiKey {
|
||||
t.Errorf("Expected apiKey %s, got %s", apiKey, client.APIKey())
|
||||
}
|
||||
|
||||
if client.BaseURL() != "https://api.onspring.com" {
|
||||
t.Errorf("Expected default baseURL, got %s", client.BaseURL())
|
||||
}
|
||||
|
||||
if client.HTTPClient().Timeout != 120*time.Second {
|
||||
t.Errorf("Expected default timeout, got %v", client.HTTPClient().Timeout)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
t.Run("it should create client with custom settings", func(t *testing.T) {
|
||||
apiKey := "test-api-key"
|
||||
customURL := "https://custom.onspring.com"
|
||||
customHTTPClient := &http.Client{Timeout: 50 * time.Second}
|
||||
|
||||
client := onspring.NewClient(
|
||||
apiKey,
|
||||
onspring.WithBaseURL(customURL),
|
||||
onspring.WithHTTPClient(customHTTPClient),
|
||||
)
|
||||
|
||||
if client.APIKey() != apiKey {
|
||||
t.Errorf("Expected apiKey %s, got %s", apiKey, client.APIKey())
|
||||
}
|
||||
|
||||
if client.BaseURL() != customURL {
|
||||
t.Errorf("Expected baseURL %s, got %s", customURL, client.BaseURL())
|
||||
}
|
||||
|
||||
if client.HTTPClient() != customHTTPClient {
|
||||
t.Errorf("Expected custom HTTP client, got %v", client.HTTPClient())
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package onspring
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// OnspringAPIError represents an error returned by the Onspring API.
|
||||
// It contains the HTTP status code and the error message from the API response.
|
||||
// This error type implements the error interface.
|
||||
type OnspringAPIError struct {
|
||||
// StatusCode is the HTTP status code returned by the API.
|
||||
StatusCode int
|
||||
// Message is the error message returned by the API or the HTTP status text.
|
||||
Message string
|
||||
}
|
||||
|
||||
// Error returns a formatted error string containing the status code and message.
|
||||
// It implements the error interface for OnspringAPIError.
|
||||
//
|
||||
// Returns:
|
||||
// - string: A formatted error message in the format "onspring api error: status={code} message={message}"
|
||||
func (e *OnspringAPIError) Error() string {
|
||||
return fmt.Sprintf("onspring api error: status=%d message=%s", e.StatusCode, e.Message)
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package onspring_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/StevanFreeborn/onspring-api-sdk-go"
|
||||
)
|
||||
|
||||
func TestOnspringAPIError(t *testing.T) {
|
||||
t.Run("it should create OnspringAPIError instance", func(t *testing.T) {
|
||||
statusCode := 500
|
||||
message := "Internal Server Error"
|
||||
|
||||
err := &onspring.OnspringAPIError{
|
||||
StatusCode: statusCode,
|
||||
Message: message,
|
||||
}
|
||||
|
||||
if err.StatusCode != statusCode {
|
||||
t.Errorf("Expected status code %d, got %d", statusCode, err.StatusCode)
|
||||
}
|
||||
|
||||
if err.Message != message {
|
||||
t.Errorf("Expected message %s, got %s", message, err.Message)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("it should return formatted error message", func(t *testing.T) {
|
||||
err := &onspring.OnspringAPIError{
|
||||
StatusCode: 404,
|
||||
Message: "Not Found",
|
||||
}
|
||||
|
||||
expectedMessage := "onspring api error: status=404 message=Not Found"
|
||||
|
||||
if err.Error() != expectedMessage {
|
||||
t.Errorf("Expected error message %s, got %s", expectedMessage, err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package onspring_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/StevanFreeborn/onspring-api-sdk-go"
|
||||
)
|
||||
|
||||
func setupMockServer(t *testing.T, handler http.HandlerFunc) (*httptest.Server, *onspring.Client) {
|
||||
t.Helper()
|
||||
|
||||
server := httptest.NewServer(handler)
|
||||
|
||||
t.Cleanup(func() {
|
||||
server.Close()
|
||||
})
|
||||
|
||||
client := onspring.NewClient(
|
||||
"test-key",
|
||||
onspring.WithBaseURL(server.URL),
|
||||
onspring.WithHTTPClient(server.Client()),
|
||||
)
|
||||
|
||||
return server, client
|
||||
}
|
||||
|
||||
type ErrorTransport struct{}
|
||||
|
||||
func (t *ErrorTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return nil, errors.New("simulated network connection failure")
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package onspring
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Option is a functional option for configuring a Client.
|
||||
type Option func(*Client)
|
||||
|
||||
// WithHTTPClient sets a custom HTTP client for the Onspring client.
|
||||
// If not provided, the client will use http.DefaultClient.
|
||||
func WithHTTPClient(client *http.Client) Option {
|
||||
return func(c *Client) {
|
||||
c.httpClient = client
|
||||
}
|
||||
}
|
||||
|
||||
// WithBaseURL sets a custom base URL for the Onspring API.
|
||||
// This is useful for testing or when using a different Onspring environment.
|
||||
func WithBaseURL(url string) Option {
|
||||
return func(c *Client) {
|
||||
c.baseURL = url
|
||||
}
|
||||
}
|
||||
|
||||
// WithAPIVersion sets a custom API version for the Onspring client.
|
||||
// If not provided, the client will use the default API version.
|
||||
func WithAPIVersion(version string) Option {
|
||||
return func(c *Client) {
|
||||
c.apiVersion = version
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package onspring_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/StevanFreeborn/onspring-api-sdk-go"
|
||||
)
|
||||
|
||||
func TestWithHTTPClient(t *testing.T) {
|
||||
t.Run("it should set a custom HTTP client on the Onsring client", func(t *testing.T) {
|
||||
customHTTPClient := &http.Client{Timeout: 10 * time.Second}
|
||||
|
||||
clientWithCustomHTTP := onspring.NewClient(
|
||||
"test-api-key",
|
||||
onspring.WithHTTPClient(customHTTPClient),
|
||||
)
|
||||
|
||||
if clientWithCustomHTTP.HTTPClient() != customHTTPClient {
|
||||
t.Errorf("Expected custom HTTP client to be set")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestWithBaseURL(t *testing.T) {
|
||||
t.Run("it should set a custom base URL on the Onsring client", func(t *testing.T) {
|
||||
customBaseURL := "https://custom.onspring.com"
|
||||
|
||||
clientWithCustomURL := onspring.NewClient(
|
||||
"test-api-key",
|
||||
onspring.WithBaseURL(customBaseURL),
|
||||
)
|
||||
|
||||
if clientWithCustomURL.BaseURL() != customBaseURL {
|
||||
t.Errorf("Expected base URL to be %s, got %s", customBaseURL, clientWithCustomURL.BaseURL())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestWithAPIVersion(t *testing.T) {
|
||||
t.Run("it should set a custom API version on the Onsring client", func(t *testing.T) {
|
||||
customVersion := "3.0"
|
||||
|
||||
clientWithCustomVersion := onspring.NewClient(
|
||||
"test-api-key",
|
||||
onspring.WithAPIVersion(customVersion),
|
||||
)
|
||||
|
||||
if clientWithCustomVersion.APIVersion() != customVersion {
|
||||
t.Errorf("Expected API version to be %s, got %s", customVersion, clientWithCustomVersion.APIVersion())
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package onspring
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
// pingPath is the API endpoint path for the ping health check.
|
||||
pingPath = "/ping"
|
||||
)
|
||||
|
||||
// PingEndpoint provides access to the Onspring API ping endpoint.
|
||||
// It can be used to verify API connectivity and authentication.
|
||||
type PingEndpoint struct {
|
||||
// client is the parent Client used to make API requests.
|
||||
client *Client
|
||||
}
|
||||
|
||||
// Get performs a ping request to verify API connectivity.
|
||||
// This is a simple health check that can be used to test if the API is
|
||||
// reachable.
|
||||
//
|
||||
// Parameters:
|
||||
// - ctx: The context for the request
|
||||
//
|
||||
// Returns:
|
||||
// - error: nil if the ping succeeds, or an error if the request fails
|
||||
// or authentication is invalid
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// client := onspring.NewClient("your-api-key")
|
||||
// err := client.Ping.Get(context.Background())
|
||||
// if err != nil {
|
||||
// log.Fatal("Ping failed:", err)
|
||||
// }
|
||||
func (p *PingEndpoint) Get(ctx context.Context) error {
|
||||
req, err := p.client.newRequest(ctx, http.MethodGet, pingPath, nil)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.client.do(req)
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
package onspring_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/StevanFreeborn/onspring-api-sdk-go"
|
||||
)
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
t.Run("it should return an error if context is nil", func(t *testing.T) {
|
||||
_, client := setupMockServer(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
var nilContext context.Context = nil
|
||||
|
||||
err := client.Ping.Get(nilContext)
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Expected error for nil context, got nil")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("it should return an error if context is canceled", func(t *testing.T) {
|
||||
_, client := setupMockServer(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
ctx, cancel := context.WithCancel(t.Context())
|
||||
|
||||
cancel()
|
||||
|
||||
err := client.Ping.Get(ctx)
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Expected error for canceled context, got nil")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("it should return an error if encounters a network error", func(t *testing.T) {
|
||||
client := onspring.NewClient(
|
||||
"test-api-key",
|
||||
onspring.WithBaseURL("http://invalid-url"),
|
||||
onspring.WithHTTPClient(&http.Client{Transport: &ErrorTransport{}}),
|
||||
)
|
||||
|
||||
err := client.Ping.Get(t.Context())
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Expected network error, got nil")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("it should return an error if create a request fails", func(t *testing.T) {
|
||||
_, client := setupMockServer(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
invalidClient := onspring.NewClient(
|
||||
"test-api-key",
|
||||
onspring.WithBaseURL("http://[::1]:namedport"),
|
||||
onspring.WithHTTPClient(client.HTTPClient()),
|
||||
)
|
||||
|
||||
err := invalidClient.Ping.Get(t.Context())
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Expected request creation error, got nil")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("it should perform a GET request to the /ping endpoint and return no error if receives 200 status code", func(t *testing.T) {
|
||||
_, client := setupMockServer(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
t.Errorf("Expected GET method, got %s", r.Method)
|
||||
}
|
||||
|
||||
if r.URL.Path != "/ping" {
|
||||
t.Errorf("Expected /ping endpoint, got %s", r.URL.Path)
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
err := client.Ping.Get(t.Context())
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("it should return an error if the /ping endpoint returns a non-200 status code", func(t *testing.T) {
|
||||
_, client := setupMockServer(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
})
|
||||
|
||||
err := client.Ping.Get(t.Context())
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Expected error, got nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user