@ledgerhq/device-management-kit 1.6.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/lib/cjs/package.json +1 -2
  2. package/lib/cjs/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.js +1 -1
  3. package/lib/cjs/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.js.map +3 -3
  4. package/lib/cjs/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.test.js +1 -1
  5. package/lib/cjs/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.test.js.map +2 -2
  6. package/lib/cjs/src/api/device-action/os/GetDeviceStatus/types.js +1 -1
  7. package/lib/cjs/src/api/device-action/os/GetDeviceStatus/types.js.map +1 -1
  8. package/lib/cjs/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.js +1 -1
  9. package/lib/cjs/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.js.map +2 -2
  10. package/lib/cjs/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.test.js +1 -1
  11. package/lib/cjs/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.test.js.map +2 -2
  12. package/lib/cjs/src/api/device-action/os/OpenAppDeviceAction/types.js +1 -1
  13. package/lib/cjs/src/api/device-action/os/OpenAppDeviceAction/types.js.map +1 -1
  14. package/lib/cjs/src/api/device-action/os/OpenAppWithDependencies/types.js.map +1 -1
  15. package/lib/cjs/src/api/logger-subscriber/service/WebLogsExporterLogger.js.map +2 -2
  16. package/lib/cjs/src/api/network/DmkNetworkClient.js +1 -1
  17. package/lib/cjs/src/api/network/DmkNetworkClient.js.map +3 -3
  18. package/lib/cjs/src/api/network/DmkNetworkClient.test.js +1 -1
  19. package/lib/cjs/src/api/network/DmkNetworkClient.test.js.map +3 -3
  20. package/lib/cjs/src/api/network/DmkNetworkClientError.js +1 -1
  21. package/lib/cjs/src/api/network/DmkNetworkClientError.js.map +2 -2
  22. package/lib/cjs/src/api/network/DmkNetworkClientHelpers.js +1 -1
  23. package/lib/cjs/src/api/network/DmkNetworkClientHelpers.js.map +3 -3
  24. package/lib/cjs/src/api/network/DmkNetworkClientHelpers.test.js +1 -1
  25. package/lib/cjs/src/api/network/DmkNetworkClientHelpers.test.js.map +3 -3
  26. package/lib/cjs/src/api/utils/Base64String.js +1 -1
  27. package/lib/cjs/src/api/utils/Base64String.js.map +3 -3
  28. package/lib/cjs/src/api/utils/Base64String.test.js +3 -1
  29. package/lib/cjs/src/api/utils/Base64String.test.js.map +3 -3
  30. package/lib/cjs/src/internal/secure-channel/data/DefaultSecureChannelDataSource.js +1 -1
  31. package/lib/cjs/src/internal/secure-channel/data/DefaultSecureChannelDataSource.js.map +3 -3
  32. package/lib/cjs/src/internal/secure-channel/data/DefaultSecureChannelDataSource.test.js +1 -1
  33. package/lib/cjs/src/internal/secure-channel/data/DefaultSecureChannelDataSource.test.js.map +2 -2
  34. package/lib/esm/package.json +1 -2
  35. package/lib/esm/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.js +1 -1
  36. package/lib/esm/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.js.map +3 -3
  37. package/lib/esm/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.test.js +1 -1
  38. package/lib/esm/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.test.js.map +2 -2
  39. package/lib/esm/src/api/device-action/os/GetDeviceStatus/types.js.map +1 -1
  40. package/lib/esm/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.js +1 -1
  41. package/lib/esm/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.js.map +2 -2
  42. package/lib/esm/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.test.js +1 -1
  43. package/lib/esm/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.test.js.map +2 -2
  44. package/lib/esm/src/api/device-action/os/OpenAppDeviceAction/types.js.map +1 -1
  45. package/lib/esm/src/api/device-action/os/OpenAppWithDependencies/types.js.map +1 -1
  46. package/lib/esm/src/api/logger-subscriber/service/WebLogsExporterLogger.js.map +2 -2
  47. package/lib/esm/src/api/network/DmkNetworkClient.js +1 -1
  48. package/lib/esm/src/api/network/DmkNetworkClient.js.map +3 -3
  49. package/lib/esm/src/api/network/DmkNetworkClient.test.js +1 -1
  50. package/lib/esm/src/api/network/DmkNetworkClient.test.js.map +3 -3
  51. package/lib/esm/src/api/network/DmkNetworkClientError.js +1 -1
  52. package/lib/esm/src/api/network/DmkNetworkClientError.js.map +2 -2
  53. package/lib/esm/src/api/network/DmkNetworkClientHelpers.js +1 -1
  54. package/lib/esm/src/api/network/DmkNetworkClientHelpers.js.map +3 -3
  55. package/lib/esm/src/api/network/DmkNetworkClientHelpers.test.js +1 -1
  56. package/lib/esm/src/api/network/DmkNetworkClientHelpers.test.js.map +3 -3
  57. package/lib/esm/src/api/utils/Base64String.js +1 -1
  58. package/lib/esm/src/api/utils/Base64String.js.map +3 -3
  59. package/lib/esm/src/api/utils/Base64String.test.js +3 -1
  60. package/lib/esm/src/api/utils/Base64String.test.js.map +3 -3
  61. package/lib/esm/src/internal/secure-channel/data/DefaultSecureChannelDataSource.js +1 -1
  62. package/lib/esm/src/internal/secure-channel/data/DefaultSecureChannelDataSource.js.map +3 -3
  63. package/lib/esm/src/internal/secure-channel/data/DefaultSecureChannelDataSource.test.js +1 -1
  64. package/lib/esm/src/internal/secure-channel/data/DefaultSecureChannelDataSource.test.js.map +2 -2
  65. package/lib/types/src/api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction.d.ts.map +1 -1
  66. package/lib/types/src/api/device-action/os/GetDeviceStatus/types.d.ts +1 -0
  67. package/lib/types/src/api/device-action/os/GetDeviceStatus/types.d.ts.map +1 -1
  68. package/lib/types/src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.d.ts.map +1 -1
  69. package/lib/types/src/api/device-action/os/OpenAppDeviceAction/types.d.ts +1 -1
  70. package/lib/types/src/api/device-action/os/OpenAppDeviceAction/types.d.ts.map +1 -1
  71. package/lib/types/src/api/device-action/os/OpenAppWithDependencies/types.d.ts +1 -1
  72. package/lib/types/src/api/device-action/os/OpenAppWithDependencies/types.d.ts.map +1 -1
  73. package/lib/types/src/api/logger-subscriber/service/WebLogsExporterLogger.d.ts.map +1 -1
  74. package/lib/types/src/api/network/DmkNetworkClient.d.ts +1 -6
  75. package/lib/types/src/api/network/DmkNetworkClient.d.ts.map +1 -1
  76. package/lib/types/src/api/network/DmkNetworkClientError.d.ts +2 -6
  77. package/lib/types/src/api/network/DmkNetworkClientError.d.ts.map +1 -1
  78. package/lib/types/src/api/network/DmkNetworkClientHelpers.d.ts +10 -7
  79. package/lib/types/src/api/network/DmkNetworkClientHelpers.d.ts.map +1 -1
  80. package/lib/types/src/api/utils/Base64String.d.ts.map +1 -1
  81. package/lib/types/src/internal/secure-channel/data/DefaultSecureChannelDataSource.d.ts.map +1 -1
  82. package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
  83. package/package.json +3 -4
@@ -1,2 +1,2 @@
1
- import{lastValueFrom as k}from"rxjs";import{InvalidStatusWordError as C}from"../../../command/Errors";import{CommandResultFactory as S}from"../../../command/model/CommandResult";import{DeviceModelId as B}from"../../../device/DeviceModel";import{DeviceStatus as a}from"../../../device/DeviceStatus";import{makeDeviceActionInternalApiMock as c}from"../../../device-action/__test-utils__/makeInternalApi";import{setupGetDeviceStatusMock as u}from"../../../device-action/__test-utils__/setupTestMachine";import{testDeviceActionStates as d}from"../../../device-action/__test-utils__/testDeviceActionStates";import{DeviceActionStatus as e}from"../../../device-action/model/DeviceActionState";import{UserInteractionRequired as t}from"../../../device-action/model/UserInteractionRequired";import{DeviceLockedError as I,DeviceNotOnboardedError as U,UnknownDAError as E}from"../../../device-action/os/Errors";import{getDeviceStatusDAStateStep as r}from"../../../device-action/os/GetDeviceStatus/types";import{DeviceSessionStateType as p}from"../../../device-session/DeviceSessionState";import{DeviceDisconnectedWhileSendingError as h}from"../../../transport/model/Errors";import{OpenAppDeviceAction as A}from"./OpenAppDeviceAction";import{openAppDAStateStep as m}from"./types";vi.mock("@api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction");describe("OpenAppDeviceAction",()=>{const V=vi.fn(),O=vi.fn(),v=vi.fn(),l=vi.fn(),R=vi.fn();function D(){return{getDeviceSessionState:l,setDeviceSessionState:R,openApp:O,closeApp:v}}const{getDeviceSessionState:T}=c();beforeEach(()=>{vi.resetAllMocks()}),describe("without overriding `extractDependencies`",()=>{it("should end if the required application is opened",()=>new Promise((o,i)=>{T.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"Bitcoin",version:"1.0.0"},installedApps:[],deviceModelId:B.NANO_X,isSecureConnectionAllowed:!1}),u([{currentApp:"Bitcoin",currentAppVersion:"0.0.0"}]);const n=new A({input:{appName:"Bitcoin"}}),s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Completed,output:void 0}];d(n,s,c(),{onDone:o,onError:i})}))}),describe("success cases",()=>{it("should end in a success if the app is already opened",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"Bitcoin",version:"1.0.0"}}),u([{currentApp:"Bitcoin",currentAppVersion:"1.0.0"}]);const n=new A({input:{appName:"Bitcoin",unlockTimeout:void 0}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Completed,output:void 0}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in a success if the dashboard is open and open app succeeds",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"BOLOS",version:"0.0.0"}}),u([{currentApp:"Bitcoin",currentAppVersion:"1.0.0"}]),O.mockResolvedValue(S({data:void 0}));const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Completed,output:void 0}],{observable:N}=d(n,s,c(),{onDone:o,onError:i});k(N).then(()=>{expect(R).toHaveBeenCalledWith({deviceStatus:a.CONNECTED,sessionStateType:p.ReadyWithoutSecureChannel,currentApp:{name:"Bitcoin",version:"1.0.0"}})})})),it("should end in a success if disconnection occurs while open app succeeds",()=>new Promise((o,i)=>{l.mockReturnValue(S({data:{sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"BOLOS",version:"0.0.0"}}})),V.mockResolvedValue(S({data:{name:"BOLOS",version:"0.0.0"}})),u([{currentApp:"BOLOS",currentAppVersion:"0.0.0"},{currentApp:"Bitcoin",currentAppVersion:"0.0.0"}]),O.mockRejectedValue(new h);const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.ConfirmOpenApp,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Completed,output:void 0}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in a success if another app is open, close app succeeds and open app succeeds",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"AnotherApp",version:"0.0.0"}}),u([{currentApp:"AnotherApp",currentAppVersion:"0.0.0"},{currentApp:"Bitcoin",currentAppVersion:"1.0.0"}]),v.mockResolvedValue(S({data:void 0})),O.mockResolvedValue(S({data:void 0}));const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.ConfirmOpenApp,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Completed,output:void 0}],{observable:N}=d(n,s,c(),{onDone:o,onError:i});k(N).then(()=>{expect(R).toHaveBeenCalledWith({currentApp:{name:"Bitcoin",version:"1.0.0"},deviceStatus:a.CONNECTED,sessionStateType:p.ReadyWithoutSecureChannel})})}))}),describe("errors cases",()=>{it("should end in an error if the device is not onboarded",()=>new Promise((o,i)=>{T.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"mockedCurrentApp",version:"1.0.0"},installedApps:[],deviceModelId:B.NANO_X,isSecureConnectionAllowed:!1}),u([new U]);const n=new A({input:{appName:"Bitcoin"}}),s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{error:new U,status:e.Error}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if the device is locked",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.LOCKED,currentApp:{name:"mockedCurrentApp",version:"1.0.0"}}),u([new I]);const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Error,error:new I}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if getAppAndVersion returns an error",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"mockedCurrentApp",version:"1.0.0"}}),u([new C("mocked error")]);const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Error,error:new C("mocked error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if the dashboard is open and open app returns an error",()=>new Promise((o,i)=>{l.mockReturnValue(S({data:{sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"BOLOS",version:"0.0.0"}}})),V.mockResolvedValue(S({data:{name:"BOLOS",version:"0.0.0"}})),u([{currentApp:"BOLOS",currentAppVersion:"0.0.0"}]),O.mockResolvedValue(S({error:new C("mocked error")}));const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.ConfirmOpenApp,step:r.ONBOARD_CHECK}},{status:e.Error,error:new C("mocked error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in a success if disconnection occurs while open app failed",()=>new Promise((o,i)=>{l.mockReturnValue(S({data:{sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"BOLOS",version:"0.0.0"}}})),V.mockResolvedValue(S({data:{name:"BOLOS",version:"0.0.0"}})),u([{currentApp:"BOLOS",currentAppVersion:"0.0.0"},{currentApp:"BOLOS",currentAppVersion:"0.0.0"}]),O.mockRejectedValue(new h);const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.ConfirmOpenApp,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Error,error:new h}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if another app is open, and close app returns an error",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"AnotherApp",version:"0.0.0"}}),u([{currentApp:"AnotherApp",currentAppVersion:"0.0.0"}]),v.mockResolvedValue(S({error:new C("mocked error")}));const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Error,error:new C("mocked error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if another app is open, close app succeeds but open app returns an error",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"AnotherApp",version:"0.0.0"}}),u([{currentApp:"AnotherApp",currentAppVersion:"0.0.0"}]),v.mockResolvedValue(S({data:void 0})),O.mockResolvedValue(S({error:new C("mocked error")}));const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.ConfirmOpenApp,step:r.ONBOARD_CHECK}},{status:e.Error,error:new C("mocked error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if getAppAndVersion actor throws an error",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"mockedCurrentApp",version:"1.0.0"}}),u([new E("Unknown error")]);const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Error,error:new E("Unknown error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if openApp actor throws an error",()=>new Promise((o,i)=>{l.mockReturnValue(S({data:{sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"BOLOS",version:"0.0.0"}}})),u([{currentApp:"BOLOS",currentAppVersion:"0.0.0"}]),O.mockImplementation(()=>{throw new E("Unknown error")});const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.ConfirmOpenApp,step:r.ONBOARD_CHECK}},{status:e.Error,error:new E("Unknown error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if closeApp actor throws an error",()=>new Promise((o,i)=>{l.mockReturnValue(S({data:{sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"BOLOS",version:"0.0.0"}}})),u([{currentApp:"anApp",currentAppVersion:"0.0.0"}]),v.mockImplementation(()=>{throw new E("Unknown error")});const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Error,error:new E("Unknown error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should emit a stopped state if the action is cancelled",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"AnotherApp",version:"0.0.0"}}),u([{currentApp:"AnotherApp",currentAppVersion:"0.0.0"}]);const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Stopped}],{cancel:N}=d(n,s,c(),{onDone:o,onError:i});N()}))})});
1
+ import{lastValueFrom as k}from"rxjs";import{InvalidStatusWordError as C}from"../../../command/Errors";import{CommandResultFactory as S}from"../../../command/model/CommandResult";import{DeviceModelId as B}from"../../../device/DeviceModel";import{DeviceStatus as a}from"../../../device/DeviceStatus";import{makeDeviceActionInternalApiMock as c}from"../../../device-action/__test-utils__/makeInternalApi";import{setupGetDeviceStatusMock as u}from"../../../device-action/__test-utils__/setupTestMachine";import{testDeviceActionStates as d}from"../../../device-action/__test-utils__/testDeviceActionStates";import{DeviceActionStatus as e}from"../../../device-action/model/DeviceActionState";import{UserInteractionRequired as t}from"../../../device-action/model/UserInteractionRequired";import{DeviceLockedError as I,DeviceNotOnboardedError as U,UnknownDAError as E}from"../../../device-action/os/Errors";import{getDeviceStatusDAStateStep as r}from"../../../device-action/os/GetDeviceStatus/types";import{DeviceSessionStateType as p}from"../../../device-session/DeviceSessionState";import{DeviceDisconnectedWhileSendingError as T}from"../../../transport/model/Errors";import{OpenAppDeviceAction as A}from"./OpenAppDeviceAction";import{openAppDAStateStep as m}from"./types";vi.mock("@api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction");describe("OpenAppDeviceAction",()=>{const V=vi.fn(),O=vi.fn(),v=vi.fn(),l=vi.fn(),R=vi.fn();function D(){return{getDeviceSessionState:l,setDeviceSessionState:R,openApp:O,closeApp:v}}const{getDeviceSessionState:h}=c();beforeEach(()=>{vi.resetAllMocks()}),describe("without overriding `extractDependencies`",()=>{it("should end if the required application is opened",()=>new Promise((o,i)=>{h.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"Bitcoin",version:"1.0.0"},installedApps:[],deviceModelId:B.NANO_X,isSecureConnectionAllowed:!1}),u([{currentApp:"Bitcoin",currentAppVersion:"0.0.0"}]);const n=new A({input:{appName:"Bitcoin"}}),s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Completed,output:void 0}];d(n,s,c(),{onDone:o,onError:i})}))}),describe("success cases",()=>{it("should end in a success if the app is already opened",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"Bitcoin",version:"1.0.0"}}),u([{currentApp:"Bitcoin",currentAppVersion:"1.0.0"}]);const n=new A({input:{appName:"Bitcoin",unlockTimeout:void 0}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Completed,output:void 0}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in a success if the dashboard is open and open app succeeds",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"BOLOS",version:"0.0.0"}}),u([{currentApp:"Bitcoin",currentAppVersion:"1.0.0"}]),O.mockResolvedValue(S({data:void 0}));const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Completed,output:void 0}],{observable:N}=d(n,s,c(),{onDone:o,onError:i});k(N).then(()=>{expect(R).toHaveBeenCalledWith({deviceStatus:a.CONNECTED,sessionStateType:p.ReadyWithoutSecureChannel,currentApp:{name:"Bitcoin",version:"1.0.0"}})})})),it("should end in a success if disconnection occurs while open app succeeds",()=>new Promise((o,i)=>{l.mockReturnValue(S({data:{sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"BOLOS",version:"0.0.0"}}})),V.mockResolvedValue(S({data:{name:"BOLOS",version:"0.0.0"}})),u([{currentApp:"BOLOS",currentAppVersion:"0.0.0"},{currentApp:"Bitcoin",currentAppVersion:"0.0.0"}]),O.mockRejectedValue(new T);const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.ConfirmOpenApp,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Completed,output:void 0}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in a success if another app is open, close app succeeds and open app succeeds",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"AnotherApp",version:"0.0.0"}}),u([{currentApp:"AnotherApp",currentAppVersion:"0.0.0"},{currentApp:"Bitcoin",currentAppVersion:"1.0.0"}]),v.mockResolvedValue(S({data:void 0})),O.mockResolvedValue(S({data:void 0}));const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.ConfirmOpenApp,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Completed,output:void 0}],{observable:N}=d(n,s,c(),{onDone:o,onError:i});k(N).then(()=>{expect(R).toHaveBeenCalledWith({currentApp:{name:"Bitcoin",version:"1.0.0"},deviceStatus:a.CONNECTED,sessionStateType:p.ReadyWithoutSecureChannel})})}))}),describe("errors cases",()=>{it("GIVEN a non-onboarded device WHEN opening an app THEN it blocks the app flow",()=>new Promise((o,i)=>{h.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"mockedCurrentApp",version:"1.0.0"},installedApps:[],deviceModelId:B.NANO_X,isSecureConnectionAllowed:!1}),u([new U]);const n=new A({input:{appName:"Bitcoin"}}),s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{error:new U,status:e.Error}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if the device is locked",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.LOCKED,currentApp:{name:"mockedCurrentApp",version:"1.0.0"}}),u([new I]);const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Error,error:new I}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if getAppAndVersion returns an error",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"mockedCurrentApp",version:"1.0.0"}}),u([new C("mocked error")]);const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Error,error:new C("mocked error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if the dashboard is open and open app returns an error",()=>new Promise((o,i)=>{l.mockReturnValue(S({data:{sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"BOLOS",version:"0.0.0"}}})),V.mockResolvedValue(S({data:{name:"BOLOS",version:"0.0.0"}})),u([{currentApp:"BOLOS",currentAppVersion:"0.0.0"}]),O.mockResolvedValue(S({error:new C("mocked error")}));const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.ConfirmOpenApp,step:r.ONBOARD_CHECK}},{status:e.Error,error:new C("mocked error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in a success if disconnection occurs while open app failed",()=>new Promise((o,i)=>{l.mockReturnValue(S({data:{sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"BOLOS",version:"0.0.0"}}})),V.mockResolvedValue(S({data:{name:"BOLOS",version:"0.0.0"}})),u([{currentApp:"BOLOS",currentAppVersion:"0.0.0"},{currentApp:"BOLOS",currentAppVersion:"0.0.0"}]),O.mockRejectedValue(new T);const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.ConfirmOpenApp,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Error,error:new T}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if another app is open, and close app returns an error",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"AnotherApp",version:"0.0.0"}}),u([{currentApp:"AnotherApp",currentAppVersion:"0.0.0"}]),v.mockResolvedValue(S({error:new C("mocked error")}));const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Error,error:new C("mocked error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if another app is open, close app succeeds but open app returns an error",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"AnotherApp",version:"0.0.0"}}),u([{currentApp:"AnotherApp",currentAppVersion:"0.0.0"}]),v.mockResolvedValue(S({data:void 0})),O.mockResolvedValue(S({error:new C("mocked error")}));const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.ConfirmOpenApp,step:r.ONBOARD_CHECK}},{status:e.Error,error:new C("mocked error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if getAppAndVersion actor throws an error",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"mockedCurrentApp",version:"1.0.0"}}),u([new E("Unknown error")]);const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Error,error:new E("Unknown error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if openApp actor throws an error",()=>new Promise((o,i)=>{l.mockReturnValue(S({data:{sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"BOLOS",version:"0.0.0"}}})),u([{currentApp:"BOLOS",currentAppVersion:"0.0.0"}]),O.mockImplementation(()=>{throw new E("Unknown error")});const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.ConfirmOpenApp,step:r.ONBOARD_CHECK}},{status:e.Error,error:new E("Unknown error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should end in an error if closeApp actor throws an error",()=>new Promise((o,i)=>{l.mockReturnValue(S({data:{sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"BOLOS",version:"0.0.0"}}})),u([{currentApp:"anApp",currentAppVersion:"0.0.0"}]),v.mockImplementation(()=>{throw new E("Unknown error")});const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Error,error:new E("Unknown error")}];d(n,s,c(),{onDone:o,onError:i})})),it("should emit a stopped state if the action is cancelled",()=>new Promise((o,i)=>{l.mockReturnValue({sessionStateType:p.ReadyWithoutSecureChannel,deviceStatus:a.CONNECTED,currentApp:{name:"AnotherApp",version:"0.0.0"}}),u([{currentApp:"AnotherApp",currentAppVersion:"0.0.0"}]);const n=new A({input:{appName:"Bitcoin"}});vi.spyOn(n,"extractDependencies").mockReturnValue(D());const s=[{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:m.GET_DEVICE_STATUS}},{status:e.Pending,intermediateValue:{requiredUserInteraction:t.None,step:r.ONBOARD_CHECK}},{status:e.Stopped}],{cancel:N}=d(n,s,c(),{onDone:o,onError:i});N()}))})});
2
2
  //# sourceMappingURL=OpenAppDeviceAction.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/api/device-action/os/OpenAppDeviceAction/OpenAppDeviceAction.test.ts"],
4
- "sourcesContent": ["import { lastValueFrom } from \"rxjs\";\n\nimport { InvalidStatusWordError } from \"@api/command/Errors\";\nimport { CommandResultFactory } from \"@api/command/model/CommandResult\";\nimport { DeviceModelId } from \"@api/device/DeviceModel\";\nimport { DeviceStatus } from \"@api/device/DeviceStatus\";\nimport { makeDeviceActionInternalApiMock } from \"@api/device-action/__test-utils__/makeInternalApi\";\nimport { setupGetDeviceStatusMock } from \"@api/device-action/__test-utils__/setupTestMachine\";\nimport { testDeviceActionStates } from \"@api/device-action/__test-utils__/testDeviceActionStates\";\nimport { DeviceActionStatus } from \"@api/device-action/model/DeviceActionState\";\nimport { UserInteractionRequired } from \"@api/device-action/model/UserInteractionRequired\";\nimport {\n DeviceLockedError,\n DeviceNotOnboardedError,\n UnknownDAError,\n} from \"@api/device-action/os/Errors\";\nimport { getDeviceStatusDAStateStep } from \"@api/device-action/os/GetDeviceStatus/types\";\nimport { DeviceSessionStateType } from \"@api/device-session/DeviceSessionState\";\nimport { DeviceDisconnectedWhileSendingError } from \"@api/transport/model/Errors\";\n\nimport { OpenAppDeviceAction } from \"./OpenAppDeviceAction\";\nimport {\n type OpenAppDAError,\n type OpenAppDAState,\n openAppDAStateStep,\n} from \"./types\";\n\nvi.mock(\"@api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction\");\n\ndescribe(\"OpenAppDeviceAction\", () => {\n const getAppAndVersionMock = vi.fn();\n const openAppMock = vi.fn();\n const closeAppMock = vi.fn();\n const getDeviceSessionStateMock = vi.fn();\n const setDeviceSessionStateMock = vi.fn();\n\n function extractDependenciesMock() {\n return {\n getDeviceSessionState: getDeviceSessionStateMock,\n setDeviceSessionState: setDeviceSessionStateMock,\n openApp: openAppMock,\n closeApp: closeAppMock,\n };\n }\n\n const { getDeviceSessionState: apiGetDeviceSessionStateMock } =\n makeDeviceActionInternalApiMock();\n\n beforeEach(() => {\n vi.resetAllMocks();\n });\n\n describe(\"without overriding `extractDependencies`\", () => {\n it(\"should end if the required application is opened\", () =>\n new Promise<void>((resolve, reject) => {\n apiGetDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"Bitcoin\", version: \"1.0.0\" },\n installedApps: [],\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: false,\n });\n setupGetDeviceStatusMock([\n {\n currentApp: \"Bitcoin\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarding status / list apps / initial step\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get device status / onboard check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Completed,\n output: undefined,\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n });\n\n describe(\"success cases\", () => {\n it(\"should end in a success if the app is already opened\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"Bitcoin\", version: \"1.0.0\" },\n });\n\n setupGetDeviceStatusMock([\n {\n currentApp: \"Bitcoin\",\n currentAppVersion: \"1.0.0\",\n },\n ]);\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\", unlockTimeout: undefined },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarding status / list apps / initial step\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get app and version / onboard check / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Completed,\n output: undefined,\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in a success if the dashboard is open and open app succeeds\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"BOLOS\", version: \"0.0.0\" },\n });\n\n setupGetDeviceStatusMock([\n {\n currentApp: \"Bitcoin\",\n currentAppVersion: \"1.0.0\",\n },\n ]);\n\n openAppMock.mockResolvedValue(\n CommandResultFactory({ data: undefined }),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get app and version /list apps / initial step\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get app and version / onboard check / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Completed,\n output: undefined,\n },\n ];\n\n const { observable } = testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n\n lastValueFrom(observable).then(() => {\n expect(setDeviceSessionStateMock).toHaveBeenCalledWith({\n deviceStatus: DeviceStatus.CONNECTED,\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n currentApp: { name: \"Bitcoin\", version: \"1.0.0\" },\n });\n });\n }));\n\n it(\"should end in a success if disconnection occurs while open app succeeds\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue(\n CommandResultFactory({\n data: {\n sessionStateType:\n DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"BOLOS\", version: \"0.0.0\" },\n },\n }),\n );\n getAppAndVersionMock.mockResolvedValue(\n CommandResultFactory({\n data: {\n name: \"BOLOS\",\n version: \"0.0.0\",\n },\n }),\n );\n setupGetDeviceStatusMock([\n {\n currentApp: \"BOLOS\",\n currentAppVersion: \"0.0.0\",\n },\n {\n currentApp: \"Bitcoin\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n openAppMock.mockRejectedValue(\n new DeviceDisconnectedWhileSendingError(),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status / list apps / initial step\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get device status / onboard check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // open app (confirm)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // device status after open\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // final device status check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Completed,\n output: undefined,\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in a success if another app is open, close app succeeds and open app succeeds\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"AnotherApp\", version: \"0.0.0\" },\n });\n setupGetDeviceStatusMock([\n {\n currentApp: \"AnotherApp\",\n currentAppVersion: \"0.0.0\",\n },\n { currentApp: \"Bitcoin\", currentAppVersion: \"1.0.0\" },\n ]);\n closeAppMock.mockResolvedValue(\n CommandResultFactory({ data: undefined }),\n );\n openAppMock.mockResolvedValue(\n CommandResultFactory({ data: undefined }),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get app and version / list apps / initial step\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get device status / close app\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get device status / close app\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // open app (confirm)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get app and version\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get app and version (final)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Completed,\n output: undefined,\n },\n ];\n\n const { observable } = testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n\n lastValueFrom(observable).then(() => {\n expect(setDeviceSessionStateMock).toHaveBeenCalledWith({\n currentApp: { name: \"Bitcoin\", version: \"1.0.0\" },\n deviceStatus: DeviceStatus.CONNECTED,\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n });\n });\n }));\n });\n\n describe(\"errors cases\", () => {\n it(\"should end in an error if the device is not onboarded\", () =>\n new Promise<void>((resolve, reject) => {\n apiGetDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"mockedCurrentApp\", version: \"1.0.0\" },\n installedApps: [],\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: false,\n });\n setupGetDeviceStatusMock([new DeviceNotOnboardedError()]);\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n error: new DeviceNotOnboardedError(),\n status: DeviceActionStatus.Error,\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if the device is locked\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.LOCKED,\n currentApp: { name: \"mockedCurrentApp\", version: \"1.0.0\" },\n });\n\n setupGetDeviceStatusMock([new DeviceLockedError()]);\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new DeviceLockedError(),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if getAppAndVersion returns an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"mockedCurrentApp\", version: \"1.0.0\" },\n });\n\n setupGetDeviceStatusMock([new InvalidStatusWordError(\"mocked error\")]);\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get app and version / list apps / initial\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // device status / onboard check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new InvalidStatusWordError(\"mocked error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if the dashboard is open and open app returns an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue(\n CommandResultFactory({\n data: {\n sessionStateType:\n DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"BOLOS\", version: \"0.0.0\" },\n },\n }),\n );\n getAppAndVersionMock.mockResolvedValue(\n CommandResultFactory({\n data: {\n name: \"BOLOS\",\n version: \"0.0.0\",\n },\n }),\n );\n setupGetDeviceStatusMock([\n {\n currentApp: \"BOLOS\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n openAppMock.mockResolvedValue(\n CommandResultFactory({\n error: new InvalidStatusWordError(\"mocked error\"),\n }),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // device status / onboard check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // open app (confirm)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new InvalidStatusWordError(\"mocked error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in a success if disconnection occurs while open app failed\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue(\n CommandResultFactory({\n data: {\n sessionStateType:\n DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"BOLOS\", version: \"0.0.0\" },\n },\n }),\n );\n getAppAndVersionMock.mockResolvedValue(\n CommandResultFactory({\n data: {\n name: \"BOLOS\",\n version: \"0.0.0\",\n },\n }),\n );\n setupGetDeviceStatusMock([\n {\n currentApp: \"BOLOS\",\n currentAppVersion: \"0.0.0\",\n },\n {\n currentApp: \"BOLOS\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n openAppMock.mockRejectedValue(\n new DeviceDisconnectedWhileSendingError(),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // open app (confirm)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // device status after failure\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // final device status check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new DeviceDisconnectedWhileSendingError() as OpenAppDAError,\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if another app is open, and close app returns an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"AnotherApp\", version: \"0.0.0\" },\n });\n setupGetDeviceStatusMock([\n {\n currentApp: \"AnotherApp\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n closeAppMock.mockResolvedValue(\n CommandResultFactory({\n error: new InvalidStatusWordError(\"mocked error\"),\n }),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // close app\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new InvalidStatusWordError(\"mocked error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if another app is open, close app succeeds but open app returns an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"AnotherApp\", version: \"0.0.0\" },\n });\n setupGetDeviceStatusMock([\n {\n currentApp: \"AnotherApp\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n closeAppMock.mockResolvedValue(\n CommandResultFactory({ data: undefined }),\n );\n openAppMock.mockResolvedValue(\n CommandResultFactory({\n error: new InvalidStatusWordError(\"mocked error\"),\n }),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // close app\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // open app (confirm)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new InvalidStatusWordError(\"mocked error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if getAppAndVersion actor throws an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"mockedCurrentApp\", version: \"1.0.0\" },\n });\n\n setupGetDeviceStatusMock([new UnknownDAError(\"Unknown error\")]);\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new UnknownDAError(\"Unknown error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if openApp actor throws an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue(\n CommandResultFactory({\n data: {\n sessionStateType:\n DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"BOLOS\", version: \"0.0.0\" },\n },\n }),\n );\n setupGetDeviceStatusMock([\n {\n currentApp: \"BOLOS\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n openAppMock.mockImplementation(() => {\n throw new UnknownDAError(\"Unknown error\");\n });\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get device onboarded\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // open app (confirm)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new UnknownDAError(\"Unknown error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if closeApp actor throws an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue(\n CommandResultFactory({\n data: {\n sessionStateType:\n DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"BOLOS\", version: \"0.0.0\" },\n },\n }),\n );\n setupGetDeviceStatusMock([\n {\n currentApp: \"anApp\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n closeAppMock.mockImplementation(() => {\n throw new UnknownDAError(\"Unknown error\");\n });\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // close app\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new UnknownDAError(\"Unknown error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should emit a stopped state if the action is cancelled\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"AnotherApp\", version: \"0.0.0\" },\n });\n setupGetDeviceStatusMock([\n {\n currentApp: \"AnotherApp\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get device onboarded\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Stopped,\n },\n ];\n\n const { cancel } = testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n cancel();\n }));\n });\n});\n"],
5
- "mappings": "AAAA,OAAS,iBAAAA,MAAqB,OAE9B,OAAS,0BAAAC,MAA8B,sBACvC,OAAS,wBAAAC,MAA4B,mCACrC,OAAS,iBAAAC,MAAqB,0BAC9B,OAAS,gBAAAC,MAAoB,2BAC7B,OAAS,mCAAAC,MAAuC,oDAChD,OAAS,4BAAAC,MAAgC,qDACzC,OAAS,0BAAAC,MAA8B,2DACvC,OAAS,sBAAAC,MAA0B,6CACnC,OAAS,2BAAAC,MAA+B,mDACxC,OACE,qBAAAC,EACA,2BAAAC,EACA,kBAAAC,MACK,+BACP,OAAS,8BAAAC,MAAkC,8CAC3C,OAAS,0BAAAC,MAA8B,yCACvC,OAAS,uCAAAC,MAA2C,8BAEpD,OAAS,uBAAAC,MAA2B,wBACpC,OAGE,sBAAAC,MACK,UAEP,GAAG,KAAK,mEAAmE,EAE3E,SAAS,sBAAuB,IAAM,CACpC,MAAMC,EAAuB,GAAG,GAAG,EAC7BC,EAAc,GAAG,GAAG,EACpBC,EAAe,GAAG,GAAG,EACrBC,EAA4B,GAAG,GAAG,EAClCC,EAA4B,GAAG,GAAG,EAExC,SAASC,GAA0B,CACjC,MAAO,CACL,sBAAuBF,EACvB,sBAAuBC,EACvB,QAASH,EACT,SAAUC,CACZ,CACF,CAEA,KAAM,CAAE,sBAAuBI,CAA6B,EAC1DnB,EAAgC,EAElC,WAAW,IAAM,CACf,GAAG,cAAc,CACnB,CAAC,EAED,SAAS,2CAA4C,IAAM,CACzD,GAAG,mDAAoD,IACrD,IAAI,QAAc,CAACoB,EAASC,IAAW,CACrCF,EAA6B,gBAAgB,CAC3C,iBAAkBV,EAAuB,0BACzC,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,UAAW,QAAS,OAAQ,EAChD,cAAe,CAAC,EAChB,cAAeD,EAAc,OAC7B,0BAA2B,EAC7B,CAAC,EACDG,EAAyB,CACvB,CACE,WAAY,UACZ,kBAAmB,OACrB,CACF,CAAC,EAED,MAAMqB,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EAEKY,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,UAC3B,OAAQ,MACV,CACF,EAEAD,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,CACN,CAAC,EAED,SAAS,gBAAiB,IAAM,CAC9B,GAAG,uDAAwD,IACzD,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBAAgB,CACxC,iBAAkBP,EAAuB,0BACzC,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,UAAW,QAAS,OAAQ,CAClD,CAAC,EAEDE,EAAyB,CACvB,CACE,WAAY,UACZ,kBAAmB,OACrB,CACF,CAAC,EACD,MAAMqB,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,UAAW,cAAe,MAAU,CACxD,CAAC,EACD,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,UAC3B,OAAQ,MACV,CACF,EAEAD,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,EAEJ,GAAG,yEAA0E,IAC3E,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBAAgB,CACxC,iBAAkBP,EAAuB,0BACzC,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,QAAS,QAAS,OAAQ,CAChD,CAAC,EAEDE,EAAyB,CACvB,CACE,WAAY,UACZ,kBAAmB,OACrB,CACF,CAAC,EAEDa,EAAY,kBACVjB,EAAqB,CAAE,KAAM,MAAU,CAAC,CAC1C,EAEA,MAAMyB,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EACD,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,UAC3B,OAAQ,MACV,CACF,EAEM,CAAE,WAAAqB,CAAW,EAAItB,EACrBoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,EAEA1B,EAAc6B,CAAU,EAAE,KAAK,IAAM,CACnC,OAAOP,CAAyB,EAAE,qBAAqB,CACrD,aAAclB,EAAa,UAC3B,iBAAkBU,EAAuB,0BACzC,WAAY,CAAE,KAAM,UAAW,QAAS,OAAQ,CAClD,CAAC,CACH,CAAC,CACH,CAAC,CAAC,EAEJ,GAAG,0EAA2E,IAC5E,IAAI,QAAc,CAACW,EAASC,IAAW,CACrCL,EAA0B,gBACxBnB,EAAqB,CACnB,KAAM,CACJ,iBACEY,EAAuB,0BACzB,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,QAAS,QAAS,OAAQ,CAChD,CACF,CAAC,CACH,EACAc,EAAqB,kBACnBhB,EAAqB,CACnB,KAAM,CACJ,KAAM,QACN,QAAS,OACX,CACF,CAAC,CACH,EACAI,EAAyB,CACvB,CACE,WAAY,QACZ,kBAAmB,OACrB,EACA,CACE,WAAY,UACZ,kBAAmB,OACrB,CACF,CAAC,EACDa,EAAY,kBACV,IAAIJ,CACN,EAEA,MAAMY,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EACD,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,eACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,UAC3B,OAAQ,MACV,CACF,EAEAD,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,EAEJ,GAAG,2FAA4F,IAC7F,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBAAgB,CACxC,iBAAkBP,EAAuB,0BACzC,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,aAAc,QAAS,OAAQ,CACrD,CAAC,EACDE,EAAyB,CACvB,CACE,WAAY,aACZ,kBAAmB,OACrB,EACA,CAAE,WAAY,UAAW,kBAAmB,OAAQ,CACtD,CAAC,EACDc,EAAa,kBACXlB,EAAqB,CAAE,KAAM,MAAU,CAAC,CAC1C,EACAiB,EAAY,kBACVjB,EAAqB,CAAE,KAAM,MAAU,CAAC,CAC1C,EAEA,MAAMyB,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EACD,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,eACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,UAC3B,OAAQ,MACV,CACF,EAEM,CAAE,WAAAqB,CAAW,EAAItB,EACrBoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,EAEA1B,EAAc6B,CAAU,EAAE,KAAK,IAAM,CACnC,OAAOP,CAAyB,EAAE,qBAAqB,CACrD,WAAY,CAAE,KAAM,UAAW,QAAS,OAAQ,EAChD,aAAclB,EAAa,UAC3B,iBAAkBU,EAAuB,yBAC3C,CAAC,CACH,CAAC,CACH,CAAC,CAAC,CACN,CAAC,EAED,SAAS,eAAgB,IAAM,CAC7B,GAAG,wDAAyD,IAC1D,IAAI,QAAc,CAACW,EAASC,IAAW,CACrCF,EAA6B,gBAAgB,CAC3C,iBAAkBV,EAAuB,0BACzC,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,mBAAoB,QAAS,OAAQ,EACzD,cAAe,CAAC,EAChB,cAAeD,EAAc,OAC7B,0BAA2B,EAC7B,CAAC,EACDG,EAAyB,CAAC,IAAIK,CAAyB,CAAC,EAExD,MAAMgB,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EAEKY,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,MAAO,IAAIF,EACX,OAAQH,EAAmB,KAC7B,CACF,EAEAD,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,EAEJ,GAAG,iDAAkD,IACnD,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBAAgB,CACxC,iBAAkBP,EAAuB,0BACzC,aAAcV,EAAa,OAC3B,WAAY,CAAE,KAAM,mBAAoB,QAAS,OAAQ,CAC3D,CAAC,EAEDE,EAAyB,CAAC,IAAII,CAAmB,CAAC,EAElD,MAAMiB,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EAED,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,MAC3B,MAAO,IAAIE,CACb,CACF,EAEAH,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,EAEJ,GAAG,8DAA+D,IAChE,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBAAgB,CACxC,iBAAkBP,EAAuB,0BACzC,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,mBAAoB,QAAS,OAAQ,CAC3D,CAAC,EAEDE,EAAyB,CAAC,IAAIL,EAAuB,cAAc,CAAC,CAAC,EAErE,MAAM0B,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EAED,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,MAC3B,MAAO,IAAIP,EAAuB,cAAc,CAClD,CACF,EAEAM,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,EAEJ,GAAG,gFAAiF,IAClF,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBACxBnB,EAAqB,CACnB,KAAM,CACJ,iBACEY,EAAuB,0BACzB,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,QAAS,QAAS,OAAQ,CAChD,CACF,CAAC,CACH,EACAc,EAAqB,kBACnBhB,EAAqB,CACnB,KAAM,CACJ,KAAM,QACN,QAAS,OACX,CACF,CAAC,CACH,EACAI,EAAyB,CACvB,CACE,WAAY,QACZ,kBAAmB,OACrB,CACF,CAAC,EACDa,EAAY,kBACVjB,EAAqB,CACnB,MAAO,IAAID,EAAuB,cAAc,CAClD,CAAC,CACH,EAEA,MAAM0B,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EACD,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,eACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,MAC3B,MAAO,IAAIP,EAAuB,cAAc,CAClD,CACF,EAEAM,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,EAEJ,GAAG,wEAAyE,IAC1E,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBACxBnB,EAAqB,CACnB,KAAM,CACJ,iBACEY,EAAuB,0BACzB,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,QAAS,QAAS,OAAQ,CAChD,CACF,CAAC,CACH,EACAc,EAAqB,kBACnBhB,EAAqB,CACnB,KAAM,CACJ,KAAM,QACN,QAAS,OACX,CACF,CAAC,CACH,EACAI,EAAyB,CACvB,CACE,WAAY,QACZ,kBAAmB,OACrB,EACA,CACE,WAAY,QACZ,kBAAmB,OACrB,CACF,CAAC,EACDa,EAAY,kBACV,IAAIJ,CACN,EAEA,MAAMY,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EACD,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,eACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,MAC3B,MAAO,IAAIO,CACb,CACF,EAEAR,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,EAEJ,GAAG,gFAAiF,IAClF,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBAAgB,CACxC,iBAAkBP,EAAuB,0BACzC,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,aAAc,QAAS,OAAQ,CACrD,CAAC,EACDE,EAAyB,CACvB,CACE,WAAY,aACZ,kBAAmB,OACrB,CACF,CAAC,EACDc,EAAa,kBACXlB,EAAqB,CACnB,MAAO,IAAID,EAAuB,cAAc,CAClD,CAAC,CACH,EAEA,MAAM0B,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EACD,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,MAC3B,MAAO,IAAIP,EAAuB,cAAc,CAClD,CACF,EAEAM,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,EAEJ,GAAG,kGAAmG,IACpG,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBAAgB,CACxC,iBAAkBP,EAAuB,0BACzC,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,aAAc,QAAS,OAAQ,CACrD,CAAC,EACDE,EAAyB,CACvB,CACE,WAAY,aACZ,kBAAmB,OACrB,CACF,CAAC,EACDc,EAAa,kBACXlB,EAAqB,CAAE,KAAM,MAAU,CAAC,CAC1C,EACAiB,EAAY,kBACVjB,EAAqB,CACnB,MAAO,IAAID,EAAuB,cAAc,CAClD,CAAC,CACH,EAEA,MAAM0B,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EACD,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,eACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,MAC3B,MAAO,IAAIP,EAAuB,cAAc,CAClD,CACF,EAEAM,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,EAEJ,GAAG,mEAAoE,IACrE,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBAAgB,CACxC,iBAAkBP,EAAuB,0BACzC,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,mBAAoB,QAAS,OAAQ,CAC3D,CAAC,EAEDE,EAAyB,CAAC,IAAIM,EAAe,eAAe,CAAC,CAAC,EAE9D,MAAMe,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EAED,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,MAC3B,MAAO,IAAII,EAAe,eAAe,CAC3C,CACF,EAEAL,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,EAEJ,GAAG,0DAA2D,IAC5D,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBACxBnB,EAAqB,CACnB,KAAM,CACJ,iBACEY,EAAuB,0BACzB,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,QAAS,QAAS,OAAQ,CAChD,CACF,CAAC,CACH,EACAE,EAAyB,CACvB,CACE,WAAY,QACZ,kBAAmB,OACrB,CACF,CAAC,EACDa,EAAY,mBAAmB,IAAM,CACnC,MAAM,IAAIP,EAAe,eAAe,CAC1C,CAAC,EAED,MAAMe,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EACD,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,eACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,MAC3B,MAAO,IAAII,EAAe,eAAe,CAC3C,CACF,EAEAL,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,EAEJ,GAAG,2DAA4D,IAC7D,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBACxBnB,EAAqB,CACnB,KAAM,CACJ,iBACEY,EAAuB,0BACzB,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,QAAS,QAAS,OAAQ,CAChD,CACF,CAAC,CACH,EACAE,EAAyB,CACvB,CACE,WAAY,QACZ,kBAAmB,OACrB,CACF,CAAC,EACDc,EAAa,mBAAmB,IAAM,CACpC,MAAM,IAAIR,EAAe,eAAe,CAC1C,CAAC,EAED,MAAMe,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EACD,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,MAC3B,MAAO,IAAII,EAAe,eAAe,CAC3C,CACF,EAEAL,EACEoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,CACF,CAAC,CAAC,EAEJ,GAAG,yDAA0D,IAC3D,IAAI,QAAc,CAACD,EAASC,IAAW,CACrCL,EAA0B,gBAAgB,CACxC,iBAAkBP,EAAuB,0BACzC,aAAcV,EAAa,UAC3B,WAAY,CAAE,KAAM,aAAc,QAAS,OAAQ,CACrD,CAAC,EACDE,EAAyB,CACvB,CACE,WAAY,aACZ,kBAAmB,OACrB,CACF,CAAC,EAED,MAAMqB,EAAsB,IAAIX,EAAoB,CAClD,MAAO,CAAE,QAAS,SAAU,CAC9B,CAAC,EACD,GAAG,MAAMW,EAAqB,qBAAqB,EAAE,gBACnDJ,EAAwB,CAC1B,EAEA,MAAMK,EAAwC,CAC5C,CACE,OAAQpB,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMQ,EAAmB,iBAC3B,CACF,EACA,CACE,OAAQT,EAAmB,QAC3B,kBAAmB,CACjB,wBAAyBC,EAAwB,KACjD,KAAMI,EAA2B,aACnC,CACF,EACA,CACE,OAAQL,EAAmB,OAC7B,CACF,EAEM,CAAE,OAAAsB,CAAO,EAAIvB,EACjBoB,EACAC,EACAvB,EAAgC,EAChC,CACE,OAAQoB,EACR,QAASC,CACX,CACF,EACAI,EAAO,CACT,CAAC,CAAC,CACN,CAAC,CACH,CAAC",
4
+ "sourcesContent": ["import { lastValueFrom } from \"rxjs\";\n\nimport { InvalidStatusWordError } from \"@api/command/Errors\";\nimport { CommandResultFactory } from \"@api/command/model/CommandResult\";\nimport { DeviceModelId } from \"@api/device/DeviceModel\";\nimport { DeviceStatus } from \"@api/device/DeviceStatus\";\nimport { makeDeviceActionInternalApiMock } from \"@api/device-action/__test-utils__/makeInternalApi\";\nimport { setupGetDeviceStatusMock } from \"@api/device-action/__test-utils__/setupTestMachine\";\nimport { testDeviceActionStates } from \"@api/device-action/__test-utils__/testDeviceActionStates\";\nimport { DeviceActionStatus } from \"@api/device-action/model/DeviceActionState\";\nimport { UserInteractionRequired } from \"@api/device-action/model/UserInteractionRequired\";\nimport {\n DeviceLockedError,\n DeviceNotOnboardedError,\n UnknownDAError,\n} from \"@api/device-action/os/Errors\";\nimport { getDeviceStatusDAStateStep } from \"@api/device-action/os/GetDeviceStatus/types\";\nimport { DeviceSessionStateType } from \"@api/device-session/DeviceSessionState\";\nimport { DeviceDisconnectedWhileSendingError } from \"@api/transport/model/Errors\";\n\nimport { OpenAppDeviceAction } from \"./OpenAppDeviceAction\";\nimport {\n type OpenAppDAError,\n type OpenAppDAState,\n openAppDAStateStep,\n} from \"./types\";\n\nvi.mock(\"@api/device-action/os/GetDeviceStatus/GetDeviceStatusDeviceAction\");\n\ndescribe(\"OpenAppDeviceAction\", () => {\n const getAppAndVersionMock = vi.fn();\n const openAppMock = vi.fn();\n const closeAppMock = vi.fn();\n const getDeviceSessionStateMock = vi.fn();\n const setDeviceSessionStateMock = vi.fn();\n\n function extractDependenciesMock() {\n return {\n getDeviceSessionState: getDeviceSessionStateMock,\n setDeviceSessionState: setDeviceSessionStateMock,\n openApp: openAppMock,\n closeApp: closeAppMock,\n };\n }\n\n const { getDeviceSessionState: apiGetDeviceSessionStateMock } =\n makeDeviceActionInternalApiMock();\n\n beforeEach(() => {\n vi.resetAllMocks();\n });\n\n describe(\"without overriding `extractDependencies`\", () => {\n it(\"should end if the required application is opened\", () =>\n new Promise<void>((resolve, reject) => {\n apiGetDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"Bitcoin\", version: \"1.0.0\" },\n installedApps: [],\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: false,\n });\n setupGetDeviceStatusMock([\n {\n currentApp: \"Bitcoin\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarding status / list apps / initial step\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get device status / onboard check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Completed,\n output: undefined,\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n });\n\n describe(\"success cases\", () => {\n it(\"should end in a success if the app is already opened\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"Bitcoin\", version: \"1.0.0\" },\n });\n\n setupGetDeviceStatusMock([\n {\n currentApp: \"Bitcoin\",\n currentAppVersion: \"1.0.0\",\n },\n ]);\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\", unlockTimeout: undefined },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarding status / list apps / initial step\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get app and version / onboard check / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Completed,\n output: undefined,\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in a success if the dashboard is open and open app succeeds\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"BOLOS\", version: \"0.0.0\" },\n });\n\n setupGetDeviceStatusMock([\n {\n currentApp: \"Bitcoin\",\n currentAppVersion: \"1.0.0\",\n },\n ]);\n\n openAppMock.mockResolvedValue(\n CommandResultFactory({ data: undefined }),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get app and version /list apps / initial step\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get app and version / onboard check / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Completed,\n output: undefined,\n },\n ];\n\n const { observable } = testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n\n lastValueFrom(observable).then(() => {\n expect(setDeviceSessionStateMock).toHaveBeenCalledWith({\n deviceStatus: DeviceStatus.CONNECTED,\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n currentApp: { name: \"Bitcoin\", version: \"1.0.0\" },\n });\n });\n }));\n\n it(\"should end in a success if disconnection occurs while open app succeeds\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue(\n CommandResultFactory({\n data: {\n sessionStateType:\n DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"BOLOS\", version: \"0.0.0\" },\n },\n }),\n );\n getAppAndVersionMock.mockResolvedValue(\n CommandResultFactory({\n data: {\n name: \"BOLOS\",\n version: \"0.0.0\",\n },\n }),\n );\n setupGetDeviceStatusMock([\n {\n currentApp: \"BOLOS\",\n currentAppVersion: \"0.0.0\",\n },\n {\n currentApp: \"Bitcoin\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n openAppMock.mockRejectedValue(\n new DeviceDisconnectedWhileSendingError(),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status / list apps / initial step\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get device status / onboard check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // open app (confirm)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // device status after open\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // final device status check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Completed,\n output: undefined,\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in a success if another app is open, close app succeeds and open app succeeds\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"AnotherApp\", version: \"0.0.0\" },\n });\n setupGetDeviceStatusMock([\n {\n currentApp: \"AnotherApp\",\n currentAppVersion: \"0.0.0\",\n },\n { currentApp: \"Bitcoin\", currentAppVersion: \"1.0.0\" },\n ]);\n closeAppMock.mockResolvedValue(\n CommandResultFactory({ data: undefined }),\n );\n openAppMock.mockResolvedValue(\n CommandResultFactory({ data: undefined }),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get app and version / list apps / initial step\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get device status / close app\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get device status / close app\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // open app (confirm)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get app and version\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // get app and version (final)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Completed,\n output: undefined,\n },\n ];\n\n const { observable } = testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n\n lastValueFrom(observable).then(() => {\n expect(setDeviceSessionStateMock).toHaveBeenCalledWith({\n currentApp: { name: \"Bitcoin\", version: \"1.0.0\" },\n deviceStatus: DeviceStatus.CONNECTED,\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n });\n });\n }));\n });\n\n describe(\"errors cases\", () => {\n it(\"GIVEN a non-onboarded device WHEN opening an app THEN it blocks the app flow\", () =>\n new Promise<void>((resolve, reject) => {\n // GIVEN\n apiGetDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"mockedCurrentApp\", version: \"1.0.0\" },\n installedApps: [],\n deviceModelId: DeviceModelId.NANO_X,\n isSecureConnectionAllowed: false,\n });\n setupGetDeviceStatusMock([new DeviceNotOnboardedError()]);\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n error: new DeviceNotOnboardedError(),\n status: DeviceActionStatus.Error,\n },\n ];\n\n // WHEN\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n // THEN\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if the device is locked\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.LOCKED,\n currentApp: { name: \"mockedCurrentApp\", version: \"1.0.0\" },\n });\n\n setupGetDeviceStatusMock([new DeviceLockedError()]);\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending,\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new DeviceLockedError(),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if getAppAndVersion returns an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"mockedCurrentApp\", version: \"1.0.0\" },\n });\n\n setupGetDeviceStatusMock([new InvalidStatusWordError(\"mocked error\")]);\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get app and version / list apps / initial\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // device status / onboard check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new InvalidStatusWordError(\"mocked error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if the dashboard is open and open app returns an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue(\n CommandResultFactory({\n data: {\n sessionStateType:\n DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"BOLOS\", version: \"0.0.0\" },\n },\n }),\n );\n getAppAndVersionMock.mockResolvedValue(\n CommandResultFactory({\n data: {\n name: \"BOLOS\",\n version: \"0.0.0\",\n },\n }),\n );\n setupGetDeviceStatusMock([\n {\n currentApp: \"BOLOS\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n openAppMock.mockResolvedValue(\n CommandResultFactory({\n error: new InvalidStatusWordError(\"mocked error\"),\n }),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // device status / onboard check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // open app (confirm)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new InvalidStatusWordError(\"mocked error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in a success if disconnection occurs while open app failed\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue(\n CommandResultFactory({\n data: {\n sessionStateType:\n DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"BOLOS\", version: \"0.0.0\" },\n },\n }),\n );\n getAppAndVersionMock.mockResolvedValue(\n CommandResultFactory({\n data: {\n name: \"BOLOS\",\n version: \"0.0.0\",\n },\n }),\n );\n setupGetDeviceStatusMock([\n {\n currentApp: \"BOLOS\",\n currentAppVersion: \"0.0.0\",\n },\n {\n currentApp: \"BOLOS\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n openAppMock.mockRejectedValue(\n new DeviceDisconnectedWhileSendingError(),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // open app (confirm)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // device status after failure\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // final device status check\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new DeviceDisconnectedWhileSendingError() as OpenAppDAError,\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if another app is open, and close app returns an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"AnotherApp\", version: \"0.0.0\" },\n });\n setupGetDeviceStatusMock([\n {\n currentApp: \"AnotherApp\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n closeAppMock.mockResolvedValue(\n CommandResultFactory({\n error: new InvalidStatusWordError(\"mocked error\"),\n }),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // close app\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new InvalidStatusWordError(\"mocked error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if another app is open, close app succeeds but open app returns an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"AnotherApp\", version: \"0.0.0\" },\n });\n setupGetDeviceStatusMock([\n {\n currentApp: \"AnotherApp\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n closeAppMock.mockResolvedValue(\n CommandResultFactory({ data: undefined }),\n );\n openAppMock.mockResolvedValue(\n CommandResultFactory({\n error: new InvalidStatusWordError(\"mocked error\"),\n }),\n );\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // close app\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // open app (confirm)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new InvalidStatusWordError(\"mocked error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if getAppAndVersion actor throws an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"mockedCurrentApp\", version: \"1.0.0\" },\n });\n\n setupGetDeviceStatusMock([new UnknownDAError(\"Unknown error\")]);\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new UnknownDAError(\"Unknown error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if openApp actor throws an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue(\n CommandResultFactory({\n data: {\n sessionStateType:\n DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"BOLOS\", version: \"0.0.0\" },\n },\n }),\n );\n setupGetDeviceStatusMock([\n {\n currentApp: \"BOLOS\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n openAppMock.mockImplementation(() => {\n throw new UnknownDAError(\"Unknown error\");\n });\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get device onboarded\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // open app (confirm)\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.ConfirmOpenApp,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new UnknownDAError(\"Unknown error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should end in an error if closeApp actor throws an error\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue(\n CommandResultFactory({\n data: {\n sessionStateType:\n DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"BOLOS\", version: \"0.0.0\" },\n },\n }),\n );\n setupGetDeviceStatusMock([\n {\n currentApp: \"anApp\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n closeAppMock.mockImplementation(() => {\n throw new UnknownDAError(\"Unknown error\");\n });\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get onboarded status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Pending, // close app\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Error,\n error: new UnknownDAError(\"Unknown error\"),\n },\n ];\n\n testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n }));\n\n it(\"should emit a stopped state if the action is cancelled\", () =>\n new Promise<void>((resolve, reject) => {\n getDeviceSessionStateMock.mockReturnValue({\n sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,\n deviceStatus: DeviceStatus.CONNECTED,\n currentApp: { name: \"AnotherApp\", version: \"0.0.0\" },\n });\n setupGetDeviceStatusMock([\n {\n currentApp: \"AnotherApp\",\n currentAppVersion: \"0.0.0\",\n },\n ]);\n\n const openAppDeviceAction = new OpenAppDeviceAction({\n input: { appName: \"Bitcoin\" },\n });\n vi.spyOn(openAppDeviceAction, \"extractDependencies\").mockReturnValue(\n extractDependenciesMock(),\n );\n\n const expectedStates: Array<OpenAppDAState> = [\n {\n status: DeviceActionStatus.Pending, // get device onboarded\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: openAppDAStateStep.GET_DEVICE_STATUS,\n },\n },\n {\n status: DeviceActionStatus.Pending, // onboard / device status\n intermediateValue: {\n requiredUserInteraction: UserInteractionRequired.None,\n step: getDeviceStatusDAStateStep.ONBOARD_CHECK,\n },\n },\n {\n status: DeviceActionStatus.Stopped,\n },\n ];\n\n const { cancel } = testDeviceActionStates(\n openAppDeviceAction,\n expectedStates,\n makeDeviceActionInternalApiMock(),\n {\n onDone: resolve,\n onError: reject,\n },\n );\n cancel();\n }));\n });\n});\n"],
5
+ "mappings": "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",
6
6
  "names": ["lastValueFrom", "InvalidStatusWordError", "CommandResultFactory", "DeviceModelId", "DeviceStatus", "makeDeviceActionInternalApiMock", "setupGetDeviceStatusMock", "testDeviceActionStates", "DeviceActionStatus", "UserInteractionRequired", "DeviceLockedError", "DeviceNotOnboardedError", "UnknownDAError", "getDeviceStatusDAStateStep", "DeviceSessionStateType", "DeviceDisconnectedWhileSendingError", "OpenAppDeviceAction", "openAppDAStateStep", "getAppAndVersionMock", "openAppMock", "closeAppMock", "getDeviceSessionStateMock", "setDeviceSessionStateMock", "extractDependenciesMock", "apiGetDeviceSessionStateMock", "resolve", "reject", "openAppDeviceAction", "expectedStates", "observable", "cancel"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/api/device-action/os/OpenAppDeviceAction/types.ts"],
4
- "sourcesContent": ["import { type CommandErrorResult } from \"@api/command/model/CommandResult\";\nimport { type OpenAppErrorCodes } from \"@api/command/os/OpenAppCommand\";\nimport { type DeviceActionState } from \"@api/device-action/model/DeviceActionState\";\nimport { type UserInteractionRequired } from \"@api/device-action/model/UserInteractionRequired\";\nimport {\n type DeviceLockedError,\n type DeviceNotOnboardedError,\n type UnknownDAError,\n} from \"@api/device-action/os/Errors\";\nimport {\n type GetDeviceStatusDAInput,\n type GetDeviceStatusDAStateStep,\n} from \"@api/device-action/os/GetDeviceStatus/types\";\n\nexport const openAppDAStateStep = Object.freeze({\n LIST_APPS: \"os.openApp.steps.listApps\",\n ONBOARD_CHECK: \"os.openApp.steps.onboardCheck\",\n GET_DEVICE_STATUS: \"os.openApp.steps.getDeviceStatus\",\n DASHBOARD_CHECK: \"os.openApp.steps.dashboardCheck\",\n CONFIRM_OPEN_APP: \"os.openApp.steps.confirmOpenApp\",\n CLOSE_APP: \"os.openApp.steps.closeApp\",\n} as const);\n\nexport type OpenAppDAStateStep =\n (typeof openAppDAStateStep)[keyof typeof openAppDAStateStep];\n\nexport type OpenAppDAOutput = void;\n\nexport type OpenAppDAInput = GetDeviceStatusDAInput & {\n readonly appName: string;\n};\n\nexport type OpenAppDAError =\n | DeviceNotOnboardedError\n | DeviceLockedError\n | UnknownDAError\n | CommandErrorResult<OpenAppErrorCodes | void>[\"error\"];\n\nexport type OpenAppDARequiredInteraction =\n | UserInteractionRequired.None\n | UserInteractionRequired.UnlockDevice\n | UserInteractionRequired.ConfirmOpenApp;\n\nexport type OpenAppDAIntermediateValue = {\n readonly requiredUserInteraction: OpenAppDARequiredInteraction;\n readonly step: OpenAppDAStateStep | GetDeviceStatusDAStateStep;\n};\n\nexport type OpenAppDAState = DeviceActionState<\n OpenAppDAOutput,\n OpenAppDAError,\n OpenAppDAIntermediateValue\n>;\n"],
4
+ "sourcesContent": ["import { type CommandErrorResult } from \"@api/command/model/CommandResult\";\nimport { type OpenAppErrorCodes } from \"@api/command/os/OpenAppCommand\";\nimport { type DeviceActionState } from \"@api/device-action/model/DeviceActionState\";\nimport { type UserInteractionRequired } from \"@api/device-action/model/UserInteractionRequired\";\nimport {\n type DeviceLockedError,\n type DeviceNotOnboardedError,\n type UnknownDAError,\n} from \"@api/device-action/os/Errors\";\nimport {\n type GetDeviceStatusDAInput,\n type GetDeviceStatusDAStateStep,\n} from \"@api/device-action/os/GetDeviceStatus/types\";\n\nexport const openAppDAStateStep = Object.freeze({\n LIST_APPS: \"os.openApp.steps.listApps\",\n ONBOARD_CHECK: \"os.openApp.steps.onboardCheck\",\n GET_DEVICE_STATUS: \"os.openApp.steps.getDeviceStatus\",\n DASHBOARD_CHECK: \"os.openApp.steps.dashboardCheck\",\n CONFIRM_OPEN_APP: \"os.openApp.steps.confirmOpenApp\",\n CLOSE_APP: \"os.openApp.steps.closeApp\",\n} as const);\n\nexport type OpenAppDAStateStep =\n (typeof openAppDAStateStep)[keyof typeof openAppDAStateStep];\n\nexport type OpenAppDAOutput = void;\n\nexport type OpenAppDAInput = Omit<\n GetDeviceStatusDAInput,\n \"allowNonOnboardedDevice\"\n> & {\n readonly appName: string;\n};\n\nexport type OpenAppDAError =\n | DeviceNotOnboardedError\n | DeviceLockedError\n | UnknownDAError\n | CommandErrorResult<OpenAppErrorCodes | void>[\"error\"];\n\nexport type OpenAppDARequiredInteraction =\n | UserInteractionRequired.None\n | UserInteractionRequired.UnlockDevice\n | UserInteractionRequired.ConfirmOpenApp;\n\nexport type OpenAppDAIntermediateValue = {\n readonly requiredUserInteraction: OpenAppDARequiredInteraction;\n readonly step: OpenAppDAStateStep | GetDeviceStatusDAStateStep;\n};\n\nexport type OpenAppDAState = DeviceActionState<\n OpenAppDAOutput,\n OpenAppDAError,\n OpenAppDAIntermediateValue\n>;\n"],
5
5
  "mappings": "AAcO,MAAMA,EAAqB,OAAO,OAAO,CAC9C,UAAW,4BACX,cAAe,gCACf,kBAAmB,mCACnB,gBAAiB,kCACjB,iBAAkB,kCAClB,UAAW,2BACb,CAAU",
6
6
  "names": ["openAppDAStateStep"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/api/device-action/os/OpenAppWithDependencies/types.ts"],
4
- "sourcesContent": ["import type { CommandErrorResult } from \"@api/command/model/CommandResult\";\nimport type { DeviceActionState } from \"@api/device-action/model/DeviceActionState\";\nimport type {\n UnknownDAError,\n UnsupportedFirmwareDAError,\n} from \"@api/device-action/os/Errors\";\nimport type {\n GetDeviceMetadataDAOutput,\n GetDeviceMetadataDARequiredInteraction,\n} from \"@api/device-action/os/GetDeviceMetadata/types\";\nimport type { GetDeviceStatusDAInput } from \"@api/device-action/os/GetDeviceStatus/types\";\nimport type {\n ApplicationDependency,\n InstallOrUpdateAppsDAError,\n InstallOrUpdateAppsDAOutput,\n InstallOrUpdateAppsDARequiredInteraction,\n InstallPlan,\n} from \"@api/device-action/os/InstallOrUpdateApps/types\";\nimport type {\n OpenAppDAError,\n OpenAppDARequiredInteraction,\n} from \"@api/device-action/os/OpenAppDeviceAction/types\";\n\nexport const openAppWithDependenciesDAStateStep = Object.freeze({\n GET_DEVICE_METADATA: \"os.openAppWithDependencies.steps.getDeviceMetadata\",\n INSTALL_OR_UPDATE_APPS:\n \"os.openAppWithDependencies.steps.installOrUpdateApps\",\n OPEN_APP: \"os.openAppWithDependencies.steps.openApp\",\n} as const);\n\nexport type OpenAppWithDependenciesDAStateStep =\n (typeof openAppWithDependenciesDAStateStep)[keyof typeof openAppWithDependenciesDAStateStep];\n\nexport type OpenAppWithDependenciesDAOutput = {\n deviceMetadata: GetDeviceMetadataDAOutput;\n installResult: InstallOrUpdateAppsDAOutput;\n};\n\nexport type OpenAppWithDependenciesDAInput = GetDeviceStatusDAInput & {\n readonly application: ApplicationDependency;\n readonly dependencies: ApplicationDependency[];\n readonly requireLatestFirmware?: boolean;\n readonly allowMissingApplication?: boolean;\n};\n\nexport type OpenAppWithDependenciesDAError =\n | InstallOrUpdateAppsDAError\n | OpenAppDAError\n | UnknownDAError\n | UnsupportedFirmwareDAError\n | CommandErrorResult[\"error\"];\n\nexport type OpenAppWithDependenciesDARequiredInteraction =\n | GetDeviceMetadataDARequiredInteraction\n | InstallOrUpdateAppsDARequiredInteraction\n | OpenAppDARequiredInteraction;\n\nexport type OpenAppWithDependenciesDAIntermediateValue = {\n requiredUserInteraction: OpenAppWithDependenciesDARequiredInteraction;\n installPlan: InstallPlan | null;\n deviceId?: Uint8Array;\n step: OpenAppWithDependenciesDAStateStep;\n};\n\nexport type OpenAppWithDependenciesDAState = DeviceActionState<\n OpenAppWithDependenciesDAOutput,\n OpenAppWithDependenciesDAError,\n OpenAppWithDependenciesDAIntermediateValue\n>;\n"],
4
+ "sourcesContent": ["import type { CommandErrorResult } from \"@api/command/model/CommandResult\";\nimport type { DeviceActionState } from \"@api/device-action/model/DeviceActionState\";\nimport type {\n UnknownDAError,\n UnsupportedFirmwareDAError,\n} from \"@api/device-action/os/Errors\";\nimport type {\n GetDeviceMetadataDAOutput,\n GetDeviceMetadataDARequiredInteraction,\n} from \"@api/device-action/os/GetDeviceMetadata/types\";\nimport type { GetDeviceStatusDAInput } from \"@api/device-action/os/GetDeviceStatus/types\";\nimport type {\n ApplicationDependency,\n InstallOrUpdateAppsDAError,\n InstallOrUpdateAppsDAOutput,\n InstallOrUpdateAppsDARequiredInteraction,\n InstallPlan,\n} from \"@api/device-action/os/InstallOrUpdateApps/types\";\nimport type {\n OpenAppDAError,\n OpenAppDARequiredInteraction,\n} from \"@api/device-action/os/OpenAppDeviceAction/types\";\n\nexport const openAppWithDependenciesDAStateStep = Object.freeze({\n GET_DEVICE_METADATA: \"os.openAppWithDependencies.steps.getDeviceMetadata\",\n INSTALL_OR_UPDATE_APPS:\n \"os.openAppWithDependencies.steps.installOrUpdateApps\",\n OPEN_APP: \"os.openAppWithDependencies.steps.openApp\",\n} as const);\n\nexport type OpenAppWithDependenciesDAStateStep =\n (typeof openAppWithDependenciesDAStateStep)[keyof typeof openAppWithDependenciesDAStateStep];\n\nexport type OpenAppWithDependenciesDAOutput = {\n deviceMetadata: GetDeviceMetadataDAOutput;\n installResult: InstallOrUpdateAppsDAOutput;\n};\n\nexport type OpenAppWithDependenciesDAInput = Omit<\n GetDeviceStatusDAInput,\n \"allowNonOnboardedDevice\"\n> & {\n readonly application: ApplicationDependency;\n readonly dependencies: ApplicationDependency[];\n readonly requireLatestFirmware?: boolean;\n readonly allowMissingApplication?: boolean;\n};\n\nexport type OpenAppWithDependenciesDAError =\n | InstallOrUpdateAppsDAError\n | OpenAppDAError\n | UnknownDAError\n | UnsupportedFirmwareDAError\n | CommandErrorResult[\"error\"];\n\nexport type OpenAppWithDependenciesDARequiredInteraction =\n | GetDeviceMetadataDARequiredInteraction\n | InstallOrUpdateAppsDARequiredInteraction\n | OpenAppDARequiredInteraction;\n\nexport type OpenAppWithDependenciesDAIntermediateValue = {\n requiredUserInteraction: OpenAppWithDependenciesDARequiredInteraction;\n installPlan: InstallPlan | null;\n deviceId?: Uint8Array;\n step: OpenAppWithDependenciesDAStateStep;\n};\n\nexport type OpenAppWithDependenciesDAState = DeviceActionState<\n OpenAppWithDependenciesDAOutput,\n OpenAppWithDependenciesDAError,\n OpenAppWithDependenciesDAIntermediateValue\n>;\n"],
5
5
  "mappings": "AAuBO,MAAMA,EAAqC,OAAO,OAAO,CAC9D,oBAAqB,qDACrB,uBACE,uDACF,SAAU,0CACZ,CAAU",
6
6
  "names": ["openAppWithDependenciesDAStateStep"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/api/logger-subscriber/service/WebLogsExporterLogger.ts"],
4
- "sourcesContent": ["import { LogLevel } from \"@api/logger-subscriber/model/LogLevel\";\nimport { type LogSubscriberOptions } from \"@api/types\";\nimport { DeviceSession } from \"@internal/device-session/model/DeviceSession\";\n\nimport { type LoggerSubscriberService } from \"./LoggerSubscriberService\";\n\n/**\n * This function is used to format the logs to JSON format,\n * remove circular dependencies and do some extra formatting.\n * */\nexport function getJSONStringifyReplacer(): (\n key: string,\n value: unknown,\n) => unknown {\n const ancestors: unknown[] = [];\n return function (_: string, value: unknown): unknown {\n // format Uint8Array values to more readable format\n if (value instanceof Uint8Array) {\n const bytesHex = Array.from(value).map((x) =>\n x.toString(16).padStart(2, \"0\"),\n );\n return {\n hex: \"0x\" + bytesHex.join(\"\"),\n readableHex: bytesHex.join(\" \"),\n value: value.toString(),\n };\n }\n\n // format DeviceSession values to avoid huge object in logs\n if (value instanceof DeviceSession) {\n const {\n connectedDevice: { deviceModel, type, id },\n } = value;\n return {\n id: value.id,\n connectedDevice: {\n deviceModel,\n type,\n id,\n },\n };\n }\n\n // format circular references to \"[Circular]\"\n // Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value#circular_references\n if (typeof value !== \"object\" || value === null) {\n return value;\n }\n // `this` is the object that value is contained in,\n // i.e., its direct parent.\n // @ts-expect-error cf. comment above\n while (ancestors.length > 0 && ancestors.at(-1) !== (this as unknown)) {\n ancestors.pop();\n }\n if (ancestors.includes(value)) {\n return \"[Circular]\";\n }\n ancestors.push(value);\n return value;\n };\n}\n\nexport class WebLogsExporterLogger implements LoggerSubscriberService {\n private logs: Array<\n [level: LogLevel, message: string, options: LogSubscriberOptions]\n > = [];\n\n log(level: LogLevel, message: string, options: LogSubscriberOptions): void {\n this.logs.push([level, message, options]);\n }\n\n private formatLogsToJSON(): string {\n const remappedLogs = this.logs.map(([level, message, options]) => {\n const { timestamp, ...restOptions } = options;\n return {\n level: LogLevel[level],\n message,\n options: {\n ...restOptions,\n date: new Date(options.timestamp),\n },\n };\n });\n\n return JSON.stringify(remappedLogs, getJSONStringifyReplacer(), 2);\n }\n\n /**\n * Export logs to JSON file.\n */\n public exportLogsToJSON(): void {\n const logs = this.formatLogsToJSON();\n const blob = new Blob([logs], { type: \"application/json\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `ledger-device-management-kit-logs-${new Date().toISOString()}.json`;\n a.click();\n }\n}\n"],
5
- "mappings": "AAAA,OAAS,YAAAA,MAAgB,wCAEzB,OAAS,iBAAAC,MAAqB,+CAQvB,SAASC,GAGH,CACX,MAAMC,EAAuB,CAAC,EAC9B,OAAO,SAAUC,EAAWC,EAAyB,CAEnD,GAAIA,aAAiB,WAAY,CAC/B,MAAMC,EAAW,MAAM,KAAKD,CAAK,EAAE,IAAKE,GACtCA,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAChC,EACA,MAAO,CACL,IAAK,KAAOD,EAAS,KAAK,EAAE,EAC5B,YAAaA,EAAS,KAAK,GAAG,EAC9B,MAAOD,EAAM,SAAS,CACxB,CACF,CAGA,GAAIA,aAAiBJ,EAAe,CAClC,KAAM,CACJ,gBAAiB,CAAE,YAAAO,EAAa,KAAAC,EAAM,GAAAC,CAAG,CAC3C,EAAIL,EACJ,MAAO,CACL,GAAIA,EAAM,GACV,gBAAiB,CACf,YAAAG,EACA,KAAAC,EACA,GAAAC,CACF,CACF,CACF,CAIA,GAAI,OAAOL,GAAU,UAAYA,IAAU,KACzC,OAAOA,EAKT,KAAOF,EAAU,OAAS,GAAKA,EAAU,GAAG,EAAE,IAAO,MACnDA,EAAU,IAAI,EAEhB,OAAIA,EAAU,SAASE,CAAK,EACnB,cAETF,EAAU,KAAKE,CAAK,EACbA,EACT,CACF,CAEO,MAAMM,CAAyD,CAC5D,KAEJ,CAAC,EAEL,IAAIC,EAAiBC,EAAiBC,EAAqC,CACzE,KAAK,KAAK,KAAK,CAACF,EAAOC,EAASC,CAAO,CAAC,CAC1C,CAEQ,kBAA2B,CACjC,MAAMC,EAAe,KAAK,KAAK,IAAI,CAAC,CAACH,EAAOC,EAASC,CAAO,IAAM,CAChE,KAAM,CAAE,UAAAE,EAAW,GAAGC,CAAY,EAAIH,EACtC,MAAO,CACL,MAAOd,EAASY,CAAK,EACrB,QAAAC,EACA,QAAS,CACP,GAAGI,EACH,KAAM,IAAI,KAAKH,EAAQ,SAAS,CAClC,CACF,CACF,CAAC,EAED,OAAO,KAAK,UAAUC,EAAcb,EAAyB,EAAG,CAAC,CACnE,CAKO,kBAAyB,CAC9B,MAAMgB,EAAO,KAAK,iBAAiB,EAC7BC,EAAO,IAAI,KAAK,CAACD,CAAI,EAAG,CAAE,KAAM,kBAAmB,CAAC,EACpDE,EAAM,IAAI,gBAAgBD,CAAI,EAC9BE,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,KAAOD,EACTC,EAAE,SAAW,qCAAqC,IAAI,KAAK,EAAE,YAAY,CAAC,QAC1EA,EAAE,MAAM,CACV,CACF",
4
+ "sourcesContent": ["import { LogLevel } from \"@api/logger-subscriber/model/LogLevel\";\nimport { type LogSubscriberOptions } from \"@api/types\";\nimport { DeviceSession } from \"@internal/device-session/model/DeviceSession\";\n\nimport { type LoggerSubscriberService } from \"./LoggerSubscriberService\";\n\n/**\n * This function is used to format the logs to JSON format,\n * remove circular dependencies and do some extra formatting.\n * */\nexport function getJSONStringifyReplacer(): (\n key: string,\n value: unknown,\n) => unknown {\n const ancestors: unknown[] = [];\n return function (_: string, value: unknown): unknown {\n // format Uint8Array values to more readable format\n if (value instanceof Uint8Array) {\n const bytesHex = Array.from(value).map((x) =>\n x.toString(16).padStart(2, \"0\"),\n );\n return {\n hex: \"0x\" + bytesHex.join(\"\"),\n readableHex: bytesHex.join(\" \"),\n value: value.toString(),\n };\n }\n\n // format DeviceSession values to avoid huge object in logs\n if (value instanceof DeviceSession) {\n const {\n connectedDevice: { deviceModel, type, id },\n } = value;\n return {\n id: value.id,\n connectedDevice: {\n deviceModel,\n type,\n id,\n },\n };\n }\n\n // format circular references to \"[Circular]\"\n // Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value#circular_references\n if (typeof value !== \"object\" || value === null) {\n return value;\n }\n // `this` is the object that value is contained in,\n // i.e., its direct parent.\n // @ts-expect-error cf. comment above\n while (ancestors.length > 0 && ancestors.at(-1) !== (this as unknown)) {\n ancestors.pop();\n }\n if (ancestors.includes(value)) {\n return \"[Circular]\";\n }\n ancestors.push(value);\n return value;\n };\n}\n\nexport class WebLogsExporterLogger implements LoggerSubscriberService {\n private logs: Array<\n [level: LogLevel, message: string, options: LogSubscriberOptions]\n > = [];\n\n log(level: LogLevel, message: string, options: LogSubscriberOptions): void {\n this.logs.push([level, message, options]);\n }\n\n private formatLogsToJSON(): string {\n const remappedLogs = this.logs.map(([level, message, options]) => {\n const { timestamp, ...restOptions } = options;\n return {\n level: LogLevel[level],\n message,\n options: {\n ...restOptions,\n date: new Date(options.timestamp),\n },\n };\n });\n\n return JSON.stringify(remappedLogs, getJSONStringifyReplacer(), 2);\n }\n\n /**\n * Export logs to JSON file.\n */\n public exportLogsToJSON(): void {\n const logs = this.formatLogsToJSON();\n /* eslint-disable no-restricted-globals -- Browser-only log export path uses Blob URLs to trigger a JSON file download. */\n const blob = new Blob([logs], { type: \"application/json\" });\n const url = URL.createObjectURL(blob);\n /* eslint-enable no-restricted-globals */\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `ledger-device-management-kit-logs-${new Date().toISOString()}.json`;\n a.click();\n }\n}\n"],
5
+ "mappings": "AAAA,OAAS,YAAAA,MAAgB,wCAEzB,OAAS,iBAAAC,MAAqB,+CAQvB,SAASC,GAGH,CACX,MAAMC,EAAuB,CAAC,EAC9B,OAAO,SAAUC,EAAWC,EAAyB,CAEnD,GAAIA,aAAiB,WAAY,CAC/B,MAAMC,EAAW,MAAM,KAAKD,CAAK,EAAE,IAAKE,GACtCA,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAChC,EACA,MAAO,CACL,IAAK,KAAOD,EAAS,KAAK,EAAE,EAC5B,YAAaA,EAAS,KAAK,GAAG,EAC9B,MAAOD,EAAM,SAAS,CACxB,CACF,CAGA,GAAIA,aAAiBJ,EAAe,CAClC,KAAM,CACJ,gBAAiB,CAAE,YAAAO,EAAa,KAAAC,EAAM,GAAAC,CAAG,CAC3C,EAAIL,EACJ,MAAO,CACL,GAAIA,EAAM,GACV,gBAAiB,CACf,YAAAG,EACA,KAAAC,EACA,GAAAC,CACF,CACF,CACF,CAIA,GAAI,OAAOL,GAAU,UAAYA,IAAU,KACzC,OAAOA,EAKT,KAAOF,EAAU,OAAS,GAAKA,EAAU,GAAG,EAAE,IAAO,MACnDA,EAAU,IAAI,EAEhB,OAAIA,EAAU,SAASE,CAAK,EACnB,cAETF,EAAU,KAAKE,CAAK,EACbA,EACT,CACF,CAEO,MAAMM,CAAyD,CAC5D,KAEJ,CAAC,EAEL,IAAIC,EAAiBC,EAAiBC,EAAqC,CACzE,KAAK,KAAK,KAAK,CAACF,EAAOC,EAASC,CAAO,CAAC,CAC1C,CAEQ,kBAA2B,CACjC,MAAMC,EAAe,KAAK,KAAK,IAAI,CAAC,CAACH,EAAOC,EAASC,CAAO,IAAM,CAChE,KAAM,CAAE,UAAAE,EAAW,GAAGC,CAAY,EAAIH,EACtC,MAAO,CACL,MAAOd,EAASY,CAAK,EACrB,QAAAC,EACA,QAAS,CACP,GAAGI,EACH,KAAM,IAAI,KAAKH,EAAQ,SAAS,CAClC,CACF,CACF,CAAC,EAED,OAAO,KAAK,UAAUC,EAAcb,EAAyB,EAAG,CAAC,CACnE,CAKO,kBAAyB,CAC9B,MAAMgB,EAAO,KAAK,iBAAiB,EAE7BC,EAAO,IAAI,KAAK,CAACD,CAAI,EAAG,CAAE,KAAM,kBAAmB,CAAC,EACpDE,EAAM,IAAI,gBAAgBD,CAAI,EAE9BE,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,KAAOD,EACTC,EAAE,SAAW,qCAAqC,IAAI,KAAK,EAAE,YAAY,CAAC,QAC1EA,EAAE,MAAM,CACV,CACF",
6
6
  "names": ["LogLevel", "DeviceSession", "getJSONStringifyReplacer", "ancestors", "_", "value", "bytesHex", "x", "deviceModel", "type", "id", "WebLogsExporterLogger", "level", "message", "options", "remappedLogs", "timestamp", "restOptions", "logs", "blob", "url", "a"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{DmkNetworkClientError as p}from"./DmkNetworkClientError";import{buildBodyAndHeaders as m,buildSignal as d,buildUrl as h,parseBody as l,safeReadText as k,wrapFetchError as y}from"./DmkNetworkClientHelpers";class D{baseUrl;defaultHeaders;fetchImpl;constructor(e={}){this.baseUrl=e.baseUrl,this.defaultHeaders=e.headers??{},this.fetchImpl=e.fetch}getFetch(){return this.fetchImpl??globalThis.fetch.bind(globalThis)}get(e,t){return this.request({...t,method:"GET",url:e}).then(r=>r.data)}post(e,t,r){return this.request({...r,method:"POST",url:e,body:t}).then(n=>n.data)}put(e,t,r){return this.request({...r,method:"PUT",url:e,body:t}).then(n=>n.data)}patch(e,t,r){return this.request({...r,method:"PATCH",url:e,body:t}).then(n=>n.data)}delete(e,t){return this.request({...t,method:"DELETE",url:e}).then(r=>r.data)}head(e,t){return this.request({...t,method:"HEAD",url:e,responseType:"void"}).then(()=>{})}async request(e){const t=h({url:e.url,params:e.params,baseUrl:this.baseUrl}),{body:r,headers:n}=m({method:e.method,body:e.body,defaultHeaders:this.defaultHeaders,perRequestHeaders:e.headers}),a=d({timeoutMs:e.timeoutMs,externalSignal:e.signal}),u=e.throwOnHttpError??!0,i=e.responseType??"json";let s;try{s=await this.getFetch()(t,{method:e.method,headers:n,body:r,signal:a})}catch(o){throw y({cause:o,externalSignal:e.signal,timeoutMs:e.timeoutMs})}if(!s.ok&&u){const o=await k(s);throw new p({message:`HTTP error ${s.status} ${s.statusText}`.trim(),status:s.status,statusText:s.statusText,responseBody:o})}return{data:await l(s,i),status:s.status,statusText:s.statusText,headers:s.headers,ok:s.ok}}}export{D as DmkNetworkClient};
1
+ import{DmkNetworkClientError as m}from"./DmkNetworkClientError";import{buildBodyAndHeaders as d,buildSignal as h,buildUrl as l,parseBody as k,safeReadText as y,wrapFetchError as c}from"./DmkNetworkClientHelpers";class f{baseUrl;defaultHeaders;fetchImpl;constructor(e={}){this.baseUrl=e.baseUrl,this.defaultHeaders=e.headers??{},this.fetchImpl=e.fetch}getFetch(){return this.fetchImpl??globalThis.fetch.bind(globalThis)}get(e,t){return this.request({...t,method:"GET",url:e}).then(r=>r.data)}post(e,t,r){return this.request({...r,method:"POST",url:e,body:t}).then(n=>n.data)}put(e,t,r){return this.request({...r,method:"PUT",url:e,body:t}).then(n=>n.data)}patch(e,t,r){return this.request({...r,method:"PATCH",url:e,body:t}).then(n=>n.data)}delete(e,t){return this.request({...t,method:"DELETE",url:e}).then(r=>r.data)}head(e,t){return this.request({...t,method:"HEAD",url:e,responseType:"void"}).then(()=>{})}async request(e){const t=l({url:e.url,params:e.params,baseUrl:this.baseUrl}),{body:r,headers:n}=d({method:e.method,body:e.body,defaultHeaders:this.defaultHeaders,perRequestHeaders:e.headers}),{signal:a,cleanup:u}=h({timeoutMs:e.timeoutMs}),i=e.throwOnHttpError??!0,p=e.responseType??"json";try{let s;try{s=await this.getFetch()(t,{method:e.method,headers:n,body:r,signal:a})}catch(o){throw c({cause:o,timeoutMs:e.timeoutMs})}if(!s.ok&&i){const o=await y(s);throw new m({message:`HTTP error ${s.status} ${s.statusText}`.trim(),status:s.status,statusText:s.statusText,responseBody:o})}return{data:await k(s,p),status:s.status,statusText:s.statusText,headers:s.headers,ok:s.ok}}finally{u()}}}export{f as DmkNetworkClient};
2
2
  //# sourceMappingURL=DmkNetworkClient.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/api/network/DmkNetworkClient.ts"],
4
- "sourcesContent": ["import { DmkNetworkClientError } from \"./DmkNetworkClientError\";\nimport {\n buildBodyAndHeaders,\n buildSignal,\n buildUrl,\n type DmkQueryParams,\n type DmkResponseType,\n parseBody,\n safeReadText,\n wrapFetchError,\n} from \"./DmkNetworkClientHelpers\";\n\nexport type { DmkQueryParamValue } from \"./DmkNetworkClientHelpers\";\nexport type { DmkQueryParams, DmkResponseType };\n\n/**\n * Per-request configuration. Everything is optional \u2014 sensible defaults are\n * applied by the client.\n */\nexport type DmkRequestConfig = {\n /** Query params merged into the URL. `null`/`undefined` entries are skipped. */\n params?: DmkQueryParams;\n /** Per-request headers merged on top of the client's default headers. */\n headers?: Record<string, string>;\n /**\n * Per-request timeout in milliseconds. When unset (or `0`), the request\n * has no timeout.\n */\n timeoutMs?: number;\n /**\n * External abort signal. Composed with the internal timeout signal, so\n * either one firing will abort the request.\n */\n signal?: AbortSignal;\n /**\n * How to parse the response body. Defaults to `\"json\"`, except for `head`\n * which always resolves to `void`.\n */\n responseType?: DmkResponseType;\n /**\n * When `true` (default), non-2xx responses throw {@link DmkNetworkClientError}.\n * Set to `false` to resolve normally and inspect {@link DmkNetworkResponse}\n * via {@link DmkNetworkClient.request}.\n */\n throwOnHttpError?: boolean;\n};\n\n/**\n * Full response envelope returned by {@link DmkNetworkClient.request}.\n * The simple method helpers (`get`, `post`, \u2026) unwrap to `data` directly.\n *\n * `data` is intentionally typed as `unknown`: network payloads are untrusted\n * input, so callers must narrow it with a type guard or runtime validator\n * (e.g. the existing DTO mappers) before use.\n */\nexport type DmkNetworkResponse = {\n data: unknown;\n status: number;\n statusText: string;\n headers: Headers;\n ok: boolean;\n};\n\nexport type DmkNetworkClientOptions = {\n /** Base URL prepended to relative request URLs. */\n baseUrl?: string;\n /** Default headers merged into every request. */\n headers?: Record<string, string>;\n /** Injection point for tests. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n};\n\ntype InternalRequestConfig = DmkRequestConfig & {\n method: string;\n url: string;\n body?: unknown;\n};\n\n/**\n * Minimal axios-like wrapper over `fetch`. Handles:\n *\n * - URL composition (base URL + relative path + query params from an object)\n * - Automatic JSON body encoding and `Content-Type` header\n * - Default and per-request headers merging\n * - Request timeout via `AbortSignal.timeout`, composable with a caller signal\n * - Automatic `response.ok` check with a typed {@link DmkNetworkClientError}\n * - Typed JSON / text / blob / arrayBuffer response parsing\n *\n * Use the high-level helpers ({@link DmkNetworkClient.get}, {@link DmkNetworkClient.post},\n * \u2026) for 95% of calls and {@link DmkNetworkClient.request} when you need the\n * full response envelope (status, headers).\n */\nexport class DmkNetworkClient {\n private readonly baseUrl?: string;\n private readonly defaultHeaders: Record<string, string>;\n private readonly fetchImpl?: typeof fetch;\n\n constructor(options: DmkNetworkClientOptions = {}) {\n this.baseUrl = options.baseUrl;\n this.defaultHeaders = options.headers ?? {};\n this.fetchImpl = options.fetch;\n }\n\n private getFetch(): typeof fetch {\n // Resolve `fetch` at call time so that spies installed on `globalThis.fetch`\n // after the client was constructed are still honored.\n return this.fetchImpl ?? globalThis.fetch.bind(globalThis);\n }\n\n public get(url: string, config?: DmkRequestConfig): Promise<unknown> {\n return this.request({ ...config, method: \"GET\", url }).then(\n (res) => res.data,\n );\n }\n\n public post(\n url: string,\n body?: unknown,\n config?: DmkRequestConfig,\n ): Promise<unknown> {\n return this.request({ ...config, method: \"POST\", url, body }).then(\n (res) => res.data,\n );\n }\n\n public put(\n url: string,\n body?: unknown,\n config?: DmkRequestConfig,\n ): Promise<unknown> {\n return this.request({ ...config, method: \"PUT\", url, body }).then(\n (res) => res.data,\n );\n }\n\n public patch(\n url: string,\n body?: unknown,\n config?: DmkRequestConfig,\n ): Promise<unknown> {\n return this.request({ ...config, method: \"PATCH\", url, body }).then(\n (res) => res.data,\n );\n }\n\n public delete(url: string, config?: DmkRequestConfig): Promise<unknown> {\n return this.request({ ...config, method: \"DELETE\", url }).then(\n (res) => res.data,\n );\n }\n\n public head(url: string, config?: DmkRequestConfig): Promise<void> {\n return this.request({\n ...config,\n method: \"HEAD\",\n url,\n responseType: \"void\",\n }).then(() => undefined);\n }\n\n /**\n * Escape hatch returning the full response envelope (status, headers, data).\n * Most callers should prefer {@link get}, {@link post}, etc.\n *\n * `data` is `unknown` by design; validate it with a type guard before use.\n */\n public async request(\n config: InternalRequestConfig,\n ): Promise<DmkNetworkResponse> {\n const url = buildUrl({\n url: config.url,\n params: config.params,\n baseUrl: this.baseUrl,\n });\n const { body, headers } = buildBodyAndHeaders({\n method: config.method,\n body: config.body,\n defaultHeaders: this.defaultHeaders,\n perRequestHeaders: config.headers,\n });\n const signal = buildSignal({\n timeoutMs: config.timeoutMs,\n externalSignal: config.signal,\n });\n const throwOnHttpError = config.throwOnHttpError ?? true;\n const responseType: DmkResponseType = config.responseType ?? \"json\";\n\n let response: Response;\n try {\n response = await this.getFetch()(url, {\n method: config.method,\n headers,\n body,\n signal,\n });\n } catch (cause) {\n throw wrapFetchError({\n cause,\n externalSignal: config.signal,\n timeoutMs: config.timeoutMs,\n });\n }\n\n if (!response.ok && throwOnHttpError) {\n const responseBody = await safeReadText(response);\n throw new DmkNetworkClientError({\n message: `HTTP error ${response.status} ${response.statusText}`.trim(),\n status: response.status,\n statusText: response.statusText,\n responseBody,\n });\n }\n\n const data = await parseBody(response, responseType);\n\n return {\n data,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n ok: response.ok,\n };\n }\n}\n"],
5
- "mappings": "AAAA,OAAS,yBAAAA,MAA6B,0BACtC,OACE,uBAAAC,EACA,eAAAC,EACA,YAAAC,EAGA,aAAAC,EACA,gBAAAC,EACA,kBAAAC,MACK,4BAkFA,MAAMC,CAAiB,CACX,QACA,eACA,UAEjB,YAAYC,EAAmC,CAAC,EAAG,CACjD,KAAK,QAAUA,EAAQ,QACvB,KAAK,eAAiBA,EAAQ,SAAW,CAAC,EAC1C,KAAK,UAAYA,EAAQ,KAC3B,CAEQ,UAAyB,CAG/B,OAAO,KAAK,WAAa,WAAW,MAAM,KAAK,UAAU,CAC3D,CAEO,IAAIC,EAAaC,EAA6C,CACnE,OAAO,KAAK,QAAQ,CAAE,GAAGA,EAAQ,OAAQ,MAAO,IAAAD,CAAI,CAAC,EAAE,KACpDE,GAAQA,EAAI,IACf,CACF,CAEO,KACLF,EACAG,EACAF,EACkB,CAClB,OAAO,KAAK,QAAQ,CAAE,GAAGA,EAAQ,OAAQ,OAAQ,IAAAD,EAAK,KAAAG,CAAK,CAAC,EAAE,KAC3DD,GAAQA,EAAI,IACf,CACF,CAEO,IACLF,EACAG,EACAF,EACkB,CAClB,OAAO,KAAK,QAAQ,CAAE,GAAGA,EAAQ,OAAQ,MAAO,IAAAD,EAAK,KAAAG,CAAK,CAAC,EAAE,KAC1DD,GAAQA,EAAI,IACf,CACF,CAEO,MACLF,EACAG,EACAF,EACkB,CAClB,OAAO,KAAK,QAAQ,CAAE,GAAGA,EAAQ,OAAQ,QAAS,IAAAD,EAAK,KAAAG,CAAK,CAAC,EAAE,KAC5DD,GAAQA,EAAI,IACf,CACF,CAEO,OAAOF,EAAaC,EAA6C,CACtE,OAAO,KAAK,QAAQ,CAAE,GAAGA,EAAQ,OAAQ,SAAU,IAAAD,CAAI,CAAC,EAAE,KACvDE,GAAQA,EAAI,IACf,CACF,CAEO,KAAKF,EAAaC,EAA0C,CACjE,OAAO,KAAK,QAAQ,CAClB,GAAGA,EACH,OAAQ,OACR,IAAAD,EACA,aAAc,MAChB,CAAC,EAAE,KAAK,IAAG,EAAY,CACzB,CAQA,MAAa,QACXC,EAC6B,CAC7B,MAAMD,EAAMN,EAAS,CACnB,IAAKO,EAAO,IACZ,OAAQA,EAAO,OACf,QAAS,KAAK,OAChB,CAAC,EACK,CAAE,KAAAE,EAAM,QAAAC,CAAQ,EAAIZ,EAAoB,CAC5C,OAAQS,EAAO,OACf,KAAMA,EAAO,KACb,eAAgB,KAAK,eACrB,kBAAmBA,EAAO,OAC5B,CAAC,EACKI,EAASZ,EAAY,CACzB,UAAWQ,EAAO,UAClB,eAAgBA,EAAO,MACzB,CAAC,EACKK,EAAmBL,EAAO,kBAAoB,GAC9CM,EAAgCN,EAAO,cAAgB,OAE7D,IAAIO,EACJ,GAAI,CACFA,EAAW,MAAM,KAAK,SAAS,EAAER,EAAK,CACpC,OAAQC,EAAO,OACf,QAAAG,EACA,KAAAD,EACA,OAAAE,CACF,CAAC,CACH,OAASI,EAAO,CACd,MAAMZ,EAAe,CACnB,MAAAY,EACA,eAAgBR,EAAO,OACvB,UAAWA,EAAO,SACpB,CAAC,CACH,CAEA,GAAI,CAACO,EAAS,IAAMF,EAAkB,CACpC,MAAMI,EAAe,MAAMd,EAAaY,CAAQ,EAChD,MAAM,IAAIjB,EAAsB,CAC9B,QAAS,cAAciB,EAAS,MAAM,IAAIA,EAAS,UAAU,GAAG,KAAK,EACrE,OAAQA,EAAS,OACjB,WAAYA,EAAS,WACrB,aAAAE,CACF,CAAC,CACH,CAIA,MAAO,CACL,KAHW,MAAMf,EAAUa,EAAUD,CAAY,EAIjD,OAAQC,EAAS,OACjB,WAAYA,EAAS,WACrB,QAASA,EAAS,QAClB,GAAIA,EAAS,EACf,CACF,CACF",
6
- "names": ["DmkNetworkClientError", "buildBodyAndHeaders", "buildSignal", "buildUrl", "parseBody", "safeReadText", "wrapFetchError", "DmkNetworkClient", "options", "url", "config", "res", "body", "headers", "signal", "throwOnHttpError", "responseType", "response", "cause", "responseBody"]
4
+ "sourcesContent": ["import { DmkNetworkClientError } from \"./DmkNetworkClientError\";\nimport {\n buildBodyAndHeaders,\n buildSignal,\n buildUrl,\n type DmkQueryParams,\n type DmkResponseType,\n parseBody,\n safeReadText,\n wrapFetchError,\n} from \"./DmkNetworkClientHelpers\";\n\nexport type { DmkQueryParamValue } from \"./DmkNetworkClientHelpers\";\nexport type { DmkQueryParams, DmkResponseType };\n\n/**\n * Per-request configuration. Everything is optional \u2014 sensible defaults are\n * applied by the client.\n */\nexport type DmkRequestConfig = {\n /** Query params merged into the URL. `null`/`undefined` entries are skipped. */\n params?: DmkQueryParams;\n /** Per-request headers merged on top of the client's default headers. */\n headers?: Record<string, string>;\n /**\n * Per-request timeout in milliseconds. When unset (or `0`), the request\n * has no timeout.\n */\n timeoutMs?: number;\n /**\n * How to parse the response body. Defaults to `\"json\"`, except for `head`\n * which always resolves to `void`.\n */\n responseType?: DmkResponseType;\n /**\n * When `true` (default), non-2xx responses throw {@link DmkNetworkClientError}.\n * Set to `false` to resolve normally and inspect {@link DmkNetworkResponse}\n * via {@link DmkNetworkClient.request}.\n */\n throwOnHttpError?: boolean;\n};\n\n/**\n * Full response envelope returned by {@link DmkNetworkClient.request}.\n * The simple method helpers (`get`, `post`, \u2026) unwrap to `data` directly.\n *\n * `data` is intentionally typed as `unknown`: network payloads are untrusted\n * input, so callers must narrow it with a type guard or runtime validator\n * (e.g. the existing DTO mappers) before use.\n */\nexport type DmkNetworkResponse = {\n data: unknown;\n status: number;\n statusText: string;\n headers: Headers;\n ok: boolean;\n};\n\nexport type DmkNetworkClientOptions = {\n /** Base URL prepended to relative request URLs. */\n baseUrl?: string;\n /** Default headers merged into every request. */\n headers?: Record<string, string>;\n /** Injection point for tests. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n};\n\ntype InternalRequestConfig = DmkRequestConfig & {\n method: string;\n url: string;\n body?: unknown;\n};\n\n/**\n * Minimal axios-like wrapper over `fetch`. Handles:\n *\n * - URL composition (base URL + relative path + query params from an object)\n * - Automatic JSON body encoding and `Content-Type` header\n * - Default and per-request headers merging\n * - Request timeout via `AbortController`\n * - Automatic `response.ok` check with a typed {@link DmkNetworkClientError}\n * - Typed JSON / text / blob / arrayBuffer response parsing\n *\n * Use the high-level helpers ({@link DmkNetworkClient.get}, {@link DmkNetworkClient.post},\n * \u2026) for 95% of calls and {@link DmkNetworkClient.request} when you need the\n * full response envelope (status, headers).\n */\nexport class DmkNetworkClient {\n private readonly baseUrl?: string;\n private readonly defaultHeaders: Record<string, string>;\n private readonly fetchImpl?: typeof fetch;\n\n constructor(options: DmkNetworkClientOptions = {}) {\n this.baseUrl = options.baseUrl;\n this.defaultHeaders = options.headers ?? {};\n this.fetchImpl = options.fetch;\n }\n\n private getFetch(): typeof fetch {\n // Resolve `fetch` at call time so that spies installed on `globalThis.fetch`\n // after the client was constructed are still honored.\n return this.fetchImpl ?? globalThis.fetch.bind(globalThis);\n }\n\n public get(url: string, config?: DmkRequestConfig): Promise<unknown> {\n return this.request({ ...config, method: \"GET\", url }).then(\n (res) => res.data,\n );\n }\n\n public post(\n url: string,\n body?: unknown,\n config?: DmkRequestConfig,\n ): Promise<unknown> {\n return this.request({ ...config, method: \"POST\", url, body }).then(\n (res) => res.data,\n );\n }\n\n public put(\n url: string,\n body?: unknown,\n config?: DmkRequestConfig,\n ): Promise<unknown> {\n return this.request({ ...config, method: \"PUT\", url, body }).then(\n (res) => res.data,\n );\n }\n\n public patch(\n url: string,\n body?: unknown,\n config?: DmkRequestConfig,\n ): Promise<unknown> {\n return this.request({ ...config, method: \"PATCH\", url, body }).then(\n (res) => res.data,\n );\n }\n\n public delete(url: string, config?: DmkRequestConfig): Promise<unknown> {\n return this.request({ ...config, method: \"DELETE\", url }).then(\n (res) => res.data,\n );\n }\n\n public head(url: string, config?: DmkRequestConfig): Promise<void> {\n return this.request({\n ...config,\n method: \"HEAD\",\n url,\n responseType: \"void\",\n }).then(() => undefined);\n }\n\n /**\n * Escape hatch returning the full response envelope (status, headers, data).\n * Most callers should prefer {@link get}, {@link post}, etc.\n *\n * `data` is `unknown` by design; validate it with a type guard before use.\n */\n public async request(\n config: InternalRequestConfig,\n ): Promise<DmkNetworkResponse> {\n const url = buildUrl({\n url: config.url,\n params: config.params,\n baseUrl: this.baseUrl,\n });\n const { body, headers } = buildBodyAndHeaders({\n method: config.method,\n body: config.body,\n defaultHeaders: this.defaultHeaders,\n perRequestHeaders: config.headers,\n });\n const { signal, cleanup } = buildSignal({\n timeoutMs: config.timeoutMs,\n });\n const throwOnHttpError = config.throwOnHttpError ?? true;\n const responseType: DmkResponseType = config.responseType ?? \"json\";\n\n try {\n let response: Response;\n try {\n response = await this.getFetch()(url, {\n method: config.method,\n headers,\n body,\n signal,\n });\n } catch (cause) {\n throw wrapFetchError({\n cause,\n timeoutMs: config.timeoutMs,\n });\n }\n\n if (!response.ok && throwOnHttpError) {\n const responseBody = await safeReadText(response);\n throw new DmkNetworkClientError({\n message:\n `HTTP error ${response.status} ${response.statusText}`.trim(),\n status: response.status,\n statusText: response.statusText,\n responseBody,\n });\n }\n\n const data = await parseBody(response, responseType);\n\n return {\n data,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n ok: response.ok,\n };\n } finally {\n cleanup();\n }\n }\n}\n"],
5
+ "mappings": "AAAA,OAAS,yBAAAA,MAA6B,0BACtC,OACE,uBAAAC,EACA,eAAAC,EACA,YAAAC,EAGA,aAAAC,EACA,gBAAAC,EACA,kBAAAC,MACK,4BA6EA,MAAMC,CAAiB,CACX,QACA,eACA,UAEjB,YAAYC,EAAmC,CAAC,EAAG,CACjD,KAAK,QAAUA,EAAQ,QACvB,KAAK,eAAiBA,EAAQ,SAAW,CAAC,EAC1C,KAAK,UAAYA,EAAQ,KAC3B,CAEQ,UAAyB,CAG/B,OAAO,KAAK,WAAa,WAAW,MAAM,KAAK,UAAU,CAC3D,CAEO,IAAIC,EAAaC,EAA6C,CACnE,OAAO,KAAK,QAAQ,CAAE,GAAGA,EAAQ,OAAQ,MAAO,IAAAD,CAAI,CAAC,EAAE,KACpDE,GAAQA,EAAI,IACf,CACF,CAEO,KACLF,EACAG,EACAF,EACkB,CAClB,OAAO,KAAK,QAAQ,CAAE,GAAGA,EAAQ,OAAQ,OAAQ,IAAAD,EAAK,KAAAG,CAAK,CAAC,EAAE,KAC3DD,GAAQA,EAAI,IACf,CACF,CAEO,IACLF,EACAG,EACAF,EACkB,CAClB,OAAO,KAAK,QAAQ,CAAE,GAAGA,EAAQ,OAAQ,MAAO,IAAAD,EAAK,KAAAG,CAAK,CAAC,EAAE,KAC1DD,GAAQA,EAAI,IACf,CACF,CAEO,MACLF,EACAG,EACAF,EACkB,CAClB,OAAO,KAAK,QAAQ,CAAE,GAAGA,EAAQ,OAAQ,QAAS,IAAAD,EAAK,KAAAG,CAAK,CAAC,EAAE,KAC5DD,GAAQA,EAAI,IACf,CACF,CAEO,OAAOF,EAAaC,EAA6C,CACtE,OAAO,KAAK,QAAQ,CAAE,GAAGA,EAAQ,OAAQ,SAAU,IAAAD,CAAI,CAAC,EAAE,KACvDE,GAAQA,EAAI,IACf,CACF,CAEO,KAAKF,EAAaC,EAA0C,CACjE,OAAO,KAAK,QAAQ,CAClB,GAAGA,EACH,OAAQ,OACR,IAAAD,EACA,aAAc,MAChB,CAAC,EAAE,KAAK,IAAG,EAAY,CACzB,CAQA,MAAa,QACXC,EAC6B,CAC7B,MAAMD,EAAMN,EAAS,CACnB,IAAKO,EAAO,IACZ,OAAQA,EAAO,OACf,QAAS,KAAK,OAChB,CAAC,EACK,CAAE,KAAAE,EAAM,QAAAC,CAAQ,EAAIZ,EAAoB,CAC5C,OAAQS,EAAO,OACf,KAAMA,EAAO,KACb,eAAgB,KAAK,eACrB,kBAAmBA,EAAO,OAC5B,CAAC,EACK,CAAE,OAAAI,EAAQ,QAAAC,CAAQ,EAAIb,EAAY,CACtC,UAAWQ,EAAO,SACpB,CAAC,EACKM,EAAmBN,EAAO,kBAAoB,GAC9CO,EAAgCP,EAAO,cAAgB,OAE7D,GAAI,CACF,IAAIQ,EACJ,GAAI,CACFA,EAAW,MAAM,KAAK,SAAS,EAAET,EAAK,CACpC,OAAQC,EAAO,OACf,QAAAG,EACA,KAAAD,EACA,OAAAE,CACF,CAAC,CACH,OAASK,EAAO,CACd,MAAMb,EAAe,CACnB,MAAAa,EACA,UAAWT,EAAO,SACpB,CAAC,CACH,CAEA,GAAI,CAACQ,EAAS,IAAMF,EAAkB,CACpC,MAAMI,EAAe,MAAMf,EAAaa,CAAQ,EAChD,MAAM,IAAIlB,EAAsB,CAC9B,QACE,cAAckB,EAAS,MAAM,IAAIA,EAAS,UAAU,GAAG,KAAK,EAC9D,OAAQA,EAAS,OACjB,WAAYA,EAAS,WACrB,aAAAE,CACF,CAAC,CACH,CAIA,MAAO,CACL,KAHW,MAAMhB,EAAUc,EAAUD,CAAY,EAIjD,OAAQC,EAAS,OACjB,WAAYA,EAAS,WACrB,QAASA,EAAS,QAClB,GAAIA,EAAS,EACf,CACF,QAAE,CACAH,EAAQ,CACV,CACF,CACF",
6
+ "names": ["DmkNetworkClientError", "buildBodyAndHeaders", "buildSignal", "buildUrl", "parseBody", "safeReadText", "wrapFetchError", "DmkNetworkClient", "options", "url", "config", "res", "body", "headers", "signal", "cleanup", "throwOnHttpError", "responseType", "response", "cause", "responseBody"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{DmkNetworkClient as c}from"./DmkNetworkClient";import{DmkNetworkClientError as i}from"./DmkNetworkClientError";describe("DmkNetworkClient",()=>{const n=(e,o={})=>new Response(JSON.stringify(e),{status:200,headers:{"Content-Type":"application/json"},...o});describe("URL composition",()=>{it("should send requests to an absolute URL as-is",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).get("https://api.example.com/items");const[t]=e.mock.calls[0];expect(typeof t).toBe("string"),expect(t).toBe("https://api.example.com/items")}),it("should prepend baseUrl to relative paths with slash normalization",async()=>{const e=vi.fn().mockImplementation(()=>Promise.resolve(n({ok:!0}))),o=new c({baseUrl:"https://api.example.com/",fetch:e});await o.get("/items"),await o.get("items"),expect(e.mock.calls[0][0]).toBe("https://api.example.com/items"),expect(e.mock.calls[1][0]).toBe("https://api.example.com/items")}),it("should set URL search params from the config",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).get("https://api.example.com/items",{params:{chain:1,contract:"0xabc",active:!0,skip:null,alsoSkip:void 0}});const t=e.mock.calls[0][0];expect(typeof t).toBe("string");const s=new URL(t);expect(s.searchParams.get("chain")).toBe("1"),expect(s.searchParams.get("contract")).toBe("0xabc"),expect(s.searchParams.get("active")).toBe("true"),expect(s.searchParams.has("skip")).toBe(!1),expect(s.searchParams.has("alsoSkip")).toBe(!1)}),it("should pass a plain string URL to fetch with no trailing slash after the query (facebook/react-native#54242)",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).get("https://manager.api.live.ledger.com/api/get_device_version",{params:{target_id:858783748,provider:1}});const[t]=e.mock.calls[0];expect(typeof t).toBe("string"),expect(t).toBe("https://manager.api.live.ledger.com/api/get_device_version?target_id=858783748&provider=1"),expect(t.endsWith("/")).toBe(!1)})}),describe("headers",()=>{it("should merge default and per-request headers",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e,headers:{"X-Default":"default","X-Shared":"from-default"}}).get("https://api.example.com/items",{headers:{"X-Shared":"overridden","X-Per-Request":"per"}});const t=e.mock.calls[0][1];expect(t.headers).toMatchObject({"X-Default":"default","X-Shared":"overridden","X-Per-Request":"per"})})}),describe("body handling",()=>{it("should JSON-stringify plain-object bodies and set Content-Type",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).post("https://api.example.com/items",{foo:"bar"});const t=e.mock.calls[0][1];expect(t.method).toBe("POST"),expect(t.body).toBe(JSON.stringify({foo:"bar"})),expect(t.headers).toMatchObject({"Content-Type":"application/json"})}),it("should not override an explicit Content-Type header",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).post("https://api.example.com/items",{foo:"bar"},{headers:{"content-type":"application/vnd.custom+json"}});const t=e.mock.calls[0][1];expect(t.headers).toMatchObject({"content-type":"application/vnd.custom+json"})}),it("should pass raw BodyInit values through unchanged",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0})),o=new c({fetch:e}),t=new FormData;t.set("field","value"),await o.post("https://api.example.com/items",t);const s=e.mock.calls[0][1];expect(s.body).toBe(t),expect(s.headers).not.toMatchObject({"Content-Type":"application/json"})}),it("should not send a body on GET or HEAD",async()=>{const e=vi.fn().mockImplementation(()=>Promise.resolve(n({ok:!0}))),o=new c({fetch:e});await o.get("https://api.example.com/items"),await o.head("https://api.example.com/items"),expect(e.mock.calls[0][1]).toMatchObject({body:void 0}),expect(e.mock.calls[1][1]).toMatchObject({body:void 0})})}),describe("response parsing",()=>{it("should return the parsed JSON body by default",async()=>{const e=vi.fn().mockResolvedValue(n({hello:"world"})),t=await new c({fetch:e}).get("https://api.example.com/items");expect(t).toEqual({hello:"world"})}),it("should return text when responseType is 'text'",async()=>{const e=vi.fn().mockResolvedValue(new Response("plain-body",{status:200})),t=await new c({fetch:e}).get("https://api.example.com/items",{responseType:"text"});expect(t).toBe("plain-body")}),it("should resolve HEAD to void without reading the body",async()=>{const e=vi.fn().mockResolvedValue(new Response(null,{status:200})),t=await new c({fetch:e}).head("https://api.example.com/items");expect(t).toBeUndefined()}),it("should resolve empty JSON body to undefined",async()=>{const e=vi.fn().mockResolvedValue(new Response(null,{status:204})),t=await new c({fetch:e}).get("https://api.example.com/items");expect(t).toBeUndefined()}),it("should throw a DmkNetworkClientError on malformed JSON",async()=>{const e=vi.fn().mockResolvedValue(new Response("not-json",{status:200})),o=new c({fetch:e});await expect(o.get("https://api.example.com/items")).rejects.toBeInstanceOf(i)})}),describe("error handling",()=>{it("should throw DmkNetworkClientError with status on non-2xx responses",async()=>{const e=vi.fn().mockResolvedValue(new Response("boom",{status:500,statusText:"Server Error"})),t=await new c({fetch:e}).get("https://api.example.com/items").catch(a=>a);expect(t).toBeInstanceOf(i);const s=t;expect(s.status).toBe(500),expect(s.statusText).toBe("Server Error"),expect(s.responseBody).toBe("boom"),expect(s.isTimeout).toBe(!1),expect(s.isAbort).toBe(!1)}),it("should not throw when throwOnHttpError is disabled",async()=>{const e=vi.fn().mockResolvedValue(new Response("boom",{status:500})),t=await new c({fetch:e}).request({method:"GET",url:"https://api.example.com/items",responseType:"text",throwOnHttpError:!1});expect(t.status).toBe(500),expect(t.ok).toBe(!1),expect(t.data).toBe("boom")}),it("should wrap generic fetch failures into DmkNetworkClientError",async()=>{const e=new TypeError("network down"),o=vi.fn().mockRejectedValue(e),s=await new c({fetch:o}).get("https://api.example.com/items").catch(a=>a);expect(s).toBeInstanceOf(i),expect(s.cause).toBe(e)})}),describe("timeout",()=>{it("should pass an AbortSignal when timeoutMs is configured",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).get("https://api.example.com/items",{timeoutMs:1e3});const t=e.mock.calls[0][1];expect(t.signal).toBeInstanceOf(AbortSignal)}),it("should not pass a signal when no timeout and no external signal are set",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).get("https://api.example.com/items");const t=e.mock.calls[0][1];expect(t.signal).toBeUndefined()}),it("should mark the error as a timeout when fetch rejects with TimeoutError",async()=>{const e=new Error("The operation was aborted");e.name="TimeoutError";const o=vi.fn().mockRejectedValue(e),s=await new c({fetch:o}).get("https://api.example.com/items",{timeoutMs:10}).catch(a=>a);expect(s).toBeInstanceOf(i),expect(s.isTimeout).toBe(!0),expect(s.isAbort).toBe(!1)}),it("should mark the error as an abort when the caller signal is aborted",async()=>{const e=new AbortController;e.abort();const o=new Error("aborted");o.name="AbortError";const t=vi.fn().mockRejectedValue(o),a=await new c({fetch:t}).get("https://api.example.com/items",{signal:e.signal}).catch(r=>r);expect(a).toBeInstanceOf(i),expect(a.isAbort).toBe(!0),expect(a.isTimeout).toBe(!1)})}),describe("request envelope",()=>{it("should expose full response metadata via request()",async()=>{const e=vi.fn().mockResolvedValue(new Response(JSON.stringify({hello:"world"}),{status:201,statusText:"Created",headers:{"X-Custom":"1","Content-Type":"application/json"}})),t=await new c({fetch:e}).request({method:"GET",url:"https://api.example.com/items"});expect(t.status).toBe(201),expect(t.statusText).toBe("Created"),expect(t.ok).toBe(!0),expect(t.data).toEqual({hello:"world"}),expect(t.headers.get("X-Custom")).toBe("1")})})});
1
+ import{DmkNetworkClient as c}from"./DmkNetworkClient";import{DmkNetworkClientError as i}from"./DmkNetworkClientError";describe("DmkNetworkClient",()=>{const n=(e,o={})=>new Response(JSON.stringify(e),{status:200,headers:{"Content-Type":"application/json"},...o});describe("URL composition",()=>{it("should send requests to an absolute URL as-is",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).get("https://api.example.com/items");const[t]=e.mock.calls[0];expect(typeof t).toBe("string"),expect(t).toBe("https://api.example.com/items")}),it("should prepend baseUrl to relative paths with slash normalization",async()=>{const e=vi.fn().mockImplementation(()=>Promise.resolve(n({ok:!0}))),o=new c({baseUrl:"https://api.example.com/",fetch:e});await o.get("/items"),await o.get("items"),expect(e.mock.calls[0][0]).toBe("https://api.example.com/items"),expect(e.mock.calls[1][0]).toBe("https://api.example.com/items")}),it("should set URL search params from the config",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).get("https://api.example.com/items",{params:{chain:1,contract:"0xabc",active:!0,skip:null,alsoSkip:void 0}});const t=e.mock.calls[0][0];expect(typeof t).toBe("string");const s=new URL(t);expect(s.searchParams.get("chain")).toBe("1"),expect(s.searchParams.get("contract")).toBe("0xabc"),expect(s.searchParams.get("active")).toBe("true"),expect(s.searchParams.has("skip")).toBe(!1),expect(s.searchParams.has("alsoSkip")).toBe(!1)}),it("should pass a plain string URL to fetch with no trailing slash after the query (facebook/react-native#54242)",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).get("https://manager.api.live.ledger.com/api/get_device_version",{params:{target_id:858783748,provider:1}});const[t]=e.mock.calls[0];expect(typeof t).toBe("string"),expect(t).toBe("https://manager.api.live.ledger.com/api/get_device_version?target_id=858783748&provider=1"),expect(t.endsWith("/")).toBe(!1)})}),describe("headers",()=>{it("should merge default and per-request headers",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e,headers:{"X-Default":"default","X-Shared":"from-default"}}).get("https://api.example.com/items",{headers:{"X-Shared":"overridden","X-Per-Request":"per"}});const t=e.mock.calls[0][1];expect(t.headers).toMatchObject({"X-Default":"default","X-Shared":"overridden","X-Per-Request":"per"})})}),describe("body handling",()=>{it("should JSON-stringify plain-object bodies and set Content-Type",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).post("https://api.example.com/items",{foo:"bar"});const t=e.mock.calls[0][1];expect(t.method).toBe("POST"),expect(t.body).toBe(JSON.stringify({foo:"bar"})),expect(t.headers).toMatchObject({"Content-Type":"application/json"})}),it("should not override an explicit Content-Type header",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).post("https://api.example.com/items",{foo:"bar"},{headers:{"content-type":"application/vnd.custom+json"}});const t=e.mock.calls[0][1];expect(t.headers).toMatchObject({"content-type":"application/vnd.custom+json"})}),it("should pass raw BodyInit values through unchanged",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0})),o=new c({fetch:e}),t=new FormData;t.set("field","value"),await o.post("https://api.example.com/items",t);const s=e.mock.calls[0][1];expect(s.body).toBe(t),expect(s.headers).not.toMatchObject({"Content-Type":"application/json"})}),it("should not send a body on GET or HEAD",async()=>{const e=vi.fn().mockImplementation(()=>Promise.resolve(n({ok:!0}))),o=new c({fetch:e});await o.get("https://api.example.com/items"),await o.head("https://api.example.com/items"),expect(e.mock.calls[0][1]).toMatchObject({body:void 0}),expect(e.mock.calls[1][1]).toMatchObject({body:void 0})})}),describe("response parsing",()=>{it("should return the parsed JSON body by default",async()=>{const e=vi.fn().mockResolvedValue(n({hello:"world"})),t=await new c({fetch:e}).get("https://api.example.com/items");expect(t).toEqual({hello:"world"})}),it("should return text when responseType is 'text'",async()=>{const e=vi.fn().mockResolvedValue(new Response("plain-body",{status:200})),t=await new c({fetch:e}).get("https://api.example.com/items",{responseType:"text"});expect(t).toBe("plain-body")}),it("should resolve HEAD to void without reading the body",async()=>{const e=vi.fn().mockResolvedValue(new Response(null,{status:200})),t=await new c({fetch:e}).head("https://api.example.com/items");expect(t).toBeUndefined()}),it("should resolve empty JSON body to undefined",async()=>{const e=vi.fn().mockResolvedValue(new Response(null,{status:204})),t=await new c({fetch:e}).get("https://api.example.com/items");expect(t).toBeUndefined()}),it("should throw a DmkNetworkClientError on malformed JSON",async()=>{const e=vi.fn().mockResolvedValue(new Response("not-json",{status:200})),o=new c({fetch:e});await expect(o.get("https://api.example.com/items")).rejects.toBeInstanceOf(i)})}),describe("error handling",()=>{it("should throw DmkNetworkClientError with status on non-2xx responses",async()=>{const e=vi.fn().mockResolvedValue(new Response("boom",{status:500,statusText:"Server Error"})),t=await new c({fetch:e}).get("https://api.example.com/items").catch(a=>a);expect(t).toBeInstanceOf(i);const s=t;expect(s.status).toBe(500),expect(s.statusText).toBe("Server Error"),expect(s.responseBody).toBe("boom"),expect(s.isTimeout).toBe(!1)}),it("should not throw when throwOnHttpError is disabled",async()=>{const e=vi.fn().mockResolvedValue(new Response("boom",{status:500})),t=await new c({fetch:e}).request({method:"GET",url:"https://api.example.com/items",responseType:"text",throwOnHttpError:!1});expect(t.status).toBe(500),expect(t.ok).toBe(!1),expect(t.data).toBe("boom")}),it("should wrap generic fetch failures into DmkNetworkClientError",async()=>{const e=new TypeError("network down"),o=vi.fn().mockRejectedValue(e),s=await new c({fetch:o}).get("https://api.example.com/items").catch(a=>a);expect(s).toBeInstanceOf(i),expect(s.cause).toBe(e)})}),describe("timeout",()=>{afterEach(()=>{vi.useRealTimers()}),it("should pass an AbortSignal when timeoutMs is configured",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).get("https://api.example.com/items",{timeoutMs:1e3});const t=e.mock.calls[0][1];expect(t.signal).toBeInstanceOf(AbortSignal)}),it("should not pass a signal when no timeout and no external signal are set",async()=>{const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).get("https://api.example.com/items");const t=e.mock.calls[0][1];expect(t.signal).toBeUndefined()}),it("GIVEN a successful request with timeout WHEN fetch resolves THEN it clears the timeout",async()=>{vi.useFakeTimers();const e=vi.fn().mockResolvedValue(n({ok:!0}));await new c({fetch:e}).get("https://api.example.com/items",{timeoutMs:1e3});const t=e.mock.calls[0][1];vi.advanceTimersByTime(1e3),expect(t.signal).toBeInstanceOf(AbortSignal),expect(t.signal?.aborted).toBe(!1)}),it("GIVEN a failed request with timeout WHEN fetch rejects THEN it clears the timeout",async()=>{vi.useFakeTimers();const e=new TypeError("network down"),o=vi.fn().mockRejectedValue(e);await new c({fetch:o}).get("https://api.example.com/items",{timeoutMs:1e3}).catch(()=>{});const s=o.mock.calls[0][1];vi.advanceTimersByTime(1e3),expect(s.signal).toBeInstanceOf(AbortSignal),expect(s.signal?.aborted).toBe(!1)}),it("GIVEN a pending request with timeout WHEN the timeout signal aborts fetch THEN it throws a timeout error",async()=>{vi.useFakeTimers();const e=vi.fn((a,l)=>new Promise((m,p)=>{l?.signal?.addEventListener("abort",()=>{const r=new Error("The operation was aborted");r.name="AbortError",p(r)})})),t=new c({fetch:e}).get("https://api.example.com/items",{timeoutMs:1e3}).catch(a=>a);await vi.advanceTimersByTimeAsync(1e3);const s=await t;expect(s).toBeInstanceOf(i),expect(s.isTimeout).toBe(!0)}),it("should mark the error as a timeout when fetch rejects with TimeoutError",async()=>{const e=new Error("The operation was aborted");e.name="TimeoutError";const o=vi.fn().mockRejectedValue(e),s=await new c({fetch:o}).get("https://api.example.com/items",{timeoutMs:10}).catch(a=>a);expect(s).toBeInstanceOf(i),expect(s.isTimeout).toBe(!0)})}),describe("request envelope",()=>{it("should expose full response metadata via request()",async()=>{const e=vi.fn().mockResolvedValue(new Response(JSON.stringify({hello:"world"}),{status:201,statusText:"Created",headers:{"X-Custom":"1","Content-Type":"application/json"}})),t=await new c({fetch:e}).request({method:"GET",url:"https://api.example.com/items"});expect(t.status).toBe(201),expect(t.statusText).toBe("Created"),expect(t.ok).toBe(!0),expect(t.data).toEqual({hello:"world"}),expect(t.headers.get("X-Custom")).toBe("1")})})});
2
2
  //# sourceMappingURL=DmkNetworkClient.test.js.map