diff --git a/apps/browser-extension/src/entrypoints/popup/hooks/useVaultMutate.ts b/apps/browser-extension/src/entrypoints/popup/hooks/useVaultMutate.ts index 4ef05c6ff..00f82905a 100644 --- a/apps/browser-extension/src/entrypoints/popup/hooks/useVaultMutate.ts +++ b/apps/browser-extension/src/entrypoints/popup/hooks/useVaultMutate.ts @@ -1,6 +1,7 @@ import { useCallback } from 'react'; import { sendMessage } from 'webext-bridge/popup'; +import type { FullVaultSyncResult } from '@/entrypoints/background/VaultMessageHandler'; import { useDb } from '@/entrypoints/popup/context/DbContext'; import { EncryptionUtility } from '@/utils/EncryptionUtility'; @@ -56,6 +57,9 @@ export function useVaultMutate(): { * Trigger a sync in the background script. * This is fire-and-forget - the sync runs entirely in the background context * and continues even if the popup closes. + * + * If a merge happened during sync (hasNewVault=true), reload the database + * so the popup shows the merged data. */ const triggerBackgroundSync = useCallback((): void => { /* @@ -63,7 +67,11 @@ export function useVaultMutate(): { * The background script will handle the full sync orchestration * and will re-sync if mutations happened during the sync. */ - sendMessage('FULL_VAULT_SYNC', {}, 'background').then(async () => { + sendMessage('FULL_VAULT_SYNC', {}, 'background').then(async (result: FullVaultSyncResult) => { + // If a merge happened, reload the database to show merged data + if (result.hasNewVault) { + await dbContext.loadStoredDatabase(); + } // Refresh sync state if popup is still open await dbContext.refreshSyncState(); }).catch((error) => { diff --git a/apps/browser-extension/tests/e2e/05-vault-merge.spec.ts b/apps/browser-extension/tests/e2e/05-vault-merge.spec.ts index 27fe6bd49..05348ff9a 100644 --- a/apps/browser-extension/tests/e2e/05-vault-merge.spec.ts +++ b/apps/browser-extension/tests/e2e/05-vault-merge.spec.ts @@ -73,8 +73,10 @@ test.describe.serial('5. Vault Merge', () => { }); test('5.4 Client B vault should contain both credentials after merge', async () => { + // Trigger sync to ensure background merge has completed and database is reloaded await clientB - .goToVault() + .triggerSync() + .then((c) => c.goToVault()) .then((c) => c.screenshot('5.4-client-b-vault-state.png')) .then((c) => c.verifyCredentialExists(credentialNameA)); diff --git a/apps/browser-extension/tests/e2e/06-field-level-merge.spec.ts b/apps/browser-extension/tests/e2e/06-field-level-merge.spec.ts index cc5c33ac5..0c70238b3 100644 --- a/apps/browser-extension/tests/e2e/06-field-level-merge.spec.ts +++ b/apps/browser-extension/tests/e2e/06-field-level-merge.spec.ts @@ -81,7 +81,9 @@ test.describe.serial('6. Field-Level Merge', () => { .then((c) => c.fillNotes(clientBNotes)) .then((c) => c.screenshot('6.4-client-b-before-save.png')) .then((c) => c.saveCredential()) - .then((c) => c.screenshot('6.4-client-b-after-save.png')); + .then((c) => c.screenshot('6.4-client-b-after-save.png')) + // Wait for background sync (including merge) to complete before next test + .then((c) => c.triggerSync()); }); test('6.5 Client B verifies field-level merge result', async () => { diff --git a/apps/browser-extension/tests/fixtures/waits.ts b/apps/browser-extension/tests/fixtures/waits.ts index 78544a789..cd4fc73cd 100644 --- a/apps/browser-extension/tests/fixtures/waits.ts +++ b/apps/browser-extension/tests/fixtures/waits.ts @@ -65,6 +65,11 @@ export async function waitForVaultReady(popup: Page, timeout: number = Timeouts. * Wait for a sync operation to complete. * Waits for vault UI to be ready, then waits for sync/pending indicators to disappear. * + * Indicator elements: + * - Syncing (green):
with bg-green-100 + * - Pending (blue):