0
0
Fork 0
Codesys-MCP-SP21-plus/tests/unit/live-values-write.test.ts
Karstein Phobic Nyvold Kvistad c565888ff5 feat(live-values): atomic writer for tui-live-values.json
Task 5 of v0.3 plan.

writeLiveValues(filePath, projectDir, payload) wraps the caller's
{device, pou_name, values} in the v1 envelope (version, updated_at,
project_dir) and writes atomically via <file>.<pid>.tmp + rename.
Creates parent dirs as needed.

Mirrors src/tui/shared/state-write.ts. Kept separate because the
TUI subpackage is ESM and the server is CJS; the duplication is
~15 lines of code that almost never changes.
2026-04-29 09:50:54 +02:00

48 lines
1.6 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import * as fs from 'fs/promises';
import * as path from 'path';
import * as os from 'os';
import { writeLiveValues } from '../../src/live-values-write';
async function tmpDir(): Promise<string> {
return fs.mkdtemp(path.join(os.tmpdir(), 'phobics-lvw-'));
}
const sample = {
device: 'D1',
pou_name: 'PLC_PRG',
values: {
counter: { value: '47', type: 'INT', ts: Date.now() },
},
};
describe('writeLiveValues', () => {
it('writes the v1 envelope with required fields', async () => {
const dir = await tmpDir();
const target = path.join(dir, 'tui-live-values.json');
await writeLiveValues(target, '/abs/project', sample);
const parsed = JSON.parse(await fs.readFile(target, 'utf8'));
expect(parsed.version).toBe(1);
expect(parsed.project_dir).toBe('/abs/project');
expect(parsed.device).toBe('D1');
expect(parsed.pou_name).toBe('PLC_PRG');
expect(parsed.values.counter.value).toBe('47');
expect(typeof parsed.updated_at).toBe('string');
});
it('creates parent dirs as needed', async () => {
const dir = await tmpDir();
const target = path.join(dir, 'a', 'b', 'tui-live-values.json');
await writeLiveValues(target, '/abs/project', sample);
expect((await fs.stat(target)).isFile()).toBe(true);
});
it('does not leave .tmp residue on success', async () => {
const dir = await tmpDir();
const target = path.join(dir, 'tui-live-values.json');
await writeLiveValues(target, '/abs/project', sample);
const entries = await fs.readdir(dir);
expect(entries.filter((e) => e.endsWith('.tmp'))).toEqual([]);
});
});