powersync-js icon indicating copy to clipboard operation
powersync-js copied to clipboard

How to wait for a full sync? (How to test PowerSync-based app?)

Open KazimirPodolski opened this issue 4 months ago • 7 comments

I'm trying to make some integraiton tests with Vitest. Some typical scenarios:

  • Call backend API affecting some tables in Sync Rules -> expect changes downloaded to the client
  • Write some data to client tables -> expect changes uploaded to the backend (-> expect changes downloaded to the client?)

Consider a test with Vitest and PowerSync Node SDK:

test('User signs up', async ({apiClient, kylesyDb, powersyncDb}) => {
  await apiClient.signUp({email: '...'});

  // HOW TO WAIT FOR A SYNC?
  // I could only come up with something like
  // await powersyncDb.disconnectAndClear();
  // await powersyncDb.connect(connector);
  // But it's not an honest test

  expect(await db.selectFrom('user').selectAll().executeTakeFirst()).toBeDefined()
});

So, how one awaits for client Sqlite to be in full sync with backend DB?

KazimirPodolski avatar Aug 16 '25 16:08 KazimirPodolski

In the nodejs client, I use waitForFirstSync().

Maybe it will work for your tests

const powerSync = new PowerSyncDatabase({ ... });
await powerSync.connect(...);
await powerSync.waitForReady();
await powerSync.waitForFirstSync();

douglascayers avatar Aug 25 '25 03:08 douglascayers

@douglascayers I'm afraid it doesn't work past the actual first sync:

    const statusMatches =
      priority === undefined
        ? (status: SyncStatus) => status.hasSynced
        : (status: SyncStatus) => status.statusForPriority(priority).hasSynced;


    if (statusMatches(this.currentStatus)) {
      return;
    }

I also tried checking for powerSync.currentStatus, but the status doesn't change syncronously.

KazimirPodolski avatar Aug 25 '25 09:08 KazimirPodolski

Basically, @powersync-ja how to test software made with PowerSync?

KazimirPodolski avatar Aug 25 '25 09:08 KazimirPodolski

We typically suggest using Vitest's waitFor utility (if possible). After initiating the upload, you can use waitFor to create a test that queries the client database and verifies the expected synced value. The utility will automatically retry the assertion if it initially fails, allowing time for the sync to complete.

We have an example of this here.

Alternatively, you could monitor the sync status directly. This method involves first capturing the current lastSyncedAt timestamp from the sync status, then making your desired change, and finally waiting for the lastSyncedAt value to advance beyond the initial timestamp. This ensures that the synchronization process has completed before proceeding with your assertions.

dean-journeyapps avatar Aug 25 '25 10:08 dean-journeyapps

@dean-journeyapps I tried the waitFor method (the data just never appears in the Sqlite) but it doesn't work despite reconnecting does . Like somehow sync is not working under Vitest, I dunno.

KazimirPodolski avatar Aug 25 '25 10:08 KazimirPodolski

@dean-journeyapps I tried the waitFor method (the data just never appears in the Sqlite) but it doesn't work despite reconnecting does . Like somehow sync is not working under Vitest, I dunno.

This seems like a more general sync issue. Possibly related to your backend connector. We would need to see more of your code to properly help diagnose that issue.

Is your client database connected when testing?

dean-journeyapps avatar Aug 25 '25 11:08 dean-journeyapps

@dean-journeyapps I see, I'll try to debug more and make a minimal repro.

KazimirPodolski avatar Aug 25 '25 13:08 KazimirPodolski