mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-08-28 02:11:38 +00:00
153 lines
5 KiB
TypeScript
153 lines
5 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 Memory from '@/components/Settings/Memory';
|
|
import type { MemoryScopeState } from '@/service/memoryApi';
|
|
import { render, screen } from '@testing-library/react';
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const memoryApiMocks = vi.hoisted(() => ({
|
|
listMemoryEntries: vi.fn(),
|
|
listMemoryReconciliation: vi.fn(),
|
|
listMemoryScopeSummaries: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('@/service/memoryApi', () => ({
|
|
archiveMemoryEntry: vi.fn(),
|
|
confirmMemoryEntry: vi.fn(),
|
|
consolidateMemoryScope: vi.fn(),
|
|
createMemoryEntry: vi.fn(),
|
|
listMemoryEntries: memoryApiMocks.listMemoryEntries,
|
|
listMemoryReconciliation: memoryApiMocks.listMemoryReconciliation,
|
|
listMemoryScopeSummaries: memoryApiMocks.listMemoryScopeSummaries,
|
|
pinMemoryEntry: vi.fn(),
|
|
resolveMemoryReconciliation: vi.fn(),
|
|
restoreMemoryEntry: vi.fn(),
|
|
updateMemoryEntry: vi.fn(),
|
|
updateMemoryScopeSettings: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('@/store/authStore', () => ({
|
|
useAuthStore: (selector: (state: { user_id: number }) => unknown) =>
|
|
selector({ user_id: 7 }),
|
|
}));
|
|
|
|
vi.mock('@/store/projectStore', () => ({
|
|
useProjectStore: (
|
|
selector: (state: { activeProjectId: string }) => unknown
|
|
) => selector({ activeProjectId: 'project-active' }),
|
|
}));
|
|
|
|
vi.mock('@/store/spaceStore', () => ({
|
|
useSpaceStore: (selector: (state: { activeSpaceId: string }) => unknown) =>
|
|
selector({ activeSpaceId: 'space-active' }),
|
|
}));
|
|
|
|
function scopeState(
|
|
scopeType: 'space' | 'project',
|
|
captureEnabled: boolean
|
|
): MemoryScopeState {
|
|
return {
|
|
scope_type: scopeType,
|
|
scope_id: `${scopeType}-1`,
|
|
owner_kind: 'desktop',
|
|
revision: 1,
|
|
capture_enabled: captureEnabled,
|
|
use_enabled: true,
|
|
sync_scope: 'full_memory',
|
|
token_limit: 640,
|
|
current_token_count: 0,
|
|
consolidate_threshold: 0.75,
|
|
processed_through_watermark: null,
|
|
extractor_version: 'test',
|
|
last_consolidated_at: null,
|
|
last_error: null,
|
|
updated_at: 1,
|
|
};
|
|
}
|
|
|
|
describe('Memory settings layout', () => {
|
|
beforeEach(() => {
|
|
memoryApiMocks.listMemoryEntries.mockReset();
|
|
memoryApiMocks.listMemoryReconciliation.mockReset();
|
|
memoryApiMocks.listMemoryReconciliation.mockResolvedValue({ items: [] });
|
|
});
|
|
|
|
it('offers automatic extraction for the shared Space scope', async () => {
|
|
memoryApiMocks.listMemoryEntries.mockResolvedValue({
|
|
scope_state: scopeState('space', true),
|
|
items: [],
|
|
sync_status: {
|
|
state: 'synced',
|
|
pending_count: 0,
|
|
blocked_count: 0,
|
|
last_error: null,
|
|
last_synced_at: 1,
|
|
},
|
|
});
|
|
|
|
render(
|
|
<Memory
|
|
fixedScope={{ type: 'space', id: 'space-1' }}
|
|
showScopeSelector={false}
|
|
/>
|
|
);
|
|
|
|
expect(await screen.findByText('Shared across this Space')).toBeVisible();
|
|
expect(screen.getByText('Shared scope')).toBeVisible();
|
|
expect(
|
|
screen.getByText(/learn stable notes explicitly meant for this Space/)
|
|
).toBeVisible();
|
|
expect(screen.getByRole('switch', { name: 'Auto Memory' })).toBeChecked();
|
|
expect(
|
|
screen.getByRole('switch', { name: 'Use Space Memory' })
|
|
).toBeChecked();
|
|
expect(
|
|
screen.getByText('Up to date — no saved notes to sync yet')
|
|
).toBeVisible();
|
|
expect(screen.getByText('No shared Memory yet')).toBeVisible();
|
|
expect(screen.queryByLabelText('Search Memory')).not.toBeInTheDocument();
|
|
expect(screen.getByRole('button', { name: 'View archived' })).toBeVisible();
|
|
});
|
|
|
|
it('keeps Auto Memory available for Project scope', async () => {
|
|
memoryApiMocks.listMemoryEntries.mockResolvedValue({
|
|
scope_state: scopeState('project', true),
|
|
items: [],
|
|
sync_status: {
|
|
state: 'synced',
|
|
pending_count: 0,
|
|
blocked_count: 0,
|
|
last_error: null,
|
|
last_synced_at: 1,
|
|
},
|
|
});
|
|
|
|
render(
|
|
<Memory
|
|
fixedScope={{ type: 'project', id: 'project-1' }}
|
|
fixedScopeLabel="Launch plan"
|
|
showScopeSelector={false}
|
|
/>
|
|
);
|
|
|
|
expect(
|
|
await screen.findByText('Remembered for this Project')
|
|
).toBeVisible();
|
|
expect(screen.getByRole('switch', { name: 'Auto Memory' })).toBeChecked();
|
|
expect(screen.getByText('Launch plan Memory')).toBeVisible();
|
|
expect(screen.getByText('Saved Project Memory')).toBeVisible();
|
|
expect(screen.getByText('No Project Memory yet')).toBeVisible();
|
|
});
|
|
});
|