Files
openchamber/packages/vscode/src/gitService.worktree-fetch-fallback.test.js
T
𝖎𝖚𝖑𝖎𝖎𝖆 0d8709a72e fix(worktrees): remove worktrees in the background (#3319)
* refactor(worktrees): fetch source once during creation

* fix(worktrees): remove worktrees in background

* fix(worktrees): show background removal progress

* fix(worktrees): name the worktree in removal toasts
2026-09-03 15:17:28 +03:00

118 lines
3.9 KiB
JavaScript

import { afterEach, describe, expect, it, mock } from 'bun:test';
import { execFileSync } from 'node:child_process';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
mock.module('vscode', () => ({
extensions: { getExtension: () => undefined },
Uri: { file: (fsPath) => ({ fsPath }) },
}));
const { createWorktree } = await import('./gitService.ts?worktree-fetch-fallback-test');
const tempDirs = [];
const createTempDir = () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'openchamber-vscode-git-'));
tempDirs.push(dir);
return dir;
};
const runGit = (cwd, args) =>
execFileSync('git', args, {
cwd,
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe'],
});
const createRepositoryWithRemote = () => {
const remote = createTempDir();
const repository = createTempDir();
runGit(remote, ['init', '--bare', '--initial-branch=main']);
runGit(repository, ['init', '-b', 'next']);
runGit(repository, ['config', 'user.email', 'test@example.com']);
runGit(repository, ['config', 'user.name', 'Test']);
fs.writeFileSync(path.join(repository, 'README.md'), '# Test\n');
runGit(repository, ['add', 'README.md']);
runGit(repository, ['commit', '-m', 'init']);
runGit(repository, ['remote', 'add', 'origin', remote]);
runGit(repository, ['push', 'origin', 'HEAD:main']);
runGit(repository, ['fetch', 'origin']);
return { repository };
};
const canRunGit = () => {
try {
execFileSync('git', ['--version'], { stdio: 'ignore' });
return true;
} catch {
return false;
}
};
afterEach(() => {
for (const dir of tempDirs.splice(0)) {
fs.rmSync(dir, { recursive: true, force: true });
}
});
describe('VS Code worktree create from a remote start ref', () => {
it('falls back to the tracked local branch when the source fetch fails', async () => {
if (!canRunGit()) return;
const previousXdgDataHome = process.env.XDG_DATA_HOME;
process.env.XDG_DATA_HOME = createTempDir();
try {
const { repository } = createRepositoryWithRemote();
runGit(repository, ['branch', '--set-upstream-to=origin/main', 'next']);
runGit(repository, ['remote', 'set-url', 'origin', '/nonexistent/openchamber-unreachable.git']);
const created = await createWorktree(repository, {
mode: 'new',
branchName: 'openchamber/stale-ref-wt',
worktreeName: 'stale-ref-wt',
startRef: 'remotes/origin/main',
});
expect(created.branch).toBe('openchamber/stale-ref-wt');
expect(created.sourceFetchFailed).toBe(true);
const expectedHead = runGit(repository, ['rev-parse', 'next']).trim();
expect(runGit(created.path, ['rev-parse', 'HEAD']).trim()).toBe(expectedHead);
} finally {
if (previousXdgDataHome === undefined) {
delete process.env.XDG_DATA_HOME;
} else {
process.env.XDG_DATA_HOME = previousXdgDataHome;
}
}
}, 30_000);
it('rejects creation when the remote start ref was never fetched and cannot be fetched', async () => {
if (!canRunGit()) return;
const previousXdgDataHome = process.env.XDG_DATA_HOME;
process.env.XDG_DATA_HOME = createTempDir();
try {
const { repository } = createRepositoryWithRemote();
runGit(repository, ['update-ref', '-d', 'refs/remotes/origin/main']);
runGit(repository, ['remote', 'set-url', 'origin', '/nonexistent/openchamber-unreachable.git']);
await expect(createWorktree(repository, {
mode: 'new',
branchName: 'openchamber/never-fetched-wt',
worktreeName: 'never-fetched-wt',
startRef: 'remotes/origin/main',
})).rejects.toThrow(/does not appear to be a git repository|Could not read from remote repository/i);
} finally {
if (previousXdgDataHome === undefined) {
delete process.env.XDG_DATA_HOME;
} else {
process.env.XDG_DATA_HOME = previousXdgDataHome;
}
}
}, 30_000);
});