mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-08-26 00:52:07 +00:00
174 lines
4.7 KiB
TypeScript
174 lines
4.7 KiB
TypeScript
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
|
|
|
import { useWorkspaceSavePoint } from '@/hooks/useWorkspaceSavePoint';
|
|
import {
|
|
createWorkspaceSavePoint,
|
|
fetchWorkspaceGitStatus,
|
|
} from '@/service/workspaceGitApi';
|
|
import { act, renderHook } from '@testing-library/react';
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
vi.mock('@/service/workspaceGitApi', () => ({
|
|
fetchWorkspaceGitStatus: vi.fn(),
|
|
bootstrapWorkspaceGit: vi.fn(),
|
|
createWorkspaceSavePoint: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('react-i18next', () => ({
|
|
useTranslation: () => ({
|
|
t: (key: string, values?: Record<string, unknown>) =>
|
|
values ? `${key}:${JSON.stringify(values)}` : key,
|
|
}),
|
|
}));
|
|
|
|
vi.mock('sonner', () => ({
|
|
toast: {
|
|
success: vi.fn(),
|
|
error: vi.fn(),
|
|
info: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
const localSpace = {
|
|
id: 'space-1',
|
|
name: 'Local Space',
|
|
sourceType: 'folder',
|
|
rootPath: '/tmp/space-1',
|
|
status: 'active',
|
|
metadata: {},
|
|
createdAt: 1,
|
|
updatedAt: 1,
|
|
} as any;
|
|
|
|
const status = {
|
|
space_id: 'space-1',
|
|
enabled: true,
|
|
state: 'ready',
|
|
managed_paths: ['report.md'],
|
|
pending_managed_paths: ['report.md'],
|
|
pending_managed_paths_truncated: false,
|
|
diagnostics: {
|
|
healthy: true,
|
|
issues: [],
|
|
repo_state: {
|
|
head_oid: 'a'.repeat(40),
|
|
branch_or_detached_head: 'main',
|
|
index_digest: 'b'.repeat(64),
|
|
operation_state: 'clean',
|
|
digest: 'c'.repeat(64),
|
|
},
|
|
},
|
|
};
|
|
|
|
describe('useWorkspaceSavePoint', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
vi.mocked(fetchWorkspaceGitStatus).mockResolvedValue(status);
|
|
vi.mocked(createWorkspaceSavePoint).mockResolvedValue({
|
|
checkpoint_id: 'checkpoint_123',
|
|
repository_id: 'repo-1',
|
|
commit_oid: 'd'.repeat(40),
|
|
parent_oid: 'a'.repeat(40),
|
|
paths: ['report.md'],
|
|
remaining_managed_changes: false,
|
|
created_at: 1,
|
|
});
|
|
});
|
|
|
|
it('does not poll and loads status only on demand', async () => {
|
|
const { result } = renderHook(() =>
|
|
useWorkspaceSavePoint({
|
|
spaceId: 'space-1',
|
|
space: localSpace,
|
|
email: 'user@example.com',
|
|
userId: 7,
|
|
})
|
|
);
|
|
|
|
expect(fetchWorkspaceGitStatus).not.toHaveBeenCalled();
|
|
await act(async () => {
|
|
await result.current.loadStatus();
|
|
});
|
|
|
|
expect(fetchWorkspaceGitStatus).toHaveBeenCalledTimes(1);
|
|
expect(result.current.status?.pending_managed_paths).toEqual(['report.md']);
|
|
});
|
|
|
|
it('creates a save point from a freshly read RepoStateToken', async () => {
|
|
const { result } = renderHook(() =>
|
|
useWorkspaceSavePoint({
|
|
spaceId: 'space-1',
|
|
space: localSpace,
|
|
email: 'user@example.com',
|
|
userId: 7,
|
|
})
|
|
);
|
|
|
|
await act(async () => {
|
|
await result.current.save();
|
|
});
|
|
|
|
expect(createWorkspaceSavePoint).toHaveBeenCalledTimes(1);
|
|
expect(createWorkspaceSavePoint).toHaveBeenCalledWith(
|
|
'space-1',
|
|
{ email: 'user@example.com', userId: 7 },
|
|
expect.objectContaining({
|
|
expectedRepoStateDigest: 'c'.repeat(64),
|
|
actorId: '7',
|
|
})
|
|
);
|
|
expect(fetchWorkspaceGitStatus).toHaveBeenCalledTimes(2);
|
|
});
|
|
|
|
it('registers one global shortcut and ignores editable targets', async () => {
|
|
renderHook(() =>
|
|
useWorkspaceSavePoint({
|
|
spaceId: 'space-1',
|
|
space: localSpace,
|
|
email: 'user@example.com',
|
|
userId: 7,
|
|
shortcut: true,
|
|
})
|
|
);
|
|
const input = document.createElement('input');
|
|
document.body.appendChild(input);
|
|
|
|
await act(async () => {
|
|
input.dispatchEvent(
|
|
new KeyboardEvent('keydown', {
|
|
key: 's',
|
|
metaKey: true,
|
|
bubbles: true,
|
|
})
|
|
);
|
|
await Promise.resolve();
|
|
});
|
|
expect(fetchWorkspaceGitStatus).not.toHaveBeenCalled();
|
|
|
|
await act(async () => {
|
|
document.body.dispatchEvent(
|
|
new KeyboardEvent('keydown', {
|
|
key: 's',
|
|
metaKey: true,
|
|
bubbles: true,
|
|
})
|
|
);
|
|
await vi.waitFor(() => {
|
|
expect(createWorkspaceSavePoint).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
input.remove();
|
|
});
|
|
});
|