79 lines
4.9 KiB
TypeScript
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();
|