diff --git a/package-lock.json b/package-lock.json index 5aa6bf4a8..62639a332 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,7 +37,7 @@ }, "../firebolt-openrpc": { "name": "@firebolt-js/openrpc", - "version": "2.3.0-next.1", + "version": "3.0.0-next.1", "dev": true, "license": "Apache-2.0", "dependencies": { diff --git a/src/sdks/core/package.json b/src/sdks/core/package.json index 16a8bd6de..62b9e2f77 100644 --- a/src/sdks/core/package.json +++ b/src/sdks/core/package.json @@ -10,7 +10,7 @@ "type": "module", "scripts": { "validate": "npx firebolt-openrpc validate --input ./dist/firebolt-core-open-rpc.json", - "sdk": "npx firebolt-openrpc sdk --input ./dist/firebolt-core-open-rpc.json --template ./src/js --output ./build/javascript/src --static-module Platform", + "sdk": "npx firebolt-openrpc sdk --input ./dist/firebolt-core-open-rpc.json --template ./src/js --output ./build/javascript/src", "native": "npx firebolt-openrpc sdk --input ./dist/firebolt-core-open-rpc.json --template ./src/cpp --output ./build/c/src --static-module Platform --language ../../../node_modules/@firebolt-js/openrpc/languages/c", "compile": "cd ../../.. && npm run compile", "slice": "npx firebolt-openrpc slice -i ../../../dist/firebolt-open-rpc.json --sdk ./sdk.config.json -o ./dist/firebolt-core-open-rpc.json", diff --git a/src/sdks/core/src/js/sdk/Device/index.mjs b/src/sdks/core/src/js/sdk/Device/index.mjs index 86f9fb39a..8d832eb2e 100644 --- a/src/sdks/core/src/js/sdk/Device/index.mjs +++ b/src/sdks/core/src/js/sdk/Device/index.mjs @@ -22,7 +22,7 @@ function version() { return new Promise( (resolve, reject) => { - Transport.send('device', 'version').then( v => { + Gateway.request('Device.version').then( v => { v = v || {} v.sdk = v.sdk || {} v.sdk.major = parseInt('${major}') diff --git a/src/sdks/core/src/js/sdk/Lifecycle/index.mjs b/src/sdks/core/src/js/sdk/Lifecycle/index.mjs index e0184ff91..1aaccd433 100644 --- a/src/sdks/core/src/js/sdk/Lifecycle/index.mjs +++ b/src/sdks/core/src/js/sdk/Lifecycle/index.mjs @@ -31,10 +31,10 @@ export const store = { async function ready() { let readyRes; - await prioritize('Lifecycle', (event, value) => { + prioritize('Lifecycle', (event, value) => { store._current = event }) - readyRes =await Transport.send('lifecycle', 'ready', {}) + readyRes = await Gateway.request('Lifecycle.ready', {}) setTimeout(_ => { logReady() }) @@ -49,7 +49,7 @@ function state() { function finished() { if (store.current === 'unloading') { - return Transport.send('lifecycle', 'finished') + return Gateway.request('Lifecycle.finished') } else { throw 'Cannot call finished() except when in the unloading transition' } diff --git a/src/sdks/core/src/js/sdk/Metrics/index.mjs b/src/sdks/core/src/js/sdk/Metrics/index.mjs index 630914358..b4955cca3 100644 --- a/src/sdks/core/src/js/sdk/Metrics/index.mjs +++ b/src/sdks/core/src/js/sdk/Metrics/index.mjs @@ -21,15 +21,15 @@ /* ${INITIALIZATION} */ function ready() { - return Transport.send('metrics', 'ready', {}) + return Gateway.request('Metrics.ready', {}) } function signIn() { - return Transport.send('metrics', 'signIn', {}) + return Gateway.request('Metrics.signIn', {}) } function signOut() { - return Transport.send('metrics', 'signOut', {}) + return Gateway.request('Metrics.signOut', {}) } diff --git a/src/sdks/core/test/suite/declarations.test.ts b/src/sdks/core/test/suite/declarations.test.ts index 8ec319eeb..2933329c7 100644 --- a/src/sdks/core/test/suite/declarations.test.ts +++ b/src/sdks/core/test/suite/declarations.test.ts @@ -2,7 +2,7 @@ import Setup from "../../../../../test/Setup" import { sent } from "../../../../../test/Setup" import { test, expect } from "@jest/globals" -import { Lifecycle, Device, Discovery } from "../../build/javascript/src/firebolt"; +import { Lifecycle, Device, Discovery, Entertainment } from "../../build/javascript/src/firebolt"; let listenerId:number @@ -39,7 +39,7 @@ const result: Discovery.EntityInfoResult = { "identifiers": { "entityId": "123" }, - "programType": Discovery.ProgramType.MOVIE, + "programType": Entertainment.ProgramType.MOVIE, "title": "A title" }, "expires": "" @@ -67,7 +67,7 @@ test('entityInfo pull', () => { return Promise.resolve(result) }) - Setup.emit('discovery', 'pullEntityInfo', { + Setup.emit('Discovery', 'pullEntityInfo', { correlationId: '123', parameters: { entityId: '123' diff --git a/src/sdks/core/test/suite/device.test.ts b/src/sdks/core/test/suite/device.test.ts index 7f9601cac..84ddfd537 100644 --- a/src/sdks/core/test/suite/device.test.ts +++ b/src/sdks/core/test/suite/device.test.ts @@ -17,33 +17,33 @@ */ import { test, expect } from "@jest/globals"; -import { Device } from "../../build/javascript/src/firebolt"; +import { Device, Types } from "../../build/javascript/src/firebolt"; test("Device.version()", () => { const debug: string = "Non-parsable build info for error logging only." - const os:Device.SemanticVersion = { + const os:Types.SemanticVersion = { major: 0, minor: 1, patch: 0, readable: "Firebolt OS v0.1.0" } - const sdk:Device.SemanticVersion = { + const sdk:Types.SemanticVersion = { major: 0, minor: 8, patch: 0, readable: "The Firebolt JS SDK", } - const firmware:Device.SemanticVersion = { + const firmware:Types.SemanticVersion = { major: 1, minor: 2, patch: 3, readable: "Device Firmware v1.2.3" } - const api:Device.SemanticVersion = { + const api:Types.SemanticVersion = { major: 0, minor: 8, patch: 0, @@ -112,17 +112,17 @@ test("Device.make()", () => { }); test("Device.hdcp()", () => { - const expectedOutput: Device.BooleanMap = { + const expectedOutput: Types.BooleanMap = { "hdcp1.4": true, "hdcp2.2": true, }; - return Device.hdcp().then((res: Device.BooleanMap) => { + return Device.hdcp().then((res: Types.BooleanMap) => { expect(res).toEqual(expectedOutput); }); }); test("Device.hdcp(subscriber)", () => { - return Device.hdcp((supportedHdrProfiles: Device.BooleanMap) => {}).then( + return Device.hdcp((supportedHdrProfiles: Types.BooleanMap) => {}).then( (res: number) => { expect(res > 0).toBe(true); } diff --git a/src/sdks/core/test/suite/discovery.test.ts b/src/sdks/core/test/suite/discovery.test.ts index 638c57432..445d3ac47 100644 --- a/src/sdks/core/test/suite/discovery.test.ts +++ b/src/sdks/core/test/suite/discovery.test.ts @@ -17,7 +17,7 @@ */ import { test, expect } from "@jest/globals"; -import { Discovery } from "../../build/javascript/src/firebolt"; +import { Discovery, Entertainment } from "../../build/javascript/src/firebolt"; test("watched(entityId)", () => { return Discovery.watched("abc").then((success: boolean) => { @@ -50,7 +50,7 @@ test("entityInfo(EntityInfoResult)", () => { }, title: "Test", entityType: "program", - programType: Discovery.ProgramType.MOVIE, + programType: Entertainment.ProgramType.MOVIE, }, }; return Discovery.entityInfo(dummyData).then((res: boolean) => { @@ -65,7 +65,7 @@ test("watchNext(title?: LocalizedString, identifiers: ContentIdentifiers, expire }); test("entitlements(entitlements: Entitlement[])", () => { - const dummyData: Array = [ + const dummyData: Array = [ { entitlementId: "test123", startTime: `${new Date().getTime()}`, @@ -84,7 +84,7 @@ test("launch(appId)", () => { }); test("signIn(appId)", () => { - const dummyData: Array = [ + const dummyData: Array = [ { entitlementId: "test123", startTime: `${new Date().getTime()}`, @@ -113,7 +113,7 @@ test("purchasedContent()", () => { }, title: "TEST", entityType: "program", - programType: Discovery.ProgramType.MOVIE, + programType: Entertainment.ProgramType.MOVIE, }, ], }; diff --git a/src/sdks/core/test/suite/federation.test.ts b/src/sdks/core/test/suite/federation.test.ts index 6e8dab8e1..a80fc180d 100644 --- a/src/sdks/core/test/suite/federation.test.ts +++ b/src/sdks/core/test/suite/federation.test.ts @@ -20,12 +20,12 @@ // setup for Firebolt SDK/TL handshake import { test, expect, beforeAll } from "@jest/globals"; -import { Lifecycle, Discovery } from '../../build/javascript/src/firebolt' +import { Lifecycle, Discovery, Entertainment, Types } from '../../build/javascript/src/firebolt' // holds test transport layer state, e.g. callback const state = { - callback:(a:string) => {} + callback:(a:object) => {} } let pullEntityInfoListenCount = 0 @@ -40,9 +40,8 @@ let secondRegistrationFailed = false beforeAll(() => { return new Promise( (resolve, reject) => { const transport = { - send: function(message: string) { + send: function(json: any) { sendCalled = true - const json = JSON.parse(message) if (json.method.toLowerCase() === 'discovery.onpullentityinfo') { // we'll assert on this later... pullEntityInfoListenCount++ @@ -54,12 +53,12 @@ beforeAll(() => { id: json.id, result: { listening: true, - event: 'discovery.onPullEntityInfo' + event: 'Discovery.onPullEntityInfo' } } // catching errors, so all tests don't fail if this breaks try { - state.callback(JSON.stringify(response)) + state.callback(response) } catch (err) { throw err @@ -71,27 +70,31 @@ beforeAll(() => { try { response = { jsonrpc: '2.0', - id: json.id, - result: { - correlationId: correlationId, - parameters: { - entityId: "345" + method: 'Discovery.pullEntityInfo', + params: { + value: { + correlationId: correlationId, + parameters: { + entityId: "345" + } } } } - state.callback(JSON.stringify(response)) + state.callback(response) - state.callback(JSON.stringify({ + state.callback({ jsonrpc: '2.0', - id: json.id, - result: { - correlationId: 'this-will-fail', - parameters: { - entityId: "this-will-fail" + method: 'Discovery.pullEntityInfo', + params: { + value: { + correlationId: 'this-will-fail', + parameters: { + entityId: "this-will-fail" + } } } - })) + }) } catch (err) { throw err @@ -111,21 +114,24 @@ beforeAll(() => { else if (!json.params.correlationId && json.params.result.entity.identifiers.entityId === "PUSH:345") { entityInfoPushed = true } - state.callback(JSON.stringify({ - jsonrpc: '2.0', - id: json.id, - result: true - })) + + setTimeout(() => { + state.callback({ + jsonrpc: '2.0', + id: json.id, + result: true + }) + }, 100) } }, - receive: function(callback: (a:string) => void) { + receive: function(callback: (a:object) => void) { // store the callback state.callback = callback } } const win:any = window; - win.__firebolt.setTransportLayer(transport) + win.__firebolt.transport = transport const result:Discovery.EntityInfoResult = { "expires": "2025-01-01T00:00:00.000Z", @@ -134,7 +140,7 @@ beforeAll(() => { "entityId": "PUSH:345" }, "entityType": "program", - "programType": Discovery.ProgramType.MOVIE, + "programType": Entertainment.ProgramType.MOVIE, "title": "Cool Runnings", "synopsis": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pulvinar sapien et ligula ullamcorper malesuada proin libero nunc.", "releaseDate": "1993-01-01T00:00:00.000Z", @@ -156,9 +162,9 @@ beforeAll(() => { "expires": "2025-01-01T00:00:00.000Z", "entitled": true, "entitledExpires": "2025-01-01T00:00:00.000Z", - "offeringType": Discovery.OfferingType.BUY, + "offeringType": Entertainment.OfferingType.BUY, "price": 2.99, - "audioProfile": [Discovery.AudioProfile.DOLBY_ATMOS], + "audioProfile": [Types.AudioProfile.DOLBY_ATMOS], "videoQuality": ["UHD"], "audioLanguages": [ "en" @@ -180,6 +186,8 @@ beforeAll(() => { // Setup a callback that returns the correct payload Discovery.entityInfo((parameters:Discovery.EntityInfoParameters) => { + console.dir(parameters) + if (parameters.entityId === 'this-will-fail') { throw "Intentional Test failure" } @@ -209,6 +217,7 @@ test('Transport was sent each listener only once', () => { }); test('Entity Info was pulled from the app', ()=> { + expect(callbackWiredUp).toBe(true) expect(entityInfoPulled).toBe(true) expect(entityInfoReceived).toBe(true) }); diff --git a/src/sdks/core/test/suite/lazy-transport.test.ts b/src/sdks/core/test/suite/lazy-transport.test.ts index ebfb739fe..f9e75cd9b 100644 --- a/src/sdks/core/test/suite/lazy-transport.test.ts +++ b/src/sdks/core/test/suite/lazy-transport.test.ts @@ -20,13 +20,43 @@ // setup for Firebolt SDK/TL handshake const win = globalThis || window +let _queue = [] +let _callback:Function +let target + +const queue = { + + send: function(json) { + if (target) { + target.send(json) + } + else { + _queue.push(json) + } + }, + + receive: function (callback) { + _callback = callback + }, + + flush: function (transport:any) { + target = transport + transport.receive(_callback) + _queue.forEach(item => transport.send(item)) + _queue = null + } +} + +// set up a queue to hold all Firebolt messages +win.__firebolt.transport = queue + import Setup from '../../../../../test/Setup' import { beforeAll, test, expect } from '@jest/globals'; -import { Lifecycle, Discovery } from "../../build/javascript/src/firebolt"; +import { Lifecycle, Discovery } from "../../build/javascript/src/firebolt"; // holds test transport layer state, e.g. callback type stateType = { - callback: (arg0: string) => void | null + callback: (arg0: any) => void | null } const state:stateType = { @@ -39,10 +69,8 @@ let callbackWiredUp = false let sendCalled = false const transport = { - send: function(message) { + send: function(json) { sendCalled = true - const json = JSON.parse(message) - console.log('transport.send: ' + json.method) if (json.method.toLowerCase() === 'lifecycle.ready') { // we'll assert on this later... navigateToListenCount++ @@ -52,12 +80,12 @@ const transport = { let response = { jsonrpc: '2.0', id: json.id, - result: true + result: null } // catching errors, so all tests don't fail if this breaks try { // send back the onInactive event immediately, to test for race conditions - state.callback(JSON.stringify(response)) + state.callback(response) } catch (err) { // fail silenetly (the boolean-based tests below will figure it out...) @@ -69,7 +97,6 @@ const transport = { } }, receive: function(callback) { - console.log('transport.receive') // store the callback state.callback = callback } @@ -92,7 +119,7 @@ beforeAll(()=> { Lifecycle.ready() - win.__firebolt.setTransportLayer(transport) + queue.flush(transport) return p }) diff --git a/src/sdks/core/test/suite/lifecycle.test.ts b/src/sdks/core/test/suite/lifecycle.test.ts index 00d777575..e5d299e34 100644 --- a/src/sdks/core/test/suite/lifecycle.test.ts +++ b/src/sdks/core/test/suite/lifecycle.test.ts @@ -26,9 +26,9 @@ let readyMetricCalled: boolean = false; let readyMetricCalledAfterResolve: boolean = false; testHarness.onSend = function (module: string, method: string) { - if (module === "lifecycle" && method === "ready") { + if (module === "Lifecycle" && method === "ready") { readyCalled = true; - } else if (module === "metrics" && method === "ready") { + } else if (module === "Metrics" && method === "ready") { readyMetricCalled = true; if (readyResolved) { diff --git a/src/sdks/core/test/suite/listeners-transport.test.ts b/src/sdks/core/test/suite/listeners-transport.test.ts index bec4db1b7..d916f624c 100644 --- a/src/sdks/core/test/suite/listeners-transport.test.ts +++ b/src/sdks/core/test/suite/listeners-transport.test.ts @@ -19,7 +19,6 @@ const win = globalThis || window; import { test, expect } from "@jest/globals"; -import { Lifecycle, Discovery } from "../../build/javascript/src/firebolt"; // holds test transport layer state, e.g. callback const state = { @@ -31,9 +30,8 @@ let callbackWiredUp: boolean = false; let sendCalled: boolean = false; const transport = { - send: function (message: string) { + send: function (json: any) { sendCalled = true; - const json = JSON.parse(message); if (json.method.toLowerCase() === "discovery.onnavigateto") { // we'll assert on this later... navigateToListenCount++; @@ -61,14 +59,21 @@ const transport = { }, }; -win.__firebolt.setTransportLayer(transport); +win.__firebolt = win.__firebolt || {} +const transportAlreadyExisted = !!win.__firebolt.transport + +win.__firebolt = { + transport +} + +import { Lifecycle, Discovery, Intents } from "../../build/javascript/src/firebolt"; // listen twice, using event-specific call FIRST -Discovery.listen("navigateTo", (value: Discovery.NavigationIntent) => { +Discovery.listen("navigateTo", (value: Intents.NavigationIntent) => { callbackWiredUp = true; }); -Discovery.listen("navigateTo", (value: Discovery.NavigationIntent) => { +Discovery.listen("navigateTo", (value: Intents.NavigationIntent) => { /* this just adds more listen calls to make sure we don't spam */ }); Discovery.listen((event: string, value: object) => { @@ -82,6 +87,7 @@ Lifecycle.ready(); test("Transport injected after SDK", () => { expect(callbackWiredUp).toBe(true); + expect(transportAlreadyExisted).toBe(false) }); test("Transport send method working", () => { diff --git a/src/sdks/core/test/suite/synchronous-transport.test.ts b/src/sdks/core/test/suite/synchronous-transport.test.ts index f7ab896d4..2694f8832 100644 --- a/src/sdks/core/test/suite/synchronous-transport.test.ts +++ b/src/sdks/core/test/suite/synchronous-transport.test.ts @@ -16,36 +16,39 @@ * SPDX-License-Identifier: Apache-2.0 */ -import transport from "../../../../../test/helpers/synchronous-transport.mjs"; +const win: any = window; -// These all get set synchronously, so we'll update them as they happen -let sendCalled: boolean = false; -let inactiveListened: boolean = false; -let callbackWiredUp: boolean = false; +let sendCalled = false +let inactiveCalled = false +let _callback: Function; +let firstId: Number -transport.onSend((json) => { - // we'll assert on this later... - sendCalled = true; - if (json.method.toLowerCase() === "device.name") { - // we'll assert on this later... - inactiveListened = true; - - // we'll assert on this later... - callbackWiredUp = true; - let response = { - jsonrpc: "2.0", - id: json.id, - result: "Test Name", - }; - // catching errors, so all tests don't fail if this breaks - try { - // send back the onInactive event immediately, to test for race conditions - transport.response(response); - } catch (err) { - // fail silenetly (the boolean-based tests below will figure it out...) +win.__firebolt = { + transport: { + send: function(json: any) { + if (firstId === undefined) { + firstId = json.id + } + sendCalled = true + if (json.method === 'Lifecycle.onInactive') { + inactiveCalled = true + } + else if (json.method === 'Device.name') { + console.dir(json) + _callback && setTimeout(() => { + _callback({ + jsonrpc: '2.0', + id: json.id, + result: 'Test Name' + }) + }, 100) + } + }, + receive: function(callback: Function) { + _callback = callback } } -}); +} import { test, expect, beforeAll } from "@jest/globals"; import { Lifecycle, Device } from "../../build/javascript/src/firebolt"; @@ -60,7 +63,11 @@ beforeAll(() => { }); test("Transport injected before SDK", () => { - expect(transport.instantiatedBeforeSdk()).toBe(true); + // NOTE: this assumes an implementation detail that we start at 1 (we do at time of this test writing) + // this isn't the best test, since there's no requirement that we start at 1 or even use numbers + // at all (could be strings or even null). + // if this test ever fails, we should find a better way to test that we didn't miss any requests + expect(firstId).toBe(1) }); test("Transport send method working", () => { @@ -68,11 +75,7 @@ test("Transport send method working", () => { }); test("Transport was sent `Lifecycle.onInactive` listener", () => { - expect( - !!transport - .history() - .find((json) => json.method.toLowerCase() === "lifecycle.oninactive") - ).toBe(true); + expect(inactiveCalled).toBe(true); }); test("Transport `receive` callback wired up", () => { diff --git a/test/helpers/synchronous-transport.mjs b/test/helpers/synchronous-transport.mjs index 9cef2b153..7f411aadd 100644 --- a/test/helpers/synchronous-transport.mjs +++ b/test/helpers/synchronous-transport.mjs @@ -7,7 +7,7 @@ let receiveCallback let first = false let _history = [] -const transport = { +window.__firebolt.transport = { send: function(message) { const json = JSON.parse(message) _history.push(json) @@ -31,13 +31,4 @@ const transport = { } } -if (!window.__firebolt.setTransportLayer) { - first = true -} - -window.__firebolt.getTransportLayer = function() { - // we'll assert on this later... - return transport -} - export default transport \ No newline at end of file