initial transfer
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
/**
|
||||
* Tests for nopy.history module
|
||||
*/
|
||||
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
import {
|
||||
HISTORY_FILE,
|
||||
type HistoryEntry,
|
||||
type SessionHistory,
|
||||
addToHistory,
|
||||
clearHistory,
|
||||
formatHistoryList,
|
||||
getLastSession,
|
||||
getSessionById,
|
||||
listHistory,
|
||||
loadHistory,
|
||||
removeFromHistory,
|
||||
saveHistory,
|
||||
} from '../src/nopy.history.js';
|
||||
import type { NopySession } from '../src/nopy.session.js';
|
||||
|
||||
describe('Session History', () => {
|
||||
let originalCwd: string;
|
||||
let tempDir: string;
|
||||
|
||||
beforeEach(() => {
|
||||
originalCwd = process.cwd();
|
||||
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nopy-history-test-'));
|
||||
process.chdir(tempDir);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.chdir(originalCwd);
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
const createTestSession = (cubes: string[] = ['test-cube']): NopySession => ({
|
||||
cubes: cubes.map((key) => ({ key, variables: {} })),
|
||||
hosts: ['@docker/test'],
|
||||
auth: { method: 'ssh-key' },
|
||||
});
|
||||
|
||||
describe('loadHistory', () => {
|
||||
it('returns empty history when file does not exist', () => {
|
||||
const history = loadHistory();
|
||||
expect(history.entries).toEqual([]);
|
||||
});
|
||||
|
||||
it('loads existing history file', () => {
|
||||
const testHistory: SessionHistory = {
|
||||
entries: [
|
||||
{
|
||||
id: 'test-id',
|
||||
name: 'Test Session',
|
||||
timestamp: new Date().toISOString(),
|
||||
session: createTestSession(),
|
||||
},
|
||||
],
|
||||
};
|
||||
fs.writeFileSync(HISTORY_FILE, JSON.stringify(testHistory));
|
||||
|
||||
const history = loadHistory();
|
||||
expect(history.entries).toHaveLength(1);
|
||||
expect(history.entries[0].id).toBe('test-id');
|
||||
});
|
||||
|
||||
it('returns empty history on invalid JSON', () => {
|
||||
fs.writeFileSync(HISTORY_FILE, 'invalid json');
|
||||
const history = loadHistory();
|
||||
expect(history.entries).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('saveHistory', () => {
|
||||
it('creates history file', () => {
|
||||
const history: SessionHistory = {
|
||||
entries: [
|
||||
{
|
||||
id: 'test-id',
|
||||
name: 'Test',
|
||||
timestamp: new Date().toISOString(),
|
||||
session: createTestSession(),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
saveHistory(history);
|
||||
|
||||
expect(fs.existsSync(HISTORY_FILE)).toBe(true);
|
||||
const content = JSON.parse(fs.readFileSync(HISTORY_FILE, 'utf-8'));
|
||||
expect(content.entries).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('addToHistory', () => {
|
||||
it('adds session to empty history', () => {
|
||||
const session = createTestSession(['apt:essentials']);
|
||||
const entry = addToHistory(session);
|
||||
|
||||
expect(entry.id).toBeDefined();
|
||||
expect(entry.session).toBe(session);
|
||||
|
||||
const history = loadHistory();
|
||||
expect(history.entries).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('adds newest entries first', () => {
|
||||
addToHistory(createTestSession(['first']));
|
||||
addToHistory(createTestSession(['second']));
|
||||
|
||||
const history = loadHistory();
|
||||
expect(history.entries[0].session.cubes[0].key).toBe('second');
|
||||
expect(history.entries[1].session.cubes[0].key).toBe('first');
|
||||
});
|
||||
|
||||
it('respects max entries limit', () => {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
addToHistory(createTestSession([`cube-${i}`]), 3);
|
||||
}
|
||||
|
||||
const history = loadHistory();
|
||||
expect(history.entries).toHaveLength(3);
|
||||
// Should have newest entries
|
||||
expect(history.entries[0].session.cubes[0].key).toBe('cube-4');
|
||||
expect(history.entries[1].session.cubes[0].key).toBe('cube-3');
|
||||
expect(history.entries[2].session.cubes[0].key).toBe('cube-2');
|
||||
});
|
||||
|
||||
it('generates descriptive name', () => {
|
||||
const session = createTestSession(['apt:essentials', 'runtime:docker']);
|
||||
const entry = addToHistory(session);
|
||||
|
||||
expect(entry.name).toContain('apt:essentials');
|
||||
expect(entry.name).toContain('runtime:docker');
|
||||
expect(entry.name).toContain('@docker/test');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getLastSession', () => {
|
||||
it('returns undefined for empty history', () => {
|
||||
expect(getLastSession()).toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns most recent session', () => {
|
||||
addToHistory(createTestSession(['first']));
|
||||
addToHistory(createTestSession(['second']));
|
||||
|
||||
const last = getLastSession();
|
||||
expect(last?.session.cubes[0].key).toBe('second');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSessionById', () => {
|
||||
it('returns undefined for non-existent ID', () => {
|
||||
expect(getSessionById('non-existent')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('finds session by ID', () => {
|
||||
const entry = addToHistory(createTestSession(['test']));
|
||||
|
||||
const found = getSessionById(entry.id);
|
||||
expect(found?.id).toBe(entry.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('listHistory', () => {
|
||||
it('returns empty array for no history', () => {
|
||||
expect(listHistory()).toEqual([]);
|
||||
});
|
||||
|
||||
it('returns all entries', () => {
|
||||
addToHistory(createTestSession(['a']));
|
||||
addToHistory(createTestSession(['b']));
|
||||
addToHistory(createTestSession(['c']));
|
||||
|
||||
expect(listHistory()).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('clearHistory', () => {
|
||||
it('removes all entries', () => {
|
||||
addToHistory(createTestSession(['a']));
|
||||
addToHistory(createTestSession(['b']));
|
||||
|
||||
clearHistory();
|
||||
|
||||
expect(listHistory()).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeFromHistory', () => {
|
||||
it('returns false for non-existent ID', () => {
|
||||
expect(removeFromHistory('non-existent')).toBe(false);
|
||||
});
|
||||
|
||||
it('removes specific entry', () => {
|
||||
const entry1 = addToHistory(createTestSession(['a']));
|
||||
const entry2 = addToHistory(createTestSession(['b']));
|
||||
|
||||
const removed = removeFromHistory(entry1.id);
|
||||
|
||||
expect(removed).toBe(true);
|
||||
expect(listHistory()).toHaveLength(1);
|
||||
expect(getSessionById(entry1.id)).toBeUndefined();
|
||||
expect(getSessionById(entry2.id)).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatHistoryList', () => {
|
||||
it('shows message for empty history', () => {
|
||||
const output = formatHistoryList([]);
|
||||
expect(output).toContain('No sessions');
|
||||
});
|
||||
|
||||
it('formats entries with numbers and IDs', () => {
|
||||
const entries: HistoryEntry[] = [
|
||||
{
|
||||
id: 'abc123',
|
||||
name: 'Test Session',
|
||||
timestamp: new Date().toISOString(),
|
||||
session: createTestSession(),
|
||||
},
|
||||
];
|
||||
|
||||
const output = formatHistoryList(entries);
|
||||
expect(output).toContain('[1]');
|
||||
expect(output).toContain('Test Session');
|
||||
expect(output).toContain('abc123');
|
||||
expect(output).toContain('Total: 1');
|
||||
});
|
||||
|
||||
it('marks first entry with arrow', () => {
|
||||
const entries: HistoryEntry[] = [
|
||||
{
|
||||
id: 'first',
|
||||
name: 'First',
|
||||
timestamp: new Date().toISOString(),
|
||||
session: createTestSession(),
|
||||
},
|
||||
{
|
||||
id: 'second',
|
||||
name: 'Second',
|
||||
timestamp: new Date().toISOString(),
|
||||
session: createTestSession(),
|
||||
},
|
||||
];
|
||||
|
||||
const output = formatHistoryList(entries);
|
||||
expect(output).toContain('→ [1]');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user