diff --git a/client-js/package.json b/client-js/package.json
index f3ec78f38..ce0d0b5a3 100644
--- a/client-js/package.json
+++ b/client-js/package.json
@@ -1,6 +1,6 @@
{
"name": "spine-web",
- "version": "1.9.0-SNAPSHOT.11",
+ "version": "1.9.0-SNAPSHOT.12",
"license": "Apache-2.0",
"description": "A JS client for interacting with Spine applications.",
"homepage": "https://spine.io",
diff --git a/firebase-web/src/main/java/io/spine/web/firebase/NodeValue.java b/firebase-web/src/main/java/io/spine/web/firebase/NodeValue.java
index fb5944819..81318d078 100644
--- a/firebase-web/src/main/java/io/spine/web/firebase/NodeValue.java
+++ b/firebase-web/src/main/java/io/spine/web/firebase/NodeValue.java
@@ -123,7 +123,7 @@ public void addChild(String key, StoredJson data) {
}
/**
- * Adds a `null` child to the value under a specified key.
+ * Adds a {@code null} child to the value under a specified key.
*/
public void addNullChild(String key) {
value.add(key, null);
diff --git a/integration-tests/js-tests/package.json b/integration-tests/js-tests/package.json
index 6d1f33db3..baf634969 100644
--- a/integration-tests/js-tests/package.json
+++ b/integration-tests/js-tests/package.json
@@ -1,6 +1,6 @@
{
"name": "client-js-tests",
- "version": "1.9.0-SNAPSHOT.11",
+ "version": "1.9.0-SNAPSHOT.12",
"license": "Apache-2.0",
"description": "Tests of a `spine-web` JS library against the Spine-based application.",
"scripts": {
diff --git a/integration-tests/js-tests/test/firebase-client/subscribe-entity-lifecycle-test.js b/integration-tests/js-tests/test/firebase-client/subscribe-entity-lifecycle-test.js
new file mode 100644
index 000000000..e4c1fb2f0
--- /dev/null
+++ b/integration-tests/js-tests/test/firebase-client/subscribe-entity-lifecycle-test.js
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2023, 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.
+ */
+
+import assert from 'assert';
+import {fail} from '../test-helpers';
+import TestEnvironment from '../given/test-environment';
+import {Task} from '@testProto/spine/web/test/given/task_pb';
+import {client} from './given/firebase-client';
+
+describe('Subscription made with FirebaseClient should', function () {
+
+ // Big timeout allows to receive model state changes during tests.
+ this.timeout(120 * 1000);
+
+ it('reflects updates of a task that gets created -> renamed -> deleted', (done) => {
+ const INITIAL_TASK_NAME = 'Initial task name';
+ const UPDATED_NAME = 'Updated task name';
+
+ const createCommand = TestEnvironment.createTaskCommand({
+ withPrefix: 'spine-web-test-entity-lifecycle-subscription',
+ named: INITIAL_TASK_NAME
+ });
+ const sendCreateTask = () => client.command(createCommand)
+ .onError(fail(done, 'Unexpected error while creating a task.'))
+ .onImmediateRejection(fail(done, 'Unexpected rejection while creating a task.'))
+ .post();
+
+ const taskId = createCommand.getId();
+ const taskIdValue = taskId.getValue();
+
+ const renameCommand = TestEnvironment.renameTaskCommand({
+ withId: taskIdValue,
+ to: UPDATED_NAME
+ });
+ const sendRenameTask = () => client.command(renameCommand)
+ .onError(fail(done, 'Unexpected error while renaming a task.'))
+ .onImmediateRejection(fail(done, 'Unexpected rejection while renaming a task.'))
+ .post();
+
+ const deleteCommand = TestEnvironment.deleteTaskCommand(taskId);
+ const sendDeleteTask = () => client.command(deleteCommand)
+ .onError(fail(done, 'Unexpected error while deleting a task.'))
+ .onImmediateRejection(fail(done, 'Unexpected rejection while deleting a task.'))
+ .post();
+
+ let reportTaskCreated, reportTaskRenamed, reportTaskDeleted;
+ const taskCreated = new Promise(resolve => reportTaskCreated = resolve);
+ const taskRenamed = new Promise(resolve => reportTaskRenamed = resolve);
+ const taskDeleted = new Promise(resolve => reportTaskDeleted = resolve);
+
+ client.subscribeTo(Task)
+ .byId(taskId)
+ .post()
+ .then(async ({itemAdded, itemChanged, itemRemoved, unsubscribe}) => {
+ itemAdded.subscribe(nextItem => {
+ const actualIdValue = nextItem.getId().getValue();
+ const actualTaskName = nextItem.getName();
+ assert.strictEqual(actualIdValue, taskIdValue,
+ `New task has ID "${actualIdValue}", expected "${taskIdValue}".`
+ );
+ assert.strictEqual(actualTaskName, INITIAL_TASK_NAME,
+ `Task is named "${actualTaskName}", expected "${INITIAL_TASK_NAME}".`
+ );
+
+ reportTaskCreated();
+ });
+
+ itemChanged.subscribe(nextItem => {
+ const actualIdValue = nextItem.getId().getValue();
+ const actualTaskName = nextItem.getName();
+ assert.strictEqual(actualIdValue, taskIdValue,
+ `Updated task has ID "${actualIdValue}", expected "${taskIdValue}".`
+ );
+ assert.strictEqual(actualTaskName, UPDATED_NAME,
+ `Renamed task is named "${actualTaskName}", expected "${UPDATED_NAME}".`
+ );
+
+ reportTaskRenamed();
+ });
+
+ itemRemoved.subscribe(nextItem => {
+ const actualIdValue = nextItem.getId().getValue();
+ assert.strictEqual(actualIdValue, taskIdValue,
+ `Deleted task has ID "${actualIdValue}", expected "${taskIdValue}".`
+ );
+
+ reportTaskDeleted();
+ });
+
+ sendCreateTask();
+ await taskCreated;
+
+ sendRenameTask();
+ await taskRenamed;
+
+ sendDeleteTask();
+ await taskDeleted;
+ })
+ .then(done)
+ .catch(fail(done));
+ });
+});
diff --git a/integration-tests/js-tests/test/given/test-environment.js b/integration-tests/js-tests/test/given/test-environment.js
index 4f0047c51..b6871cd42 100644
--- a/integration-tests/js-tests/test/given/test-environment.js
+++ b/integration-tests/js-tests/test/given/test-environment.js
@@ -26,7 +26,7 @@
import {v4 as newUuid} from 'uuid';
import {TenantIds} from '@lib/client/tenant';
-import {CreateTask, RenameTask} from '@testProto/spine/web/test/given/commands_pb';
+import {CreateTask, RenameTask, DeleteTask} from '@testProto/spine/web/test/given/commands_pb';
import {TaskId} from '@testProto/spine/web/test/given/task_pb';
import {AddUserInfo} from '@testProto/spine/web/test/given/user_commands_pb';
import {UserId} from '@testProto/spine/core/user_id_pb';
@@ -106,7 +106,16 @@ export default class TestEnvironment {
command.setName(newName);
return command;
+ }
+ /**
+ * @param {TaskId} taskId
+ * @returns {DeleteTask}
+ */
+ static deleteTaskCommand(taskId) {
+ const command = new DeleteTask();
+ command.setId(taskId);
+ return command;
}
/**
diff --git a/integration-tests/test-app/src/main/java/io/spine/web/test/given/TaskAggregate.java b/integration-tests/test-app/src/main/java/io/spine/web/test/given/TaskAggregate.java
index 677e73e67..aac226b0a 100644
--- a/integration-tests/test-app/src/main/java/io/spine/web/test/given/TaskAggregate.java
+++ b/integration-tests/test-app/src/main/java/io/spine/web/test/given/TaskAggregate.java
@@ -75,6 +75,18 @@ TaskReassigned handle(ReassignTask command) {
return taskReassigned.vBuild();
}
+ @Assign
+ TaskDeleted handle(DeleteTask command) {
+ TaskDeleted.Builder taskDeleted = TaskDeleted.newBuilder()
+ .setId(command.getId())
+ .setWhen(currentTime());
+ if (state().hasAssignee()) {
+ taskDeleted.setAssignee(state().getAssignee());
+ }
+
+ return taskDeleted.vBuild();
+ }
+
@Apply
private void on(TaskCreated event) {
builder().setId(event.getId())
@@ -96,4 +108,9 @@ private void on(TaskRenamed event) {
private void on(TaskReassigned event) {
builder().setAssignee(event.getTo());
}
+
+ @Apply
+ private void on(TaskDeleted event) {
+ setDeleted(true);
+ }
}
diff --git a/integration-tests/test-app/src/main/proto/spine/web/test/given/commands.proto b/integration-tests/test-app/src/main/proto/spine/web/test/given/commands.proto
index 8b6e4cabf..9b9623997 100644
--- a/integration-tests/test-app/src/main/proto/spine/web/test/given/commands.proto
+++ b/integration-tests/test-app/src/main/proto/spine/web/test/given/commands.proto
@@ -71,6 +71,11 @@ message ReassignTask {
spine.core.UserId new_assignee = 2 [(required) = true];
}
+message DeleteTask {
+
+ TaskId id = 1;
+}
+
message CreateProject {
ProjectId id = 1;
diff --git a/integration-tests/test-app/src/main/proto/spine/web/test/given/events.proto b/integration-tests/test-app/src/main/proto/spine/web/test/given/events.proto
index d1970c593..dcca7aa1c 100644
--- a/integration-tests/test-app/src/main/proto/spine/web/test/given/events.proto
+++ b/integration-tests/test-app/src/main/proto/spine/web/test/given/events.proto
@@ -73,6 +73,14 @@ message TaskReassigned {
google.protobuf.Timestamp when = 4 [(required) = true];
}
+message TaskDeleted {
+
+ TaskId id = 1;
+
+ spine.core.UserId assignee = 2;
+
+ google.protobuf.Timestamp when = 3 [(required) = true];
+}
message ProjectCreated {
diff --git a/license-report.md b/license-report.md
index 8ce9adc3a..0fc70098f 100644
--- a/license-report.md
+++ b/license-report.md
@@ -1,6 +1,6 @@
-# Dependencies of `io.spine:spine-client-js:1.9.0-SNAPSHOT.11`
+# Dependencies of `io.spine:spine-client-js:1.9.0-SNAPSHOT.12`
## Runtime
1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2
@@ -370,10 +370,10 @@
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Tue Jan 31 14:15:16 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
+This report was generated on **Mon Mar 06 15:11:39 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-#NPM dependencies of `spine-web@1.9.0-SNAPSHOT.11`
+#NPM dependencies of `spine-web@1.9.0-SNAPSHOT.12`
## `Production` dependencies:
@@ -407,7 +407,7 @@ This report was generated on **Tue Jan 31 14:15:16 WET 2023** using [Gradle-Lice
1. **rxjs@7.8.0**
* Licenses: Apache-2.0
* Repository: [https://github.com/reactivex/rxjs](https://github.com/reactivex/rxjs)
-1. **spine-web@1.9.0-SNAPSHOT.11**
+1. **spine-web@1.9.0-SNAPSHOT.12**
* Licenses: Apache-2.0
* Repository: [https://github.com/SpineEventEngine/web](https://github.com/SpineEventEngine/web)
1. **tr46@0.0.3**
@@ -1969,7 +1969,7 @@ This report was generated on **Tue Jan 31 14:15:16 WET 2023** using [Gradle-Lice
1. **spdx-satisfies@4.0.1**
* Licenses: MIT
* Repository: [https://github.com/kemitchell/spdx-satisfies.js](https://github.com/kemitchell/spdx-satisfies.js)
-1. **spine-web@1.9.0-SNAPSHOT.11**
+1. **spine-web@1.9.0-SNAPSHOT.12**
* Licenses: Apache-2.0
* Repository: [https://github.com/SpineEventEngine/web](https://github.com/SpineEventEngine/web)
1. **sprintf-js@1.0.3**
@@ -2148,12 +2148,12 @@ This report was generated on **Tue Jan 31 14:15:16 WET 2023** using [Gradle-Lice
* Repository: [https://github.com/sindresorhus/yocto-queue](https://github.com/sindresorhus/yocto-queue)
-This report was generated on **Tue Jan 31 2023 14:15:17 GMT+0000 (Western European Standard Time)** using [NPM License Checker](https://github.com/davglass/license-checker) library.
+This report was generated on **Mon Mar 06 2023 15:11:40 GMT+0000 (Western European Standard Time)** using [NPM License Checker](https://github.com/davglass/license-checker) library.
-# Dependencies of `io.spine.gcloud:spine-firebase-web:1.9.0-SNAPSHOT.11`
+# Dependencies of `io.spine.gcloud:spine-firebase-web:1.9.0-SNAPSHOT.12`
## Runtime
1. **Group:** com.fasterxml.jackson **Name:** jackson-bom **Version:** 2.14.2 **No license information found**
@@ -2996,12 +2996,12 @@ This report was generated on **Tue Jan 31 2023 14:15:17 GMT+0000 (Western Europe
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Tue Jan 31 14:15:25 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
+This report was generated on **Mon Mar 06 15:11:46 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine:spine-js-tests:1.9.0-SNAPSHOT.11`
+# Dependencies of `io.spine:spine-js-tests:1.9.0-SNAPSHOT.12`
## Runtime
1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2
@@ -3396,12 +3396,12 @@ This report was generated on **Tue Jan 31 14:15:25 WET 2023** using [Gradle-Lice
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Tue Jan 31 14:15:31 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
+This report was generated on **Mon Mar 06 15:11:53 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine:spine-test-app:1.9.0-SNAPSHOT.11`
+# Dependencies of `io.spine:spine-test-app:1.9.0-SNAPSHOT.12`
## Runtime
1. **Group:** com.fasterxml.jackson **Name:** jackson-bom **Version:** 2.14.2 **No license information found**
@@ -5031,12 +5031,12 @@ This report was generated on **Tue Jan 31 14:15:31 WET 2023** using [Gradle-Lice
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Tue Jan 31 14:15:33 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
+This report was generated on **Mon Mar 06 15:11:56 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine:spine-testutil-web:1.9.0-SNAPSHOT.11`
+# Dependencies of `io.spine:spine-testutil-web:1.9.0-SNAPSHOT.12`
## Runtime
1. **Group:** com.google.android **Name:** annotations **Version:** 4.1.1.4
@@ -5497,12 +5497,12 @@ This report was generated on **Tue Jan 31 14:15:33 WET 2023** using [Gradle-Lice
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Tue Jan 31 14:15:35 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
+This report was generated on **Mon Mar 06 15:11:59 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine:spine-web:1.9.0-SNAPSHOT.11`
+# Dependencies of `io.spine:spine-web:1.9.0-SNAPSHOT.12`
## Runtime
1. **Group:** com.google.android **Name:** annotations **Version:** 4.1.1.4
@@ -6002,4 +6002,4 @@ This report was generated on **Tue Jan 31 14:15:35 WET 2023** using [Gradle-Lice
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Tue Jan 31 14:15:39 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
\ No newline at end of file
+This report was generated on **Mon Mar 06 15:12:03 WET 2023** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 4878caaf3..09d36c08f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@ all modules and does not describe the project structure per-subproject.
io.spine
spine-web
-1.9.0-SNAPSHOT.11
+1.9.0-SNAPSHOT.12
2015
@@ -58,7 +58,7 @@ all modules and does not describe the project structure per-subproject.
io.spine
spine-server
- 1.9.0-SNAPSHOT.6
+ 1.9.0-SNAPSHOT.10
compile
@@ -94,7 +94,7 @@ all modules and does not describe the project structure per-subproject.
io.spine
spine-testutil-client
- 1.9.0-SNAPSHOT.6
+ 1.9.0-SNAPSHOT.10
test
@@ -168,7 +168,7 @@ all modules and does not describe the project structure per-subproject.
io.spine
spine-client
- 1.9.0-SNAPSHOT.6
+ 1.9.0-SNAPSHOT.10
io.spine.tools
diff --git a/version.gradle.kts b/version.gradle.kts
index 2e4ef8b16..f9cefb1b6 100644
--- a/version.gradle.kts
+++ b/version.gradle.kts
@@ -26,8 +26,8 @@
val spineBaseVersion: String by extra("1.9.0-SNAPSHOT.5")
val spineTimeVersion: String by extra("1.9.0-SNAPSHOT.5")
-val spineCoreVersion: String by extra("1.9.0-SNAPSHOT.6")
+val spineCoreVersion: String by extra("1.9.0-SNAPSHOT.10")
val spineVersion: String by extra(spineCoreVersion)
-val versionToPublish: String by extra("1.9.0-SNAPSHOT.11")
+val versionToPublish: String by extra("1.9.0-SNAPSHOT.12")
val versionToPublishJs: String by extra(versionToPublish)