Skip to content

Add test that awaitDocumentPushed() resolves after a push conflict is resolved#8739

Draft
pubkey with Copilot wants to merge 5 commits into
masterfrom
copilot/add-test-await-document-pushed
Draft

Add test that awaitDocumentPushed() resolves after a push conflict is resolved#8739
pubkey with Copilot wants to merge 5 commits into
masterfrom
copilot/add-test-await-document-pushed

Conversation

Copilot AI commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Adds a test covering the case where a document push first returns a conflict: after the conflict is resolved, awaitDocumentPushed() must still resolve.

Changes

  • test/unit/replication.test.ts: New test should resolve after a push conflict was resolved in the .awaitDocumentPushed() suite:
    • The master already holds a different state for the document id, so the first push of the local insert returns a conflict (asserted via a hadConflict flag in the push handler).
    • The collection uses a conflict handler that resolves by keeping the local state, so the resolved document gets pushed again and succeeds.
    • Asserts awaitDocumentPushed(doc) resolves afterwards and the resolved state reached the master.
    • The push handler operates on an in-memory master document map instead of a second remote collection. Using a second collection per test reproducibly pushed the parallel test:fast:memory run over the open-collections limit (COL23).
  • orga/changelog/add-await-document-pushed-conflict-test.md: Changelog entry linking issue Feature request: awaitable per-write push acknowledgement (opt-in write-through for replication) #8632.
const conflictHandler: RxConflictHandler<TestDocType> = {
    isEqual: defaultConflictHandler.isEqual,
    resolve: (i) => Promise.resolve(i.newDocumentState) // local wins -> re-push happens
};

const doc = await localCollection.insert({ id: 'conflict-doc', name: 'local-name', ... });
await replicationState.awaitDocumentPushed(doc); // resolves after conflict + re-push

Test is stable across repeated runs, including the memory-random-delay storage.

Copilot AI and others added 2 commits July 6, 2026 09:40
Co-authored-by: pubkey <8926560+pubkey@users.noreply.github.com>
…limit

Co-authored-by: pubkey <8926560+pubkey@users.noreply.github.com>
Co-authored-by: pubkey <8926560+pubkey@users.noreply.github.com>
Copilot AI requested a review from pubkey July 6, 2026 11:11
Copilot finished work on behalf of pubkey July 6, 2026 11:11
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

⚠️ Verify Test Reproduction: Tests PASSED without the fix (unexpected)

The changed tests do not fail without the source changes from this PR. Please inspect whether the test changes actually test the bug that the source changes fix.

This workflow runs the changed tests without the source fix to verify they reproduce the bug.

Show output
...(truncated, showing last 200 of 4402 lines)
      �[32m✓ �[39mfull roundtrip should preserve MIME type for non-compressible type

  attachments-compression.test.ts (mode: gzip)
    basics
      �[32m✓ �[39mcompress->decompress
    CRUD
      �[32m✓ �[39mshould insert one attachment
      �[32m✓ �[39mshould get the attachment
      �[32m✓ �[39mshould get the data
    compare size
      �[32m✓ �[39mshould have a smaller size when compression is used
    selective compression
      �[32m✓ �[39mshould compress a compressible type (text/plain) and roundtrip correctly
      �[32m✓ �[39mshould NOT compress a non-compressible type (image/jpeg) but still roundtrip correctly
      �[32m✓ �[39mshould compress text but not jpeg on the same document
    isCompressibleType()
      �[32m✓ �[39mshould match wildcard patterns
      �[32m✓ �[39mshould match exact patterns
      �[32m✓ �[39mshould be case-insensitive
      �[32m✓ �[39mshould NOT match non-compressible types
      �[32m✓ �[39mshould match types that include RFC 2045 parameters like charset
    MIME type preservation
      �[32m✓ �[39mfull roundtrip through storage should preserve MIME type on getData()
      �[32m✓ �[39mfull roundtrip should preserve MIME type for non-compressible type
WARN LOG: �[36m'-------------- RxDB Open Core RxStorage -------------------------------
You are using the free Dexie.js based RxStorage implementation from RxDB https://rxdb.info/rx-storage-dexie.html?console=dexie 
While this is a great option, we want to let you know that there are faster storage solutions available in our premium plugins.
For professional users and production environments, we highly recommend considering these premium options to enhance performance and reliability.
 https://rxdb.info/premium/?console=dexie 
If you already purchased premium access you can disable this log by calling the setPremiumFlag() function from rxdb-premium/plugins/shared.
---------------------------------------------------------------------'�[39m

  migration-storage.test.ts (prev-major to newest (dexie))
    basic migrations
      �[32m✓ �[39mcreate both databases
      �[32m✓ �[39mshould migrate all documents
      �[32m✓ �[39mshould migrate in parallel
      �[32m✓ �[39mmigrate new->new should also work
    issues
      �[32m✓ �[39mmigration with multiple collections

  migration-storage.test.ts (newest to newest)
    basic migrations
      �[32m✓ �[39mcreate both databases
      �[32m✓ �[39mshould migrate all documents
      �[32m✓ �[39mshould migrate in parallel
      �[32m✓ �[39mmigrate new->new should also work
    issues
      �[32m✓ �[39mmigration with multiple collections
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext is deprecated. The May 27, 2026 WebMCP draft moved the modelContext getter from Navigator to Document — use document.modelContext instead. See https://github.com/webmachinelearning/webmcp/pull/184.'�[39m

  webmcp.test.ts
    �[32m✓ �[39mshould register query tool when registerWebMCP is called
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext.unregisterTool() is deprecated. The April 23, 2026 WebMCP draft removed it in favor of registerTool(tool, { signal }) — pass an AbortSignal and abort it to unregister.'�[39m
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext is deprecated. The May 27, 2026 WebMCP draft moved the modelContext getter from Navigator to Document — use document.modelContext instead. See https://github.com/webmachinelearning/webmcp/pull/184.'�[39m
    �[32m✓ �[39mshould wait for changes using wait_changes tool
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext.unregisterTool() is deprecated. The April 23, 2026 WebMCP draft removed it in favor of registerTool(tool, { signal }) — pass an AbortSignal and abort it to unregister.'�[39m
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext is deprecated. The May 27, 2026 WebMCP draft moved the modelContext getter from Navigator to Document — use document.modelContext instead. See https://github.com/webmachinelearning/webmcp/pull/184.'�[39m
    �[32m✓ �[39mchanges tool should return documents without internal meta fields
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext.unregisterTool() is deprecated. The April 23, 2026 WebMCP draft removed it in favor of registerTool(tool, { signal }) — pass an AbortSignal and abort it to unregister.'�[39m
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext is deprecated. The May 27, 2026 WebMCP draft moved the modelContext getter from Navigator to Document — use document.modelContext instead. See https://github.com/webmachinelearning/webmcp/pull/184.'�[39m
    �[32m✓ �[39mshould iterate over changes using checkpoint
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext.unregisterTool() is deprecated. The April 23, 2026 WebMCP draft removed it in favor of registerTool(tool, { signal }) — pass an AbortSignal and abort it to unregister.'�[39m
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext is deprecated. The May 27, 2026 WebMCP draft moved the modelContext getter from Navigator to Document — use document.modelContext instead. See https://github.com/webmachinelearning/webmcp/pull/184.'�[39m
    �[32m✓ �[39mshould execute modifier tools successfully (insert/upsert/delete)
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext.unregisterTool() is deprecated. The April 23, 2026 WebMCP draft removed it in favor of registerTool(tool, { signal }) — pass an AbortSignal and abort it to unregister.'�[39m
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext is deprecated. The May 27, 2026 WebMCP draft moved the modelContext getter from Navigator to Document — use document.modelContext instead. See https://github.com/webmachinelearning/webmcp/pull/184.'�[39m
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext.unregisterTool() is deprecated. The April 23, 2026 WebMCP draft removed it in favor of registerTool(tool, { signal }) — pass an AbortSignal and abort it to unregister.'�[39m
    �[32m✓ �[39mshould unregister tools when collection is closed
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext is deprecated. The May 27, 2026 WebMCP draft moved the modelContext getter from Navigator to Document — use document.modelContext instead. See https://github.com/webmachinelearning/webmcp/pull/184.'�[39m
    �[32m✓ �[39mshould not register modifier tools when readOnly is true
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext.unregisterTool() is deprecated. The April 23, 2026 WebMCP draft removed it in favor of registerTool(tool, { signal }) — pass an AbortSignal and abort it to unregister.'�[39m
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext is deprecated. The May 27, 2026 WebMCP draft moved the modelContext getter from Navigator to Document — use document.modelContext instead. See https://github.com/webmachinelearning/webmcp/pull/184.'�[39m
    �[32m✓ �[39mshould emit log$ and error$ events for executed tools
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext.unregisterTool() is deprecated. The April 23, 2026 WebMCP draft removed it in favor of registerTool(tool, { signal }) — pass an AbortSignal and abort it to unregister.'�[39m
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext is deprecated. The May 27, 2026 WebMCP draft moved the modelContext getter from Navigator to Document — use document.modelContext instead. See https://github.com/webmachinelearning/webmcp/pull/184.'�[39m
    �[32m✓ �[39mshould register tools for newly added collections dynamically
WARN LOG: �[36m'[WebMCPPolyfill] navigator.modelContext.unregisterTool() is deprecated. The April 23, 2026 WebMCP draft removed it in favor of registerTool(tool, { signal }) — pass an AbortSignal and abort it to unregister.'�[39m

  crdt.test.ts
    collection creation
      �[32m✓ �[39mshould throw if the wrong conflict handler is set
      �[32m✓ �[39mshould automatically set the CRDT conflict handler
    .insert()
      �[32m✓ �[39mshould insert a document and initialize the crdt state
      �[32m✓ �[39mshould insert document via bulkInsert
    .insertCRDT()
      �[32m✓ �[39mshould insert the document
      �[32m✓ �[39mshould insert the document with undefined argument
      �[32m✓ �[39mshould respect the if-else logic
    .remove()
      �[32m✓ �[39mshould delete the document via .remove
    .incrementalPatch()
      �[32m✓ �[39mshould update the document
    disallowed methods
      �[32m✓ �[39mshould throw on incrementalModify
      �[32m✓ �[39mshould throw on modify
    redirected methods
      �[32m✓ �[39mshould redirect patch through updateCRDT
      �[32m✓ �[39mshould redirect incrementalRemove through updateCRDT
      �[32m✓ �[39mshould redirect update through updateCRDT
    conflict handling
      init
        �[32m✓ �[39minit
      .getCRDTConflictHandler()
        �[32m✓ �[39mshould merge 2 inserts correctly
        �[32m✓ �[39mshould preserve schema default values during conflict resolution
        �[32m✓ �[39mshould preserve the composite primary key during conflict resolution
      conflicts during replication
        �[32m✓ �[39mshould merge the +1 increments

  population.test.js
    createRxSchema
      positive
        �[32m✓ �[39mshould allow to create a schema with a relation
        �[32m✓ �[39mshould allow primary as relation key
        �[32m✓ �[39mshould allow to create a schema with a relation in nested
        �[32m✓ �[39mshould allow to create relation of array
        �[32m✓ �[39mshould allow to create relation with nullable string
      negative
        �[32m✓ �[39mthrow if ref-type is no string
        �[32m✓ �[39mthrow if ref-type is no string (array)
    RxDocument().populate()
      positive
        �[32m✓ �[39mpopulate top-level-field
        �[32m✓ �[39mpopulate nested field
        �[32m✓ �[39mpopulate string-array
        �[32m✓ �[39mpopulate with primary as ref
      negative
        �[32m✓ �[39mthrow DOC5 for a path that does not exist in the schema, even when the value is falsy
        �[32m✓ �[39mthrow DOC6 when populating a non-ref schema field, even when the value is falsy
    RxDocument populate via pseudo-proxy
      positive
        �[32m✓ �[39mpopulate top-level-field
        �[32m✓ �[39mpopulate nested field
    issues
      �[32m✓ �[39m#222 population not working when multiInstance: false
      �[32m✓ �[39mpopulate array should preserve the order of ref ids when two documents reference the same set in different order
      �[32m✓ �[39mpopulate array when ref is defined on items instead of on the array field

  leader-election.test.js
    .die()
      �[32m✓ �[39mother instance applies on death of leader
    election
      �[32m✓ �[39ma single instance should always elect itself as leader
      �[32m✓ �[39mshould not elect as leader if other instance is leader
      �[32m✓ �[39mwhen 2 instances apply at the same time, one should win
      �[32m✓ �[39mwhen many instances apply, one should win
      �[32m✓ �[39mwhen the leader dies, a new one should be elected
    cleanup
      �[32m✓ �[39mshould properly call die() on the elector when the database is closed
    integration
      �[32m✓ �[39mnon-multiInstance should always be leader
      �[32m✓ �[39mnon-multiInstance: waitForLeadership should instant
      �[32m✓ �[39mwaitForLeadership: run once when instance becomes leader

  import-export.test.js
    Collection
      .exportJSON()
        �[32m✓ �[39mexport the collection
        �[32m✓ �[39mexport encrypted as decrypted
      .importJSON()
        positive
          �[32m✓ �[39mimport json
        negative
          �[32m✓ �[39mshould not import if schema is different
    Database
      .exportJSON()
        �[32m✓ �[39mshould export a valid dump
        �[32m✓ �[39mexport encrypted as decrypted
        �[32m✓ �[39mexport with multiple collections
        �[32m✓ �[39mexport 1 of 2 collections
      .importJSON()
        positive
          �[32m✓ �[39mimport dump
        negative
          �[32m✓ �[39mshould not import if schema is different
    issues
      �[32m✓ �[39m#319 collections must be created before importDump
      �[32m✓ �[39m#1396 import/export should work with attachments

  database-lifecycle.ts
    �[32m✓ �[39mdo some writes updates and deletes and cleanups and reopens

  last.test.ts (dexie)
    �[32m✓ �[39mrun a minimal performance test to ensure the performance function works
    �[32m✓ �[39mensure all Memory RxStorage instances are closed
    �[32m✓ �[39mensure every db is cleaned up
    �[32m✓ �[39mensure all collections are closed
    �[32m✓ �[39mensure all BroadcastChannels are closed
    �[32m✓ �[39mensure all replication states are closed
    �[32m✓ �[39mensure all RemoteMessageChannels have been closed
    �[32m✓ �[39mensure all websockets have been closed
    �[32m✓ �[39mensure all leader electors are dead
    �[32m✓ �[39mexit the process

Chrome Headless 149.0.0.0 (Linux 0.0.0): Executed 1341 of 1341�[32m SUCCESS�[39m (57.72 secs / 56.893 secs)
�[32mTOTAL: 1341 SUCCESS�[39m



View full workflow run

Co-authored-by: pubkey <8926560+pubkey@users.noreply.github.com>
Copilot finished work on behalf of pubkey July 6, 2026 11:43
@pubkey

pubkey commented Jul 6, 2026

Copy link
Copy Markdown
Owner

@copilot resolve the merge conflicts in this pull request

Co-authored-by: pubkey <8926560+pubkey@users.noreply.github.com>

Copilot AI commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

Merge conflicts resolved in a4e8297. The only conflict was in the type imports of test/unit/replication.test.ts; both RxConflictHandler (this PR) and RxReplicationConflict (from master) are kept since both are used. Lint, type check, build and test:fast:memory (1401 tests) pass.

Copilot finished work on behalf of pubkey July 6, 2026 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants