@ledgerhq/device-mockserver-react 0.0.0-develop-20261004005728 → 0.0.0-develop-20261007001516

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 (32) hide show
  1. package/README.md +2 -1
  2. package/lib/cjs/package.json +1 -1
  3. package/lib/cjs/src/index.js +1 -1
  4. package/lib/cjs/src/index.js.map +1 -1
  5. package/lib/cjs/src/mockServerScreenApi.js +1 -1
  6. package/lib/cjs/src/mockServerScreenApi.js.map +2 -2
  7. package/lib/cjs/src/mockServerScreenApi.test.js.map +2 -2
  8. package/lib/cjs/src/types.js +1 -1
  9. package/lib/cjs/src/types.js.map +1 -1
  10. package/lib/cjs/src/useMockServerDevice.js +1 -1
  11. package/lib/cjs/src/useMockServerDevice.js.map +2 -2
  12. package/lib/cjs/src/useMockServerDevice.test.js +1 -1
  13. package/lib/cjs/src/useMockServerDevice.test.js.map +3 -3
  14. package/lib/esm/package.json +1 -1
  15. package/lib/esm/src/index.js.map +1 -1
  16. package/lib/esm/src/mockServerScreenApi.js +1 -1
  17. package/lib/esm/src/mockServerScreenApi.js.map +2 -2
  18. package/lib/esm/src/mockServerScreenApi.test.js.map +2 -2
  19. package/lib/esm/src/useMockServerDevice.js +1 -1
  20. package/lib/esm/src/useMockServerDevice.js.map +2 -2
  21. package/lib/esm/src/useMockServerDevice.test.js +1 -1
  22. package/lib/esm/src/useMockServerDevice.test.js.map +3 -3
  23. package/lib/types/src/index.d.ts +1 -1
  24. package/lib/types/src/index.d.ts.map +1 -1
  25. package/lib/types/src/mockServerScreenApi.d.ts +2 -3
  26. package/lib/types/src/mockServerScreenApi.d.ts.map +1 -1
  27. package/lib/types/src/types.d.ts +6 -1
  28. package/lib/types/src/types.d.ts.map +1 -1
  29. package/lib/types/src/useMockServerDevice.d.ts +3 -2
  30. package/lib/types/src/useMockServerDevice.d.ts.map +1 -1
  31. package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
  32. package/package.json +5 -5
package/README.md CHANGED
@@ -31,7 +31,8 @@ import { MockServerDevice } from "@ledgerhq/device-mockserver-react";
31
31
 
32
32
  `DeviceScreen` renders the same screen from any `ScreenApi`, for instance one
33
33
  that talks to Speculos directly. `mockServerScreenApi(client, deviceId)` is the
34
- one `MockServerDevice` uses, for hosts that already hold a `MockClient`, and
34
+ one `MockServerDevice` uses, for hosts that already hold a `MockClient` (any
35
+ object with the `MockServerClient` methods fits), and
35
36
  `findDeviceScreenModel(deviceType)` gives a model's label for their own header.
36
37
 
37
38
  ## Styles
@@ -63,5 +63,5 @@
63
63
  "watch:types": "concurrently \"tsc --watch -p tsconfig.prod.json\" \"tsc-alias --watch -p tsconfig.prod.json\""
64
64
  },
65
65
  "types": "lib/index.d.ts",
66
- "version": "0.0.0-develop-20261004005728"
66
+ "version": "0.0.0-develop-20261007001516"
67
67
  }
@@ -1,2 +1,2 @@
1
- "use strict";var p=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var y=(r,e)=>{for(var c in e)p(r,c,{get:e[c],enumerable:!0})},M=(r,e,c,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of m(e))!x.call(r,o)&&o!==c&&p(r,o,{get:()=>e[o],enumerable:!(t=f(e,o))||t.enumerable});return r};var k=r=>M(p({},"__esModule",{value:!0}),r);var s={};y(s,{DeviceScreen:()=>S.DeviceScreen,MockServerDevice:()=>i.MockServerDevice,findDeviceScreenModel:()=>v.findDeviceScreenModel,mockServerScreenApi:()=>n.mockServerScreenApi,useMockServerDevice:()=>D.useMockServerDevice});module.exports=k(s);var v=require("./deviceModels"),S=require("./DeviceScreen"),i=require("./MockServerDevice"),n=require("./mockServerScreenApi"),D=require("./useMockServerDevice");0&&(module.exports={DeviceScreen,MockServerDevice,findDeviceScreenModel,mockServerScreenApi,useMockServerDevice});
1
+ "use strict";var p=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var M=(r,e)=>{for(var c in e)p(r,c,{get:e[c],enumerable:!0})},k=(r,e,c,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of m(e))!x.call(r,o)&&o!==c&&p(r,o,{get:()=>e[o],enumerable:!(t=f(e,o))||t.enumerable});return r};var y=r=>k(p({},"__esModule",{value:!0}),r);var s={};M(s,{DeviceScreen:()=>S.DeviceScreen,MockServerDevice:()=>i.MockServerDevice,findDeviceScreenModel:()=>v.findDeviceScreenModel,mockServerScreenApi:()=>n.mockServerScreenApi,useMockServerDevice:()=>D.useMockServerDevice});module.exports=y(s);var v=require("./deviceModels"),S=require("./DeviceScreen"),i=require("./MockServerDevice"),n=require("./mockServerScreenApi"),D=require("./useMockServerDevice");0&&(module.exports={DeviceScreen,MockServerDevice,findDeviceScreenModel,mockServerScreenApi,useMockServerDevice});
2
2
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/index.ts"],
4
- "sourcesContent": ["export { type DeviceScreenModel, findDeviceScreenModel } from \"./deviceModels\";\nexport { DeviceScreen, type DeviceScreenProps } from \"./DeviceScreen\";\nexport {\n MockServerDevice,\n type MockServerDeviceProps,\n} from \"./MockServerDevice\";\nexport { mockServerScreenApi } from \"./mockServerScreenApi\";\nexport type { DeviceScreenState, ScreenApi } from \"./types\";\nexport { useMockServerDevice } from \"./useMockServerDevice\";\n"],
4
+ "sourcesContent": ["export { type DeviceScreenModel, findDeviceScreenModel } from \"./deviceModels\";\nexport { DeviceScreen, type DeviceScreenProps } from \"./DeviceScreen\";\nexport {\n MockServerDevice,\n type MockServerDeviceProps,\n} from \"./MockServerDevice\";\nexport { mockServerScreenApi } from \"./mockServerScreenApi\";\nexport type { DeviceScreenState, MockServerClient, ScreenApi } from \"./types\";\nexport { useMockServerDevice } from \"./useMockServerDevice\";\n"],
5
5
  "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,wOAAAE,EAAAF,GAAA,IAAAG,EAA8D,0BAC9DC,EAAqD,0BACrDC,EAGO,8BACPC,EAAoC,iCAEpCC,EAAoC",
6
6
  "names": ["src_exports", "__export", "__toCommonJS", "import_deviceModels", "import_DeviceScreen", "import_MockServerDevice", "import_mockServerScreenApi", "import_useMockServerDevice"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var s=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var i=(n,o)=>{for(var t in o)s(n,t,{get:o[t],enumerable:!0})},w=(n,o,t,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let e of p(o))!u.call(n,e)&&e!==t&&s(n,e,{get:()=>o[e],enumerable:!(r=a(o,e))||r.enumerable});return n};var h=n=>w(s({},"__esModule",{value:!0}),n);var x={};i(x,{mockServerScreenApi:()=>l});module.exports=h(x);const f=n=>n?.status===409,l=(n,o)=>({screenshot:async()=>{try{return await n.getScreenshot(o)}catch(t){if(f(t))return null;throw t}},idle:async()=>({kind:"os-info",device:await n.getDevice(o)}),pressButton:(t,r)=>n.pressButton(o,t,r),touch:(t,r,e)=>n.touchScreen(o,t,r,e),openApp:async t=>{const r=new TextEncoder().encode(t);if(r.length>255)throw new Error(`App name too long to open: ${t}`);const{response:e}=await n.sendApdu(o,Uint8Array.from([224,216,0,0,r.length,...r])),c=e.slice(-4);if(c!=="9000")throw new Error(`Could not open ${t} (${c})`)}});0&&(module.exports={mockServerScreenApi});
1
+ "use strict";var s=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var i=(n,o)=>{for(var e in o)s(n,e,{get:o[e],enumerable:!0})},w=(n,o,e,t)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of u(o))!p.call(n,r)&&r!==e&&s(n,r,{get:()=>o[r],enumerable:!(t=a(o,r))||t.enumerable});return n};var h=n=>w(s({},"__esModule",{value:!0}),n);var S={};i(S,{mockServerScreenApi:()=>f});module.exports=h(S);const l=n=>n?.status===409,f=(n,o)=>({screenshot:async()=>{try{return await n.getScreenshot(o)}catch(e){if(l(e))return null;throw e}},idle:async()=>({kind:"os-info",device:await n.getDevice(o)}),pressButton:(e,t)=>n.pressButton(o,e,t),touch:(e,t,r)=>n.touchScreen(o,e,t,r),openApp:async e=>{const t=new TextEncoder().encode(e);if(t.length>255)throw new Error(`App name too long to open: ${e}`);const{response:r}=await n.sendApdu(o,Uint8Array.from([224,216,0,0,t.length,...t])),c=r.slice(-4);if(c!=="9000")throw new Error(`Could not open ${e} (${c})`)}});0&&(module.exports={mockServerScreenApi});
2
2
  //# sourceMappingURL=mockServerScreenApi.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/mockServerScreenApi.ts"],
4
- "sourcesContent": ["import { type MockClient } from \"@ledgerhq/device-mockserver-client\";\n\nimport { type ScreenApi } from \"./types\";\n\n/** The proxy answers 409 when the device has no Speculos instance. */\nconst isNoInstance = (error: unknown): boolean =>\n (error as { status?: unknown } | null)?.status === 409;\n\nexport const mockServerScreenApi = (\n client: MockClient,\n deviceId: string,\n): ScreenApi => ({\n screenshot: async () => {\n try {\n return await client.getScreenshot(deviceId);\n } catch (error) {\n if (isNoInstance(error)) return null;\n throw error;\n }\n },\n idle: async () => ({\n kind: \"os-info\",\n device: await client.getDevice(deviceId),\n }),\n pressButton: (button, action) => client.pressButton(deviceId, button, action),\n touch: (x, y, action) => client.touchScreen(deviceId, x, y, action),\n openApp: async (appName) => {\n const name = new TextEncoder().encode(appName);\n // Lc is a single byte.\n if (name.length > 0xff) {\n throw new Error(`App name too long to open: ${appName}`);\n }\n const { response } = await client.sendApdu(\n deviceId,\n Uint8Array.from([0xe0, 0xd8, 0x00, 0x00, name.length, ...name]),\n );\n const statusWord = response.slice(-4);\n if (statusWord !== \"9000\") {\n throw new Error(`Could not open ${appName} (${statusWord})`);\n }\n },\n});\n"],
5
- "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,yBAAAE,IAAA,eAAAC,EAAAH,GAKA,MAAMI,EAAgBC,GACnBA,GAAuC,SAAW,IAExCH,EAAsB,CACjCI,EACAC,KACe,CACf,WAAY,SAAY,CACtB,GAAI,CACF,OAAO,MAAMD,EAAO,cAAcC,CAAQ,CAC5C,OAASF,EAAO,CACd,GAAID,EAAaC,CAAK,EAAG,OAAO,KAChC,MAAMA,CACR,CACF,EACA,KAAM,UAAa,CACjB,KAAM,UACN,OAAQ,MAAMC,EAAO,UAAUC,CAAQ,CACzC,GACA,YAAa,CAACC,EAAQC,IAAWH,EAAO,YAAYC,EAAUC,EAAQC,CAAM,EAC5E,MAAO,CAACC,EAAGC,EAAGF,IAAWH,EAAO,YAAYC,EAAUG,EAAGC,EAAGF,CAAM,EAClE,QAAS,MAAOG,GAAY,CAC1B,MAAMC,EAAO,IAAI,YAAY,EAAE,OAAOD,CAAO,EAE7C,GAAIC,EAAK,OAAS,IAChB,MAAM,IAAI,MAAM,8BAA8BD,CAAO,EAAE,EAEzD,KAAM,CAAE,SAAAE,CAAS,EAAI,MAAMR,EAAO,SAChCC,EACA,WAAW,KAAK,CAAC,IAAM,IAAM,EAAM,EAAMM,EAAK,OAAQ,GAAGA,CAAI,CAAC,CAChE,EACME,EAAaD,EAAS,MAAM,EAAE,EACpC,GAAIC,IAAe,OACjB,MAAM,IAAI,MAAM,kBAAkBH,CAAO,KAAKG,CAAU,GAAG,CAE/D,CACF",
4
+ "sourcesContent": ["import { type MockServerClient, type ScreenApi } from \"./types\";\n\n/** The proxy answers 409 when the device has no Speculos instance. */\nconst isNoInstance = (error: unknown): boolean =>\n (error as { status?: unknown } | null)?.status === 409;\n\nexport const mockServerScreenApi = (\n client: MockServerClient,\n deviceId: string,\n): ScreenApi => ({\n screenshot: async () => {\n try {\n return await client.getScreenshot(deviceId);\n } catch (error) {\n if (isNoInstance(error)) return null;\n throw error;\n }\n },\n idle: async () => ({\n kind: \"os-info\",\n device: await client.getDevice(deviceId),\n }),\n pressButton: (button, action) => client.pressButton(deviceId, button, action),\n touch: (x, y, action) => client.touchScreen(deviceId, x, y, action),\n openApp: async (appName) => {\n const name = new TextEncoder().encode(appName);\n // Lc is a single byte.\n if (name.length > 0xff) {\n throw new Error(`App name too long to open: ${appName}`);\n }\n const { response } = await client.sendApdu(\n deviceId,\n Uint8Array.from([0xe0, 0xd8, 0x00, 0x00, name.length, ...name]),\n );\n const statusWord = response.slice(-4);\n if (statusWord !== \"9000\") {\n throw new Error(`Could not open ${appName} (${statusWord})`);\n }\n },\n});\n"],
5
+ "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,yBAAAE,IAAA,eAAAC,EAAAH,GAGA,MAAMI,EAAgBC,GACnBA,GAAuC,SAAW,IAExCH,EAAsB,CACjCI,EACAC,KACe,CACf,WAAY,SAAY,CACtB,GAAI,CACF,OAAO,MAAMD,EAAO,cAAcC,CAAQ,CAC5C,OAASF,EAAO,CACd,GAAID,EAAaC,CAAK,EAAG,OAAO,KAChC,MAAMA,CACR,CACF,EACA,KAAM,UAAa,CACjB,KAAM,UACN,OAAQ,MAAMC,EAAO,UAAUC,CAAQ,CACzC,GACA,YAAa,CAACC,EAAQC,IAAWH,EAAO,YAAYC,EAAUC,EAAQC,CAAM,EAC5E,MAAO,CAACC,EAAGC,EAAGF,IAAWH,EAAO,YAAYC,EAAUG,EAAGC,EAAGF,CAAM,EAClE,QAAS,MAAOG,GAAY,CAC1B,MAAMC,EAAO,IAAI,YAAY,EAAE,OAAOD,CAAO,EAE7C,GAAIC,EAAK,OAAS,IAChB,MAAM,IAAI,MAAM,8BAA8BD,CAAO,EAAE,EAEzD,KAAM,CAAE,SAAAE,CAAS,EAAI,MAAMR,EAAO,SAChCC,EACA,WAAW,KAAK,CAAC,IAAM,IAAM,EAAM,EAAMM,EAAK,OAAQ,GAAGA,CAAI,CAAC,CAChE,EACME,EAAaD,EAAS,MAAM,EAAE,EACpC,GAAIC,IAAe,OACjB,MAAM,IAAI,MAAM,kBAAkBH,CAAO,KAAKG,CAAU,GAAG,CAE/D,CACF",
6
6
  "names": ["mockServerScreenApi_exports", "__export", "mockServerScreenApi", "__toCommonJS", "isNoInstance", "error", "client", "deviceId", "button", "action", "x", "y", "appName", "name", "response", "statusWord"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/mockServerScreenApi.test.ts"],
4
- "sourcesContent": ["import { type MockClient } from \"@ledgerhq/device-mockserver-client\";\n\nimport { mockServerScreenApi } from \"./mockServerScreenApi\";\n\nconst aClient = (overrides: Partial<Record<keyof MockClient, unknown>>) =>\n ({\n getScreenshot: vi.fn(),\n getDevice: vi.fn(),\n pressButton: vi.fn(() => Promise.resolve()),\n touchScreen: vi.fn(() => Promise.resolve()),\n ...overrides,\n }) as unknown as MockClient;\n\ndescribe(\"mockServerScreenApi\", () => {\n it(\"resolves the screenshot of the device\", async () => {\n const blob = new Blob([\"png\"]);\n const client = aClient({\n getScreenshot: vi.fn(() => Promise.resolve(blob)),\n });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").screenshot(),\n ).resolves.toBe(blob);\n expect(client.getScreenshot).toHaveBeenCalledWith(\"device-1\");\n });\n\n it(\"resolves no screenshot when the device has no Speculos instance\", async () => {\n const client = aClient({\n getScreenshot: vi.fn(() => Promise.reject({ status: 409 })),\n });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").screenshot(),\n ).resolves.toBeNull();\n });\n\n it(\"rethrows any other screenshot failure\", async () => {\n const error = Object.assign(new Error(\"boom\"), { status: 500 });\n const client = aClient({\n getScreenshot: vi.fn(() => Promise.reject(error)),\n });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").screenshot(),\n ).rejects.toBe(error);\n });\n\n it(\"shows the device record while idle\", async () => {\n const device = { id: \"device-1\", device_type: \"nanoX\" };\n const client = aClient({ getDevice: vi.fn(() => Promise.resolve(device)) });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").idle?.(),\n ).resolves.toEqual({\n kind: \"os-info\",\n device,\n });\n });\n\n it(\"forwards buttons and touches to the device\", async () => {\n const client = aClient({});\n const api = mockServerScreenApi(client, \"device-1\");\n\n await api.pressButton(\"left\", \"press\");\n await api.touch(10, 20, \"release\");\n\n expect(client.pressButton).toHaveBeenCalledWith(\n \"device-1\",\n \"left\",\n \"press\",\n );\n expect(client.touchScreen).toHaveBeenCalledWith(\n \"device-1\",\n 10,\n 20,\n \"release\",\n );\n });\n\n it(\"opens an app by name\", async () => {\n const sendApdu = vi.fn(() => Promise.resolve({ response: \"9000\" }));\n const api = mockServerScreenApi(aClient({ sendApdu }), \"device-1\");\n\n await api.openApp?.(\"Bitcoin\");\n\n expect(sendApdu).toHaveBeenCalledWith(\n \"device-1\",\n Uint8Array.from([\n 0xe0,\n 0xd8,\n 0x00,\n 0x00,\n 0x07,\n ...new TextEncoder().encode(\"Bitcoin\"),\n ]),\n );\n });\n\n it(\"fails to open an app the device refuses\", async () => {\n const sendApdu = vi.fn(() => Promise.resolve({ response: \"6807\" }));\n const api = mockServerScreenApi(aClient({ sendApdu }), \"device-1\");\n\n await expect(api.openApp?.(\"Bitcoin\")).rejects.toThrow(\"6807\");\n });\n\n it(\"refuses an app name too long for one APDU\", async () => {\n const sendApdu = vi.fn(() => Promise.resolve({ response: \"9000\" }));\n const api = mockServerScreenApi(aClient({ sendApdu }), \"device-1\");\n\n await expect(api.openApp?.(\"a\".repeat(256))).rejects.toThrow(\"too long\");\n expect(sendApdu).not.toHaveBeenCalled();\n });\n});\n"],
5
- "mappings": "aAEA,IAAAA,EAAoC,iCAEpC,MAAMC,EAAWC,IACd,CACC,cAAe,GAAG,GAAG,EACrB,UAAW,GAAG,GAAG,EACjB,YAAa,GAAG,GAAG,IAAM,QAAQ,QAAQ,CAAC,EAC1C,YAAa,GAAG,GAAG,IAAM,QAAQ,QAAQ,CAAC,EAC1C,GAAGA,CACL,GAEF,SAAS,sBAAuB,IAAM,CACpC,GAAG,wCAAyC,SAAY,CACtD,MAAMC,EAAO,IAAI,KAAK,CAAC,KAAK,CAAC,EACvBC,EAASH,EAAQ,CACrB,cAAe,GAAG,GAAG,IAAM,QAAQ,QAAQE,CAAI,CAAC,CAClD,CAAC,EAED,MAAM,UACJ,uBAAoBC,EAAQ,UAAU,EAAE,WAAW,CACrD,EAAE,SAAS,KAAKD,CAAI,EACpB,OAAOC,EAAO,aAAa,EAAE,qBAAqB,UAAU,CAC9D,CAAC,EAED,GAAG,kEAAmE,SAAY,CAChF,MAAMA,EAASH,EAAQ,CACrB,cAAe,GAAG,GAAG,IAAM,QAAQ,OAAO,CAAE,OAAQ,GAAI,CAAC,CAAC,CAC5D,CAAC,EAED,MAAM,UACJ,uBAAoBG,EAAQ,UAAU,EAAE,WAAW,CACrD,EAAE,SAAS,SAAS,CACtB,CAAC,EAED,GAAG,wCAAyC,SAAY,CACtD,MAAMC,EAAQ,OAAO,OAAO,IAAI,MAAM,MAAM,EAAG,CAAE,OAAQ,GAAI,CAAC,EACxDD,EAASH,EAAQ,CACrB,cAAe,GAAG,GAAG,IAAM,QAAQ,OAAOI,CAAK,CAAC,CAClD,CAAC,EAED,MAAM,UACJ,uBAAoBD,EAAQ,UAAU,EAAE,WAAW,CACrD,EAAE,QAAQ,KAAKC,CAAK,CACtB,CAAC,EAED,GAAG,qCAAsC,SAAY,CACnD,MAAMC,EAAS,CAAE,GAAI,WAAY,YAAa,OAAQ,EAChDF,EAASH,EAAQ,CAAE,UAAW,GAAG,GAAG,IAAM,QAAQ,QAAQK,CAAM,CAAC,CAAE,CAAC,EAE1E,MAAM,UACJ,uBAAoBF,EAAQ,UAAU,EAAE,OAAO,CACjD,EAAE,SAAS,QAAQ,CACjB,KAAM,UACN,OAAAE,CACF,CAAC,CACH,CAAC,EAED,GAAG,6CAA8C,SAAY,CAC3D,MAAMF,EAASH,EAAQ,CAAC,CAAC,EACnBM,KAAM,uBAAoBH,EAAQ,UAAU,EAElD,MAAMG,EAAI,YAAY,OAAQ,OAAO,EACrC,MAAMA,EAAI,MAAM,GAAI,GAAI,SAAS,EAEjC,OAAOH,EAAO,WAAW,EAAE,qBACzB,WACA,OACA,OACF,EACA,OAAOA,EAAO,WAAW,EAAE,qBACzB,WACA,GACA,GACA,SACF,CACF,CAAC,EAED,GAAG,uBAAwB,SAAY,CACrC,MAAMI,EAAW,GAAG,GAAG,IAAM,QAAQ,QAAQ,CAAE,SAAU,MAAO,CAAC,CAAC,EAGlE,QAFY,uBAAoBP,EAAQ,CAAE,SAAAO,CAAS,CAAC,EAAG,UAAU,EAEvD,UAAU,SAAS,EAE7B,OAAOA,CAAQ,EAAE,qBACf,WACA,WAAW,KAAK,CACd,IACA,IACA,EACA,EACA,EACA,GAAG,IAAI,YAAY,EAAE,OAAO,SAAS,CACvC,CAAC,CACH,CACF,CAAC,EAED,GAAG,0CAA2C,SAAY,CACxD,MAAMA,EAAW,GAAG,GAAG,IAAM,QAAQ,QAAQ,CAAE,SAAU,MAAO,CAAC,CAAC,EAC5DD,KAAM,uBAAoBN,EAAQ,CAAE,SAAAO,CAAS,CAAC,EAAG,UAAU,EAEjE,MAAM,OAAOD,EAAI,UAAU,SAAS,CAAC,EAAE,QAAQ,QAAQ,MAAM,CAC/D,CAAC,EAED,GAAG,4CAA6C,SAAY,CAC1D,MAAMC,EAAW,GAAG,GAAG,IAAM,QAAQ,QAAQ,CAAE,SAAU,MAAO,CAAC,CAAC,EAC5DD,KAAM,uBAAoBN,EAAQ,CAAE,SAAAO,CAAS,CAAC,EAAG,UAAU,EAEjE,MAAM,OAAOD,EAAI,UAAU,IAAI,OAAO,GAAG,CAAC,CAAC,EAAE,QAAQ,QAAQ,UAAU,EACvE,OAAOC,CAAQ,EAAE,IAAI,iBAAiB,CACxC,CAAC,CACH,CAAC",
4
+ "sourcesContent": ["import { mockServerScreenApi } from \"./mockServerScreenApi\";\nimport { type MockServerClient } from \"./types\";\n\nconst aClient = (overrides: Partial<Record<keyof MockServerClient, unknown>>) =>\n ({\n getScreenshot: vi.fn(),\n getDevice: vi.fn(),\n pressButton: vi.fn(() => Promise.resolve()),\n touchScreen: vi.fn(() => Promise.resolve()),\n ...overrides,\n }) as unknown as MockServerClient;\n\ndescribe(\"mockServerScreenApi\", () => {\n it(\"resolves the screenshot of the device\", async () => {\n const blob = new Blob([\"png\"]);\n const client = aClient({\n getScreenshot: vi.fn(() => Promise.resolve(blob)),\n });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").screenshot(),\n ).resolves.toBe(blob);\n expect(client.getScreenshot).toHaveBeenCalledWith(\"device-1\");\n });\n\n it(\"resolves no screenshot when the device has no Speculos instance\", async () => {\n const client = aClient({\n getScreenshot: vi.fn(() => Promise.reject({ status: 409 })),\n });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").screenshot(),\n ).resolves.toBeNull();\n });\n\n it(\"rethrows any other screenshot failure\", async () => {\n const error = Object.assign(new Error(\"boom\"), { status: 500 });\n const client = aClient({\n getScreenshot: vi.fn(() => Promise.reject(error)),\n });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").screenshot(),\n ).rejects.toBe(error);\n });\n\n it(\"shows the device record while idle\", async () => {\n const device = { id: \"device-1\", device_type: \"nanoX\" };\n const client = aClient({ getDevice: vi.fn(() => Promise.resolve(device)) });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").idle?.(),\n ).resolves.toEqual({\n kind: \"os-info\",\n device,\n });\n });\n\n it(\"forwards buttons and touches to the device\", async () => {\n const client = aClient({});\n const api = mockServerScreenApi(client, \"device-1\");\n\n await api.pressButton(\"left\", \"press\");\n await api.touch(10, 20, \"release\");\n\n expect(client.pressButton).toHaveBeenCalledWith(\n \"device-1\",\n \"left\",\n \"press\",\n );\n expect(client.touchScreen).toHaveBeenCalledWith(\n \"device-1\",\n 10,\n 20,\n \"release\",\n );\n });\n\n it(\"opens an app by name\", async () => {\n const sendApdu = vi.fn(() => Promise.resolve({ response: \"9000\" }));\n const api = mockServerScreenApi(aClient({ sendApdu }), \"device-1\");\n\n await api.openApp?.(\"Bitcoin\");\n\n expect(sendApdu).toHaveBeenCalledWith(\n \"device-1\",\n Uint8Array.from([\n 0xe0,\n 0xd8,\n 0x00,\n 0x00,\n 0x07,\n ...new TextEncoder().encode(\"Bitcoin\"),\n ]),\n );\n });\n\n it(\"fails to open an app the device refuses\", async () => {\n const sendApdu = vi.fn(() => Promise.resolve({ response: \"6807\" }));\n const api = mockServerScreenApi(aClient({ sendApdu }), \"device-1\");\n\n await expect(api.openApp?.(\"Bitcoin\")).rejects.toThrow(\"6807\");\n });\n\n it(\"refuses an app name too long for one APDU\", async () => {\n const sendApdu = vi.fn(() => Promise.resolve({ response: \"9000\" }));\n const api = mockServerScreenApi(aClient({ sendApdu }), \"device-1\");\n\n await expect(api.openApp?.(\"a\".repeat(256))).rejects.toThrow(\"too long\");\n expect(sendApdu).not.toHaveBeenCalled();\n });\n});\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_mockServerScreenApi", "aClient", "overrides", "blob", "client", "error", "device", "api", "sendApdu"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var n=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var u=(o,e,c,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of p(e))!s.call(o,t)&&t!==c&&n(o,t,{get:()=>e[t],enumerable:!(i=r(e,t))||i.enumerable});return o};var S=o=>u(n({},"__esModule",{value:!0}),o);var m={};module.exports=S(m);
1
+ "use strict";var i=Object.defineProperty;var r=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var u=(t,e,c,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of p(e))!s.call(t,o)&&o!==c&&i(t,o,{get:()=>e[o],enumerable:!(n=r(e,o))||n.enumerable});return t};var S=t=>u(i({},"__esModule",{value:!0}),t);var l={};module.exports=S(l);
2
2
  //# sourceMappingURL=types.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/types.ts"],
4
- "sourcesContent": ["import {\n type Device,\n type SpeculosAction,\n type SpeculosButton,\n} from \"@ledgerhq/device-mockserver-client\";\n\n/**\n * How the screen is reached. The mock server proxies to the Speculos instance\n * backing a device and a Speculos transport talks to one directly, but both\n * answer the same calls.\n */\nexport interface ScreenApi {\n /** Resolves null when there is no screen to capture right now. */\n screenshot(): Promise<Blob | null>;\n /** What to show while `screenshot` keeps resolving null. */\n idle?(): Promise<DeviceScreenState>;\n pressButton(button: SpeculosButton, action: SpeculosAction): Promise<void>;\n /** Coordinates in device screen pixels. */\n touch(x: number, y: number, action: SpeculosAction): Promise<void>;\n /** Omitted by apis whose device always runs an app. */\n openApp?(appName: string): Promise<void>;\n}\n\n/**\n * Press and release are separate so a hold reaches the device as a hold: Stax\n * and Flex gate their confirmations behind one.\n */\nexport interface DeviceScreenInput {\n pressButton(button: SpeculosButton, action: SpeculosAction): void;\n touch(x: number, y: number, action: SpeculosAction): void;\n}\n\nexport type DeviceScreenState =\n | { kind: \"loading\" }\n /** No app runs, so no Speculos instance: the device record stands in. */\n | { kind: \"os-info\"; device: Device }\n | { kind: \"image\"; src: string; input: DeviceScreenInput }\n | { kind: \"error\"; message: string };\n"],
4
+ "sourcesContent": ["import {\n type Device,\n type MockClient,\n type SpeculosAction,\n type SpeculosButton,\n} from \"@ledgerhq/device-mockserver-client\";\n\n/**\n * The MockClient calls this library makes. Picking them drops the class's\n * private fields, so a client from another copy of the package still fits.\n */\nexport type MockServerClient = Pick<\n MockClient,\n \"getDevice\" | \"getScreenshot\" | \"pressButton\" | \"touchScreen\" | \"sendApdu\"\n>;\n\n/**\n * How the screen is reached. The mock server proxies to the Speculos instance\n * backing a device and a Speculos transport talks to one directly, but both\n * answer the same calls.\n */\nexport interface ScreenApi {\n /** Resolves null when there is no screen to capture right now. */\n screenshot(): Promise<Blob | null>;\n /** What to show while `screenshot` keeps resolving null. */\n idle?(): Promise<DeviceScreenState>;\n pressButton(button: SpeculosButton, action: SpeculosAction): Promise<void>;\n /** Coordinates in device screen pixels. */\n touch(x: number, y: number, action: SpeculosAction): Promise<void>;\n /** Omitted by apis whose device always runs an app. */\n openApp?(appName: string): Promise<void>;\n}\n\n/**\n * Press and release are separate so a hold reaches the device as a hold: Stax\n * and Flex gate their confirmations behind one.\n */\nexport interface DeviceScreenInput {\n pressButton(button: SpeculosButton, action: SpeculosAction): void;\n touch(x: number, y: number, action: SpeculosAction): void;\n}\n\nexport type DeviceScreenState =\n | { kind: \"loading\" }\n /** No app runs, so no Speculos instance: the device record stands in. */\n | { kind: \"os-info\"; device: Device }\n | { kind: \"image\"; src: string; input: DeviceScreenInput }\n | { kind: \"error\"; message: string };\n"],
5
5
  "mappings": "+WAAA,IAAAA,EAAA,kBAAAC,EAAAD",
6
6
  "names": ["types_exports", "__toCommonJS"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var o=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var v=(t,e)=>{for(var r in e)o(t,r,{get:e[r],enumerable:!0})},D=(t,e,r,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of m(e))!p.call(t,n)&&n!==r&&o(t,n,{get:()=>e[n],enumerable:!(i=s(e,n))||i.enumerable});return t};var a=t=>D(o({},"__esModule",{value:!0}),t);var T={};v(T,{useMockServerDevice:()=>y});module.exports=a(T);var u=require("react");const d=2e3;function y(t,e){const[r,i]=(0,u.useState)();return(0,u.useEffect)(()=>{let n=!1,c;if(i(void 0),!e)return;const l=()=>{t.getDevice(e).then(f=>{n||i(f)},()=>{n||(i(null),c=setTimeout(l,d))})};return l(),()=>{n=!0,clearTimeout(c)}},[t,e]),r}0&&(module.exports={useMockServerDevice});
1
+ "use strict";var u=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var v=(t,e)=>{for(var n in e)u(t,n,{get:e[n],enumerable:!0})},D=(t,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of m(e))!p.call(t,r)&&r!==n&&u(t,r,{get:()=>e[r],enumerable:!(i=s(e,r))||i.enumerable});return t};var a=t=>D(u({},"__esModule",{value:!0}),t);var S={};v(S,{useMockServerDevice:()=>y});module.exports=a(S);var o=require("react");const d=2e3;function y(t,e){const[n,i]=(0,o.useState)();return(0,o.useEffect)(()=>{let r=!1,c;if(i(void 0),!e)return;const f=()=>{t.getDevice(e).then(l=>{r||i(l)},()=>{r||(i(null),c=setTimeout(f,d))})};return f(),()=>{r=!0,clearTimeout(c)}},[t,e]),n}0&&(module.exports={useMockServerDevice});
2
2
  //# sourceMappingURL=useMockServerDevice.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/useMockServerDevice.ts"],
4
- "sourcesContent": ["import { useEffect, useState } from \"react\";\nimport {\n type Device,\n type MockClient,\n} from \"@ledgerhq/device-mockserver-client\";\n\nconst RETRY_MS = 2000;\n\n/**\n * The mock server's record of a device: undefined while it loads, or while no\n * device id is given, and null while it cannot be read. A failed read is\n * retried, so a transient error does not leave the device without its model.\n */\nexport function useMockServerDevice(\n client: MockClient,\n deviceId: string,\n): Device | null | undefined {\n const [device, setDevice] = useState<Device | null>();\n\n useEffect(() => {\n let cancelled = false;\n let retry: ReturnType<typeof setTimeout> | undefined;\n setDevice(undefined);\n if (!deviceId) return;\n\n const load = () => {\n client.getDevice(deviceId).then(\n (record) => {\n if (!cancelled) setDevice(record);\n },\n () => {\n if (cancelled) return;\n setDevice(null);\n retry = setTimeout(load, RETRY_MS);\n },\n );\n };\n load();\n\n return () => {\n cancelled = true;\n clearTimeout(retry);\n };\n }, [client, deviceId]);\n\n return device;\n}\n"],
5
- "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,yBAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAAoC,iBAMpC,MAAMC,EAAW,IAOV,SAASH,EACdI,EACAC,EAC2B,CAC3B,KAAM,CAACC,EAAQC,CAAS,KAAI,YAAwB,EAEpD,sBAAU,IAAM,CACd,IAAIC,EAAY,GACZC,EAEJ,GADAF,EAAU,MAAS,EACf,CAACF,EAAU,OAEf,MAAMK,EAAO,IAAM,CACjBN,EAAO,UAAUC,CAAQ,EAAE,KACxBM,GAAW,CACLH,GAAWD,EAAUI,CAAM,CAClC,EACA,IAAM,CACAH,IACJD,EAAU,IAAI,EACdE,EAAQ,WAAWC,EAAMP,CAAQ,EACnC,CACF,CACF,EACA,OAAAO,EAAK,EAEE,IAAM,CACXF,EAAY,GACZ,aAAaC,CAAK,CACpB,CACF,EAAG,CAACL,EAAQC,CAAQ,CAAC,EAEdC,CACT",
4
+ "sourcesContent": ["import { useEffect, useState } from \"react\";\nimport { type Device } from \"@ledgerhq/device-mockserver-client\";\n\nimport { type MockServerClient } from \"./types\";\n\nconst RETRY_MS = 2000;\n\n/**\n * The mock server's record of a device: undefined while it loads, or while no\n * device id is given, and null while it cannot be read. A failed read is\n * retried, so a transient error does not leave the device without its model.\n */\nexport function useMockServerDevice(\n client: MockServerClient,\n deviceId: string,\n): Device | null | undefined {\n const [device, setDevice] = useState<Device | null>();\n\n useEffect(() => {\n let cancelled = false;\n let retry: ReturnType<typeof setTimeout> | undefined;\n setDevice(undefined);\n if (!deviceId) return;\n\n const load = () => {\n client.getDevice(deviceId).then(\n (record) => {\n if (!cancelled) setDevice(record);\n },\n () => {\n if (cancelled) return;\n setDevice(null);\n retry = setTimeout(load, RETRY_MS);\n },\n );\n };\n load();\n\n return () => {\n cancelled = true;\n clearTimeout(retry);\n };\n }, [client, deviceId]);\n\n return device;\n}\n"],
5
+ "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,yBAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAAoC,iBAKpC,MAAMC,EAAW,IAOV,SAASH,EACdI,EACAC,EAC2B,CAC3B,KAAM,CAACC,EAAQC,CAAS,KAAI,YAAwB,EAEpD,sBAAU,IAAM,CACd,IAAIC,EAAY,GACZC,EAEJ,GADAF,EAAU,MAAS,EACf,CAACF,EAAU,OAEf,MAAMK,EAAO,IAAM,CACjBN,EAAO,UAAUC,CAAQ,EAAE,KACxBM,GAAW,CACLH,GAAWD,EAAUI,CAAM,CAClC,EACA,IAAM,CACAH,IACJD,EAAU,IAAI,EACdE,EAAQ,WAAWC,EAAMP,CAAQ,EACnC,CACF,CACF,EACA,OAAAO,EAAK,EAEE,IAAM,CACXF,EAAY,GACZ,aAAaC,CAAK,CACpB,CACF,EAAG,CAACL,EAAQC,CAAQ,CAAC,EAEdC,CACT",
6
6
  "names": ["useMockServerDevice_exports", "__export", "useMockServerDevice", "__toCommonJS", "import_react", "RETRY_MS", "client", "deviceId", "device", "setDevice", "cancelled", "retry", "load", "record"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var f=Object.create;var v=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var D=Object.getPrototypeOf,T=Object.prototype.hasOwnProperty;var C=(t,i,c,s)=>{if(i&&typeof i=="object"||typeof i=="function")for(let o of y(i))!T.call(t,o)&&o!==c&&v(t,o,{get:()=>i[o],enumerable:!(s=p(i,o))||s.enumerable});return t};var B=(t,i,c)=>(c=t!=null?f(D(t)):{},C(i||!t||!t.__esModule?v(c,"default",{value:t,enumerable:!0}):c,t));var n=B(require("react")),m=require("react-dom/client"),u=require("./useMockServerDevice");Object.assign(globalThis,{IS_REACT_ACT_ENVIRONMENT:!0});const a={id:"device-1",device_type:"stax"};describe("useMockServerDevice",()=>{let t,i,c;const s=({client:e,deviceId:r})=>(c=(0,u.useMockServerDevice)(e,r),null),o=e=>({getDevice:vi.fn(e)}),l=(e,r="device-1")=>(0,n.act)(()=>i.render(n.default.createElement(s,{client:e,deviceId:r}))),d=()=>(0,n.act)(()=>vi.advanceTimersByTimeAsync(0));beforeEach(()=>{vi.useFakeTimers(),c=void 0,t=document.createElement("div"),i=(0,m.createRoot)(t)}),afterEach(()=>{(0,n.act)(()=>i.unmount()),vi.useRealTimers()}),it("reads the device record",async()=>{const e=o(()=>Promise.resolve(a));l(e),expect(c).toBeUndefined(),await d(),expect(c).toBe(a),expect(e.getDevice).toHaveBeenCalledWith("device-1")}),it("reads nothing without a device id",async()=>{const e=o(()=>Promise.resolve(a));l(e,""),await d(),expect(c).toBeUndefined(),expect(e.getDevice).not.toHaveBeenCalled()}),it("retries a failed read until it succeeds",async()=>{const e=vi.fn().mockRejectedValueOnce(new Error("offline")).mockResolvedValue(a),r=o(e);l(r),await d(),expect(c).toBeNull(),await(0,n.act)(()=>vi.advanceTimersByTimeAsync(2e3)),expect(c).toBe(a),expect(e).toHaveBeenCalledTimes(2)}),it("stops retrying once unmounted",async()=>{const e=o(()=>Promise.reject(new Error("offline")));l(e),await d(),(0,n.act)(()=>i.render(n.default.createElement(n.default.Fragment,null))),await(0,n.act)(()=>vi.advanceTimersByTimeAsync(1e4)),expect(e.getDevice).toHaveBeenCalledOnce()})});
1
+ "use strict";var u=Object.create;var d=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var y=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty;var k=(i,n,t,l)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of C(n))!h.call(i,r)&&r!==t&&d(i,r,{get:()=>n[r],enumerable:!(l=f(n,r))||l.enumerable});return i};var S=(i,n,t)=>(t=i!=null?u(y(i)):{},k(n||!i||!i.__esModule?d(t,"default",{value:i,enumerable:!0}):t,i));var c=S(require("react")),m=require("react-dom/client"),p=require("./useMockServerDevice");Object.assign(globalThis,{IS_REACT_ACT_ENVIRONMENT:!0});const s={id:"device-1",device_type:"stax"};describe("useMockServerDevice",()=>{let i,n,t;const l=({client:e,deviceId:o})=>(t=(0,p.useMockServerDevice)(e,o),null),r=e=>({getDevice:vi.fn(e)}),a=(e,o="device-1")=>(0,c.act)(()=>n.render(c.default.createElement(l,{client:e,deviceId:o}))),v=()=>(0,c.act)(()=>vi.advanceTimersByTimeAsync(0));beforeEach(()=>{vi.useFakeTimers(),t=void 0,i=document.createElement("div"),n=(0,m.createRoot)(i)}),afterEach(()=>{(0,c.act)(()=>n.unmount()),vi.useRealTimers()}),it("reads the device record",async()=>{const e=r(()=>Promise.resolve(s));a(e),expect(t).toBeUndefined(),await v(),expect(t).toBe(s),expect(e.getDevice).toHaveBeenCalledWith("device-1")}),it("accepts a client from another copy of the package",async()=>{class e{record=s;getDevice=vi.fn(()=>Promise.resolve(this.record));getScreenshot=vi.fn();pressButton=vi.fn();touchScreen=vi.fn();sendApdu=vi.fn()}const o=new e;a(o),await v(),expect(t).toBe(s)}),it("reads nothing without a device id",async()=>{const e=r(()=>Promise.resolve(s));a(e,""),await v(),expect(t).toBeUndefined(),expect(e.getDevice).not.toHaveBeenCalled()}),it("retries a failed read until it succeeds",async()=>{const e=vi.fn().mockRejectedValueOnce(new Error("offline")).mockResolvedValue(s),o=r(e);a(o),await v(),expect(t).toBeNull(),await(0,c.act)(()=>vi.advanceTimersByTimeAsync(2e3)),expect(t).toBe(s),expect(e).toHaveBeenCalledTimes(2)}),it("stops retrying once unmounted",async()=>{const e=r(()=>Promise.reject(new Error("offline")));a(e),await v(),(0,c.act)(()=>n.render(c.default.createElement(c.default.Fragment,null))),await(0,c.act)(()=>vi.advanceTimersByTimeAsync(1e4)),expect(e.getDevice).toHaveBeenCalledOnce()})});
2
2
  //# sourceMappingURL=useMockServerDevice.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/useMockServerDevice.test.tsx"],
4
- "sourcesContent": ["import React, { act } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport {\n type Device,\n type MockClient,\n} from \"@ledgerhq/device-mockserver-client\";\n\nimport { useMockServerDevice } from \"./useMockServerDevice\";\n\nObject.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true });\n\nconst DEVICE = { id: \"device-1\", device_type: \"stax\" } as Device;\n\ndescribe(\"useMockServerDevice\", () => {\n let container: HTMLDivElement;\n let root: Root;\n let result: Device | null | undefined;\n\n const Probe: React.FC<{ client: MockClient; deviceId: string }> = ({\n client,\n deviceId,\n }) => {\n result = useMockServerDevice(client, deviceId);\n return null;\n };\n const aClient = (getDevice: () => Promise<Device>) =>\n ({ getDevice: vi.fn(getDevice) }) as unknown as MockClient;\n const render = (client: MockClient, deviceId = \"device-1\") =>\n act(() => root.render(<Probe client={client} deviceId={deviceId} />));\n const flush = () => act(() => vi.advanceTimersByTimeAsync(0));\n\n beforeEach(() => {\n vi.useFakeTimers();\n result = undefined;\n container = document.createElement(\"div\");\n root = createRoot(container);\n });\n\n afterEach(() => {\n act(() => root.unmount());\n vi.useRealTimers();\n });\n\n it(\"reads the device record\", async () => {\n const client = aClient(() => Promise.resolve(DEVICE));\n\n render(client);\n expect(result).toBeUndefined();\n await flush();\n\n expect(result).toBe(DEVICE);\n expect(client.getDevice).toHaveBeenCalledWith(\"device-1\");\n });\n\n it(\"reads nothing without a device id\", async () => {\n const client = aClient(() => Promise.resolve(DEVICE));\n\n render(client, \"\");\n await flush();\n\n expect(result).toBeUndefined();\n expect(client.getDevice).not.toHaveBeenCalled();\n });\n\n it(\"retries a failed read until it succeeds\", async () => {\n const getDevice = vi\n .fn<() => Promise<Device>>()\n .mockRejectedValueOnce(new Error(\"offline\"))\n .mockResolvedValue(DEVICE);\n const client = aClient(getDevice);\n\n render(client);\n await flush();\n expect(result).toBeNull();\n\n await act(() => vi.advanceTimersByTimeAsync(2000));\n\n expect(result).toBe(DEVICE);\n expect(getDevice).toHaveBeenCalledTimes(2);\n });\n\n it(\"stops retrying once unmounted\", async () => {\n const client = aClient(() => Promise.reject(new Error(\"offline\")));\n\n render(client);\n await flush();\n act(() => root.render(<></>));\n await act(() => vi.advanceTimersByTimeAsync(10_000));\n\n expect(client.getDevice).toHaveBeenCalledOnce();\n });\n});\n"],
5
- "mappings": "wdAAA,IAAAA,EAA2B,oBAC3BC,EAAsC,4BAMtCC,EAAoC,iCAEpC,OAAO,OAAO,WAAY,CAAE,yBAA0B,EAAK,CAAC,EAE5D,MAAMC,EAAS,CAAE,GAAI,WAAY,YAAa,MAAO,EAErD,SAAS,sBAAuB,IAAM,CACpC,IAAIC,EACAC,EACAC,EAEJ,MAAMC,EAA4D,CAAC,CACjE,OAAAC,EACA,SAAAC,CACF,KACEH,KAAS,uBAAoBE,EAAQC,CAAQ,EACtC,MAEHC,EAAWC,IACd,CAAE,UAAW,GAAG,GAAGA,CAAS,CAAE,GAC3BC,EAAS,CAACJ,EAAoBC,EAAW,gBAC7C,OAAI,IAAMJ,EAAK,OAAO,EAAAQ,QAAA,cAACN,EAAA,CAAM,OAAQC,EAAQ,SAAUC,EAAU,CAAE,CAAC,EAChEK,EAAQ,OAAM,OAAI,IAAM,GAAG,yBAAyB,CAAC,CAAC,EAE5D,WAAW,IAAM,CACf,GAAG,cAAc,EACjBR,EAAS,OACTF,EAAY,SAAS,cAAc,KAAK,EACxCC,KAAO,cAAWD,CAAS,CAC7B,CAAC,EAED,UAAU,IAAM,IACd,OAAI,IAAMC,EAAK,QAAQ,CAAC,EACxB,GAAG,cAAc,CACnB,CAAC,EAED,GAAG,0BAA2B,SAAY,CACxC,MAAMG,EAASE,EAAQ,IAAM,QAAQ,QAAQP,CAAM,CAAC,EAEpDS,EAAOJ,CAAM,EACb,OAAOF,CAAM,EAAE,cAAc,EAC7B,MAAMQ,EAAM,EAEZ,OAAOR,CAAM,EAAE,KAAKH,CAAM,EAC1B,OAAOK,EAAO,SAAS,EAAE,qBAAqB,UAAU,CAC1D,CAAC,EAED,GAAG,oCAAqC,SAAY,CAClD,MAAMA,EAASE,EAAQ,IAAM,QAAQ,QAAQP,CAAM,CAAC,EAEpDS,EAAOJ,EAAQ,EAAE,EACjB,MAAMM,EAAM,EAEZ,OAAOR,CAAM,EAAE,cAAc,EAC7B,OAAOE,EAAO,SAAS,EAAE,IAAI,iBAAiB,CAChD,CAAC,EAED,GAAG,0CAA2C,SAAY,CACxD,MAAMG,EAAY,GACf,GAA0B,EAC1B,sBAAsB,IAAI,MAAM,SAAS,CAAC,EAC1C,kBAAkBR,CAAM,EACrBK,EAASE,EAAQC,CAAS,EAEhCC,EAAOJ,CAAM,EACb,MAAMM,EAAM,EACZ,OAAOR,CAAM,EAAE,SAAS,EAExB,QAAM,OAAI,IAAM,GAAG,yBAAyB,GAAI,CAAC,EAEjD,OAAOA,CAAM,EAAE,KAAKH,CAAM,EAC1B,OAAOQ,CAAS,EAAE,sBAAsB,CAAC,CAC3C,CAAC,EAED,GAAG,gCAAiC,SAAY,CAC9C,MAAMH,EAASE,EAAQ,IAAM,QAAQ,OAAO,IAAI,MAAM,SAAS,CAAC,CAAC,EAEjEE,EAAOJ,CAAM,EACb,MAAMM,EAAM,KACZ,OAAI,IAAMT,EAAK,OAAO,EAAAQ,QAAA,gBAAAA,QAAA,aAAE,CAAG,CAAC,EAC5B,QAAM,OAAI,IAAM,GAAG,yBAAyB,GAAM,CAAC,EAEnD,OAAOL,EAAO,SAAS,EAAE,qBAAqB,CAChD,CAAC,CACH,CAAC",
6
- "names": ["import_react", "import_client", "import_useMockServerDevice", "DEVICE", "container", "root", "result", "Probe", "client", "deviceId", "aClient", "getDevice", "render", "React", "flush"]
4
+ "sourcesContent": ["import React, { act } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport { type Device } from \"@ledgerhq/device-mockserver-client\";\n\nimport { type MockServerClient } from \"./types\";\nimport { useMockServerDevice } from \"./useMockServerDevice\";\n\nObject.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true });\n\nconst DEVICE = { id: \"device-1\", device_type: \"stax\" } as Device;\n\ndescribe(\"useMockServerDevice\", () => {\n let container: HTMLDivElement;\n let root: Root;\n let result: Device | null | undefined;\n\n const Probe: React.FC<{ client: MockServerClient; deviceId: string }> = ({\n client,\n deviceId,\n }) => {\n result = useMockServerDevice(client, deviceId);\n return null;\n };\n const aClient = (getDevice: () => Promise<Device>) =>\n ({ getDevice: vi.fn(getDevice) }) as unknown as MockServerClient;\n const render = (client: MockServerClient, deviceId = \"device-1\") =>\n act(() => root.render(<Probe client={client} deviceId={deviceId} />));\n const flush = () => act(() => vi.advanceTimersByTimeAsync(0));\n\n beforeEach(() => {\n vi.useFakeTimers();\n result = undefined;\n container = document.createElement(\"div\");\n root = createRoot(container);\n });\n\n afterEach(() => {\n act(() => root.unmount());\n vi.useRealTimers();\n });\n\n it(\"reads the device record\", async () => {\n const client = aClient(() => Promise.resolve(DEVICE));\n\n render(client);\n expect(result).toBeUndefined();\n await flush();\n\n expect(result).toBe(DEVICE);\n expect(client.getDevice).toHaveBeenCalledWith(\"device-1\");\n });\n\n it(\"accepts a client from another copy of the package\", async () => {\n // Its own private field, as a MockClient from a second install would have:\n // only the public calls must match.\n class OtherCopyClient implements MockServerClient {\n private readonly record = DEVICE;\n getDevice = vi.fn(() => Promise.resolve(this.record));\n getScreenshot = vi.fn<MockServerClient[\"getScreenshot\"]>();\n pressButton = vi.fn<MockServerClient[\"pressButton\"]>();\n touchScreen = vi.fn<MockServerClient[\"touchScreen\"]>();\n sendApdu = vi.fn<MockServerClient[\"sendApdu\"]>();\n }\n const client = new OtherCopyClient();\n\n render(client);\n await flush();\n\n expect(result).toBe(DEVICE);\n });\n\n it(\"reads nothing without a device id\", async () => {\n const client = aClient(() => Promise.resolve(DEVICE));\n\n render(client, \"\");\n await flush();\n\n expect(result).toBeUndefined();\n expect(client.getDevice).not.toHaveBeenCalled();\n });\n\n it(\"retries a failed read until it succeeds\", async () => {\n const getDevice = vi\n .fn<() => Promise<Device>>()\n .mockRejectedValueOnce(new Error(\"offline\"))\n .mockResolvedValue(DEVICE);\n const client = aClient(getDevice);\n\n render(client);\n await flush();\n expect(result).toBeNull();\n\n await act(() => vi.advanceTimersByTimeAsync(2000));\n\n expect(result).toBe(DEVICE);\n expect(getDevice).toHaveBeenCalledTimes(2);\n });\n\n it(\"stops retrying once unmounted\", async () => {\n const client = aClient(() => Promise.reject(new Error(\"offline\")));\n\n render(client);\n await flush();\n act(() => root.render(<></>));\n await act(() => vi.advanceTimersByTimeAsync(10_000));\n\n expect(client.getDevice).toHaveBeenCalledOnce();\n });\n});\n"],
5
+ "mappings": "wdAAA,IAAAA,EAA2B,oBAC3BC,EAAsC,4BAItCC,EAAoC,iCAEpC,OAAO,OAAO,WAAY,CAAE,yBAA0B,EAAK,CAAC,EAE5D,MAAMC,EAAS,CAAE,GAAI,WAAY,YAAa,MAAO,EAErD,SAAS,sBAAuB,IAAM,CACpC,IAAIC,EACAC,EACAC,EAEJ,MAAMC,EAAkE,CAAC,CACvE,OAAAC,EACA,SAAAC,CACF,KACEH,KAAS,uBAAoBE,EAAQC,CAAQ,EACtC,MAEHC,EAAWC,IACd,CAAE,UAAW,GAAG,GAAGA,CAAS,CAAE,GAC3BC,EAAS,CAACJ,EAA0BC,EAAW,gBACnD,OAAI,IAAMJ,EAAK,OAAO,EAAAQ,QAAA,cAACN,EAAA,CAAM,OAAQC,EAAQ,SAAUC,EAAU,CAAE,CAAC,EAChEK,EAAQ,OAAM,OAAI,IAAM,GAAG,yBAAyB,CAAC,CAAC,EAE5D,WAAW,IAAM,CACf,GAAG,cAAc,EACjBR,EAAS,OACTF,EAAY,SAAS,cAAc,KAAK,EACxCC,KAAO,cAAWD,CAAS,CAC7B,CAAC,EAED,UAAU,IAAM,IACd,OAAI,IAAMC,EAAK,QAAQ,CAAC,EACxB,GAAG,cAAc,CACnB,CAAC,EAED,GAAG,0BAA2B,SAAY,CACxC,MAAMG,EAASE,EAAQ,IAAM,QAAQ,QAAQP,CAAM,CAAC,EAEpDS,EAAOJ,CAAM,EACb,OAAOF,CAAM,EAAE,cAAc,EAC7B,MAAMQ,EAAM,EAEZ,OAAOR,CAAM,EAAE,KAAKH,CAAM,EAC1B,OAAOK,EAAO,SAAS,EAAE,qBAAqB,UAAU,CAC1D,CAAC,EAED,GAAG,oDAAqD,SAAY,CAGlE,MAAMO,CAA4C,CAC/B,OAASZ,EAC1B,UAAY,GAAG,GAAG,IAAM,QAAQ,QAAQ,KAAK,MAAM,CAAC,EACpD,cAAgB,GAAG,GAAsC,EACzD,YAAc,GAAG,GAAoC,EACrD,YAAc,GAAG,GAAoC,EACrD,SAAW,GAAG,GAAiC,CACjD,CACA,MAAMK,EAAS,IAAIO,EAEnBH,EAAOJ,CAAM,EACb,MAAMM,EAAM,EAEZ,OAAOR,CAAM,EAAE,KAAKH,CAAM,CAC5B,CAAC,EAED,GAAG,oCAAqC,SAAY,CAClD,MAAMK,EAASE,EAAQ,IAAM,QAAQ,QAAQP,CAAM,CAAC,EAEpDS,EAAOJ,EAAQ,EAAE,EACjB,MAAMM,EAAM,EAEZ,OAAOR,CAAM,EAAE,cAAc,EAC7B,OAAOE,EAAO,SAAS,EAAE,IAAI,iBAAiB,CAChD,CAAC,EAED,GAAG,0CAA2C,SAAY,CACxD,MAAMG,EAAY,GACf,GAA0B,EAC1B,sBAAsB,IAAI,MAAM,SAAS,CAAC,EAC1C,kBAAkBR,CAAM,EACrBK,EAASE,EAAQC,CAAS,EAEhCC,EAAOJ,CAAM,EACb,MAAMM,EAAM,EACZ,OAAOR,CAAM,EAAE,SAAS,EAExB,QAAM,OAAI,IAAM,GAAG,yBAAyB,GAAI,CAAC,EAEjD,OAAOA,CAAM,EAAE,KAAKH,CAAM,EAC1B,OAAOQ,CAAS,EAAE,sBAAsB,CAAC,CAC3C,CAAC,EAED,GAAG,gCAAiC,SAAY,CAC9C,MAAMH,EAASE,EAAQ,IAAM,QAAQ,OAAO,IAAI,MAAM,SAAS,CAAC,CAAC,EAEjEE,EAAOJ,CAAM,EACb,MAAMM,EAAM,KACZ,OAAI,IAAMT,EAAK,OAAO,EAAAQ,QAAA,gBAAAA,QAAA,aAAE,CAAG,CAAC,EAC5B,QAAM,OAAI,IAAM,GAAG,yBAAyB,GAAM,CAAC,EAEnD,OAAOL,EAAO,SAAS,EAAE,qBAAqB,CAChD,CAAC,CACH,CAAC",
6
+ "names": ["import_react", "import_client", "import_useMockServerDevice", "DEVICE", "container", "root", "result", "Probe", "client", "deviceId", "aClient", "getDevice", "render", "React", "flush", "OtherCopyClient"]
7
7
  }
@@ -63,5 +63,5 @@
63
63
  "watch:types": "concurrently \"tsc --watch -p tsconfig.prod.json\" \"tsc-alias --watch -p tsconfig.prod.json\""
64
64
  },
65
65
  "types": "lib/index.d.ts",
66
- "version": "0.0.0-develop-20261004005728"
66
+ "version": "0.0.0-develop-20261007001516"
67
67
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/index.ts"],
4
- "sourcesContent": ["export { type DeviceScreenModel, findDeviceScreenModel } from \"./deviceModels\";\nexport { DeviceScreen, type DeviceScreenProps } from \"./DeviceScreen\";\nexport {\n MockServerDevice,\n type MockServerDeviceProps,\n} from \"./MockServerDevice\";\nexport { mockServerScreenApi } from \"./mockServerScreenApi\";\nexport type { DeviceScreenState, ScreenApi } from \"./types\";\nexport { useMockServerDevice } from \"./useMockServerDevice\";\n"],
4
+ "sourcesContent": ["export { type DeviceScreenModel, findDeviceScreenModel } from \"./deviceModels\";\nexport { DeviceScreen, type DeviceScreenProps } from \"./DeviceScreen\";\nexport {\n MockServerDevice,\n type MockServerDeviceProps,\n} from \"./MockServerDevice\";\nexport { mockServerScreenApi } from \"./mockServerScreenApi\";\nexport type { DeviceScreenState, MockServerClient, ScreenApi } from \"./types\";\nexport { useMockServerDevice } from \"./useMockServerDevice\";\n"],
5
5
  "mappings": "AAAA,OAAiC,yBAAAA,MAA6B,iBAC9D,OAAS,gBAAAC,MAA4C,iBACrD,OACE,oBAAAC,MAEK,qBACP,OAAS,uBAAAC,MAA2B,wBAEpC,OAAS,uBAAAC,MAA2B",
6
6
  "names": ["findDeviceScreenModel", "DeviceScreen", "MockServerDevice", "mockServerScreenApi", "useMockServerDevice"]
7
7
  }
@@ -1,2 +1,2 @@
1
- const c=o=>o?.status===409,a=(o,r)=>({screenshot:async()=>{try{return await o.getScreenshot(r)}catch(n){if(c(n))return null;throw n}},idle:async()=>({kind:"os-info",device:await o.getDevice(r)}),pressButton:(n,t)=>o.pressButton(r,n,t),touch:(n,t,e)=>o.touchScreen(r,n,t,e),openApp:async n=>{const t=new TextEncoder().encode(n);if(t.length>255)throw new Error(`App name too long to open: ${n}`);const{response:e}=await o.sendApdu(r,Uint8Array.from([224,216,0,0,t.length,...t])),s=e.slice(-4);if(s!=="9000")throw new Error(`Could not open ${n} (${s})`)}});export{a as mockServerScreenApi};
1
+ const c=o=>o?.status===409,a=(o,t)=>({screenshot:async()=>{try{return await o.getScreenshot(t)}catch(n){if(c(n))return null;throw n}},idle:async()=>({kind:"os-info",device:await o.getDevice(t)}),pressButton:(n,e)=>o.pressButton(t,n,e),touch:(n,e,r)=>o.touchScreen(t,n,e,r),openApp:async n=>{const e=new TextEncoder().encode(n);if(e.length>255)throw new Error(`App name too long to open: ${n}`);const{response:r}=await o.sendApdu(t,Uint8Array.from([224,216,0,0,e.length,...e])),s=r.slice(-4);if(s!=="9000")throw new Error(`Could not open ${n} (${s})`)}});export{a as mockServerScreenApi};
2
2
  //# sourceMappingURL=mockServerScreenApi.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/mockServerScreenApi.ts"],
4
- "sourcesContent": ["import { type MockClient } from \"@ledgerhq/device-mockserver-client\";\n\nimport { type ScreenApi } from \"./types\";\n\n/** The proxy answers 409 when the device has no Speculos instance. */\nconst isNoInstance = (error: unknown): boolean =>\n (error as { status?: unknown } | null)?.status === 409;\n\nexport const mockServerScreenApi = (\n client: MockClient,\n deviceId: string,\n): ScreenApi => ({\n screenshot: async () => {\n try {\n return await client.getScreenshot(deviceId);\n } catch (error) {\n if (isNoInstance(error)) return null;\n throw error;\n }\n },\n idle: async () => ({\n kind: \"os-info\",\n device: await client.getDevice(deviceId),\n }),\n pressButton: (button, action) => client.pressButton(deviceId, button, action),\n touch: (x, y, action) => client.touchScreen(deviceId, x, y, action),\n openApp: async (appName) => {\n const name = new TextEncoder().encode(appName);\n // Lc is a single byte.\n if (name.length > 0xff) {\n throw new Error(`App name too long to open: ${appName}`);\n }\n const { response } = await client.sendApdu(\n deviceId,\n Uint8Array.from([0xe0, 0xd8, 0x00, 0x00, name.length, ...name]),\n );\n const statusWord = response.slice(-4);\n if (statusWord !== \"9000\") {\n throw new Error(`Could not open ${appName} (${statusWord})`);\n }\n },\n});\n"],
5
- "mappings": "AAKA,MAAMA,EAAgBC,GACnBA,GAAuC,SAAW,IAExCC,EAAsB,CACjCC,EACAC,KACe,CACf,WAAY,SAAY,CACtB,GAAI,CACF,OAAO,MAAMD,EAAO,cAAcC,CAAQ,CAC5C,OAASH,EAAO,CACd,GAAID,EAAaC,CAAK,EAAG,OAAO,KAChC,MAAMA,CACR,CACF,EACA,KAAM,UAAa,CACjB,KAAM,UACN,OAAQ,MAAME,EAAO,UAAUC,CAAQ,CACzC,GACA,YAAa,CAACC,EAAQC,IAAWH,EAAO,YAAYC,EAAUC,EAAQC,CAAM,EAC5E,MAAO,CAACC,EAAGC,EAAGF,IAAWH,EAAO,YAAYC,EAAUG,EAAGC,EAAGF,CAAM,EAClE,QAAS,MAAOG,GAAY,CAC1B,MAAMC,EAAO,IAAI,YAAY,EAAE,OAAOD,CAAO,EAE7C,GAAIC,EAAK,OAAS,IAChB,MAAM,IAAI,MAAM,8BAA8BD,CAAO,EAAE,EAEzD,KAAM,CAAE,SAAAE,CAAS,EAAI,MAAMR,EAAO,SAChCC,EACA,WAAW,KAAK,CAAC,IAAM,IAAM,EAAM,EAAMM,EAAK,OAAQ,GAAGA,CAAI,CAAC,CAChE,EACME,EAAaD,EAAS,MAAM,EAAE,EACpC,GAAIC,IAAe,OACjB,MAAM,IAAI,MAAM,kBAAkBH,CAAO,KAAKG,CAAU,GAAG,CAE/D,CACF",
4
+ "sourcesContent": ["import { type MockServerClient, type ScreenApi } from \"./types\";\n\n/** The proxy answers 409 when the device has no Speculos instance. */\nconst isNoInstance = (error: unknown): boolean =>\n (error as { status?: unknown } | null)?.status === 409;\n\nexport const mockServerScreenApi = (\n client: MockServerClient,\n deviceId: string,\n): ScreenApi => ({\n screenshot: async () => {\n try {\n return await client.getScreenshot(deviceId);\n } catch (error) {\n if (isNoInstance(error)) return null;\n throw error;\n }\n },\n idle: async () => ({\n kind: \"os-info\",\n device: await client.getDevice(deviceId),\n }),\n pressButton: (button, action) => client.pressButton(deviceId, button, action),\n touch: (x, y, action) => client.touchScreen(deviceId, x, y, action),\n openApp: async (appName) => {\n const name = new TextEncoder().encode(appName);\n // Lc is a single byte.\n if (name.length > 0xff) {\n throw new Error(`App name too long to open: ${appName}`);\n }\n const { response } = await client.sendApdu(\n deviceId,\n Uint8Array.from([0xe0, 0xd8, 0x00, 0x00, name.length, ...name]),\n );\n const statusWord = response.slice(-4);\n if (statusWord !== \"9000\") {\n throw new Error(`Could not open ${appName} (${statusWord})`);\n }\n },\n});\n"],
5
+ "mappings": "AAGA,MAAMA,EAAgBC,GACnBA,GAAuC,SAAW,IAExCC,EAAsB,CACjCC,EACAC,KACe,CACf,WAAY,SAAY,CACtB,GAAI,CACF,OAAO,MAAMD,EAAO,cAAcC,CAAQ,CAC5C,OAASH,EAAO,CACd,GAAID,EAAaC,CAAK,EAAG,OAAO,KAChC,MAAMA,CACR,CACF,EACA,KAAM,UAAa,CACjB,KAAM,UACN,OAAQ,MAAME,EAAO,UAAUC,CAAQ,CACzC,GACA,YAAa,CAACC,EAAQC,IAAWH,EAAO,YAAYC,EAAUC,EAAQC,CAAM,EAC5E,MAAO,CAACC,EAAGC,EAAGF,IAAWH,EAAO,YAAYC,EAAUG,EAAGC,EAAGF,CAAM,EAClE,QAAS,MAAOG,GAAY,CAC1B,MAAMC,EAAO,IAAI,YAAY,EAAE,OAAOD,CAAO,EAE7C,GAAIC,EAAK,OAAS,IAChB,MAAM,IAAI,MAAM,8BAA8BD,CAAO,EAAE,EAEzD,KAAM,CAAE,SAAAE,CAAS,EAAI,MAAMR,EAAO,SAChCC,EACA,WAAW,KAAK,CAAC,IAAM,IAAM,EAAM,EAAMM,EAAK,OAAQ,GAAGA,CAAI,CAAC,CAChE,EACME,EAAaD,EAAS,MAAM,EAAE,EACpC,GAAIC,IAAe,OACjB,MAAM,IAAI,MAAM,kBAAkBH,CAAO,KAAKG,CAAU,GAAG,CAE/D,CACF",
6
6
  "names": ["isNoInstance", "error", "mockServerScreenApi", "client", "deviceId", "button", "action", "x", "y", "appName", "name", "response", "statusWord"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/mockServerScreenApi.test.ts"],
4
- "sourcesContent": ["import { type MockClient } from \"@ledgerhq/device-mockserver-client\";\n\nimport { mockServerScreenApi } from \"./mockServerScreenApi\";\n\nconst aClient = (overrides: Partial<Record<keyof MockClient, unknown>>) =>\n ({\n getScreenshot: vi.fn(),\n getDevice: vi.fn(),\n pressButton: vi.fn(() => Promise.resolve()),\n touchScreen: vi.fn(() => Promise.resolve()),\n ...overrides,\n }) as unknown as MockClient;\n\ndescribe(\"mockServerScreenApi\", () => {\n it(\"resolves the screenshot of the device\", async () => {\n const blob = new Blob([\"png\"]);\n const client = aClient({\n getScreenshot: vi.fn(() => Promise.resolve(blob)),\n });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").screenshot(),\n ).resolves.toBe(blob);\n expect(client.getScreenshot).toHaveBeenCalledWith(\"device-1\");\n });\n\n it(\"resolves no screenshot when the device has no Speculos instance\", async () => {\n const client = aClient({\n getScreenshot: vi.fn(() => Promise.reject({ status: 409 })),\n });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").screenshot(),\n ).resolves.toBeNull();\n });\n\n it(\"rethrows any other screenshot failure\", async () => {\n const error = Object.assign(new Error(\"boom\"), { status: 500 });\n const client = aClient({\n getScreenshot: vi.fn(() => Promise.reject(error)),\n });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").screenshot(),\n ).rejects.toBe(error);\n });\n\n it(\"shows the device record while idle\", async () => {\n const device = { id: \"device-1\", device_type: \"nanoX\" };\n const client = aClient({ getDevice: vi.fn(() => Promise.resolve(device)) });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").idle?.(),\n ).resolves.toEqual({\n kind: \"os-info\",\n device,\n });\n });\n\n it(\"forwards buttons and touches to the device\", async () => {\n const client = aClient({});\n const api = mockServerScreenApi(client, \"device-1\");\n\n await api.pressButton(\"left\", \"press\");\n await api.touch(10, 20, \"release\");\n\n expect(client.pressButton).toHaveBeenCalledWith(\n \"device-1\",\n \"left\",\n \"press\",\n );\n expect(client.touchScreen).toHaveBeenCalledWith(\n \"device-1\",\n 10,\n 20,\n \"release\",\n );\n });\n\n it(\"opens an app by name\", async () => {\n const sendApdu = vi.fn(() => Promise.resolve({ response: \"9000\" }));\n const api = mockServerScreenApi(aClient({ sendApdu }), \"device-1\");\n\n await api.openApp?.(\"Bitcoin\");\n\n expect(sendApdu).toHaveBeenCalledWith(\n \"device-1\",\n Uint8Array.from([\n 0xe0,\n 0xd8,\n 0x00,\n 0x00,\n 0x07,\n ...new TextEncoder().encode(\"Bitcoin\"),\n ]),\n );\n });\n\n it(\"fails to open an app the device refuses\", async () => {\n const sendApdu = vi.fn(() => Promise.resolve({ response: \"6807\" }));\n const api = mockServerScreenApi(aClient({ sendApdu }), \"device-1\");\n\n await expect(api.openApp?.(\"Bitcoin\")).rejects.toThrow(\"6807\");\n });\n\n it(\"refuses an app name too long for one APDU\", async () => {\n const sendApdu = vi.fn(() => Promise.resolve({ response: \"9000\" }));\n const api = mockServerScreenApi(aClient({ sendApdu }), \"device-1\");\n\n await expect(api.openApp?.(\"a\".repeat(256))).rejects.toThrow(\"too long\");\n expect(sendApdu).not.toHaveBeenCalled();\n });\n});\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { mockServerScreenApi } from \"./mockServerScreenApi\";\nimport { type MockServerClient } from \"./types\";\n\nconst aClient = (overrides: Partial<Record<keyof MockServerClient, unknown>>) =>\n ({\n getScreenshot: vi.fn(),\n getDevice: vi.fn(),\n pressButton: vi.fn(() => Promise.resolve()),\n touchScreen: vi.fn(() => Promise.resolve()),\n ...overrides,\n }) as unknown as MockServerClient;\n\ndescribe(\"mockServerScreenApi\", () => {\n it(\"resolves the screenshot of the device\", async () => {\n const blob = new Blob([\"png\"]);\n const client = aClient({\n getScreenshot: vi.fn(() => Promise.resolve(blob)),\n });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").screenshot(),\n ).resolves.toBe(blob);\n expect(client.getScreenshot).toHaveBeenCalledWith(\"device-1\");\n });\n\n it(\"resolves no screenshot when the device has no Speculos instance\", async () => {\n const client = aClient({\n getScreenshot: vi.fn(() => Promise.reject({ status: 409 })),\n });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").screenshot(),\n ).resolves.toBeNull();\n });\n\n it(\"rethrows any other screenshot failure\", async () => {\n const error = Object.assign(new Error(\"boom\"), { status: 500 });\n const client = aClient({\n getScreenshot: vi.fn(() => Promise.reject(error)),\n });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").screenshot(),\n ).rejects.toBe(error);\n });\n\n it(\"shows the device record while idle\", async () => {\n const device = { id: \"device-1\", device_type: \"nanoX\" };\n const client = aClient({ getDevice: vi.fn(() => Promise.resolve(device)) });\n\n await expect(\n mockServerScreenApi(client, \"device-1\").idle?.(),\n ).resolves.toEqual({\n kind: \"os-info\",\n device,\n });\n });\n\n it(\"forwards buttons and touches to the device\", async () => {\n const client = aClient({});\n const api = mockServerScreenApi(client, \"device-1\");\n\n await api.pressButton(\"left\", \"press\");\n await api.touch(10, 20, \"release\");\n\n expect(client.pressButton).toHaveBeenCalledWith(\n \"device-1\",\n \"left\",\n \"press\",\n );\n expect(client.touchScreen).toHaveBeenCalledWith(\n \"device-1\",\n 10,\n 20,\n \"release\",\n );\n });\n\n it(\"opens an app by name\", async () => {\n const sendApdu = vi.fn(() => Promise.resolve({ response: \"9000\" }));\n const api = mockServerScreenApi(aClient({ sendApdu }), \"device-1\");\n\n await api.openApp?.(\"Bitcoin\");\n\n expect(sendApdu).toHaveBeenCalledWith(\n \"device-1\",\n Uint8Array.from([\n 0xe0,\n 0xd8,\n 0x00,\n 0x00,\n 0x07,\n ...new TextEncoder().encode(\"Bitcoin\"),\n ]),\n );\n });\n\n it(\"fails to open an app the device refuses\", async () => {\n const sendApdu = vi.fn(() => Promise.resolve({ response: \"6807\" }));\n const api = mockServerScreenApi(aClient({ sendApdu }), \"device-1\");\n\n await expect(api.openApp?.(\"Bitcoin\")).rejects.toThrow(\"6807\");\n });\n\n it(\"refuses an app name too long for one APDU\", async () => {\n const sendApdu = vi.fn(() => Promise.resolve({ response: \"9000\" }));\n const api = mockServerScreenApi(aClient({ sendApdu }), \"device-1\");\n\n await expect(api.openApp?.(\"a\".repeat(256))).rejects.toThrow(\"too long\");\n expect(sendApdu).not.toHaveBeenCalled();\n });\n});\n"],
5
+ "mappings": "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",
6
6
  "names": ["mockServerScreenApi", "aClient", "overrides", "blob", "client", "error", "device", "api", "sendApdu"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{useEffect as l,useState as f}from"react";const s=2e3;function p(r,e){const[o,t]=f();return l(()=>{let n=!1,i;if(t(void 0),!e)return;const u=()=>{r.getDevice(e).then(c=>{n||t(c)},()=>{n||(t(null),i=setTimeout(u,s))})};return u(),()=>{n=!0,clearTimeout(i)}},[r,e]),o}export{p as useMockServerDevice};
1
+ import{useEffect as f,useState as l}from"react";const s=2e3;function p(n,e){const[u,t]=l();return f(()=>{let r=!1,i;if(t(void 0),!e)return;const o=()=>{n.getDevice(e).then(c=>{r||t(c)},()=>{r||(t(null),i=setTimeout(o,s))})};return o(),()=>{r=!0,clearTimeout(i)}},[n,e]),u}export{p as useMockServerDevice};
2
2
  //# sourceMappingURL=useMockServerDevice.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/useMockServerDevice.ts"],
4
- "sourcesContent": ["import { useEffect, useState } from \"react\";\nimport {\n type Device,\n type MockClient,\n} from \"@ledgerhq/device-mockserver-client\";\n\nconst RETRY_MS = 2000;\n\n/**\n * The mock server's record of a device: undefined while it loads, or while no\n * device id is given, and null while it cannot be read. A failed read is\n * retried, so a transient error does not leave the device without its model.\n */\nexport function useMockServerDevice(\n client: MockClient,\n deviceId: string,\n): Device | null | undefined {\n const [device, setDevice] = useState<Device | null>();\n\n useEffect(() => {\n let cancelled = false;\n let retry: ReturnType<typeof setTimeout> | undefined;\n setDevice(undefined);\n if (!deviceId) return;\n\n const load = () => {\n client.getDevice(deviceId).then(\n (record) => {\n if (!cancelled) setDevice(record);\n },\n () => {\n if (cancelled) return;\n setDevice(null);\n retry = setTimeout(load, RETRY_MS);\n },\n );\n };\n load();\n\n return () => {\n cancelled = true;\n clearTimeout(retry);\n };\n }, [client, deviceId]);\n\n return device;\n}\n"],
5
- "mappings": "AAAA,OAAS,aAAAA,EAAW,YAAAC,MAAgB,QAMpC,MAAMC,EAAW,IAOV,SAASC,EACdC,EACAC,EAC2B,CAC3B,KAAM,CAACC,EAAQC,CAAS,EAAIN,EAAwB,EAEpD,OAAAD,EAAU,IAAM,CACd,IAAIQ,EAAY,GACZC,EAEJ,GADAF,EAAU,MAAS,EACf,CAACF,EAAU,OAEf,MAAMK,EAAO,IAAM,CACjBN,EAAO,UAAUC,CAAQ,EAAE,KACxBM,GAAW,CACLH,GAAWD,EAAUI,CAAM,CAClC,EACA,IAAM,CACAH,IACJD,EAAU,IAAI,EACdE,EAAQ,WAAWC,EAAMR,CAAQ,EACnC,CACF,CACF,EACA,OAAAQ,EAAK,EAEE,IAAM,CACXF,EAAY,GACZ,aAAaC,CAAK,CACpB,CACF,EAAG,CAACL,EAAQC,CAAQ,CAAC,EAEdC,CACT",
4
+ "sourcesContent": ["import { useEffect, useState } from \"react\";\nimport { type Device } from \"@ledgerhq/device-mockserver-client\";\n\nimport { type MockServerClient } from \"./types\";\n\nconst RETRY_MS = 2000;\n\n/**\n * The mock server's record of a device: undefined while it loads, or while no\n * device id is given, and null while it cannot be read. A failed read is\n * retried, so a transient error does not leave the device without its model.\n */\nexport function useMockServerDevice(\n client: MockServerClient,\n deviceId: string,\n): Device | null | undefined {\n const [device, setDevice] = useState<Device | null>();\n\n useEffect(() => {\n let cancelled = false;\n let retry: ReturnType<typeof setTimeout> | undefined;\n setDevice(undefined);\n if (!deviceId) return;\n\n const load = () => {\n client.getDevice(deviceId).then(\n (record) => {\n if (!cancelled) setDevice(record);\n },\n () => {\n if (cancelled) return;\n setDevice(null);\n retry = setTimeout(load, RETRY_MS);\n },\n );\n };\n load();\n\n return () => {\n cancelled = true;\n clearTimeout(retry);\n };\n }, [client, deviceId]);\n\n return device;\n}\n"],
5
+ "mappings": "AAAA,OAAS,aAAAA,EAAW,YAAAC,MAAgB,QAKpC,MAAMC,EAAW,IAOV,SAASC,EACdC,EACAC,EAC2B,CAC3B,KAAM,CAACC,EAAQC,CAAS,EAAIN,EAAwB,EAEpD,OAAAD,EAAU,IAAM,CACd,IAAIQ,EAAY,GACZC,EAEJ,GADAF,EAAU,MAAS,EACf,CAACF,EAAU,OAEf,MAAMK,EAAO,IAAM,CACjBN,EAAO,UAAUC,CAAQ,EAAE,KACxBM,GAAW,CACLH,GAAWD,EAAUI,CAAM,CAClC,EACA,IAAM,CACAH,IACJD,EAAU,IAAI,EACdE,EAAQ,WAAWC,EAAMR,CAAQ,EACnC,CACF,CACF,EACA,OAAAQ,EAAK,EAEE,IAAM,CACXF,EAAY,GACZ,aAAaC,CAAK,CACpB,CACF,EAAG,CAACL,EAAQC,CAAQ,CAAC,EAEdC,CACT",
6
6
  "names": ["useEffect", "useState", "RETRY_MS", "useMockServerDevice", "client", "deviceId", "device", "setDevice", "cancelled", "retry", "load", "record"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import l,{act as i}from"react";import{createRoot as m}from"react-dom/client";import{useMockServerDevice as u}from"./useMockServerDevice";Object.assign(globalThis,{IS_REACT_ACT_ENVIRONMENT:!0});const n={id:"device-1",device_type:"stax"};describe("useMockServerDevice",()=>{let d,o,t;const v=({client:e,deviceId:c})=>(t=u(e,c),null),r=e=>({getDevice:vi.fn(e)}),a=(e,c="device-1")=>i(()=>o.render(l.createElement(v,{client:e,deviceId:c}))),s=()=>i(()=>vi.advanceTimersByTimeAsync(0));beforeEach(()=>{vi.useFakeTimers(),t=void 0,d=document.createElement("div"),o=m(d)}),afterEach(()=>{i(()=>o.unmount()),vi.useRealTimers()}),it("reads the device record",async()=>{const e=r(()=>Promise.resolve(n));a(e),expect(t).toBeUndefined(),await s(),expect(t).toBe(n),expect(e.getDevice).toHaveBeenCalledWith("device-1")}),it("reads nothing without a device id",async()=>{const e=r(()=>Promise.resolve(n));a(e,""),await s(),expect(t).toBeUndefined(),expect(e.getDevice).not.toHaveBeenCalled()}),it("retries a failed read until it succeeds",async()=>{const e=vi.fn().mockRejectedValueOnce(new Error("offline")).mockResolvedValue(n),c=r(e);a(c),await s(),expect(t).toBeNull(),await i(()=>vi.advanceTimersByTimeAsync(2e3)),expect(t).toBe(n),expect(e).toHaveBeenCalledTimes(2)}),it("stops retrying once unmounted",async()=>{const e=r(()=>Promise.reject(new Error("offline")));a(e),await s(),i(()=>o.render(l.createElement(l.Fragment,null))),await i(()=>vi.advanceTimersByTimeAsync(1e4)),expect(e.getDevice).toHaveBeenCalledOnce()})});
1
+ import v,{act as c}from"react";import{createRoot as m}from"react-dom/client";import{useMockServerDevice as p}from"./useMockServerDevice";Object.assign(globalThis,{IS_REACT_ACT_ENVIRONMENT:!0});const n={id:"device-1",device_type:"stax"};describe("useMockServerDevice",()=>{let l,s,t;const d=({client:e,deviceId:i})=>(t=p(e,i),null),a=e=>({getDevice:vi.fn(e)}),r=(e,i="device-1")=>c(()=>s.render(v.createElement(d,{client:e,deviceId:i}))),o=()=>c(()=>vi.advanceTimersByTimeAsync(0));beforeEach(()=>{vi.useFakeTimers(),t=void 0,l=document.createElement("div"),s=m(l)}),afterEach(()=>{c(()=>s.unmount()),vi.useRealTimers()}),it("reads the device record",async()=>{const e=a(()=>Promise.resolve(n));r(e),expect(t).toBeUndefined(),await o(),expect(t).toBe(n),expect(e.getDevice).toHaveBeenCalledWith("device-1")}),it("accepts a client from another copy of the package",async()=>{class e{record=n;getDevice=vi.fn(()=>Promise.resolve(this.record));getScreenshot=vi.fn();pressButton=vi.fn();touchScreen=vi.fn();sendApdu=vi.fn()}const i=new e;r(i),await o(),expect(t).toBe(n)}),it("reads nothing without a device id",async()=>{const e=a(()=>Promise.resolve(n));r(e,""),await o(),expect(t).toBeUndefined(),expect(e.getDevice).not.toHaveBeenCalled()}),it("retries a failed read until it succeeds",async()=>{const e=vi.fn().mockRejectedValueOnce(new Error("offline")).mockResolvedValue(n),i=a(e);r(i),await o(),expect(t).toBeNull(),await c(()=>vi.advanceTimersByTimeAsync(2e3)),expect(t).toBe(n),expect(e).toHaveBeenCalledTimes(2)}),it("stops retrying once unmounted",async()=>{const e=a(()=>Promise.reject(new Error("offline")));r(e),await o(),c(()=>s.render(v.createElement(v.Fragment,null))),await c(()=>vi.advanceTimersByTimeAsync(1e4)),expect(e.getDevice).toHaveBeenCalledOnce()})});
2
2
  //# sourceMappingURL=useMockServerDevice.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/useMockServerDevice.test.tsx"],
4
- "sourcesContent": ["import React, { act } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport {\n type Device,\n type MockClient,\n} from \"@ledgerhq/device-mockserver-client\";\n\nimport { useMockServerDevice } from \"./useMockServerDevice\";\n\nObject.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true });\n\nconst DEVICE = { id: \"device-1\", device_type: \"stax\" } as Device;\n\ndescribe(\"useMockServerDevice\", () => {\n let container: HTMLDivElement;\n let root: Root;\n let result: Device | null | undefined;\n\n const Probe: React.FC<{ client: MockClient; deviceId: string }> = ({\n client,\n deviceId,\n }) => {\n result = useMockServerDevice(client, deviceId);\n return null;\n };\n const aClient = (getDevice: () => Promise<Device>) =>\n ({ getDevice: vi.fn(getDevice) }) as unknown as MockClient;\n const render = (client: MockClient, deviceId = \"device-1\") =>\n act(() => root.render(<Probe client={client} deviceId={deviceId} />));\n const flush = () => act(() => vi.advanceTimersByTimeAsync(0));\n\n beforeEach(() => {\n vi.useFakeTimers();\n result = undefined;\n container = document.createElement(\"div\");\n root = createRoot(container);\n });\n\n afterEach(() => {\n act(() => root.unmount());\n vi.useRealTimers();\n });\n\n it(\"reads the device record\", async () => {\n const client = aClient(() => Promise.resolve(DEVICE));\n\n render(client);\n expect(result).toBeUndefined();\n await flush();\n\n expect(result).toBe(DEVICE);\n expect(client.getDevice).toHaveBeenCalledWith(\"device-1\");\n });\n\n it(\"reads nothing without a device id\", async () => {\n const client = aClient(() => Promise.resolve(DEVICE));\n\n render(client, \"\");\n await flush();\n\n expect(result).toBeUndefined();\n expect(client.getDevice).not.toHaveBeenCalled();\n });\n\n it(\"retries a failed read until it succeeds\", async () => {\n const getDevice = vi\n .fn<() => Promise<Device>>()\n .mockRejectedValueOnce(new Error(\"offline\"))\n .mockResolvedValue(DEVICE);\n const client = aClient(getDevice);\n\n render(client);\n await flush();\n expect(result).toBeNull();\n\n await act(() => vi.advanceTimersByTimeAsync(2000));\n\n expect(result).toBe(DEVICE);\n expect(getDevice).toHaveBeenCalledTimes(2);\n });\n\n it(\"stops retrying once unmounted\", async () => {\n const client = aClient(() => Promise.reject(new Error(\"offline\")));\n\n render(client);\n await flush();\n act(() => root.render(<></>));\n await act(() => vi.advanceTimersByTimeAsync(10_000));\n\n expect(client.getDevice).toHaveBeenCalledOnce();\n });\n});\n"],
5
- "mappings": "AAAA,OAAOA,GAAS,OAAAC,MAAW,QAC3B,OAAS,cAAAC,MAA6B,mBAMtC,OAAS,uBAAAC,MAA2B,wBAEpC,OAAO,OAAO,WAAY,CAAE,yBAA0B,EAAK,CAAC,EAE5D,MAAMC,EAAS,CAAE,GAAI,WAAY,YAAa,MAAO,EAErD,SAAS,sBAAuB,IAAM,CACpC,IAAIC,EACAC,EACAC,EAEJ,MAAMC,EAA4D,CAAC,CACjE,OAAAC,EACA,SAAAC,CACF,KACEH,EAASJ,EAAoBM,EAAQC,CAAQ,EACtC,MAEHC,EAAWC,IACd,CAAE,UAAW,GAAG,GAAGA,CAAS,CAAE,GAC3BC,EAAS,CAACJ,EAAoBC,EAAW,aAC7CT,EAAI,IAAMK,EAAK,OAAON,EAAA,cAACQ,EAAA,CAAM,OAAQC,EAAQ,SAAUC,EAAU,CAAE,CAAC,EAChEI,EAAQ,IAAMb,EAAI,IAAM,GAAG,yBAAyB,CAAC,CAAC,EAE5D,WAAW,IAAM,CACf,GAAG,cAAc,EACjBM,EAAS,OACTF,EAAY,SAAS,cAAc,KAAK,EACxCC,EAAOJ,EAAWG,CAAS,CAC7B,CAAC,EAED,UAAU,IAAM,CACdJ,EAAI,IAAMK,EAAK,QAAQ,CAAC,EACxB,GAAG,cAAc,CACnB,CAAC,EAED,GAAG,0BAA2B,SAAY,CACxC,MAAMG,EAASE,EAAQ,IAAM,QAAQ,QAAQP,CAAM,CAAC,EAEpDS,EAAOJ,CAAM,EACb,OAAOF,CAAM,EAAE,cAAc,EAC7B,MAAMO,EAAM,EAEZ,OAAOP,CAAM,EAAE,KAAKH,CAAM,EAC1B,OAAOK,EAAO,SAAS,EAAE,qBAAqB,UAAU,CAC1D,CAAC,EAED,GAAG,oCAAqC,SAAY,CAClD,MAAMA,EAASE,EAAQ,IAAM,QAAQ,QAAQP,CAAM,CAAC,EAEpDS,EAAOJ,EAAQ,EAAE,EACjB,MAAMK,EAAM,EAEZ,OAAOP,CAAM,EAAE,cAAc,EAC7B,OAAOE,EAAO,SAAS,EAAE,IAAI,iBAAiB,CAChD,CAAC,EAED,GAAG,0CAA2C,SAAY,CACxD,MAAMG,EAAY,GACf,GAA0B,EAC1B,sBAAsB,IAAI,MAAM,SAAS,CAAC,EAC1C,kBAAkBR,CAAM,EACrBK,EAASE,EAAQC,CAAS,EAEhCC,EAAOJ,CAAM,EACb,MAAMK,EAAM,EACZ,OAAOP,CAAM,EAAE,SAAS,EAExB,MAAMN,EAAI,IAAM,GAAG,yBAAyB,GAAI,CAAC,EAEjD,OAAOM,CAAM,EAAE,KAAKH,CAAM,EAC1B,OAAOQ,CAAS,EAAE,sBAAsB,CAAC,CAC3C,CAAC,EAED,GAAG,gCAAiC,SAAY,CAC9C,MAAMH,EAASE,EAAQ,IAAM,QAAQ,OAAO,IAAI,MAAM,SAAS,CAAC,CAAC,EAEjEE,EAAOJ,CAAM,EACb,MAAMK,EAAM,EACZb,EAAI,IAAMK,EAAK,OAAON,EAAA,cAAAA,EAAA,aAAE,CAAG,CAAC,EAC5B,MAAMC,EAAI,IAAM,GAAG,yBAAyB,GAAM,CAAC,EAEnD,OAAOQ,EAAO,SAAS,EAAE,qBAAqB,CAChD,CAAC,CACH,CAAC",
6
- "names": ["React", "act", "createRoot", "useMockServerDevice", "DEVICE", "container", "root", "result", "Probe", "client", "deviceId", "aClient", "getDevice", "render", "flush"]
4
+ "sourcesContent": ["import React, { act } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport { type Device } from \"@ledgerhq/device-mockserver-client\";\n\nimport { type MockServerClient } from \"./types\";\nimport { useMockServerDevice } from \"./useMockServerDevice\";\n\nObject.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true });\n\nconst DEVICE = { id: \"device-1\", device_type: \"stax\" } as Device;\n\ndescribe(\"useMockServerDevice\", () => {\n let container: HTMLDivElement;\n let root: Root;\n let result: Device | null | undefined;\n\n const Probe: React.FC<{ client: MockServerClient; deviceId: string }> = ({\n client,\n deviceId,\n }) => {\n result = useMockServerDevice(client, deviceId);\n return null;\n };\n const aClient = (getDevice: () => Promise<Device>) =>\n ({ getDevice: vi.fn(getDevice) }) as unknown as MockServerClient;\n const render = (client: MockServerClient, deviceId = \"device-1\") =>\n act(() => root.render(<Probe client={client} deviceId={deviceId} />));\n const flush = () => act(() => vi.advanceTimersByTimeAsync(0));\n\n beforeEach(() => {\n vi.useFakeTimers();\n result = undefined;\n container = document.createElement(\"div\");\n root = createRoot(container);\n });\n\n afterEach(() => {\n act(() => root.unmount());\n vi.useRealTimers();\n });\n\n it(\"reads the device record\", async () => {\n const client = aClient(() => Promise.resolve(DEVICE));\n\n render(client);\n expect(result).toBeUndefined();\n await flush();\n\n expect(result).toBe(DEVICE);\n expect(client.getDevice).toHaveBeenCalledWith(\"device-1\");\n });\n\n it(\"accepts a client from another copy of the package\", async () => {\n // Its own private field, as a MockClient from a second install would have:\n // only the public calls must match.\n class OtherCopyClient implements MockServerClient {\n private readonly record = DEVICE;\n getDevice = vi.fn(() => Promise.resolve(this.record));\n getScreenshot = vi.fn<MockServerClient[\"getScreenshot\"]>();\n pressButton = vi.fn<MockServerClient[\"pressButton\"]>();\n touchScreen = vi.fn<MockServerClient[\"touchScreen\"]>();\n sendApdu = vi.fn<MockServerClient[\"sendApdu\"]>();\n }\n const client = new OtherCopyClient();\n\n render(client);\n await flush();\n\n expect(result).toBe(DEVICE);\n });\n\n it(\"reads nothing without a device id\", async () => {\n const client = aClient(() => Promise.resolve(DEVICE));\n\n render(client, \"\");\n await flush();\n\n expect(result).toBeUndefined();\n expect(client.getDevice).not.toHaveBeenCalled();\n });\n\n it(\"retries a failed read until it succeeds\", async () => {\n const getDevice = vi\n .fn<() => Promise<Device>>()\n .mockRejectedValueOnce(new Error(\"offline\"))\n .mockResolvedValue(DEVICE);\n const client = aClient(getDevice);\n\n render(client);\n await flush();\n expect(result).toBeNull();\n\n await act(() => vi.advanceTimersByTimeAsync(2000));\n\n expect(result).toBe(DEVICE);\n expect(getDevice).toHaveBeenCalledTimes(2);\n });\n\n it(\"stops retrying once unmounted\", async () => {\n const client = aClient(() => Promise.reject(new Error(\"offline\")));\n\n render(client);\n await flush();\n act(() => root.render(<></>));\n await act(() => vi.advanceTimersByTimeAsync(10_000));\n\n expect(client.getDevice).toHaveBeenCalledOnce();\n });\n});\n"],
5
+ "mappings": "AAAA,OAAOA,GAAS,OAAAC,MAAW,QAC3B,OAAS,cAAAC,MAA6B,mBAItC,OAAS,uBAAAC,MAA2B,wBAEpC,OAAO,OAAO,WAAY,CAAE,yBAA0B,EAAK,CAAC,EAE5D,MAAMC,EAAS,CAAE,GAAI,WAAY,YAAa,MAAO,EAErD,SAAS,sBAAuB,IAAM,CACpC,IAAIC,EACAC,EACAC,EAEJ,MAAMC,EAAkE,CAAC,CACvE,OAAAC,EACA,SAAAC,CACF,KACEH,EAASJ,EAAoBM,EAAQC,CAAQ,EACtC,MAEHC,EAAWC,IACd,CAAE,UAAW,GAAG,GAAGA,CAAS,CAAE,GAC3BC,EAAS,CAACJ,EAA0BC,EAAW,aACnDT,EAAI,IAAMK,EAAK,OAAON,EAAA,cAACQ,EAAA,CAAM,OAAQC,EAAQ,SAAUC,EAAU,CAAE,CAAC,EAChEI,EAAQ,IAAMb,EAAI,IAAM,GAAG,yBAAyB,CAAC,CAAC,EAE5D,WAAW,IAAM,CACf,GAAG,cAAc,EACjBM,EAAS,OACTF,EAAY,SAAS,cAAc,KAAK,EACxCC,EAAOJ,EAAWG,CAAS,CAC7B,CAAC,EAED,UAAU,IAAM,CACdJ,EAAI,IAAMK,EAAK,QAAQ,CAAC,EACxB,GAAG,cAAc,CACnB,CAAC,EAED,GAAG,0BAA2B,SAAY,CACxC,MAAMG,EAASE,EAAQ,IAAM,QAAQ,QAAQP,CAAM,CAAC,EAEpDS,EAAOJ,CAAM,EACb,OAAOF,CAAM,EAAE,cAAc,EAC7B,MAAMO,EAAM,EAEZ,OAAOP,CAAM,EAAE,KAAKH,CAAM,EAC1B,OAAOK,EAAO,SAAS,EAAE,qBAAqB,UAAU,CAC1D,CAAC,EAED,GAAG,oDAAqD,SAAY,CAGlE,MAAMM,CAA4C,CAC/B,OAASX,EAC1B,UAAY,GAAG,GAAG,IAAM,QAAQ,QAAQ,KAAK,MAAM,CAAC,EACpD,cAAgB,GAAG,GAAsC,EACzD,YAAc,GAAG,GAAoC,EACrD,YAAc,GAAG,GAAoC,EACrD,SAAW,GAAG,GAAiC,CACjD,CACA,MAAMK,EAAS,IAAIM,EAEnBF,EAAOJ,CAAM,EACb,MAAMK,EAAM,EAEZ,OAAOP,CAAM,EAAE,KAAKH,CAAM,CAC5B,CAAC,EAED,GAAG,oCAAqC,SAAY,CAClD,MAAMK,EAASE,EAAQ,IAAM,QAAQ,QAAQP,CAAM,CAAC,EAEpDS,EAAOJ,EAAQ,EAAE,EACjB,MAAMK,EAAM,EAEZ,OAAOP,CAAM,EAAE,cAAc,EAC7B,OAAOE,EAAO,SAAS,EAAE,IAAI,iBAAiB,CAChD,CAAC,EAED,GAAG,0CAA2C,SAAY,CACxD,MAAMG,EAAY,GACf,GAA0B,EAC1B,sBAAsB,IAAI,MAAM,SAAS,CAAC,EAC1C,kBAAkBR,CAAM,EACrBK,EAASE,EAAQC,CAAS,EAEhCC,EAAOJ,CAAM,EACb,MAAMK,EAAM,EACZ,OAAOP,CAAM,EAAE,SAAS,EAExB,MAAMN,EAAI,IAAM,GAAG,yBAAyB,GAAI,CAAC,EAEjD,OAAOM,CAAM,EAAE,KAAKH,CAAM,EAC1B,OAAOQ,CAAS,EAAE,sBAAsB,CAAC,CAC3C,CAAC,EAED,GAAG,gCAAiC,SAAY,CAC9C,MAAMH,EAASE,EAAQ,IAAM,QAAQ,OAAO,IAAI,MAAM,SAAS,CAAC,CAAC,EAEjEE,EAAOJ,CAAM,EACb,MAAMK,EAAM,EACZb,EAAI,IAAMK,EAAK,OAAON,EAAA,cAAAA,EAAA,aAAE,CAAG,CAAC,EAC5B,MAAMC,EAAI,IAAM,GAAG,yBAAyB,GAAM,CAAC,EAEnD,OAAOQ,EAAO,SAAS,EAAE,qBAAqB,CAChD,CAAC,CACH,CAAC",
6
+ "names": ["React", "act", "createRoot", "useMockServerDevice", "DEVICE", "container", "root", "result", "Probe", "client", "deviceId", "aClient", "getDevice", "render", "flush", "OtherCopyClient"]
7
7
  }
@@ -2,6 +2,6 @@ export { type DeviceScreenModel, findDeviceScreenModel } from "./deviceModels";
2
2
  export { DeviceScreen, type DeviceScreenProps } from "./DeviceScreen";
3
3
  export { MockServerDevice, type MockServerDeviceProps, } from "./MockServerDevice";
4
4
  export { mockServerScreenApi } from "./mockServerScreenApi";
5
- export type { DeviceScreenState, ScreenApi } from "./types";
5
+ export type { DeviceScreenState, MockServerClient, ScreenApi } from "./types";
6
6
  export { useMockServerDevice } from "./useMockServerDevice";
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,GAC3B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,GAC3B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -1,4 +1,3 @@
1
- import { type MockClient } from "@ledgerhq/device-mockserver-client";
2
- import { type ScreenApi } from "./types";
3
- export declare const mockServerScreenApi: (client: MockClient, deviceId: string) => ScreenApi;
1
+ import { type MockServerClient, type ScreenApi } from "./types";
2
+ export declare const mockServerScreenApi: (client: MockServerClient, deviceId: string) => ScreenApi;
4
3
  //# sourceMappingURL=mockServerScreenApi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mockServerScreenApi.d.ts","sourceRoot":"","sources":["../../../src/mockServerScreenApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAErE,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAMzC,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,UAAU,EAClB,UAAU,MAAM,KACf,SA8BD,CAAC"}
1
+ {"version":3,"file":"mockServerScreenApi.d.ts","sourceRoot":"","sources":["../../../src/mockServerScreenApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAMhE,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,gBAAgB,EACxB,UAAU,MAAM,KACf,SA8BD,CAAC"}
@@ -1,4 +1,9 @@
1
- import { type Device, type SpeculosAction, type SpeculosButton } from "@ledgerhq/device-mockserver-client";
1
+ import { type Device, type MockClient, type SpeculosAction, type SpeculosButton } from "@ledgerhq/device-mockserver-client";
2
+ /**
3
+ * The MockClient calls this library makes. Picking them drops the class's
4
+ * private fields, so a client from another copy of the package still fits.
5
+ */
6
+ export type MockServerClient = Pick<MockClient, "getDevice" | "getScreenshot" | "pressButton" | "touchScreen" | "sendApdu">;
2
7
  /**
3
8
  * How the screen is reached. The mock server proxies to the Speculos instance
4
9
  * backing a device and a Speculos transport talks to one directly, but both
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,oCAAoC,CAAC;AAE5C;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,kEAAkE;IAClE,UAAU,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACnC,4DAA4D;IAC5D,IAAI,CAAC,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACpC,WAAW,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,2CAA2C;IAC3C,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,uDAAuD;IACvD,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAClE,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;CAC3D;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE;AACrB,yEAAyE;GACvE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,oCAAoC,CAAC;AAE5C;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,UAAU,EACV,WAAW,GAAG,eAAe,GAAG,aAAa,GAAG,aAAa,GAAG,UAAU,CAC3E,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,kEAAkE;IAClE,UAAU,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACnC,4DAA4D;IAC5D,IAAI,CAAC,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACpC,WAAW,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,2CAA2C;IAC3C,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,uDAAuD;IACvD,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAClE,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;CAC3D;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE;AACrB,yEAAyE;GACvE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC"}
@@ -1,8 +1,9 @@
1
- import { type Device, type MockClient } from "@ledgerhq/device-mockserver-client";
1
+ import { type Device } from "@ledgerhq/device-mockserver-client";
2
+ import { type MockServerClient } from "./types";
2
3
  /**
3
4
  * The mock server's record of a device: undefined while it loads, or while no
4
5
  * device id is given, and null while it cannot be read. A failed read is
5
6
  * retried, so a transient error does not leave the device without its model.
6
7
  */
7
- export declare function useMockServerDevice(client: MockClient, deviceId: string): Device | null | undefined;
8
+ export declare function useMockServerDevice(client: MockServerClient, deviceId: string): Device | null | undefined;
8
9
  //# sourceMappingURL=useMockServerDevice.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useMockServerDevice.d.ts","sourceRoot":"","sources":["../../../src/useMockServerDevice.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,UAAU,EAChB,MAAM,oCAAoC,CAAC;AAI5C;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,GAAG,SAAS,CA8B3B"}
1
+ {"version":3,"file":"useMockServerDevice.d.ts","sourceRoot":"","sources":["../../../src/useMockServerDevice.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAEjE,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAIhD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,gBAAgB,EACxB,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,GAAG,SAAS,CA8B3B"}