@ledgerhq/device-mockserver-react 0.0.0-mockserver-react-20260929114136 → 0.1.0

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/README.md +3 -2
  2. package/lib/cjs/package.json +9 -9
  3. package/lib/cjs/src/DeviceOsInfo.js +1 -1
  4. package/lib/cjs/src/DeviceOsInfo.js.map +2 -2
  5. package/lib/cjs/src/DeviceOsInfo.test.js +2 -0
  6. package/lib/cjs/src/DeviceOsInfo.test.js.map +7 -0
  7. package/lib/cjs/src/DeviceScreen.js +1 -1
  8. package/lib/cjs/src/DeviceScreen.js.map +3 -3
  9. package/lib/cjs/src/DeviceScreen.test.js +2 -0
  10. package/lib/cjs/src/DeviceScreen.test.js.map +7 -0
  11. package/lib/cjs/src/DeviceScreenButtons.test.js +2 -0
  12. package/lib/cjs/src/DeviceScreenButtons.test.js.map +7 -0
  13. package/lib/cjs/src/DeviceScreenImage.test.js +2 -0
  14. package/lib/cjs/src/DeviceScreenImage.test.js.map +7 -0
  15. package/lib/cjs/src/MockServerDevice.js.map +1 -1
  16. package/lib/cjs/src/MockServerDevice.test.js +2 -0
  17. package/lib/cjs/src/MockServerDevice.test.js.map +7 -0
  18. package/lib/cjs/src/deviceModels.test.js +2 -0
  19. package/lib/cjs/src/deviceModels.test.js.map +7 -0
  20. package/lib/cjs/src/index.js +1 -1
  21. package/lib/cjs/src/index.js.map +1 -1
  22. package/lib/cjs/src/mockServerScreenApi.js +1 -1
  23. package/lib/cjs/src/mockServerScreenApi.js.map +2 -2
  24. package/lib/cjs/src/mockServerScreenApi.test.js.map +2 -2
  25. package/lib/cjs/src/types.js +1 -1
  26. package/lib/cjs/src/types.js.map +1 -1
  27. package/lib/cjs/src/useMockServerDevice.js +1 -1
  28. package/lib/cjs/src/useMockServerDevice.js.map +3 -3
  29. package/lib/cjs/src/useMockServerDevice.test.js +2 -0
  30. package/lib/cjs/src/useMockServerDevice.test.js.map +7 -0
  31. package/lib/esm/package.json +9 -9
  32. package/lib/esm/src/DeviceOsInfo.js +1 -1
  33. package/lib/esm/src/DeviceOsInfo.js.map +2 -2
  34. package/lib/esm/src/DeviceOsInfo.test.js +2 -0
  35. package/lib/esm/src/DeviceOsInfo.test.js.map +7 -0
  36. package/lib/esm/src/DeviceScreen.js +1 -1
  37. package/lib/esm/src/DeviceScreen.js.map +3 -3
  38. package/lib/esm/src/DeviceScreen.test.js +2 -0
  39. package/lib/esm/src/DeviceScreen.test.js.map +7 -0
  40. package/lib/esm/src/DeviceScreenButtons.test.js +2 -0
  41. package/lib/esm/src/DeviceScreenButtons.test.js.map +7 -0
  42. package/lib/esm/src/DeviceScreenImage.test.js +2 -0
  43. package/lib/esm/src/DeviceScreenImage.test.js.map +7 -0
  44. package/lib/esm/src/MockServerDevice.js.map +1 -1
  45. package/lib/esm/src/MockServerDevice.test.js +2 -0
  46. package/lib/esm/src/MockServerDevice.test.js.map +7 -0
  47. package/lib/esm/src/deviceModels.test.js +2 -0
  48. package/lib/esm/src/deviceModels.test.js.map +7 -0
  49. package/lib/esm/src/index.js.map +1 -1
  50. package/lib/esm/src/mockServerScreenApi.js +1 -1
  51. package/lib/esm/src/mockServerScreenApi.js.map +2 -2
  52. package/lib/esm/src/mockServerScreenApi.test.js.map +2 -2
  53. package/lib/esm/src/useMockServerDevice.js +1 -1
  54. package/lib/esm/src/useMockServerDevice.js.map +3 -3
  55. package/lib/esm/src/useMockServerDevice.test.js +2 -0
  56. package/lib/esm/src/useMockServerDevice.test.js.map +7 -0
  57. package/lib/types/src/DeviceOsInfo.test.d.ts +2 -0
  58. package/lib/types/src/DeviceOsInfo.test.d.ts.map +1 -0
  59. package/lib/types/src/DeviceScreen.d.ts.map +1 -1
  60. package/lib/types/src/DeviceScreen.test.d.ts +2 -0
  61. package/lib/types/src/DeviceScreen.test.d.ts.map +1 -0
  62. package/lib/types/src/DeviceScreenButtons.test.d.ts +2 -0
  63. package/lib/types/src/DeviceScreenButtons.test.d.ts.map +1 -0
  64. package/lib/types/src/DeviceScreenImage.test.d.ts +2 -0
  65. package/lib/types/src/DeviceScreenImage.test.d.ts.map +1 -0
  66. package/lib/types/src/MockServerDevice.d.ts +2 -2
  67. package/lib/types/src/MockServerDevice.d.ts.map +1 -1
  68. package/lib/types/src/MockServerDevice.test.d.ts +2 -0
  69. package/lib/types/src/MockServerDevice.test.d.ts.map +1 -0
  70. package/lib/types/src/deviceModels.test.d.ts +2 -0
  71. package/lib/types/src/deviceModels.test.d.ts.map +1 -0
  72. package/lib/types/src/index.d.ts +1 -1
  73. package/lib/types/src/index.d.ts.map +1 -1
  74. package/lib/types/src/mockServerScreenApi.d.ts +2 -3
  75. package/lib/types/src/mockServerScreenApi.d.ts.map +1 -1
  76. package/lib/types/src/types.d.ts +6 -1
  77. package/lib/types/src/types.d.ts.map +1 -1
  78. package/lib/types/src/useMockServerDevice.d.ts +5 -3
  79. package/lib/types/src/useMockServerDevice.d.ts.map +1 -1
  80. package/lib/types/src/useMockServerDevice.test.d.ts +2 -0
  81. package/lib/types/src/useMockServerDevice.test.d.ts.map +1 -0
  82. package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
  83. package/package.json +9 -9
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/deviceModels.test.ts"],
4
+ "sourcesContent": ["import { findDeviceScreenModel } from \"./deviceModels\";\n\ndescribe(\"findDeviceScreenModel\", () => {\n it(\"finds a model by the mock server's device type\", () => {\n expect(findDeviceScreenModel(\"stax\")).toMatchObject({\n label: \"Stax\",\n touch: true,\n speculos: true,\n });\n });\n\n it(\"marks Nano S as having no emulator\", () => {\n expect(findDeviceScreenModel(\"nanoS\").speculos).toBe(false);\n });\n\n it(\"falls back to a button-driven model for an unknown type\", () => {\n expect(findDeviceScreenModel(\"unknown\")).toMatchObject({\n label: \"Device\",\n touch: false,\n });\n });\n});\n"],
5
+ "mappings": "AAAA,OAAS,yBAAAA,MAA6B,iBAEtC,SAAS,wBAAyB,IAAM,CACtC,GAAG,iDAAkD,IAAM,CACzD,OAAOA,EAAsB,MAAM,CAAC,EAAE,cAAc,CAClD,MAAO,OACP,MAAO,GACP,SAAU,EACZ,CAAC,CACH,CAAC,EAED,GAAG,qCAAsC,IAAM,CAC7C,OAAOA,EAAsB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAK,CAC5D,CAAC,EAED,GAAG,0DAA2D,IAAM,CAClE,OAAOA,EAAsB,SAAS,CAAC,EAAE,cAAc,CACrD,MAAO,SACP,MAAO,EACT,CAAC,CACH,CAAC,CACH,CAAC",
6
+ "names": ["findDeviceScreenModel"]
7
+ }
@@ -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": "AAAA,OAAS,uBAAAA,MAA2B,wBAGpC,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,OACJH,EAAoBI,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,OACJD,EAAoBI,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,OACJL,EAAoBI,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,OACJN,EAAoBI,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,EAAMP,EAAoBI,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,MAFYR,EAAoBC,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,EAAMP,EAAoBC,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,EAAMP,EAAoBC,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",
6
6
  "names": ["mockServerScreenApi", "aClient", "overrides", "blob", "client", "error", "device", "api", "sendApdu"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{useEffect as u,useState as f}from"react";function o(i,e){const[r,t]=f();return u(()=>{let n=!1;if(t(void 0),!!e)return i.getDevice(e).then(c=>{n||t(c)}).catch(()=>{n||t(null)}),()=>{n=!0}},[i,e]),r}export{o 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\n/**\n * The mock server's record of a device: undefined while it loads, or while no\n * device id is given, and null when it could not be read.\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 setDevice(undefined);\n if (!deviceId) return;\n client\n .getDevice(deviceId)\n .then((record) => {\n if (!cancelled) setDevice(record);\n })\n .catch(() => {\n if (!cancelled) setDevice(null);\n });\n return () => {\n cancelled = true;\n };\n }, [client, deviceId]);\n\n return device;\n}\n"],
5
- "mappings": "AAAA,OAAS,aAAAA,EAAW,YAAAC,MAAgB,QAU7B,SAASC,EACdC,EACAC,EAC2B,CAC3B,KAAM,CAACC,EAAQC,CAAS,EAAIL,EAAwB,EAEpD,OAAAD,EAAU,IAAM,CACd,IAAIO,EAAY,GAEhB,GADAD,EAAU,MAAS,EACf,EAACF,EACL,OAAAD,EACG,UAAUC,CAAQ,EAClB,KAAMI,GAAW,CACXD,GAAWD,EAAUE,CAAM,CAClC,CAAC,EACA,MAAM,IAAM,CACND,GAAWD,EAAU,IAAI,CAChC,CAAC,EACI,IAAM,CACXC,EAAY,EACd,CACF,EAAG,CAACJ,EAAQC,CAAQ,CAAC,EAEdC,CACT",
6
- "names": ["useEffect", "useState", "useMockServerDevice", "client", "deviceId", "device", "setDevice", "cancelled", "record"]
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
+ "names": ["useEffect", "useState", "RETRY_MS", "useMockServerDevice", "client", "deviceId", "device", "setDevice", "cancelled", "retry", "load", "record"]
7
7
  }
@@ -0,0 +1,2 @@
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
+ //# sourceMappingURL=useMockServerDevice.test.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/useMockServerDevice.test.tsx"],
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
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=DeviceOsInfo.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeviceOsInfo.test.d.ts","sourceRoot":"","sources":["../../../src/DeviceOsInfo.test.tsx"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"DeviceScreen.d.ts","sourceRoot":"","sources":["../../../src/DeviceScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2B,MAAM,OAAO,CAAC;AAShD,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAGjE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,SAAS,CAAC;IACf,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAcF,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgCpD,CAAC"}
1
+ {"version":3,"file":"DeviceScreen.d.ts","sourceRoot":"","sources":["../../../src/DeviceScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAS3D,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAGjE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,SAAS,CAAC;IACf,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AA4BF,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgCpD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=DeviceScreen.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeviceScreen.test.d.ts","sourceRoot":"","sources":["../../../src/DeviceScreen.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=DeviceScreenButtons.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeviceScreenButtons.test.d.ts","sourceRoot":"","sources":["../../../src/DeviceScreenButtons.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=DeviceScreenImage.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeviceScreenImage.test.d.ts","sourceRoot":"","sources":["../../../src/DeviceScreenImage.test.tsx"],"names":[],"mappings":""}
@@ -2,8 +2,8 @@ import React from "react";
2
2
  import { type DeviceScreenProps } from "./DeviceScreen";
3
3
  export type MockServerDeviceProps = Pick<DeviceScreenProps, "floating" | "defaultCollapsed"> & {
4
4
  url: string;
5
- /** Omitted, the client opens a session of its own. */
6
- token?: string;
5
+ /** Of the session owning the device: devices are scoped to their session. */
6
+ token: string;
7
7
  deviceId: string;
8
8
  };
9
9
  export declare const MockServerDevice: React.FC<MockServerDeviceProps>;
@@ -1 +1 @@
1
- {"version":3,"file":"MockServerDevice.d.ts","sourceRoot":"","sources":["../../../src/MockServerDevice.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAGvC,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAItE,MAAM,MAAM,qBAAqB,GAAG,IAAI,CACtC,iBAAiB,EACjB,UAAU,GAAG,kBAAkB,CAChC,GAAG;IACF,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAyB5D,CAAC"}
1
+ {"version":3,"file":"MockServerDevice.d.ts","sourceRoot":"","sources":["../../../src/MockServerDevice.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAGvC,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAItE,MAAM,MAAM,qBAAqB,GAAG,IAAI,CACtC,iBAAiB,EACjB,UAAU,GAAG,kBAAkB,CAChC,GAAG;IACF,GAAG,EAAE,MAAM,CAAC;IACZ,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAyB5D,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=MockServerDevice.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockServerDevice.test.d.ts","sourceRoot":"","sources":["../../../src/MockServerDevice.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=deviceModels.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deviceModels.test.d.ts","sourceRoot":"","sources":["../../../src/deviceModels.test.ts"],"names":[],"mappings":""}
@@ -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,7 +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
- * device id is given, and null when it could not be read.
5
+ * device id is given, and null while it cannot be read. A failed read is
6
+ * retried, so a transient error does not leave the device without its model.
5
7
  */
6
- export declare function useMockServerDevice(client: MockClient, deviceId: string): Device | null | undefined;
8
+ export declare function useMockServerDevice(client: MockServerClient, deviceId: string): Device | null | undefined;
7
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;AAE5C;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,GAAG,SAAS,CAqB3B"}
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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=useMockServerDevice.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMockServerDevice.test.d.ts","sourceRoot":"","sources":["../../../src/useMockServerDevice.test.tsx"],"names":[],"mappings":""}