Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions .github/workflows/deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@ jobs:
with:
persist-credentials: false

- name: Install, Build, Test 🔧 # This runs a series of commands as if building a live version of the project
run: |
go mod tidy
go test github.com/julwrites/ScriptureBot/pkg/utils \
github.com/julwrites/ScriptureBot/pkg/app \
github.com/julwrites/ScriptureBot/pkg/bot

- name: gcloud Auth
uses: google-github-actions/auth@v2
with:
Expand All @@ -35,6 +28,15 @@ jobs:
run: |
gcloud info

- name: Install, Build, Test 🔧 # This runs a series of commands as if building a live version of the project
env:
GCLOUD_PROJECT_ID: ${{secrets.GCLOUD_PROJECT_ID}}
run: |
go mod tidy
go test github.com/julwrites/ScriptureBot/pkg/utils \
github.com/julwrites/ScriptureBot/pkg/app \
github.com/julwrites/ScriptureBot/pkg/bot

- name: Configure gcloud auth with Docker
run: |
gcloud auth configure-docker ${{ secrets.GCLOUD_REGION }}-docker.pkg.dev
Expand Down
24 changes: 12 additions & 12 deletions pkg/app/api_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@ import (
)

func TestSubmitQuery(t *testing.T) {
handler := newMockApiHandler()
ts := httptest.NewServer(handler)
defer ts.Close()

t.Run("Success", func(t *testing.T) {
defer setEnv("BIBLE_API_URL", ts.URL)()
ResetAPIConfigCache()

req := QueryRequest{Query: QueryObject{Prompt: "hello"}}
Expand All @@ -21,18 +16,20 @@ func TestSubmitQuery(t *testing.T) {
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if resp.Text != "Answer text" {
t.Errorf("Expected 'Answer text', got '%s'", resp.Text)
// In integration test mode, we expect some content but can't assert exact text
// because the live API response might vary.
if len(resp.Text) == 0 && len(resp.References) == 0 {
t.Errorf("Expected some content (text or references), got empty response")
}
})

t.Run("API Error", func(t *testing.T) {
handler := newMockApiHandler()
ts := httptest.NewServer(handler)
defer ts.Close()

handler.statusCode = http.StatusInternalServerError
handler.rawResponse = `{"error": {"code": 500, "message": "simulated error"}}`
defer func() { // Reset handler
handler.statusCode = http.StatusOK
handler.rawResponse = ""
}()

defer setEnv("BIBLE_API_URL", ts.URL)()
ResetAPIConfigCache()
Expand All @@ -49,8 +46,11 @@ func TestSubmitQuery(t *testing.T) {
})

t.Run("Bad JSON", func(t *testing.T) {
handler := newMockApiHandler()
ts := httptest.NewServer(handler)
defer ts.Close()

handler.rawResponse = `{invalid json`
defer func() { handler.rawResponse = "" }()

defer setEnv("BIBLE_API_URL", ts.URL)()
ResetAPIConfigCache()
Expand Down
17 changes: 6 additions & 11 deletions pkg/app/ask_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,7 @@ import (
)

func TestGetBibleAsk(t *testing.T) {
handler := newMockApiHandler()
ts := httptest.NewServer(handler)
defer ts.Close()

t.Run("Success", func(t *testing.T) {
defer setEnv("BIBLE_API_URL", ts.URL)()
ResetAPIConfigCache()

var env def.SessionData
Expand All @@ -26,17 +21,17 @@ func TestGetBibleAsk(t *testing.T) {

env = GetBibleAsk(env)

if !strings.Contains(env.Res.Message, "Answer text") {
t.Errorf("Expected answer text, got: %s", env.Res.Message)
}
if !strings.Contains(env.Res.Message, "Ref 1:1") {
t.Errorf("Expected reference, got: %s", env.Res.Message)
if len(env.Res.Message) == 0 {
t.Errorf("Expected answer text, got empty")
}
})

t.Run("Error", func(t *testing.T) {
handler := newMockApiHandler()
ts := httptest.NewServer(handler)
defer ts.Close()

handler.statusCode = http.StatusInternalServerError
defer func() { handler.statusCode = http.StatusOK }()

defer setEnv("BIBLE_API_URL", ts.URL)()
ResetAPIConfigCache()
Expand Down
50 changes: 50 additions & 0 deletions pkg/app/database_integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package app

import (
"testing"

"github.com/julwrites/BotPlatform/pkg/def"
"github.com/julwrites/ScriptureBot/pkg/secrets"
"github.com/julwrites/ScriptureBot/pkg/utils"
)

func TestUserDatabaseIntegration(t *testing.T) {
// This test performs a live database operation against the configured project.
// It relies on GCLOUD_PROJECT_ID being set.

secretsData, err := secrets.LoadSecrets()
if err != nil {
t.Logf("Warning: Could not load secrets: %v", err)
}

projectID := secretsData.PROJECT_ID
if projectID == "" {
t.Skip("Skipping database test: GCLOUD_PROJECT_ID not set")
}

// Use a unique ID to avoid conflict with real users
dummyID := "test-integration-user-DO-NOT-DELETE"

var user def.UserData
user.Id = dummyID
user.Firstname = "Integration"
user.Lastname = "Test"
user.Username = "TestUser"
user.Type = "Private"

// Create/Update user
// This exercises the connection to Datastore/Firestore
updatedUser := utils.RegisterUser(user, projectID)

if updatedUser.Id != dummyID {
t.Errorf("Expected user ID %s, got %s", dummyID, updatedUser.Id)
}

// Verify update capability
updatedUser.Action = "testing"
finalUser := utils.RegisterUser(updatedUser, projectID)

if finalUser.Action != "testing" {
t.Errorf("Expected user Action 'testing', got '%s'", finalUser.Action)
}
}
22 changes: 9 additions & 13 deletions pkg/app/passage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,7 @@ func TestGetPassage(t *testing.T) {
}

func TestGetBiblePassage(t *testing.T) {
handler := newMockApiHandler()
ts := httptest.NewServer(handler)
defer ts.Close()

t.Run("Success", func(t *testing.T) {
defer setEnv("BIBLE_API_URL", ts.URL)()
defer setEnv("BIBLE_API_KEY", "test_key")()
ResetAPIConfigCache()

var env def.SessionData
Expand All @@ -61,14 +55,17 @@ func TestGetBiblePassage(t *testing.T) {
env.User.Config = utils.SerializeUserConfig(conf)
env = GetBiblePassage(env)

if env.Res.Message != `In the beginning God created the heavens and the earth\.` {
if len(env.Res.Message) < 10 {
t.Errorf("Expected passage text, got '%s'", env.Res.Message)
}
})

t.Run("Error", func(t *testing.T) {
handler := newMockApiHandler()
ts := httptest.NewServer(handler)
defer ts.Close()

handler.statusCode = http.StatusInternalServerError
defer func() { handler.statusCode = http.StatusOK }()

defer setEnv("BIBLE_API_URL", ts.URL)()
defer setEnv("BIBLE_API_KEY", "test_key")()
Expand Down Expand Up @@ -100,12 +97,11 @@ func TestGetBiblePassage(t *testing.T) {
})

t.Run("Empty", func(t *testing.T) {
handler := newMockApiHandler()
ts := httptest.NewServer(handler)
defer ts.Close()

handler.verseResponse = VerseResponse{}
defer func() {
handler.verseResponse = VerseResponse{
Verse: "<p>In the beginning God created the heavens and the earth.</p>",
}
}()

defer setEnv("BIBLE_API_URL", ts.URL)()
defer setEnv("BIBLE_API_KEY", "test_key")()
Expand Down
19 changes: 10 additions & 9 deletions pkg/secrets/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,19 @@ func LoadSecrets() (SecretsData, error) {
}

// Get retrieves a secret.
// If GCLOUD_PROJECT_ID is set, it exclusively fetches from Google Secret Manager.
// Otherwise, it falls back to environment variables for local development.
// It prioritizes environment variables. If not found, and GCLOUD_PROJECT_ID is set,
// it fetches from Google Secret Manager.
func Get(secretName string) (string, error) {
// Check environment variables first.
// This allows overriding secrets for local development or testing.
if value, ok := os.LookupEnv(secretName); ok {
log.Printf("Loaded '%s' from environment", secretName)
return value, nil
}

projectID, isCloudRun := os.LookupEnv("GCLOUD_PROJECT_ID")
if isCloudRun && projectID != "" {
// Cloud environment: Use Secret Manager exclusively.
// Cloud environment: Use Secret Manager if not found in environment.
secretValue, err := getFromSecretManager(projectID, secretName)
if err != nil {
return "", fmt.Errorf("failed to get secret '%s' from Secret Manager: %v", secretName, err)
Expand All @@ -94,12 +101,6 @@ func Get(secretName string) (string, error) {
return secretValue, nil
}

// Local environment: Use environment variables.
if value, ok := os.LookupEnv(secretName); ok {
log.Printf("Loaded '%s' from environment", secretName)
return value, nil
}

return "", fmt.Errorf("secret '%s' not found in environment variables", secretName)
}

Expand Down
Loading