@flighthq/tray 0.3.1-next.975.01aea94 → 0.4.0-edge.1908.751021c

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.
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { disableTrayGuards, enableTrayGuards, createTrayIcon, destroyTrayIcon, displayTrayBalloon, getTrayCapabilities, getTrayIconBounds, getTrayIconTitle, getTrayIconTooltip, getTrayIcons, isTrayDestroyed, isTrayIconAnimating, onTrayEvent, popupTrayContextMenu, removeTrayBalloon, setTrayIcon, setTrayIconContextMenu, setTrayIconTemplate, setTrayIconTitle, setTrayIconTooltip, setTrayIgnoreDoubleClickEvents, setTrayPressedIcon, startTrayIconAnimation, stopTrayIconAnimation, } from './contract';
1
+ export { disableTrayGuards, enableTrayGuards, createTrayIcon, destroyTrayIcon, displayTrayBalloon, explainTrayBackend, getTrayCapabilities, getTrayIconBounds, getTrayIconTitle, getTrayIconTooltip, getTrayIcons, isTrayDestroyed, isTrayIconAnimating, onTrayEvent, popupTrayContextMenu, removeTrayBalloon, setTrayIcon, setTrayIconContextMenu, setTrayIconTemplate, setTrayIconTitle, setTrayIconTooltip, setTrayIgnoreDoubleClickEvents, setTrayPressedIcon, startTrayIconAnimation, stopTrayIconAnimation, } from './contract';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,oBAAoB,EACpB,iBAAiB,EACjB,WAAW,EACX,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,8BAA8B,EAC9B,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,oBAAoB,EACpB,iBAAiB,EACjB,WAAW,EACX,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,8BAA8B,EAC9B,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { disableTrayGuards, enableTrayGuards, createTrayIcon, destroyTrayIcon, displayTrayBalloon, getTrayCapabilities, getTrayIconBounds, getTrayIconTitle, getTrayIconTooltip, getTrayIcons, isTrayDestroyed, isTrayIconAnimating, onTrayEvent, popupTrayContextMenu, removeTrayBalloon, setTrayIcon, setTrayIconContextMenu, setTrayIconTemplate, setTrayIconTitle, setTrayIconTooltip, setTrayIgnoreDoubleClickEvents, setTrayPressedIcon, startTrayIconAnimation, stopTrayIconAnimation, } from './contract';
1
+ export { disableTrayGuards, enableTrayGuards, createTrayIcon, destroyTrayIcon, displayTrayBalloon, explainTrayBackend, getTrayCapabilities, getTrayIconBounds, getTrayIconTitle, getTrayIconTooltip, getTrayIcons, isTrayDestroyed, isTrayIconAnimating, onTrayEvent, popupTrayContextMenu, removeTrayBalloon, setTrayIcon, setTrayIconContextMenu, setTrayIconTemplate, setTrayIconTitle, setTrayIconTooltip, setTrayIgnoreDoubleClickEvents, setTrayPressedIcon, startTrayIconAnimation, stopTrayIconAnimation, } from './contract';
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,oBAAoB,EACpB,iBAAiB,EACjB,WAAW,EACX,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,8BAA8B,EAC9B,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,oBAAoB,EACpB,iBAAiB,EACjB,WAAW,EACX,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,8BAA8B,EAC9B,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
package/dist/tray.d.ts CHANGED
@@ -1,20 +1,24 @@
1
+ import type { BackendExplanation } from '@flighthq/types/contract';
1
2
  import type { MenuItemTemplate, RectangleLike, TrayBackend, TrayBalloonOptions, TrayCapabilities, TrayEventData, TrayIcon, TrayIconOptions } from '@flighthq/types/contract';
2
3
  import type { Vector2Like } from '@flighthq/types/contract';
3
4
  export declare function createTrayIcon(options?: Readonly<TrayIconOptions>): TrayIcon | null;
4
- export declare function createWebTrayBackend(): TrayBackend;
5
5
  export declare function destroyTrayIcon(tray: TrayIcon): void;
6
6
  export declare function displayTrayBalloon(tray: TrayIcon, options: Readonly<TrayBalloonOptions>): void;
7
+ export declare function explainTrayBackend(): BackendExplanation;
7
8
  export declare function getTrayBackend(): TrayBackend;
8
9
  export declare function getTrayCapabilities(): Readonly<TrayCapabilities>;
9
10
  export declare function getTrayIconBounds(tray: TrayIcon): Readonly<RectangleLike> | null;
10
11
  export declare function getTrayIcons(): readonly TrayIcon[];
11
12
  export declare function getTrayIconTitle(tray: TrayIcon): string;
12
13
  export declare function getTrayIconTooltip(tray: TrayIcon): string;
14
+ export declare function installTrayHostBackend(backend: TrayBackend): void;
13
15
  export declare function isTrayDestroyed(tray: TrayIcon): boolean;
14
16
  export declare function isTrayIconAnimating(tray: TrayIcon): boolean;
17
+ export declare function observeTrayHostResult(operation: string, succeeded: boolean): void;
15
18
  export declare function onTrayEvent(listener: (event: Readonly<TrayEventData>) => void): () => void;
16
19
  export declare function popupTrayContextMenu(tray: TrayIcon, position?: Readonly<Vector2Like>): void;
17
20
  export declare function removeTrayBalloon(tray: TrayIcon): void;
21
+ export declare function resetTrayBackendForTest(): void;
18
22
  /** Installs the tray guard, or clears it with `null`. The seam exists so the messages and the
19
23
  * `@flighthq/log` dependency live in the separately-importable guard module rather than here; not
20
24
  * importing that module costs production nothing. Called by `enableTrayGuards`, not directly. */
@@ -1 +1 @@
1
- {"version":3,"file":"tray.d.ts","sourceRoot":"","sources":["../src/tray.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tray.d.ts","sourceRoot":"","sources":["../src/tray.ts"],"names":[],"mappings":"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"}
package/dist/tray.js CHANGED
@@ -15,77 +15,6 @@ export function createTrayIcon(options) {
15
15
  const id = getTrayBackend().create(options ?? {});
16
16
  return id < 0 ? null : { id };
17
17
  }
18
- // Builds the default web backend. Web has no system tray, so create returns -1 and the tray mutators
19
- // are no-ops — a native host (Electron's Tray, Tauri) is required for the tray icon itself. (The
20
- // application/dock badge lives in @flighthq/app's setAppBadgeCount, not here.)
21
- export function createWebTrayBackend() {
22
- return {
23
- create() {
24
- // No tray on web. -1 signals "unsupported"; createTrayIcon maps it to null.
25
- return -1;
26
- },
27
- destroy() {
28
- // No-op: web has no tray icon to destroy.
29
- },
30
- displayBalloon() {
31
- // No-op: balloon notifications require a native host (Windows only).
32
- },
33
- getBounds() {
34
- // No tray on web; null signals unavailable.
35
- return null;
36
- },
37
- getCapabilities() {
38
- return WEB_CAPABILITIES;
39
- },
40
- getTitle() {
41
- // No tray on web.
42
- return '';
43
- },
44
- getTooltip() {
45
- // No tray on web.
46
- return '';
47
- },
48
- isDestroyed() {
49
- // No tray icons exist on web; treat every id as destroyed.
50
- return true;
51
- },
52
- listIds() {
53
- // No tray icons exist on web.
54
- return [];
55
- },
56
- popUpContextMenu() {
57
- // No-op: web has no context menu to pop up.
58
- },
59
- removeBalloon() {
60
- // No-op: balloon notifications require a native host (Windows only).
61
- },
62
- setContextMenu() {
63
- // No-op: web has no tray icon — a native host (Electron/Tauri) is required.
64
- },
65
- setIcon() {
66
- // No-op: web has no tray icon to update.
67
- },
68
- setIgnoreDoubleClickEvents() {
69
- // No-op: web has no tray icon double-click behavior to configure.
70
- },
71
- setPressedIcon() {
72
- // No-op: web has no tray icon; pressed icon is macOS-specific.
73
- },
74
- setTemplate() {
75
- // No-op: template images are a macOS menu-bar concept; irrelevant on web.
76
- },
77
- setTitle() {
78
- // No-op: web has no tray icon to update.
79
- },
80
- setTooltip() {
81
- // No-op: web has no tray icon to update.
82
- },
83
- subscribe() {
84
- // No tray on web — a native host (Electron/Tauri) is required to emit tray events.
85
- return () => { };
86
- },
87
- };
88
- }
89
18
  // Destroys a tray icon and frees its host resource. No-op when the host has no tray.
90
19
  // Any icon animation running on this tray is stopped first: the interval writes through setTrayIcon,
91
20
  // and left running it would keep calling into a resource the host has freed — forever, since the
@@ -100,11 +29,23 @@ export function destroyTrayIcon(tray) {
100
29
  export function displayTrayBalloon(tray, options) {
101
30
  getTrayBackend().displayBalloon(tray.id, options);
102
31
  }
103
- // The active tray backend, or a lazily-created web default. There is always a backend.
32
+ export function explainTrayBackend() {
33
+ if (_custom !== null) {
34
+ return { conflict: _hostConflict, layer: 'custom', operation: null, viability: 'unobserved' };
35
+ }
36
+ if (_host !== null) {
37
+ return {
38
+ conflict: _hostConflict,
39
+ layer: 'host',
40
+ operation: _hostObservation !== null ? _hostObservation.operation : null,
41
+ viability: _hostObservation !== null ? _hostObservation.viability : 'unobserved',
42
+ };
43
+ }
44
+ return { conflict: false, layer: 'host-not-enabled', operation: null, viability: 'unobserved' };
45
+ }
46
+ // The active tray backend. Precedence: custom > host > sentinel.
104
47
  export function getTrayBackend() {
105
- if (_backend === null)
106
- _backend = createWebTrayBackend();
107
- return _backend;
48
+ return _custom ?? _host ?? _sentinel;
108
49
  }
109
50
  // Returns the capability flags for the active tray backend. Use before calling APIs that may
110
51
  // silently no-op — for example, check capabilities.balloon before displayTrayBalloon, or
@@ -131,6 +72,14 @@ export function getTrayIconTitle(tray) {
131
72
  export function getTrayIconTooltip(tray) {
132
73
  return getTrayBackend().getTooltip(tray.id);
133
74
  }
75
+ export function installTrayHostBackend(backend) {
76
+ if (_host !== null) {
77
+ if (_host !== backend)
78
+ _hostConflict = true;
79
+ return;
80
+ }
81
+ _host = backend;
82
+ }
134
83
  // Returns whether a tray icon has been destroyed. Returns true on web (no trays exist).
135
84
  // Use this to guard calls after destroyTrayIcon when the tray lifecycle is unclear.
136
85
  export function isTrayDestroyed(tray) {
@@ -141,6 +90,12 @@ export function isTrayDestroyed(tray) {
141
90
  export function isTrayIconAnimating(tray) {
142
91
  return _animations.has(tray.id);
143
92
  }
93
+ export function observeTrayHostResult(operation, succeeded) {
94
+ _hostObservation = {
95
+ operation,
96
+ viability: succeeded ? 'available' : 'runtime-api-unavailable',
97
+ };
98
+ }
144
99
  // Subscribes to tray icon events, delivering a rich TrayEventData payload (id, type, bounds,
145
100
  // position, modifier keys, and drop payloads). Returns an unsubscribe function. On web this
146
101
  // never fires (no tray); a native host is required.
@@ -157,15 +112,21 @@ export function popupTrayContextMenu(tray, position) {
157
112
  export function removeTrayBalloon(tray) {
158
113
  getTrayBackend().removeBalloon(tray.id);
159
114
  }
115
+ export function resetTrayBackendForTest() {
116
+ _custom = null;
117
+ _host = null;
118
+ _hostConflict = false;
119
+ _hostObservation = null;
120
+ }
160
121
  /** Installs the tray guard, or clears it with `null`. The seam exists so the messages and the
161
122
  * `@flighthq/log` dependency live in the separately-importable guard module rather than here; not
162
123
  * importing that module costs production nothing. Called by `enableTrayGuards`, not directly. */
163
124
  export function setTrayAnimationGuard(guard) {
164
125
  _animationGuard = guard;
165
126
  }
166
- // Installs a native host tray backend; pass null to fall back to the web default.
127
+ // Installs a custom tray backend; pass null to clear the custom override.
167
128
  export function setTrayBackend(backend) {
168
- _backend = backend;
129
+ _custom = backend;
169
130
  }
170
131
  // Sets the image for the tray icon. Accepts the same icon path/data-URI accepted by createTrayIcon.
171
132
  // Use this for runtime status updates (indicators, spinners, theme changes).
@@ -233,7 +194,6 @@ export function startTrayIconAnimation(tray, frames, intervalMs) {
233
194
  _animations.delete(tray.id);
234
195
  };
235
196
  }
236
- let _backend = null;
237
197
  // The interval per animating tray id. Module-scoped like the backend, and correct at that scope: an
238
198
  // id is the host's, so one id is one icon is one animation.
239
199
  const _animations = new Map();
@@ -250,4 +210,74 @@ export function stopTrayIconAnimation(tray) {
250
210
  _animations.delete(tray.id);
251
211
  }
252
212
  let _animationGuard = null;
213
+ let _custom = null;
214
+ let _host = null;
215
+ let _hostConflict = false;
216
+ let _hostObservation = null;
217
+ const _sentinel = {
218
+ create() {
219
+ // No tray on web. -1 signals "unsupported"; createTrayIcon maps it to null.
220
+ return -1;
221
+ },
222
+ destroy() {
223
+ // No-op: web has no tray icon to destroy.
224
+ },
225
+ displayBalloon() {
226
+ // No-op: balloon notifications require a native host (Windows only).
227
+ },
228
+ getBounds() {
229
+ // No tray on web; null signals unavailable.
230
+ return null;
231
+ },
232
+ getCapabilities() {
233
+ return WEB_CAPABILITIES;
234
+ },
235
+ getTitle() {
236
+ // No tray on web.
237
+ return '';
238
+ },
239
+ getTooltip() {
240
+ // No tray on web.
241
+ return '';
242
+ },
243
+ isDestroyed() {
244
+ // No tray icons exist on web; treat every id as destroyed.
245
+ return true;
246
+ },
247
+ listIds() {
248
+ // No tray icons exist on web.
249
+ return [];
250
+ },
251
+ popUpContextMenu() {
252
+ // No-op: web has no context menu to pop up.
253
+ },
254
+ removeBalloon() {
255
+ // No-op: balloon notifications require a native host (Windows only).
256
+ },
257
+ setContextMenu() {
258
+ // No-op: web has no tray icon — a native host (Electron/Tauri) is required.
259
+ },
260
+ setIcon() {
261
+ // No-op: web has no tray icon to update.
262
+ },
263
+ setIgnoreDoubleClickEvents() {
264
+ // No-op: web has no tray icon double-click behavior to configure.
265
+ },
266
+ setPressedIcon() {
267
+ // No-op: web has no tray icon; pressed icon is macOS-specific.
268
+ },
269
+ setTemplate() {
270
+ // No-op: template images are a macOS menu-bar concept; irrelevant on web.
271
+ },
272
+ setTitle() {
273
+ // No-op: web has no tray icon to update.
274
+ },
275
+ setTooltip() {
276
+ // No-op: web has no tray icon to update.
277
+ },
278
+ subscribe() {
279
+ // No tray on web — a native host (Electron/Tauri) is required to emit tray events.
280
+ return () => { };
281
+ },
282
+ };
253
283
  //# sourceMappingURL=tray.js.map
package/dist/tray.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tray.js","sourceRoot":"","sources":["../src/tray.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tray.js","sourceRoot":"","sources":["../src/tray.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/tray",
3
- "version": "0.3.1-next.975.01aea94",
3
+ "version": "0.4.0-edge.1908.751021c",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,8 +38,8 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/log": "0.3.1-next.975.01aea94",
42
- "@flighthq/types": "0.3.1-next.975.01aea94"
41
+ "@flighthq/log": "0.4.0-edge.1908.751021c",
42
+ "@flighthq/types": "0.4.0-edge.1908.751021c"
43
43
  },
44
44
  "devDependencies": {
45
45
  "typescript": "^5.3.0"
package/src/tray.test.ts CHANGED
@@ -10,7 +10,6 @@ import type {
10
10
 
11
11
  import {
12
12
  createTrayIcon,
13
- createWebTrayBackend,
14
13
  destroyTrayIcon,
15
14
  displayTrayBalloon,
16
15
  getTrayBackend,
@@ -35,6 +34,10 @@ import {
35
34
  setTrayPressedIcon,
36
35
  startTrayIconAnimation,
37
36
  stopTrayIconAnimation,
37
+ explainTrayBackend,
38
+ installTrayHostBackend,
39
+ observeTrayHostResult,
40
+ resetTrayBackendForTest,
38
41
  } from './tray';
39
42
 
40
43
  // Fake backend state per icon.
@@ -213,41 +216,6 @@ describe('createTrayIcon', () => {
213
216
  });
214
217
  });
215
218
 
216
- describe('createWebTrayBackend', () => {
217
- it('returns sentinels without throwing (web has no tray)', () => {
218
- const backend = createWebTrayBackend();
219
- expect(backend.create({})).toBe(-1);
220
- expect(() => backend.destroy(0)).not.toThrow();
221
- expect(() => backend.setTooltip(0, 'x')).not.toThrow();
222
- expect(() => backend.setTitle(0, 'x')).not.toThrow();
223
- expect(() => backend.setContextMenu(0, [])).not.toThrow();
224
- expect(() => backend.setIcon(0, 'icon.png')).not.toThrow();
225
- expect(() => backend.setTemplate(0, true)).not.toThrow();
226
- expect(() => backend.setPressedIcon(0, 'pressed.png')).not.toThrow();
227
- expect(() => backend.setIgnoreDoubleClickEvents(0, true)).not.toThrow();
228
- expect(() => backend.popUpContextMenu(0)).not.toThrow();
229
- expect(() => backend.displayBalloon(0, { title: 'T', text: 'B' })).not.toThrow();
230
- expect(() => backend.removeBalloon(0)).not.toThrow();
231
- expect(backend.getBounds(0)).toBeNull();
232
- expect(backend.getTitle(0)).toBe('');
233
- expect(backend.getTooltip(0)).toBe('');
234
- expect(backend.isDestroyed(0)).toBe(true);
235
- expect(backend.listIds()).toEqual([]);
236
- expect(typeof backend.subscribe(() => {})).toBe('function');
237
- });
238
-
239
- it('web capabilities are all false', () => {
240
- const backend = createWebTrayBackend();
241
- const caps = backend.getCapabilities();
242
- expect(caps.balloon).toBe(false);
243
- expect(caps.bounds).toBe(false);
244
- expect(caps.clickEvents).toBe(false);
245
- expect(caps.dropFiles).toBe(false);
246
- expect(caps.pressedIcon).toBe(false);
247
- expect(caps.title).toBe(false);
248
- });
249
- });
250
-
251
219
  describe('destroyTrayIcon', () => {
252
220
  it('destroys the tray via the active backend', () => {
253
221
  const backend = fakeBackend();
@@ -289,6 +257,34 @@ describe('displayTrayBalloon', () => {
289
257
  });
290
258
  });
291
259
 
260
+ describe('explainTrayBackend', () => {
261
+ afterEach(() => resetTrayBackendForTest());
262
+
263
+ it('reports host-not-enabled when no backend is installed', () => {
264
+ resetTrayBackendForTest();
265
+ const explanation = explainTrayBackend();
266
+ expect(explanation.layer).toBe('host-not-enabled');
267
+ expect(explanation.conflict).toBe(false);
268
+ expect(explanation.viability).toBe('unobserved');
269
+ });
270
+
271
+ it('reports custom layer when a custom backend is set', () => {
272
+ setTrayBackend(fakeBackend());
273
+ expect(explainTrayBackend().layer).toBe('custom');
274
+ });
275
+
276
+ it('reports host layer when a host backend is installed', () => {
277
+ installTrayHostBackend(fakeBackend());
278
+ expect(explainTrayBackend().layer).toBe('host');
279
+ });
280
+
281
+ it('reports conflict when two different host backends are installed', () => {
282
+ installTrayHostBackend(fakeBackend());
283
+ installTrayHostBackend(fakeBackend());
284
+ expect(explainTrayBackend().conflict).toBe(true);
285
+ });
286
+ });
287
+
292
288
  describe('getTrayBackend', () => {
293
289
  it('falls back to a web backend', () => {
294
290
  expect(getTrayBackend()).not.toBeNull();
@@ -301,6 +297,41 @@ describe('getTrayBackend', () => {
301
297
  });
302
298
  });
303
299
 
300
+ describe('getTrayBackend (sentinel)', () => {
301
+ it('returns sentinels without throwing (web has no tray)', () => {
302
+ const backend = getTrayBackend();
303
+ expect(backend.create({})).toBe(-1);
304
+ expect(() => backend.destroy(0)).not.toThrow();
305
+ expect(() => backend.setTooltip(0, 'x')).not.toThrow();
306
+ expect(() => backend.setTitle(0, 'x')).not.toThrow();
307
+ expect(() => backend.setContextMenu(0, [])).not.toThrow();
308
+ expect(() => backend.setIcon(0, 'icon.png')).not.toThrow();
309
+ expect(() => backend.setTemplate(0, true)).not.toThrow();
310
+ expect(() => backend.setPressedIcon(0, 'pressed.png')).not.toThrow();
311
+ expect(() => backend.setIgnoreDoubleClickEvents(0, true)).not.toThrow();
312
+ expect(() => backend.popUpContextMenu(0)).not.toThrow();
313
+ expect(() => backend.displayBalloon(0, { title: 'T', text: 'B' })).not.toThrow();
314
+ expect(() => backend.removeBalloon(0)).not.toThrow();
315
+ expect(backend.getBounds(0)).toBeNull();
316
+ expect(backend.getTitle(0)).toBe('');
317
+ expect(backend.getTooltip(0)).toBe('');
318
+ expect(backend.isDestroyed(0)).toBe(true);
319
+ expect(backend.listIds()).toEqual([]);
320
+ expect(typeof backend.subscribe(() => {})).toBe('function');
321
+ });
322
+
323
+ it('sentinel capabilities are all false', () => {
324
+ const backend = getTrayBackend();
325
+ const caps = backend.getCapabilities();
326
+ expect(caps.balloon).toBe(false);
327
+ expect(caps.bounds).toBe(false);
328
+ expect(caps.clickEvents).toBe(false);
329
+ expect(caps.dropFiles).toBe(false);
330
+ expect(caps.pressedIcon).toBe(false);
331
+ expect(caps.title).toBe(false);
332
+ });
333
+ });
334
+
304
335
  describe('getTrayCapabilities', () => {
305
336
  it('returns capabilities from the active backend', () => {
306
337
  const backend = fakeBackend({ balloon: true, bounds: false });
@@ -385,6 +416,25 @@ describe('getTrayIconTooltip', () => {
385
416
  });
386
417
  });
387
418
 
419
+ describe('installTrayHostBackend', () => {
420
+ afterEach(() => resetTrayBackendForTest());
421
+
422
+ it('installs a host backend that getTrayBackend returns', () => {
423
+ const backend = fakeBackend();
424
+ installTrayHostBackend(backend);
425
+ expect(getTrayBackend()).toBe(backend);
426
+ });
427
+
428
+ it('is first-host-wins: a second different backend sets conflict', () => {
429
+ const first = fakeBackend();
430
+ const second = fakeBackend();
431
+ installTrayHostBackend(first);
432
+ installTrayHostBackend(second);
433
+ expect(getTrayBackend()).toBe(first);
434
+ expect(explainTrayBackend().conflict).toBe(true);
435
+ });
436
+ });
437
+
388
438
  describe('isTrayDestroyed', () => {
389
439
  it('returns false for a live tray', () => {
390
440
  const backend = fakeBackend();
@@ -443,6 +493,24 @@ describe('isTrayIconAnimating', () => {
443
493
  });
444
494
  });
445
495
 
496
+ describe('observeTrayHostResult', () => {
497
+ afterEach(() => resetTrayBackendForTest());
498
+
499
+ it('records a successful observation', () => {
500
+ installTrayHostBackend(fakeBackend());
501
+ observeTrayHostResult('create', true);
502
+ const explanation = explainTrayBackend();
503
+ expect(explanation.operation).toBe('create');
504
+ expect(explanation.viability).toBe('available');
505
+ });
506
+
507
+ it('records a failed observation', () => {
508
+ installTrayHostBackend(fakeBackend());
509
+ observeTrayHostResult('create', false);
510
+ expect(explainTrayBackend().viability).toBe('runtime-api-unavailable');
511
+ });
512
+ });
513
+
446
514
  describe('onTrayEvent', () => {
447
515
  it('delivers rich TrayEventData via the active backend', () => {
448
516
  const backend = fakeBackend();
@@ -541,6 +609,18 @@ describe('removeTrayBalloon', () => {
541
609
  });
542
610
  });
543
611
 
612
+ describe('resetTrayBackendForTest', () => {
613
+ it('clears all backend slots', () => {
614
+ setTrayBackend(fakeBackend());
615
+ installTrayHostBackend(fakeBackend());
616
+ observeTrayHostResult('create', true);
617
+ resetTrayBackendForTest();
618
+ expect(explainTrayBackend().layer).toBe('host-not-enabled');
619
+ expect(explainTrayBackend().conflict).toBe(false);
620
+ expect(explainTrayBackend().viability).toBe('unobserved');
621
+ });
622
+ });
623
+
544
624
  describe('setTrayAnimationGuard', () => {
545
625
  afterEach(() => {
546
626
  setTrayAnimationGuard(null);