package shopify import ( "errors" "testing" "time" ) func TestParseAccessTokenResponse(t *testing.T) { t.Parallel() parsed, err := parseAccessTokenResponse([]byte(`{"access_token":"tok_abc","scope":"read_products","expires_in":86399}`)) if err != nil { t.Fatalf("parse: %v", err) } if parsed.AccessToken != "tok_abc" || parsed.Scope != "read_products" || parsed.ExpiresIn != 86399 { t.Fatalf("unexpected parse: %+v", parsed) } } func TestParseAccessTokenResponseEmpty(t *testing.T) { t.Parallel() _, err := parseAccessTokenResponse(nil) if !errors.Is(err, ErrTokenExchangeFailed) { t.Fatalf("want ErrTokenExchangeFailed, got %v", err) } } func TestExchangeClientCredentialsRequiresPair(t *testing.T) { t.Parallel() _, err := ExchangeClientCredentials(t.Context(), nil, "demo.myshopify.com", "id-only", "") if !errors.Is(err, ErrInvalidClientCredentials) { t.Fatalf("want ErrInvalidClientCredentials, got %v", err) } } func TestTokenNeedsRefresh(t *testing.T) { t.Parallel() now := time.Date(2026, 8, 9, 12, 0, 0, 0, time.UTC) if !tokenNeedsRefresh(nil, now) { t.Fatal("nil expiry should refresh") } soon := now.Add(30 * time.Second) if !tokenNeedsRefresh(&soon, now) { t.Fatal("within skew should refresh") } later := now.Add(time.Hour) if tokenNeedsRefresh(&later, now) { t.Fatal("fresh token should not refresh") } } func TestClientErrorTokenExchange(t *testing.T) { t.Parallel() msg, ok := ClientError(ErrTokenExchangeFailed) if !ok || msg == "" { t.Fatalf("ClientError should map token exchange: ok=%v msg=%q", ok, msg) } }