Initialize smartkvm package
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||
import { SmartBrowserKvm } from '../ts/smartkvm.classes.browserkvm.js';
|
||||
|
||||
tap.test('SmartBrowserKvm manual smoke test', async () => {
|
||||
if (!process.env.SMARTKVM_TEST_URL) {
|
||||
expect(true).toBeTrue();
|
||||
return;
|
||||
}
|
||||
|
||||
const kvm = new SmartBrowserKvm({
|
||||
url: process.env.SMARTKVM_TEST_URL,
|
||||
username: process.env.SMARTKVM_TEST_USERNAME,
|
||||
password: process.env.SMARTKVM_TEST_PASSWORD,
|
||||
headless: process.env.SMARTKVM_TEST_HEADLESS !== 'false',
|
||||
ignoreHttpsErrors: true,
|
||||
timeoutMs: 30000,
|
||||
});
|
||||
|
||||
try {
|
||||
await kvm.connect();
|
||||
const frame = await kvm.captureFrame();
|
||||
expect(frame.mimeType).toEqual('image/png');
|
||||
expect(frame.dataBase64).toBeTypeofString();
|
||||
} finally {
|
||||
await kvm.disconnect();
|
||||
}
|
||||
});
|
||||
|
||||
export default tap.start();
|
||||
@@ -0,0 +1,59 @@
|
||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||
import {
|
||||
createWrappedKvmCommand,
|
||||
parseWrappedKvmCommandOutput,
|
||||
} from '../ts/smartkvm.commandwrappers.js';
|
||||
|
||||
tap.test('bash wrapper should contain OCR-friendly markers', async () => {
|
||||
const wrappedCommand = createWrappedKvmCommand('echo hello', 'bash');
|
||||
expect(wrappedCommand.commandId).toMatch(/^[a-f0-9]{32}$/);
|
||||
expect(wrappedCommand.startMarker).toEqual(`SMARTKVM_START_${wrappedCommand.commandId}`);
|
||||
expect(wrappedCommand.endMarkerPrefix).toEqual(`SMARTKVM_END_${wrappedCommand.commandId}_`);
|
||||
expect(wrappedCommand.textToType).toInclude(wrappedCommand.startMarker);
|
||||
expect(wrappedCommand.textToType).toInclude(wrappedCommand.endMarkerPrefix);
|
||||
expect(wrappedCommand.textToType).toInclude('echo hello');
|
||||
});
|
||||
|
||||
tap.test('powershell wrapper should contain valid markers', async () => {
|
||||
const wrappedCommand = createWrappedKvmCommand('Get-Location', 'powershell');
|
||||
expect(wrappedCommand.textToType).toInclude(wrappedCommand.startMarker);
|
||||
expect(wrappedCommand.textToType).toInclude(wrappedCommand.endMarkerPrefix);
|
||||
expect(wrappedCommand.textToType).toInclude('try { Get-Location;');
|
||||
});
|
||||
|
||||
tap.test('cmd wrapper should contain valid markers', async () => {
|
||||
const wrappedCommand = createWrappedKvmCommand('dir', 'cmd');
|
||||
expect(wrappedCommand.textToType).toInclude(`echo ${wrappedCommand.startMarker}`);
|
||||
expect(wrappedCommand.textToType).toInclude(`echo ${wrappedCommand.endMarkerPrefix}%ERRORLEVEL%`);
|
||||
});
|
||||
|
||||
tap.test('parser should extract command output and exit code', async () => {
|
||||
const parsedResult = parseWrappedKvmCommandOutput({
|
||||
commandId: 'abc123',
|
||||
startMarker: 'SMARTKVM_START_abc123',
|
||||
endMarkerPrefix: 'SMARTKVM_END_abc123_',
|
||||
rawText: `something before
|
||||
SMARTKVM_START_abc123
|
||||
hello world
|
||||
SMARTKVM_END_abc123_0
|
||||
prompt after`,
|
||||
});
|
||||
|
||||
expect(parsedResult.completed).toBeTrue();
|
||||
expect(parsedResult.exitCode).toEqual(0);
|
||||
expect(parsedResult.combinedText).toEqual('hello world');
|
||||
});
|
||||
|
||||
tap.test('parser should return incomplete result if markers are missing', async () => {
|
||||
const parsedResult = parseWrappedKvmCommandOutput({
|
||||
commandId: 'abc123',
|
||||
startMarker: 'SMARTKVM_START_abc123',
|
||||
endMarkerPrefix: 'SMARTKVM_END_abc123_',
|
||||
rawText: 'hello world',
|
||||
});
|
||||
|
||||
expect(parsedResult.completed).toBeFalse();
|
||||
expect(parsedResult.combinedText).toEqual('hello world');
|
||||
});
|
||||
|
||||
export default tap.start();
|
||||
@@ -0,0 +1,109 @@
|
||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||
import { SmartKvmTerminal } from '../ts/smartkvm.classes.kvmterminal.js';
|
||||
import type {
|
||||
IKvmDriver,
|
||||
IKvmFrame,
|
||||
IOcrEngine,
|
||||
IOcrRecognizeOptions,
|
||||
TKvmKey,
|
||||
TKvmKind,
|
||||
} from '../ts/smartkvm.interfaces.js';
|
||||
|
||||
class MockKvmDriver implements IKvmDriver {
|
||||
public readonly kind: TKvmKind = 'generic';
|
||||
public typedTexts: string[] = [];
|
||||
public pressedKeys: TKvmKey[] = [];
|
||||
public pressedShortcuts: TKvmKey[][] = [];
|
||||
public focusViewerCalls = 0;
|
||||
|
||||
public async connect(): Promise<void> {}
|
||||
|
||||
public async disconnect(): Promise<void> {}
|
||||
|
||||
public async focusViewer(): Promise<void> {
|
||||
this.focusViewerCalls++;
|
||||
}
|
||||
|
||||
public async captureFrame(): Promise<IKvmFrame> {
|
||||
return {
|
||||
timestamp: Date.now(),
|
||||
width: 1,
|
||||
height: 1,
|
||||
mimeType: 'image/png',
|
||||
dataBase64: 'iVBORw0KGgo=',
|
||||
};
|
||||
}
|
||||
|
||||
public async typeText(text: string): Promise<void> {
|
||||
this.typedTexts.push(text);
|
||||
}
|
||||
|
||||
public async pressKey(key: TKvmKey): Promise<void> {
|
||||
this.pressedKeys.push(key);
|
||||
}
|
||||
|
||||
public async pressShortcut(keys: TKvmKey[]): Promise<void> {
|
||||
this.pressedShortcuts.push(keys);
|
||||
}
|
||||
|
||||
public async wait(): Promise<void> {}
|
||||
}
|
||||
|
||||
tap.test('SmartKvmTerminal should run wrapped commands through mock KVM and OCR', async () => {
|
||||
const mockKvm = new MockKvmDriver();
|
||||
let recognizeCalls = 0;
|
||||
|
||||
const mockOcrEngine: IOcrEngine = {
|
||||
recognize: async (_frame: IKvmFrame, options?: IOcrRecognizeOptions) => {
|
||||
recognizeCalls++;
|
||||
expect(options?.language).toEqual('eng');
|
||||
const typedText = mockKvm.typedTexts.join('\n');
|
||||
const commandId = typedText.match(/SMARTKVM_START_([a-f0-9]+)/)?.[1] ?? 'missing';
|
||||
if (recognizeCalls === 1) {
|
||||
return {
|
||||
text: `SMARTKVM_START_${commandId}\npartial output`,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
text: `prompt\nSMARTKVM_START_${commandId}\nhello terminal\nSMARTKVM_END_${commandId}_0\nprompt`,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
const terminal = new SmartKvmTerminal({
|
||||
kvm: mockKvm,
|
||||
ocrEngine: mockOcrEngine,
|
||||
shellHint: 'bash',
|
||||
commandTimeoutMs: 2000,
|
||||
ocrPollIntervalMs: 1,
|
||||
});
|
||||
|
||||
const result = await terminal.runCommand('echo hello');
|
||||
|
||||
expect(mockKvm.focusViewerCalls).toBeGreaterThan(0);
|
||||
expect(mockKvm.typedTexts[0]).toInclude('echo hello');
|
||||
expect(mockKvm.typedTexts[0]).toInclude('SMARTKVM_START_');
|
||||
expect(mockKvm.pressedKeys).toContain('Enter');
|
||||
expect(recognizeCalls).toEqual(2);
|
||||
expect(result.completed).toBeTrue();
|
||||
expect(result.timedOut).toBeFalse();
|
||||
expect(result.exitCode).toEqual(0);
|
||||
expect(result.combinedText).toEqual('hello terminal');
|
||||
});
|
||||
|
||||
tap.test('SmartKvmTerminal bootstrap should use generic Linux shortcut', async () => {
|
||||
const mockKvm = new MockKvmDriver();
|
||||
const terminal = new SmartKvmTerminal({
|
||||
kvm: mockKvm,
|
||||
ocrEngine: {
|
||||
recognize: async () => ({ text: '' }),
|
||||
},
|
||||
osHint: 'linux',
|
||||
});
|
||||
|
||||
await terminal.bootstrap();
|
||||
expect(mockKvm.pressedShortcuts).toEqual([['Control', 'Alt', 'T']]);
|
||||
});
|
||||
|
||||
export default tap.start();
|
||||
Reference in New Issue
Block a user