@flighthq/notification 0.4.0-next.1903.50bfa67 → 0.4.0-next.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/notification",
3
- "version": "0.4.0-next.1903.50bfa67",
3
+ "version": "0.4.0-next.1908.751021c",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,7 +38,7 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/types": "0.4.0-next.1903.50bfa67"
41
+ "@flighthq/types": "0.4.0-next.1908.751021c"
42
42
  },
43
43
  "devDependencies": {
44
44
  "typescript": "^5.3.0"
@@ -35,6 +35,10 @@ import {
35
35
  setNotificationBackend,
36
36
  showNotification,
37
37
  updateNotification,
38
+ explainNotificationBackend,
39
+ installNotificationHostBackend,
40
+ observeNotificationHostResult,
41
+ resetNotificationBackendForTest,
38
42
  } from './notification';
39
43
 
40
44
  const WEB_CAPABILITIES: NotificationCapabilities = {
@@ -426,6 +430,34 @@ describe('deleteNotificationChannel', () => {
426
430
  });
427
431
  });
428
432
 
433
+ describe('explainNotificationBackend', () => {
434
+ afterEach(() => resetNotificationBackendForTest());
435
+
436
+ it('reports host-not-enabled when no backend is installed', () => {
437
+ resetNotificationBackendForTest();
438
+ const explanation = explainNotificationBackend();
439
+ expect(explanation.layer).toBe('host-not-enabled');
440
+ expect(explanation.conflict).toBe(false);
441
+ expect(explanation.viability).toBe('unobserved');
442
+ });
443
+
444
+ it('reports custom layer when a custom backend is set', () => {
445
+ setNotificationBackend(fakeBackend());
446
+ expect(explainNotificationBackend().layer).toBe('custom');
447
+ });
448
+
449
+ it('reports host layer when a host backend is installed', () => {
450
+ installNotificationHostBackend(fakeBackend());
451
+ expect(explainNotificationBackend().layer).toBe('host');
452
+ });
453
+
454
+ it('reports conflict when two different host backends are installed', () => {
455
+ installNotificationHostBackend(fakeBackend());
456
+ installNotificationHostBackend(fakeBackend());
457
+ expect(explainNotificationBackend().conflict).toBe(true);
458
+ });
459
+ });
460
+
429
461
  describe('getActiveNotifications', () => {
430
462
  it('delegates to the active backend', async () => {
431
463
  const backend = fakeBackend();
@@ -511,6 +543,25 @@ describe('getPendingNotifications', () => {
511
543
  });
512
544
  });
513
545
 
546
+ describe('installNotificationHostBackend', () => {
547
+ afterEach(() => resetNotificationBackendForTest());
548
+
549
+ it('installs a host backend that getNotificationBackend returns', () => {
550
+ const backend = fakeBackend();
551
+ installNotificationHostBackend(backend);
552
+ expect(getNotificationBackend()).toBe(backend);
553
+ });
554
+
555
+ it('is first-host-wins: a second different backend sets conflict', () => {
556
+ const first = fakeBackend();
557
+ const second = fakeBackend();
558
+ installNotificationHostBackend(first);
559
+ installNotificationHostBackend(second);
560
+ expect(getNotificationBackend()).toBe(first);
561
+ expect(explainNotificationBackend().conflict).toBe(true);
562
+ });
563
+ });
564
+
514
565
  describe('isNotificationSupported', () => {
515
566
  it('delegates to the active backend', () => {
516
567
  setNotificationBackend(fakeBackend());
@@ -612,6 +663,24 @@ describe('notifyServiceWorkerBackendAction', () => {
612
663
  });
613
664
  });
614
665
 
666
+ describe('observeNotificationHostResult', () => {
667
+ afterEach(() => resetNotificationBackendForTest());
668
+
669
+ it('records a successful observation', () => {
670
+ installNotificationHostBackend(fakeBackend());
671
+ observeNotificationHostResult('cancelScheduledNotification', true);
672
+ const explanation = explainNotificationBackend();
673
+ expect(explanation.operation).toBe('cancelScheduledNotification');
674
+ expect(explanation.viability).toBe('available');
675
+ });
676
+
677
+ it('records a failed observation', () => {
678
+ installNotificationHostBackend(fakeBackend());
679
+ observeNotificationHostResult('cancelScheduledNotification', false);
680
+ expect(explainNotificationBackend().viability).toBe('runtime-api-unavailable');
681
+ });
682
+ });
683
+
615
684
  describe('onNotificationAction', () => {
616
685
  it('delivers id and action id via the active backend', () => {
617
686
  const backend = fakeBackend();
@@ -759,6 +828,18 @@ describe('requestNotificationPermission', () => {
759
828
  });
760
829
  });
761
830
 
831
+ describe('resetNotificationBackendForTest', () => {
832
+ it('clears all backend slots', () => {
833
+ setNotificationBackend(fakeBackend());
834
+ installNotificationHostBackend(fakeBackend());
835
+ observeNotificationHostResult('cancelScheduledNotification', true);
836
+ resetNotificationBackendForTest();
837
+ expect(explainNotificationBackend().layer).toBe('host-not-enabled');
838
+ expect(explainNotificationBackend().conflict).toBe(false);
839
+ expect(explainNotificationBackend().viability).toBe('unobserved');
840
+ });
841
+ });
842
+
762
843
  describe('scheduleNotification', () => {
763
844
  it('echoes the supplied id', async () => {
764
845
  const backend = fakeBackend();