amaran-light-cli
Version:
Command line tool for controlling Aputure Amaran lights via WebSocket to a local Amaran desktop app.
108 lines • 4.3 kB
JavaScript
import { Command } from 'commander';
import { vi } from 'vitest';
import registerCommands from '../commands.js';
vi.mock('../daylightSimulation/geoipUtil', () => ({
getLocationFromIP: vi.fn(() => ({ ll: [37.7749, -122.4194] })),
}));
vi.mock('../daylightSimulation/cctUtil', () => ({
calculateCCT: vi.fn(() => ({ cct: 5600, intensity: 500 })),
parseCurveType: vi.fn(() => 'HANN'),
CurveType: {
HANN: 'hann',
WIDER_MIDDLE_SMALL: 'wider-middle-small',
WIDER_MIDDLE_MEDIUM: 'wider-middle-medium',
WIDER_MIDDLE_LARGE: 'wider-middle-large',
CIE_DAYLIGHT: 'cie-daylight',
SUN_ALTITUDE: 'sun-altitude',
PEREZ_DAYLIGHT: 'perez-daylight',
},
}));
describe('auto-cct command', () => {
const originalFetch = global.fetch;
const mockFetch = vi.fn();
beforeAll(() => {
mockFetch.mockImplementation(async () => ({
json: async () => ({ ip: '1.2.3.4' }),
}));
global.fetch = mockFetch;
});
afterEach(() => {
mockFetch.mockClear();
});
afterAll(() => {
global.fetch = originalFetch;
});
test('skips sleeping lights when running auto-cct', async () => {
const setCCT = vi.fn((_, _cct, _intensity, cb) => {
cb?.(true, 'ok');
});
const disconnect = vi.fn(async () => Promise.resolve());
const sleepState = {
'400J5-F2C008': false,
'400J5-F2C009': true,
};
const controllerStub = {
getDevices: vi.fn(() => [
{ node_id: '400J5-F2C008', device_name: 'On Light' },
{ node_id: '400J5-F2C009', device_name: 'Off Light' },
]),
getLightSleepStatus: vi.fn((nodeId, cb) => {
setImmediate(() => cb(true, 'ok', { sleep: sleepState[nodeId] }));
}),
setCCT,
disconnect,
};
const deps = {
createController: async () => controllerStub,
findDevice: (_controller, _deviceQuery) => null,
asyncCommand: (fn) => (...args) => fn(...args),
loadConfig: () => ({}),
saveWsUrl: undefined,
};
const program = new Command();
program.exitOverride();
registerCommands(program, deps);
await program.parseAsync(['node', 'test', 'auto-cct']);
expect(setCCT).toHaveBeenCalledTimes(1);
// auto-cct should pass through calculateCCT result
expect(setCCT).toHaveBeenCalledWith('400J5-F2C008', 5600, 500, expect.any(Function));
expect(disconnect).toHaveBeenCalledTimes(1);
});
test('targets specific device when argument is provided', async () => {
const setCCT = vi.fn((_, _cct, _intensity, cb) => {
cb?.(true, 'ok');
});
const disconnect = vi.fn(async () => Promise.resolve());
const targetDevice = { node_id: '400J5-F2C008', device_name: 'Target Light' };
const otherDevice = { node_id: '400J5-F2C009', device_name: 'Other Light' };
const controllerStub = {
getDevices: vi.fn(() => [targetDevice, otherDevice]),
getLightSleepStatus: vi.fn((_nodeId, cb) => {
setImmediate(() => cb(true, 'ok', { sleep: false }));
}),
setCCT,
disconnect,
};
const findDeviceMock = vi.fn((_controller, query) => {
if (query === 'Target')
return targetDevice;
return null;
});
const deps = {
createController: async () => controllerStub,
findDevice: findDeviceMock,
asyncCommand: (fn) => (...args) => fn(...args),
loadConfig: () => ({}),
saveWsUrl: undefined,
};
const program = new Command();
program.exitOverride();
registerCommands(program, deps);
await program.parseAsync(['node', 'test', 'auto-cct', 'Target']);
expect(findDeviceMock).toHaveBeenCalledWith(controllerStub, 'Target');
expect(setCCT).toHaveBeenCalledTimes(1);
expect(setCCT).toHaveBeenCalledWith('400J5-F2C008', 5600, 500, expect.any(Function));
expect(disconnect).toHaveBeenCalledTimes(1);
});
});
//# sourceMappingURL=autoCct.test.js.map