Files
integrations/test/frontier_silicon/test.frontier_silicon.client.node.ts
T

79 lines
4.9 KiB
TypeScript

import { expect, tap } from '@git.zone/tstest/tapbundle';
import { FrontierSiliconClient, FrontierSiliconMapper } from '../../ts/integrations/frontier_silicon/index.js';
const valueResponse = (tagArg: 'c8_array' | 'u8' | 'u32' | 's32', valueArg: string | number): string => `<fsapiResponse><status>FS_OK</status><value><${tagArg}>${valueArg}</${tagArg}></value></fsapiResponse>`;
const okResponse = '<fsapiResponse><status>FS_OK</status></fsapiResponse>';
const listResponse = (itemsArg: string): string => `<fsapiResponse><status>FS_OK</status>${itemsArg}<listend>1</listend></fsapiResponse>`;
const field = (nameArg: string, tagArg: 'c8_array' | 'u8', valueArg: string | number): string => `<field name="${nameArg}"><${tagArg}>${valueArg}</${tagArg}></field>`;
const item = (keyArg: string, fieldsArg: string): string => `<item key="${keyArg}">${fieldsArg}</item>`;
tap.test('reads local FSAPI snapshot and maps entities', async () => {
const originalFetch = globalThis.fetch;
const requests: URL[] = [];
const responses: Record<string, string> = {
'GET/netRemote.sys.info.friendlyName': valueResponse('c8_array', 'Kitchen Radio'),
'GET/netRemote.sys.info.radioId': valueResponse('c8_array', 'radio-uuid'),
'GET/netRemote.sys.info.version': valueResponse('c8_array', 'ir-mmi-FS2026'),
'GET/netRemote.sys.power': valueResponse('u8', 1),
'GET/netRemote.sys.mode': valueResponse('u32', 0),
'GET/netRemote.sys.caps.volumeSteps': valueResponse('u8', 41),
'GET/netRemote.sys.net.wlan.interfaceEnable': valueResponse('u8', 1),
'GET/netRemote.sys.net.wlan.macAddress': valueResponse('c8_array', '00:11:22:33:44:55'),
'GET/netRemote.sys.net.wlan.rssi': valueResponse('u8', 75),
'GET/netRemote.play.status': valueResponse('u8', 2),
'GET/netRemote.sys.audio.volume': valueResponse('u8', 20),
'GET/netRemote.sys.audio.mute': valueResponse('u8', 0),
'GET/netRemote.play.info.name': valueResponse('c8_array', 'BBC 6 Music'),
'GET/netRemote.play.info.text': valueResponse('c8_array', 'Example Show'),
'GET/netRemote.play.info.artist': valueResponse('c8_array', 'Example Artist'),
'GET/netRemote.play.info.album': valueResponse('c8_array', 'Example Album'),
'GET/netRemote.play.info.graphicUri': valueResponse('c8_array', 'http://radio.example/cover.jpg'),
'GET/netRemote.play.info.duration': valueResponse('u32', 180000),
'GET/netRemote.play.position': valueResponse('u32', 30000),
'GET/netRemote.play.repeat': valueResponse('u8', 1),
'GET/netRemote.play.shuffle': valueResponse('u8', 0),
'GET/netRemote.sys.audio.eqpreset': valueResponse('u8', 1),
'LIST_GET_NEXT/netRemote.sys.caps.validModes/-1': listResponse(item('0', field('id', 'c8_array', 'ir') + field('label', 'c8_array', 'Internet Radio')) + item('1', field('id', 'c8_array', 'fm') + field('label', 'c8_array', 'FM'))),
'LIST_GET_NEXT/netRemote.sys.caps.eqPresets/-1': listResponse(item('0', field('label', 'c8_array', 'Flat')) + item('1', field('label', 'c8_array', 'Rock'))),
'LIST_GET_NEXT/netRemote.nav.presets/-1': listResponse(item('0', field('name', 'c8_array', 'BBC 6 Music') + field('type', 'u8', 1))),
'SET/netRemote.sys.power': okResponse,
};
globalThis.fetch = (async (urlArg: URL | RequestInfo, initArg?: RequestInit) => {
void initArg;
const url = new URL(String(urlArg));
requests.push(url);
const path = url.pathname.replace(/^\/fsapi\//, '');
return new Response(responses[path] || '<fsapiResponse><status>FS_NODE_DOES_NOT_EXIST</status></fsapiResponse>', { status: 200 });
}) as typeof globalThis.fetch;
try {
const client = new FrontierSiliconClient({ webfsapiUrl: 'http://radio.local/fsapi', pin: '1234' });
const snapshot = await client.getSnapshot();
expect(snapshot.online).toBeTrue();
expect(snapshot.device.name).toEqual('Kitchen Radio');
expect(snapshot.device.radioId).toEqual('radio-uuid');
expect(snapshot.player.playState).toEqual('playing');
expect(snapshot.player.volume).toEqual(20);
expect(snapshot.player.maxVolume).toEqual(40);
expect(snapshot.player.source).toEqual('Internet Radio');
expect(snapshot.player.soundMode?.label).toEqual('Rock');
expect(snapshot.presets[0].name).toEqual('BBC 6 Music');
const entities = FrontierSiliconMapper.toEntities(snapshot);
const mediaPlayer = entities.find((entityArg) => entityArg.id === 'media_player.kitchen_radio');
expect(mediaPlayer?.state).toEqual('playing');
expect(mediaPlayer?.attributes?.volumeLevel).toEqual(0.5);
expect(mediaPlayer?.attributes?.mediaDuration).toEqual(180);
expect(mediaPlayer?.attributes?.mediaPosition).toEqual(30);
await client.execute({ command: 'set_power', powered: false });
const setPower = requests.find((requestArg) => requestArg.pathname.endsWith('/SET/netRemote.sys.power'));
expect(setPower?.searchParams.get('value')).toEqual('0');
} finally {
globalThis.fetch = originalFetch;
}
});
export default tap.start();