diff --git a/Tests/Integration/ClientIntegrationTests.swift b/Tests/Integration/ClientIntegrationTests.swift
index 3dc64cc7..768822d8 100644
--- a/Tests/Integration/ClientIntegrationTests.swift
+++ b/Tests/Integration/ClientIntegrationTests.swift
@@ -745,4 +745,37 @@ final class ClientIntegrationTests: XCTestCase {
try await c1.deactivate()
try await c2.deactivate()
}
+
+ func test_duplicated_local_changes_not_sent_to_server() async throws {
+ try await withTwoClientsAndDocuments(self.description, detachDocuments: false) { c1, d1, c2, d2 in
+ try await d1.update { root, _ in
+ root.t = JSONTree(initialRoot:
+ JSONTreeElementNode(type: "doc",
+ children: [
+ JSONTreeElementNode(type: "p", children: [JSONTreeTextNode(value: "12")]),
+ JSONTreeElementNode(type: "p", children: [JSONTreeTextNode(value: "34")])
+ ])
+ )
+ }
+
+ try await c1.sync()
+ try await c1.sync()
+ try await c1.sync()
+ try await c1.detach(d1)
+
+ try await Task.sleep(nanoseconds: 3_000_000_000)
+
+ try await c2.sync()
+
+ let d1XML = await(d1.getRoot().t as? JSONTree)?.toXML()
+ let d2XML = await(d2.getRoot().t as? JSONTree)?.toXML()
+ XCTAssertEqual(d1XML, /* html */ "12
34
")
+ XCTAssertEqual(d2XML, /* html */ "12
34
")
+
+ try await c2.detach(d2)
+
+ try await c1.deactivate()
+ try await c2.deactivate()
+ }
+ }
}
diff --git a/Tests/Integration/IntegrationHelper.swift b/Tests/Integration/IntegrationHelper.swift
index d87fdd01..6d74a069 100644
--- a/Tests/Integration/IntegrationHelper.swift
+++ b/Tests/Integration/IntegrationHelper.swift
@@ -17,7 +17,7 @@
import XCTest
@testable import Yorkie
-func withTwoClientsAndDocuments(_ title: String, _ callback: (Client, Document, Client, Document) async throws -> Void) async throws {
+func withTwoClientsAndDocuments(_ title: String, detachDocuments: Bool = true, _ callback: (Client, Document, Client, Document) async throws -> Void) async throws {
let rpcAddress = "http://localhost:8080"
let docKey = "\(Date().description)-\(title)".toDocKey
@@ -36,11 +36,13 @@ func withTwoClientsAndDocuments(_ title: String, _ callback: (Client, Document,
try await callback(c1, d1, c2, d2)
- try await c1.detach(d1)
- try await c2.detach(d2)
+ if detachDocuments {
+ try await c1.detach(d1)
+ try await c2.detach(d2)
- try await c1.deactivate()
- try await c2.deactivate()
+ try await c1.deactivate()
+ try await c2.deactivate()
+ }
}
protocol OperationInfoForDebug {}