diff --git a/client.go b/client.go index a0bf99e..1b650a7 100644 --- a/client.go +++ b/client.go @@ -171,6 +171,9 @@ type Client struct { // // baseURL := client.BaseURL() func (c *Client) BaseURL() string { + if c == nil { + return "" + } return c.baseURL } @@ -180,6 +183,9 @@ func (c *Client) BaseURL() string { // // rl := client.RateLimit() func (c *Client) RateLimit() RateLimit { + if c == nil { + return RateLimit{} + } return c.rateLimit } @@ -189,6 +195,9 @@ func (c *Client) RateLimit() RateLimit { // // ua := client.UserAgent() func (c *Client) UserAgent() string { + if c == nil { + return "" + } return c.userAgent } @@ -198,6 +207,9 @@ func (c *Client) UserAgent() string { // // hc := client.HTTPClient() func (c *Client) HTTPClient() *http.Client { + if c == nil { + return nil + } return c.httpClient } @@ -232,6 +244,9 @@ func (c *Client) GoString() string { return c.String() } // _ = "authenticated" // } func (c *Client) HasToken() bool { + if c == nil { + return false + } return c.token != "" } diff --git a/client_test.go b/client_test.go index c8e8555..818383a 100644 --- a/client_test.go +++ b/client_test.go @@ -215,6 +215,25 @@ func TestClient_HasToken_Bad(t *testing.T) { } } +func TestClient_NilSafeAccessors(t *testing.T) { + var c *Client + if got := c.BaseURL(); got != "" { + t.Fatalf("got BaseURL()=%q, want empty string", got) + } + if got := c.RateLimit(); got != (RateLimit{}) { + t.Fatalf("got RateLimit()=%#v, want zero value", got) + } + if got := c.UserAgent(); got != "" { + t.Fatalf("got UserAgent()=%q, want empty string", got) + } + if got := c.HTTPClient(); got != nil { + t.Fatal("expected HTTPClient() to return nil") + } + if got := c.HasToken(); got { + t.Fatal("expected HasToken() to report false") + } +} + func TestClient_WithHTTPClient_Good(t *testing.T) { custom := &http.Client{} c := NewClient("https://forge.lthn.ai", "tok", WithHTTPClient(custom)) diff --git a/forge.go b/forge.go index 22e08fe..e24eb8b 100644 --- a/forge.go +++ b/forge.go @@ -72,35 +72,60 @@ func NewForge(url, token string, opts ...Option) *Forge { // Usage: // // client := f.Client() -func (f *Forge) Client() *Client { return f.client } +func (f *Forge) Client() *Client { + if f == nil { + return nil + } + return f.client +} // BaseURL returns the configured Forgejo base URL. // // Usage: // // baseURL := f.BaseURL() -func (f *Forge) BaseURL() string { return f.client.BaseURL() } +func (f *Forge) BaseURL() string { + if f == nil || f.client == nil { + return "" + } + return f.client.BaseURL() +} // RateLimit returns the last known rate limit information. // // Usage: // // rl := f.RateLimit() -func (f *Forge) RateLimit() RateLimit { return f.client.RateLimit() } +func (f *Forge) RateLimit() RateLimit { + if f == nil || f.client == nil { + return RateLimit{} + } + return f.client.RateLimit() +} // UserAgent returns the configured User-Agent header value. // // Usage: // // ua := f.UserAgent() -func (f *Forge) UserAgent() string { return f.client.UserAgent() } +func (f *Forge) UserAgent() string { + if f == nil || f.client == nil { + return "" + } + return f.client.UserAgent() +} // HTTPClient returns the configured underlying HTTP client. // // Usage: // // hc := f.HTTPClient() -func (f *Forge) HTTPClient() *http.Client { return f.client.HTTPClient() } +func (f *Forge) HTTPClient() *http.Client { + if f == nil || f.client == nil { + return nil + } + return f.client.HTTPClient() +} // HasToken reports whether the Forge client was configured with an API token. // @@ -109,7 +134,12 @@ func (f *Forge) HTTPClient() *http.Client { return f.client.HTTPClient() } // if f.HasToken() { // _ = "authenticated" // } -func (f *Forge) HasToken() bool { return f.client.HasToken() } +func (f *Forge) HasToken() bool { + if f == nil || f.client == nil { + return false + } + return f.client.HasToken() +} // String returns a safe summary of the Forge client. // diff --git a/forge_test.go b/forge_test.go index 8a47bf5..78e3792 100644 --- a/forge_test.go +++ b/forge_test.go @@ -82,6 +82,28 @@ func TestForge_HasToken_Bad(t *testing.T) { } } +func TestForge_NilSafeAccessors(t *testing.T) { + var f *Forge + if got := f.Client(); got != nil { + t.Fatal("expected Client() to return nil") + } + if got := f.BaseURL(); got != "" { + t.Fatalf("got BaseURL()=%q, want empty string", got) + } + if got := f.RateLimit(); got != (RateLimit{}) { + t.Fatalf("got RateLimit()=%#v, want zero value", got) + } + if got := f.UserAgent(); got != "" { + t.Fatalf("got UserAgent()=%q, want empty string", got) + } + if got := f.HTTPClient(); got != nil { + t.Fatal("expected HTTPClient() to return nil") + } + if got := f.HasToken(); got { + t.Fatal("expected HasToken() to report false") + } +} + func TestForge_String_Good(t *testing.T) { f := NewForge("https://forge.lthn.ai", "tok", WithUserAgent("go-forge/1.0")) got := fmt.Sprint(f)