Skip to content

Commit

Permalink
Merge pull request #166 from SpineEventEngine/v1.7.2
Browse files Browse the repository at this point in the history
Allow using Firebase RDB emulator with Firebase client
  • Loading branch information
yuri-sergiichuk authored Feb 1, 2021
2 parents 28748bf + cb2be82 commit e270f6b
Show file tree
Hide file tree
Showing 13 changed files with 275 additions and 138 deletions.
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/io/spine/gradle/internal/deps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ object Versions {
val javaPoet = "1.13.0"
val autoService = "1.0-rc7"
val autoCommon = "0.10"
val jackson = "2.9.10.5"
val jackson = "2.9.10.8"
val animalSniffer = "1.19"
val apiguardian = "1.1.0"
val javaxAnnotation = "1.3.2"
Expand Down
2 changes: 1 addition & 1 deletion client-js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "spine-web",
"version": "1.7.1",
"version": "1.7.2",
"license": "Apache-2.0",
"description": "A JS client for interacting with Spine applications.",
"homepage": "https://spine.io",
Expand Down
2 changes: 1 addition & 1 deletion config
26 changes: 19 additions & 7 deletions firebase-web/src/main/java/io/spine/web/firebase/DatabaseUrls.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,41 @@

import io.spine.net.Urls;

import static com.google.common.base.Preconditions.checkNotNull;
import static io.spine.util.Preconditions2.checkNotEmptyOrBlank;

/**
* Utilities and static factories dealing with {@link DatabaseUrl}.
*/
public final class DatabaseUrls {

/** Prevents instantiation of this utility class. */
/**
* Prevents instantiation of this utility class.
*/
private DatabaseUrls() {
}

/**
* Creates a {@code DatabaseUrls} instance from the given string.
* Creates a {@code DatabaseUrl} instance from the given string.
*
* @param url
* @param dbUrl
* a {@code String} containing database URL
* @return a new instance of {@code DatabaseUrls}
* @return a new instance of {@code DatabaseUrl}
* @see com.google.firebase.database.util.EmulatorHelper
*/
public static DatabaseUrl from(String url) {
checkNotNull(url);
public static DatabaseUrl from(String dbUrl) {
checkNotEmptyOrBlank(dbUrl);
String namespace = "";
String url = dbUrl;
String namespaceQuery = "?ns=";
int queryIndex = dbUrl.indexOf(namespaceQuery);
if (queryIndex > 0) {
namespace = dbUrl.substring(queryIndex + namespaceQuery.length());
url = dbUrl.substring(0, queryIndex);
}
return DatabaseUrl
.newBuilder()
.setUrl(Urls.create(url))
.setNamespace(namespace)
.vBuild();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import io.spine.web.firebase.DatabaseUrl;
import io.spine.web.firebase.NodePath;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;

/**
Expand All @@ -40,25 +42,46 @@
*/
final class RestNodeUrls {

private final String template;
private final DatabaseUrl database;

RestNodeUrls(DatabaseUrl url) {
this.template = Urls.toString(url.getUrl()) + "/%s.json";
/**
* Creates a new factory for the specified {@code database}.
*/
RestNodeUrls(DatabaseUrl database) {
this.database = checkNotNull(database);
}

/**
* Creates a new {@link RestNodeUrl} for a node at the specified {@link NodePath path}.
*/
RestNodeUrl with(NodePath path) {
Url url = Urls.create(format(template, path.getValue()));
checkNotNull(path);
Url url = withinDatabase(path);
RestNodeUrl node = RestNodeUrl
.newBuilder()
.setUrl(url)
.vBuild();
return node;
}

private Url withinDatabase(NodePath path) {
Url dbUrl = database.getUrl();
String result;
if (isNullOrEmpty(database.getNamespace())) {
result = format("%s/%s.json", dbUrl.getSpec(), path.getValue());
} else {
result = format(
"%s/%s.json?ns=%s", dbUrl.getSpec(), path.getValue(), database.getNamespace()
);
}
return Urls.create(result);
}

/**
* Converts supplied {@code node} into a {@code GenericUrl}.
*/
static GenericUrl asGenericUrl(RestNodeUrl node) {
checkNotNull(node);
GenericUrl url = new GenericUrl(Urls.toString(node.getUrl()));
return url;
}
Expand Down
12 changes: 12 additions & 0 deletions firebase-web/src/main/proto/spine/web/firebase/client.proto
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,20 @@ import "spine/net/url.proto";

// A Firebase database URL.
//
// The Firebase endpoint URL may be of two formats.
// The first one is a URL to connect to a remote database which must be specified as
// `https://<project-id>.firebaseio.com` or `https://<database-alias>.firebaseio.com`.
// The second one is a URL to connect to an emulator database that has the following format:
// `http://<local-ip>:<local-port>?ns=<database-alias>`. The `ns` stands for a `namespace`
// and by default is set to the project ID.
//
message DatabaseUrl {

// The Firebase RDB endpoint.
spine.net.Url url = 1 [(required) = true];

// The namespace to connect to.
string namespace = 2;
}

// A path in a Firebase Realtime Database.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,35 @@
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;

@DisplayName("`DatabaseUrls` should")
class DatabaseUrlsTest extends UtilityClassTest<DatabaseUrls> {

private static final String VALID_URL = "https://spine-dev.appspot.com/";

DatabaseUrlsTest() {
super(DatabaseUrls.class);
}

@Test
@DisplayName("be successfully created from valid URL")
void acceptValidUrl() {
DatabaseUrl url = DatabaseUrls.from(VALID_URL);
@DisplayName("be created from a remote RDB URL")
void acceptRemoteRdb() {
String dbUrl = "https://spine-dev.firebaseio.com";
DatabaseUrl url = DatabaseUrls.from(dbUrl);
assertThat(url.getUrl())
.isEqualTo(Urls.create(dbUrl));
assertThat(url.getNamespace())
.isEmpty();
}

@Test
@DisplayName("be created from a local emulator URL")
void acceptLocalEmulator() {
String dbUrl = "http://localhost:5000?ns=spine-dev";
DatabaseUrl url = DatabaseUrls.from(dbUrl);
assertThat(url.getUrl())
.isEqualTo(Urls.create(VALID_URL));
.isEqualTo(Urls.create("http://localhost:5000"));
assertThat(url.getNamespace())
.isEqualTo("spine-dev");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright 2021, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and/or binary forms, with or without
* modification, must retain the above copyright notice and the following
* disclaimer.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package io.spine.web.firebase.rest;

import com.google.common.testing.NullPointerTester;
import com.google.common.testing.NullPointerTester.Visibility;
import io.spine.net.Urls;
import io.spine.web.firebase.DatabaseUrl;
import io.spine.web.firebase.DatabaseUrls;
import io.spine.web.firebase.NodePaths;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;

@DisplayName("`RestNodeUrls` should")
final class RestNodeUrlsTest {

@Test
@DisplayName("not accept `null`s")
void notAcceptNulls() {
NullPointerTester tester = new NullPointerTester();
tester.testConstructors(RestNodeUrls.class, Visibility.PACKAGE);
tester.testAllPublicInstanceMethods(new RestNodeUrls(DatabaseUrl.getDefaultInstance()));
}

@Test
@DisplayName("create a `RestNodeUrl` for the specified `NodePath` and remote RDB")
void createRemoteDbUrl() {
String dbUrl = "https://spine-dev.firebaseio.com";
RestNodeUrls factory = new RestNodeUrls(DatabaseUrls.from(dbUrl));
String node = "subscriptions/111";
RestNodeUrl result = factory.with(NodePaths.of(node));
assertThat(result.getUrl())
.isEqualTo(Urls.create(dbUrl + '/' + node + ".json"));
}

@Test
@DisplayName("create a `RestNodeUrl` for the specified `NodePath` and local emulator")
void createEmulatorUrl() {
String dbUrl = "http://localhost:5000?ns=spine-dev";
RestNodeUrls factory = new RestNodeUrls(DatabaseUrls.from(dbUrl));
String node = "query/currentYear";
RestNodeUrl result = factory.with(NodePaths.of(node));
assertThat(result.getUrl())
.isEqualTo(Urls.create("http://localhost:5000/" + node + ".json?ns=spine-dev"));
}
}
2 changes: 1 addition & 1 deletion integration-tests/js-tests/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "client-js-tests",
"version": "1.7.1",
"version": "1.7.2",
"license": "Apache-2.0",
"description": "Tests of a `spine-web` JS library against the Spine-based application.",
"scripts": {
Expand Down
Loading

0 comments on commit e270f6b

Please sign in to comment.