mirror of
https://github.com/firstsun-dev/git-files-sync.git
synced 2026-07-22 17:20:30 +00:00
- Conflict modal (#42): resize to min(1100px,92vw) x min(85vh,800px) flex layout, remove the 280px content height cap, and add a Diff/Local/Remote tab switcher on narrow screens (defaults to Diff). - Settings connection status (#41): show a persistent Connected/Not connected/Checking badge in the settings tab, auto-tested on open and after an 800ms debounce on token/branch/URL/owner/repo edits, updated in place (no full re-render, so typing focus is preserved). - Local ignore patterns (#40): new "Ignore patterns" setting (.gitignore- style, multi-line) applied in GitignoreManager.isIgnored() in addition to the repo's own .gitignore, covering push/pull/refresh uniformly. Closes #42, #41, #40. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YYCTyZw7gUmJ7oh1VTmAqh
95 lines
3.5 KiB
TypeScript
95 lines
3.5 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-deprecated -- exercising the Obsidian < 1.13 display() compat fallback intentionally */
|
|
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { App } from 'obsidian';
|
|
import { DEFAULT_SETTINGS, GitLabSyncSettingTab } from '../../src/settings';
|
|
import GitLabFilesPush from '../../src/main';
|
|
import { createContainer, setupObsidianDOM } from './setup-dom';
|
|
|
|
vi.mock('../../src/main', () => ({
|
|
default: class {},
|
|
}));
|
|
|
|
beforeAll(() => { setupObsidianDOM(); });
|
|
|
|
function createPluginStub(testConnection: ReturnType<typeof vi.fn>): GitLabFilesPush {
|
|
return {
|
|
settings: { ...DEFAULT_SETTINGS },
|
|
saveSettings: vi.fn().mockResolvedValue(undefined),
|
|
initializeGitService: vi.fn(),
|
|
gitService: { testConnection },
|
|
} as unknown as GitLabFilesPush;
|
|
}
|
|
|
|
function scheduleConnectionTest(tab: GitLabSyncSettingTab): void {
|
|
(tab as unknown as { scheduleConnectionTest: () => void }).scheduleConnectionTest();
|
|
}
|
|
|
|
describe('GitLabSyncSettingTab connection status badge', () => {
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
});
|
|
|
|
it('shows checking then connected after opening the tab', async () => {
|
|
const testConnection = vi.fn().mockResolvedValue({ repoOk: true, branchOk: true });
|
|
const tab = new GitLabSyncSettingTab(new App(), createPluginStub(testConnection));
|
|
tab.containerEl = createContainer();
|
|
|
|
tab.display();
|
|
|
|
const badge = tab.containerEl.querySelector('.gfs-connection-status') as HTMLElement;
|
|
expect(badge.classList.contains('is-checking')).toBe(true);
|
|
|
|
await vi.advanceTimersByTimeAsync(800);
|
|
|
|
expect(testConnection).toHaveBeenCalledTimes(1);
|
|
expect(badge.classList.contains('is-connected')).toBe(true);
|
|
expect(badge.textContent).toBe('Connected');
|
|
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it('debounces repeated field edits into a single connection test', async () => {
|
|
const testConnection = vi.fn().mockResolvedValue({ repoOk: false, branchOk: false, error: 'bad token' });
|
|
const plugin = createPluginStub(testConnection);
|
|
const tab = new GitLabSyncSettingTab(new App(), plugin);
|
|
tab.containerEl = createContainer();
|
|
|
|
tab.display();
|
|
await vi.advanceTimersByTimeAsync(800);
|
|
testConnection.mockClear();
|
|
|
|
// Simulate rapid keystrokes in the token field via the debounced hook directly.
|
|
scheduleConnectionTest(tab);
|
|
scheduleConnectionTest(tab);
|
|
scheduleConnectionTest(tab);
|
|
|
|
await vi.advanceTimersByTimeAsync(799);
|
|
expect(testConnection).not.toHaveBeenCalled();
|
|
|
|
await vi.advanceTimersByTimeAsync(1);
|
|
expect(testConnection).toHaveBeenCalledTimes(1);
|
|
|
|
const badge = tab.containerEl.querySelector('.gfs-connection-status') as HTMLElement;
|
|
expect(badge.classList.contains('is-disconnected')).toBe(true);
|
|
expect(badge.textContent).toContain('bad token');
|
|
|
|
vi.useRealTimers();
|
|
});
|
|
});
|
|
|
|
describe('GitLabSyncSettingTab ignore patterns setting', () => {
|
|
it('renders a textarea seeded with the saved ignorePatterns value', async () => {
|
|
const plugin = createPluginStub(vi.fn().mockResolvedValue({ repoOk: true, branchOk: true }));
|
|
plugin.settings.ignorePatterns = 'draft/\n*.tmp';
|
|
const tab = new GitLabSyncSettingTab(new App(), plugin);
|
|
tab.containerEl = createContainer();
|
|
|
|
vi.useFakeTimers();
|
|
tab.display();
|
|
await vi.advanceTimersByTimeAsync(800);
|
|
vi.useRealTimers();
|
|
|
|
const textarea = tab.containerEl.querySelector('textarea') as HTMLTextAreaElement;
|
|
expect(textarea.value).toBe('draft/\n*.tmp');
|
|
});
|
|
});
|