mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
4d2dc5772e
* fix(review): restore the prior diff when leaving the Commits view Clicking a commit in the Commits panel (or its HEAD auto-select) switches the single session-global diff to commit:<sha>, and switching the panel back to Tree never switched it back, leaving the review stuck on a historical commit (shipped as an accepted v1 edge in #994). A page reload did not escape either, since GET /api/diff serves the current session diff. Client-only fix: - preCommitDiffRef captures the pre-commit diff (full diff type + base) on the first non-commit to commit switch in handleSelectCommit. - Leaving Commits for Tree restores it via fetchDiffSwitch; without a memo (post-reload) it falls back to the session default with the same resolution handleWorktreeSwitch uses. Exiting while the commit switch is still in flight also restores, superseding it server-side. - Any applied non-commit switch clears the memo in fetchDiffSwitch. - Reload un-trap: a load that is served a commit diff while the opening panel view is not Commits snaps back to the session default once. Git status keeps its existing since-base reset; the server keeps its single-active-diff model unchanged. * test(review): cover the offered-but-not-first preferred default; document the Commits detour contract
69 lines
2.8 KiB
TypeScript
69 lines
2.8 KiB
TypeScript
import { describe, expect, test } from 'bun:test';
|
|
import { isCommitDiffType, resolveCommitExitDiff } from './commitViewRestore';
|
|
|
|
// isCommitDiffType must agree with App.tsx's worktree parse and the server's
|
|
// parseCommitDiffType about what the commit family IS — a divergence would
|
|
// capture/clear the leave-Commits restore memo on the wrong transitions.
|
|
describe('isCommitDiffType', () => {
|
|
test('matches plain and worktree-composed commit diffs', () => {
|
|
expect(isCommitDiffType('commit:36b855f57eb53531c1baa734586e2fb9981f9881')).toBe(true);
|
|
expect(isCommitDiffType('commit:abcd')).toBe(true); // 4-char minimum, same as the parse
|
|
expect(isCommitDiffType('worktree:/tmp/wt:commit:abcdef12')).toBe(true);
|
|
// Worktree paths may contain colons; only the anchored tail decides.
|
|
expect(isCommitDiffType('worktree:C:/work/tree:commit:abcdef12')).toBe(true);
|
|
});
|
|
|
|
test('rejects every non-commit diff type', () => {
|
|
for (const t of [
|
|
'since-base',
|
|
'uncommitted',
|
|
'last-commit',
|
|
'worktree:/tmp/wt:since-base',
|
|
'worktree:/tmp/wt:uncommitted',
|
|
'gitbutler:workspace',
|
|
'commit:', // no sha
|
|
'commit:xyz!', // non-hex
|
|
'commit:abc', // below the 4-char minimum the parse enforces
|
|
'my-commit-mode', // contains the word, not the family
|
|
]) {
|
|
expect(isCommitDiffType(t)).toBe(false);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('resolveCommitExitDiff', () => {
|
|
const fallback = {
|
|
preferredDefault: 'since-base',
|
|
diffOptions: [{ id: 'since-base' }, { id: 'uncommitted' }],
|
|
activeWorktreePath: null,
|
|
};
|
|
|
|
test('memo wins verbatim, base included', () => {
|
|
const memo = { diffType: 'worktree:/tmp/wt:merge-base', base: 'origin/main' };
|
|
expect(resolveCommitExitDiff(memo, fallback)).toEqual(memo);
|
|
});
|
|
|
|
test('no memo: preferred default used only when the session offers it', () => {
|
|
expect(resolveCommitExitDiff(null, fallback)).toEqual({ diffType: 'since-base', base: null });
|
|
// Offered but not first: must win over diffOptions[0].
|
|
expect(
|
|
resolveCommitExitDiff(null, { ...fallback, preferredDefault: 'uncommitted' }),
|
|
).toEqual({ diffType: 'uncommitted', base: null });
|
|
expect(
|
|
resolveCommitExitDiff(null, { ...fallback, preferredDefault: 'merge-base' }),
|
|
).toEqual({ diffType: 'since-base', base: null }); // first offered option
|
|
});
|
|
|
|
test('no memo, no options: uncommitted', () => {
|
|
expect(
|
|
resolveCommitExitDiff(null, { preferredDefault: undefined, diffOptions: [], activeWorktreePath: null }),
|
|
).toEqual({ diffType: 'uncommitted', base: null });
|
|
});
|
|
|
|
test('no memo in a worktree session: fallback composes the worktree prefix', () => {
|
|
expect(
|
|
resolveCommitExitDiff(null, { ...fallback, activeWorktreePath: '/tmp/wt' }),
|
|
).toEqual({ diffType: 'worktree:/tmp/wt:since-base', base: null });
|
|
});
|
|
});
|