Files
tolaria/tests/smoke/git-divergence-conflicts.spec.ts
Test 05dca72ef3 feat: handle git divergence, conflicts, and manual pull from within Laputa
When push is rejected due to remote having newer commits, the bottom bar
now shows "Pull required" (orange). Clicking it pulls then auto-pushes.
Conflicted notes show an inline banner with "Keep mine" / "Keep theirs"
buttons. A new "Pull from Remote" command is available in Cmd+K and the
Vault menu. Clicking the sync badge opens a popup showing branch name,
ahead/behind counts, and a Pull button.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:51:06 +01:00

91 lines
3.2 KiB
TypeScript

import { test, expect } from '@playwright/test'
import { openCommandPalette, executeCommand } from './helpers'
test.describe('Git divergence, conflicts, and manual pull', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/')
await page.waitForLoadState('networkidle')
})
test('push rejection sets pull_required status in bottom bar', async ({ page }) => {
// Override git_push mock to return rejected
await page.evaluate(() => {
window.__mockHandlers!.git_push = () => ({
status: 'rejected',
message: 'Push rejected: remote has new commits. Pull first, then push.',
})
})
// Commit to trigger push
await openCommandPalette(page)
await executeCommand(page, 'Commit & Push')
const textarea = page.locator('textarea[placeholder="Commit message..."]')
await textarea.waitFor({ timeout: 5000 })
await textarea.fill('test commit')
await page.getByRole('button', { name: 'Commit & Push' }).click()
// Verify toast shows rejection message
const toast = page.locator('.fixed.bottom-8')
await expect(toast).toContainText('push rejected', { timeout: 5000 })
// Verify "Pull required" label appears in the status bar
const syncBadge = page.getByTestId('status-sync')
await expect(syncBadge).toContainText('Pull required', { timeout: 5000 })
})
test('Pull from Remote command exists in command palette', async ({ page }) => {
await openCommandPalette(page)
const input = page.locator('input[placeholder="Type a command..."]')
await input.fill('Pull')
// Verify the Pull from Remote command appears as the selected item
const match = page.locator('[data-selected="true"]').first()
await expect(match).toContainText('Pull from Remote', { timeout: 3000 })
})
test('git status popup shows branch and sync info when clicking sync badge', async ({ page }) => {
// Override git_remote_status to return data with ahead/behind
await page.evaluate(() => {
window.__mockHandlers!.git_remote_status = () => ({
branch: 'main',
ahead: 3,
behind: 1,
hasRemote: true,
})
})
// Trigger a sync so the remote status gets fetched
const syncBadge = page.getByTestId('status-sync')
await syncBadge.click()
// The popup should appear
const popup = page.getByTestId('git-status-popup')
await expect(popup).toBeVisible({ timeout: 3000 })
await expect(popup).toContainText('main')
})
test('conflict badge shows count when conflicts exist', async ({ page }) => {
// Override git_pull to return conflicts
await page.evaluate(() => {
window.__mockHandlers!.git_pull = () => ({
status: 'conflict',
message: 'Merge conflict in 2 file(s)',
updatedFiles: [],
conflictFiles: ['note-a.md', 'note-b.md'],
})
window.__mockHandlers!.get_conflict_files = () => ['note-a.md', 'note-b.md']
})
// Trigger a sync
await openCommandPalette(page)
await executeCommand(page, 'Pull from Remote')
// Verify conflict count badge appears
const conflictBadge = page.getByTestId('status-conflict-count')
await expect(conflictBadge).toBeVisible({ timeout: 5000 })
await expect(conflictBadge).toContainText('2 conflicts')
})
})