Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 9 additions & 0 deletions firebase.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ func (a *App) Firestore(ctx context.Context) (*firestore.Client, error) {
return firestore.NewClient(ctx, a.projectID, a.opts...)
}

// FirestoreWithDatabase returns a new firestore.Client instance with the specified named database from the
// https://godoc.org/cloud.google.com/go/firestore package.
func (a *App) FirestoreWithDatabase(ctx context.Context, databaseID string) (*firestore.Client, error) {
if a.projectID == "" {
return nil, errors.New("project id is required to access Firestore")
}
return firestore.NewClientWithDatabase(ctx, a.projectID, databaseID, a.opts...)
}

// InstanceID returns an instance of iid.Client.
func (a *App) InstanceID(ctx context.Context) (*iid.Client, error) {
conf := &internal.InstanceIDConfig{
Expand Down
16 changes: 16 additions & 0 deletions firebase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,18 @@ func TestFirestore(t *testing.T) {
}
}

func TestFirestoreWithDatabase(t *testing.T) {
ctx := context.Background()
app, err := NewApp(ctx, nil, option.WithCredentialsFile("testdata/service_account.json"))
if err != nil {
t.Fatal(err)
}

if c, err := app.FirestoreWithDatabase(ctx, "other-db"); c == nil || err != nil {
t.Errorf("FirestoreWithDatabase() = (%v, %v); want (client, nil)", c, err)
}
}

func TestFirestoreWithProjectID(t *testing.T) {
verify := func(varName string) {
current := os.Getenv(varName)
Expand Down Expand Up @@ -336,6 +348,10 @@ func TestFirestoreWithNoProjectID(t *testing.T) {
if c, err := app.Firestore(ctx); c != nil || err == nil {
t.Errorf("Firestore() = (%v, %v); want (nil, error)", c, err)
}

if c, err := app.FirestoreWithDatabase(ctx, "other-db"); c != nil || err == nil {
t.Errorf("FirestoreWithDatabase() = (%v, %v); want (nil, error)", c, err)
}
}

func TestInstanceID(t *testing.T) {
Expand Down
153 changes: 147 additions & 6 deletions integration/firestore/firestore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,27 @@ import (
"reflect"
"testing"

"time"

"cloud.google.com/go/firestore"
"firebase.google.com/go/v4/integration/internal"
)

var (
cityData = map[string]interface{}{
"name": "Mountain View",
"country": "USA",
"population": int64(77846),
"capital": false,
}
movieData = map[string]interface{}{
"Name": "Interstellar",
"Year": int64(2014),
"Runtime": "2h 49m",
"Academy Award Winner": true,
}
)

func TestFirestore(t *testing.T) {
if testing.Short() {
log.Println("skipping Firestore integration tests in short mode.")
Expand All @@ -40,11 +58,130 @@ func TestFirestore(t *testing.T) {
}

doc := client.Collection("cities").Doc("Mountain View")
if _, err := doc.Set(ctx, cityData); err != nil {
t.Fatal(err)
}
snap, err := doc.Get(ctx)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(snap.Data(), cityData) {
t.Errorf("Get() = %v; want %v", snap.Data(), cityData)
}
if _, err := doc.Delete(ctx); err != nil {
t.Fatal(err)
}
}

func TestFirestoreWithDatabase(t *testing.T) {
if testing.Short() {
log.Println("skipping Firestore integration tests in short mode.")
return
}
ctx := context.Background()
app, err := internal.NewTestApp(ctx, nil)
if err != nil {
t.Fatal(err)
}

// This test requires a non-default database to exist in the project.
// If it doesn't exist, this test will fail.
client, err := app.FirestoreWithDatabase(ctx, "testing-database")
if err != nil {
t.Fatal(err)
}

doc := client.Collection("cities").NewDoc()
if _, err := doc.Set(ctx, cityData); err != nil {
t.Fatal(err)
}
snap, err := doc.Get(ctx)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(snap.Data(), cityData) {
t.Errorf("Get() = %v; want %v", snap.Data(), cityData)
}
if _, err := doc.Delete(ctx); err != nil {
t.Fatal(err)
}
}

func TestFirestoreMultiDB(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels repetitive. Doesn't TestFirestoreWithDatabaseID and TestFirestore cover this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test in for verifying that two databases clients can be opened and modified at once with no impact on the other.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. We can keep this, but as a clarification, to me this feels like we are trying to test the cloud firestore SDK here. This should be a more fitting test for the Firestore SDK and slightly beyond the Admin SDK scope. The Admin SDK should test the part where we are setting the database ID in the Firestore SDK and everything beyond that should be tested in the Firestore SDK itself (which I think they do).

if testing.Short() {
log.Println("skipping Firestore integration tests in short mode.")
return
}
ctx := context.Background()
app, err := internal.NewTestApp(ctx, nil)
if err != nil {
t.Fatal(err)
}

cityClient, err := app.Firestore(ctx)
if err != nil {
t.Fatal(err)
}
// This test requires a non-default database to exist in the project.
movieClient, err := app.FirestoreWithDatabase(ctx, "testing-database")
if err != nil {
t.Fatal(err)
}

cityDoc := cityClient.Collection("cities").NewDoc()
movieDoc := movieClient.Collection("movies").NewDoc()

if _, err := cityDoc.Set(ctx, cityData); err != nil {
t.Fatal(err)
}
if _, err := movieDoc.Set(ctx, movieData); err != nil {
t.Fatal(err)
}

citySnap, err := cityDoc.Get(ctx)
if err != nil {
t.Fatal(err)
}
movieSnap, err := movieDoc.Get(ctx)
if err != nil {
t.Fatal(err)
}

if !reflect.DeepEqual(citySnap.Data(), cityData) {
t.Errorf("City Get() = %v; want %v", citySnap.Data(), cityData)
}
if !reflect.DeepEqual(movieSnap.Data(), movieData) {
t.Errorf("Movie Get() = %v; want %v", movieSnap.Data(), movieData)
}

if _, err := cityDoc.Delete(ctx); err != nil {
t.Fatal(err)
}
if _, err := movieDoc.Delete(ctx); err != nil {
t.Fatal(err)
}
}

func TestServerTimestamp(t *testing.T) {
if testing.Short() {
log.Println("skipping Firestore integration tests in short mode.")
return
}
ctx := context.Background()
app, err := internal.NewTestApp(ctx, nil)
if err != nil {
t.Fatal(err)
}

client, err := app.Firestore(ctx)
if err != nil {
t.Fatal(err)
}

doc := client.Collection("cities").NewDoc()
data := map[string]interface{}{
"name": "Mountain View",
"country": "USA",
"population": int64(77846),
"capital": false,
"name": "Mountain View",
"timestamp": firestore.ServerTimestamp,
}
if _, err := doc.Set(ctx, data); err != nil {
t.Fatal(err)
Expand All @@ -53,8 +190,12 @@ func TestFirestore(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(snap.Data(), data) {
t.Errorf("Get() = %v; want %v", snap.Data(), data)
got := snap.Data()
if got["name"] != "Mountain View" {
t.Errorf("Name = %v; want Mountain View", got["name"])
}
if _, ok := got["timestamp"].(time.Time); !ok {
t.Errorf("Timestamp is not a time.Time: %v", got["timestamp"])
}
if _, err := doc.Delete(ctx); err != nil {
t.Fatal(err)
Expand Down
Loading