From 50778d6f462d73f03c3339b5587ef912a779a46d Mon Sep 17 00:00:00 2001 From: Christopher Dwyer-Perkins Date: Fri, 14 Feb 2025 14:23:04 -0400 Subject: [PATCH] Moved to thrown errors --- src/RokuECP.spec.ts | 71 +++++++--------------------- src/RokuECP.ts | 26 +++++----- src/debugSession/ecpRegistryUtils.ts | 9 ++-- 3 files changed, 33 insertions(+), 73 deletions(-) diff --git a/src/RokuECP.spec.ts b/src/RokuECP.spec.ts index 31b5a130..fba71d06 100644 --- a/src/RokuECP.spec.ts +++ b/src/RokuECP.spec.ts @@ -4,11 +4,12 @@ import { describe } from 'mocha'; import type { EcpAppStateData, EcpRegistryData } from './RokuECP'; import { AppState, EcpStatus, rokuECP } from './RokuECP'; import { util } from './util'; +import { expectThrowsAsync } from './testHelpers.spec'; const sinon = createSandbox(); -describe('RokuECP', () => { +describe.only('RokuECP', () => { beforeEach(() => { sinon.restore(); @@ -90,6 +91,7 @@ describe('RokuECP', () => { body: '', statusCode: 200 }); + sinon.stub(rokuECP as any, 'processRegistry').resolves({}); await rokuECP.getRegistry(options); expect(stub.getCall(0).args).to.eql(['query/registry/dev', options]); @@ -214,11 +216,7 @@ describe('RokuECP', () => { `, statusCode: 200 }; - let result = await rokuECP['processRegistry'](response as any); - expect(result).to.eql({ - status: EcpStatus.failed, - errorMessage: 'Plugin dev not found' - } as EcpRegistryData); + await expectThrowsAsync(() => rokuECP['processRegistry'](response as any), 'Plugin dev not found'); }); it('handles device not keyed', async () => { @@ -231,11 +229,7 @@ describe('RokuECP', () => { `, statusCode: 200 }; - let result = await rokuECP['processRegistry'](response as any); - expect(result).to.eql({ - status: EcpStatus.failed, - errorMessage: 'Device not keyed' - } as EcpRegistryData); + await expectThrowsAsync(() => rokuECP['processRegistry'](response as any), 'Device not keyed'); }); it('handles failed status with missing error', async () => { @@ -247,11 +241,7 @@ describe('RokuECP', () => { `, statusCode: 200 }; - let result = await rokuECP['processRegistry'](response as any); - expect(result).to.eql({ - status: EcpStatus.failed, - errorMessage: 'Unknown error' - } as EcpRegistryData); + await expectThrowsAsync(() => rokuECP['processRegistry'](response as any), 'Unknown error'); }); it('handles error response without xml', async () => { @@ -259,11 +249,7 @@ describe('RokuECP', () => { body: `ECP command not allowed in Limited mode.`, statusCode: 403 }; - let result = await rokuECP['processRegistry'](response as any); - expect(result).to.eql({ - status: EcpStatus.failed, - errorMessage: 'ECP command not allowed in Limited mode.' - } as EcpRegistryData); + await expectThrowsAsync(() => rokuECP['processRegistry'](response as any), 'ECP command not allowed in Limited mode.'); }); }); }); @@ -281,12 +267,14 @@ describe('RokuECP', () => { statusCode: 200 }); + sinon.stub(rokuECP as any, 'processAppState').resolves({}); + await rokuECP.getAppState(options); expect(stub.getCall(0).args).to.eql(['query/app-status/dev', options]); }); }); - describe('parseAppState', () => { + describe('processAppState', () => { describe('non-error responses', () => { it('handles ok response', async () => { let response = { @@ -377,11 +365,7 @@ describe('RokuECP', () => { `, statusCode: 200 }; - let result = await rokuECP['processAppState'](response as any); - expect(result).to.eql({ - status: EcpStatus.failed, - errorMessage: 'Unknown error' - } as EcpAppStateData); + await expectThrowsAsync(() => rokuECP['processAppState'](response as any), 'Unknown error'); }); it('handles failed status with populated error', async () => { @@ -394,11 +378,7 @@ describe('RokuECP', () => { `, statusCode: 200 }; - let result = await rokuECP['processAppState'](response as any); - expect(result).to.eql({ - status: EcpStatus.failed, - errorMessage: 'App not found' - } as EcpAppStateData); + await expectThrowsAsync(() => rokuECP['processAppState'](response as any), 'App not found'); }); it('handles error response without xml', async () => { @@ -406,11 +386,7 @@ describe('RokuECP', () => { body: `ECP command not allowed in Limited mode.`, statusCode: 403 }; - let result = await rokuECP['processAppState'](response as any); - expect(result).to.eql({ - status: EcpStatus.failed, - errorMessage: 'ECP command not allowed in Limited mode.' - } as EcpAppStateData); + await expectThrowsAsync(() => rokuECP['processAppState'](response as any), 'ECP command not allowed in Limited mode.'); }); }); }); @@ -427,13 +403,14 @@ describe('RokuECP', () => { body: '', statusCode: 200 }); + sinon.stub(rokuECP as any, 'processExitApp').resolves({}); await rokuECP.exitApp(options); expect(stub.getCall(0).args).to.eql(['exit-app/dev', options]); }); }); - describe('parseExitApp', () => { + describe('processExitApp', () => { describe('non-error responses', () => { it('handles ok response', async () => { let response = { @@ -462,11 +439,7 @@ describe('RokuECP', () => { `, statusCode: 200 }; - let result = await rokuECP['processExitApp'](response as any); - expect(result).to.eql({ - status: EcpStatus.failed, - errorMessage: 'Unknown error' - }); + await expectThrowsAsync(() => rokuECP['processExitApp'](response as any), 'Unknown error'); }); it('handles failed status with populated error', async () => { @@ -479,11 +452,7 @@ describe('RokuECP', () => { `, statusCode: 200 }; - let result = await rokuECP['processExitApp'](response as any); - expect(result).to.eql({ - status: EcpStatus.failed, - errorMessage: 'App not found' - }); + await expectThrowsAsync(() => rokuECP['processExitApp'](response as any), 'App not found'); }); it('handles error response without xml', async () => { @@ -491,11 +460,7 @@ describe('RokuECP', () => { body: `ECP command not allowed in Limited mode.`, statusCode: 403 }; - let result = await rokuECP['processExitApp'](response as any); - expect(result).to.eql({ - status: EcpStatus.failed, - errorMessage: 'ECP command not allowed in Limited mode.' - }); + await expectThrowsAsync(() => rokuECP['processExitApp'](response as any), 'ECP command not allowed in Limited mode.'); }); }); }); diff --git a/src/RokuECP.ts b/src/RokuECP.ts index 3bbb36f9..5d040881 100644 --- a/src/RokuECP.ts +++ b/src/RokuECP.ts @@ -12,25 +12,21 @@ export class RokuECP { return EcpStatus[response?.[rootKey]?.status?.[0]?.toLowerCase()] ?? EcpStatus.failed; } - private async parseResponse(response: Response, rootKey: string, callback: (parsed: any, status: EcpStatus) => R): Promise { + private async parseResponse(response: Response, rootKey: string, callback: (parsed: any, status: EcpStatus) => R): Promise { if (typeof response.body === 'string') { + let parsed: ParsedEcpRoot; try { - let parsed = await util.parseXml(response.body); - const status = this.getEcpStatus(parsed, rootKey); - if (status === EcpStatus.ok) { - return callback(parsed?.[rootKey], status); - } else { - return { - status: status, - errorMessage: parsed?.[rootKey]?.error?.[0] ?? 'Unknown error' - }; - } + parsed = await util.parseXml(response.body); } catch { //if the response is not xml, just return the body as-is - return { - status: EcpStatus.failed, - errorMessage: response.body ?? 'Unknown error' - }; + throw new Error(response.body ?? 'Unknown error'); + } + + const status = this.getEcpStatus(parsed, rootKey); + if (status === EcpStatus.ok) { + return callback(parsed?.[rootKey], status); + } else { + throw new Error(parsed?.[rootKey]?.error?.[0] ?? 'Unknown error'); } } } diff --git a/src/debugSession/ecpRegistryUtils.ts b/src/debugSession/ecpRegistryUtils.ts index 47d69612..e3f1f9a8 100644 --- a/src/debugSession/ecpRegistryUtils.ts +++ b/src/debugSession/ecpRegistryUtils.ts @@ -4,9 +4,8 @@ import type { RokuEcpParam } from '../RokuECP'; import type { AugmentedVariable } from './BrightScriptDebugSession'; export async function populateVariableFromRegistryEcp(options: RokuEcpParam<'getRegistry'>, v: AugmentedVariable, variables: Record, refIdFactory: (key: string, frameId: number) => number) { - let result = await rokuECP.getRegistry(options); - - if (result.status === EcpStatus.ok) { + try { + let registryData = await rokuECP.getRegistry(options); // Add registry data to variable list if (registryData.devId) { v.childVariables.push({ @@ -114,10 +113,10 @@ export async function populateVariableFromRegistryEcp(options: RokuEcpParam<'get return sectionItemVariable; })); } - } else { + } catch (e) { v.childVariables.push({ name: 'error', - value: `❌ Error: ${registryData.errorMessage ?? 'Unknown error'}`, + value: `❌ Error: ${e.message ?? 'Unknown error'}`, type: VariableType.String, variablesReference: 0, childVariables: []