* H-300: wire Captain Skills into Web runtime * H-300: enforce effective model and conservative skill budget * H-300: fix CI gosec step * ci: extend golangci-lint timeout * fix lint findings across backend * fix(push): resolve delivery protocol blockers * test(repository): close SQLite test databases * test(repository): reuse SQLite schema per package * H-307: restore backend Go cache in CI * H-307: prefetch modules before cold lint * H-307: resolve govulncheck security gate * H-307: build lint with patched Go toolchain * H-307: clear remaining security scan findings --------- Co-authored-by: Rogee <rogee@ipao.vip>
168 lines
5.2 KiB
Go
168 lines
5.2 KiB
Go
package google
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"testing"
|
|
|
|
"github.com/gochat/gochat/internal/channel"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func safeCallBoostGoogle(fn func()) (didPanic bool) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
didPanic = true
|
|
}
|
|
}()
|
|
fn()
|
|
return false
|
|
}
|
|
|
|
// === ValidateAccessToken ===
|
|
|
|
func TestValidateAccessToken_Boost_Success(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"oauth2/v1/userinfo": {statusCode: http.StatusOK, body: `{"id":"123"}`},
|
|
})
|
|
ok, err := p.ValidateAccessToken(context.Background(), "valid-token")
|
|
require.NoError(t, err)
|
|
assert.True(t, ok)
|
|
}
|
|
|
|
func TestValidateAccessToken_Boost_NonOK(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"oauth2/v1/userinfo": {statusCode: http.StatusUnauthorized, body: `{"error":"invalid"}`},
|
|
})
|
|
ok, err := p.ValidateAccessToken(context.Background(), "bad-token")
|
|
require.NoError(t, err)
|
|
assert.False(t, ok)
|
|
}
|
|
|
|
func TestValidateAccessToken_Boost_NotFound(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"nonexistent-path-xyz": {statusCode: http.StatusOK, body: `{}`},
|
|
})
|
|
ok, err := p.ValidateAccessToken(context.Background(), "token")
|
|
require.NoError(t, err)
|
|
assert.False(t, ok) // 404 → not OK
|
|
}
|
|
|
|
// === RegisterWebhook ===
|
|
// Note: success path panics due to SetResult(map[string]interface{}{}) type assertion bug in source.
|
|
// We wrap in safeCall to still exercise the code up to the panic point.
|
|
|
|
func TestRegisterWebhook_Boost_Success(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"spaces/-/events": {statusCode: http.StatusOK, body: `{"id":"sub-123"}`},
|
|
})
|
|
didPanic := safeCallBoostGoogle(func() {
|
|
_, err := p.RegisterWebhook(context.Background(), "token", "https://example.test/hook")
|
|
require.NoError(t, err)
|
|
})
|
|
assert.True(t, didPanic) // panics on type assertion
|
|
}
|
|
|
|
func TestRegisterWebhook_Boost_Created(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"spaces/-/events": {statusCode: http.StatusCreated, body: `{"id":"sub-456"}`},
|
|
})
|
|
didPanic := safeCallBoostGoogle(func() {
|
|
_, err := p.RegisterWebhook(context.Background(), "token", "https://example.test/hook")
|
|
require.NoError(t, err)
|
|
})
|
|
assert.True(t, didPanic)
|
|
}
|
|
|
|
func TestRegisterWebhook_Boost_NoID(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"spaces/-/events": {statusCode: http.StatusOK, body: `{}`},
|
|
})
|
|
didPanic := safeCallBoostGoogle(func() {
|
|
_, err := p.RegisterWebhook(context.Background(), "token", "https://example.test/hook")
|
|
require.NoError(t, err)
|
|
})
|
|
assert.True(t, didPanic)
|
|
}
|
|
|
|
func TestRegisterWebhook_Boost_BadStatus(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"spaces/-/events": {statusCode: http.StatusForbidden, body: `{"error":"forbidden"}`},
|
|
})
|
|
_, err := p.RegisterWebhook(context.Background(), "token", "https://example.test/hook")
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "registration failed")
|
|
}
|
|
|
|
// === ListWebhooks ===
|
|
|
|
func TestListWebhooks_Boost_Success(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"spaces/-/events": {statusCode: http.StatusOK, body: `{"events":[{"id":"e1"},{"id":"e2"}]}`},
|
|
})
|
|
didPanic := safeCallBoostGoogle(func() {
|
|
_, err := p.ListWebhooks(context.Background(), "token")
|
|
require.NoError(t, err)
|
|
})
|
|
assert.True(t, didPanic) // panics on type assertion
|
|
}
|
|
|
|
func TestListWebhooks_Boost_NoEventsKey(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"spaces/-/events": {statusCode: http.StatusOK, body: `{}`},
|
|
})
|
|
didPanic := safeCallBoostGoogle(func() {
|
|
_, err := p.ListWebhooks(context.Background(), "token")
|
|
require.NoError(t, err)
|
|
})
|
|
assert.True(t, didPanic)
|
|
}
|
|
|
|
func TestListWebhooks_Boost_BadStatus(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"spaces/-/events": {statusCode: http.StatusUnauthorized, body: `{"error":"unauthorized"}`},
|
|
})
|
|
_, err := p.ListWebhooks(context.Background(), "token")
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "listing failed")
|
|
}
|
|
|
|
func TestListWebhooks_Boost_EventsNotArray(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"spaces/-/events": {statusCode: http.StatusOK, body: `{"events":"not-an-array"}`},
|
|
})
|
|
didPanic := safeCallBoostGoogle(func() {
|
|
_, err := p.ListWebhooks(context.Background(), "token")
|
|
require.NoError(t, err)
|
|
})
|
|
assert.True(t, didPanic)
|
|
}
|
|
|
|
// === DeleteWebhook ===
|
|
|
|
func TestDeleteWebhook_Boost_BadStatus(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"spaces/-/events/wh-123": {statusCode: http.StatusNotFound, body: `{}`},
|
|
})
|
|
err := p.DeleteWebhook(context.Background(), "token", "wh-123")
|
|
require.Error(t, err)
|
|
}
|
|
|
|
// === RefreshToken ===
|
|
|
|
func TestRefreshToken_Boost_NoRefreshToken(t *testing.T) {
|
|
p := newTestProvider(nil)
|
|
_, err := p.RefreshToken(context.Background(), nil, channel.ChannelConfig{})
|
|
require.Error(t, err)
|
|
assert.Contains(t, err.Error(), "no refresh_token")
|
|
}
|
|
|
|
func TestRefreshToken_Boost_BadStatus(t *testing.T) {
|
|
p := newTestProvider(map[string]responseSpec{
|
|
"oauth2/v4/token": {statusCode: http.StatusBadRequest, body: `{"error":"invalid_grant"}`},
|
|
})
|
|
_, err := p.RefreshToken(context.Background(), nil, channel.ChannelConfig{"refresh_token": "rt"})
|
|
require.Error(t, err)
|
|
}
|