Firestore¶
package firestore
import (
"context"
"fmt"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)
// firestoreContainer represents the firestore container type used in the module
type firestoreContainer struct {
testcontainers.Container
URI string
}
// startContainer creates an instance of the firestore container type
func startContainer(ctx context.Context) (*firestoreContainer, error) {
req := testcontainers.ContainerRequest{
Image: "gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators",
ExposedPorts: []string{"8080/tcp"},
WaitingFor: wait.ForLog("running"),
Cmd: []string{
"/bin/sh",
"-c",
"gcloud beta emulators firestore start --host-port 0.0.0.0:8080",
},
}
container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
})
if err != nil {
return nil, err
}
mappedPort, err := container.MappedPort(ctx, "8080")
if err != nil {
return nil, err
}
hostIP, err := container.Host(ctx)
if err != nil {
return nil, err
}
uri := fmt.Sprintf("%s:%s", hostIP, mappedPort.Port())
return &firestoreContainer{Container: container, URI: uri}, nil
}
package firestore
import (
"context"
"testing"
"cloud.google.com/go/firestore"
"google.golang.org/api/option"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
type Person struct {
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
}
type emulatorCreds struct{}
func (ec emulatorCreds) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
return map[string]string{"authorization": "Bearer owner"}, nil
}
func (ec emulatorCreds) RequireTransportSecurity() bool {
return false
}
func TestFirestore(t *testing.T) {
ctx := context.Background()
container, err := startContainer(ctx)
if err != nil {
t.Fatal(err)
}
// Clean up the container after the test is complete
t.Cleanup(func() {
if err := container.Terminate(ctx); err != nil {
t.Fatalf("failed to terminate container: %s", err)
}
})
conn, err := grpc.Dial(container.URI, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithPerRPCCredentials(emulatorCreds{}))
if err != nil {
t.Fatal(err)
}
options := []option.ClientOption{option.WithGRPCConn(conn)}
client, err := firestore.NewClient(ctx, "test-project", options...)
if err != nil {
t.Fatal(err)
}
defer client.Close()
users := client.Collection("users")
docRef := users.Doc("alovelace")
data := Person{
Firstname: "Ada",
Lastname: "Lovelace",
}
_, err = docRef.Create(ctx, data)
if err != nil {
t.Fatal(err)
}
// perform assertions
docsnap, err := docRef.Get(ctx)
if err != nil {
t.Fatal(err)
}
var saved Person
if err := docsnap.DataTo(&saved); err != nil {
t.Fatal(err)
}
if saved != data {
t.Fatalf("Expected value %s. Got %s.", data, saved)
}
}