@flighthq/lifecycle 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/lifecycle",
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,8 +38,8 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/signals": "0.4.0-next.1903.50bfa67",
42
- "@flighthq/types": "0.4.0-next.1903.50bfa67"
41
+ "@flighthq/signals": "0.4.0-next.1908.751021c",
42
+ "@flighthq/types": "0.4.0-next.1908.751021c"
43
43
  },
44
44
  "devDependencies": {
45
45
  "typescript": "^5.3.0"
@@ -15,6 +15,10 @@ import {
15
15
  isAppInactive,
16
16
  requestAppBack,
17
17
  setLifecycleBackend,
18
+ explainLifecycleBackend,
19
+ installLifecycleHostBackend,
20
+ observeLifecycleHostResult,
21
+ resetLifecycleBackendForTest,
18
22
  } from './lifecycle';
19
23
 
20
24
  type FakeBackend = LifecycleBackend & {
@@ -432,6 +436,34 @@ describe('disposeAppLifecycle', () => {
432
436
  });
433
437
  });
434
438
 
439
+ describe('explainLifecycleBackend', () => {
440
+ afterEach(() => resetLifecycleBackendForTest());
441
+
442
+ it('reports host-not-enabled when no backend is installed', () => {
443
+ resetLifecycleBackendForTest();
444
+ const explanation = explainLifecycleBackend();
445
+ expect(explanation.layer).toBe('host-not-enabled');
446
+ expect(explanation.conflict).toBe(false);
447
+ expect(explanation.viability).toBe('unobserved');
448
+ });
449
+
450
+ it('reports custom layer when a custom backend is set', () => {
451
+ setLifecycleBackend(fakeBackend());
452
+ expect(explainLifecycleBackend().layer).toBe('custom');
453
+ });
454
+
455
+ it('reports host layer when a host backend is installed', () => {
456
+ installLifecycleHostBackend(fakeBackend());
457
+ expect(explainLifecycleBackend().layer).toBe('host');
458
+ });
459
+
460
+ it('reports conflict when two different host backends are installed', () => {
461
+ installLifecycleHostBackend(fakeBackend());
462
+ installLifecycleHostBackend(fakeBackend());
463
+ expect(explainLifecycleBackend().conflict).toBe(true);
464
+ });
465
+ });
466
+
435
467
  describe('getAppLaunchKind', () => {
436
468
  it("returns 'warm' when backend does not implement getLaunchKind", () => {
437
469
  const backend = fakeBackend();
@@ -465,6 +497,25 @@ describe('getLifecycleBackend', () => {
465
497
  });
466
498
  });
467
499
 
500
+ describe('installLifecycleHostBackend', () => {
501
+ afterEach(() => resetLifecycleBackendForTest());
502
+
503
+ it('installs a host backend that getLifecycleBackend returns', () => {
504
+ const backend = fakeBackend();
505
+ installLifecycleHostBackend(backend);
506
+ expect(getLifecycleBackend()).toBe(backend);
507
+ });
508
+
509
+ it('is first-host-wins: a second different backend sets conflict', () => {
510
+ const first = fakeBackend();
511
+ const second = fakeBackend();
512
+ installLifecycleHostBackend(first);
513
+ installLifecycleHostBackend(second);
514
+ expect(getLifecycleBackend()).toBe(first);
515
+ expect(explainLifecycleBackend().conflict).toBe(true);
516
+ });
517
+ });
518
+
468
519
  describe('isAppActive', () => {
469
520
  it("returns true when state is 'active'", () => {
470
521
  const backend = fakeBackend();
@@ -520,6 +571,24 @@ describe('isAppInactive', () => {
520
571
  });
521
572
  });
522
573
 
574
+ describe('observeLifecycleHostResult', () => {
575
+ afterEach(() => resetLifecycleBackendForTest());
576
+
577
+ it('records a successful observation', () => {
578
+ installLifecycleHostBackend(fakeBackend());
579
+ observeLifecycleHostResult('getState', true);
580
+ const explanation = explainLifecycleBackend();
581
+ expect(explanation.operation).toBe('getState');
582
+ expect(explanation.viability).toBe('available');
583
+ });
584
+
585
+ it('records a failed observation', () => {
586
+ installLifecycleHostBackend(fakeBackend());
587
+ observeLifecycleHostResult('getState', false);
588
+ expect(explainLifecycleBackend().viability).toBe('runtime-api-unavailable');
589
+ });
590
+ });
591
+
523
592
  describe('requestAppBack', () => {
524
593
  it('returns true when no listener vetoes', () => {
525
594
  const app = createAppLifecycle();
@@ -541,6 +610,18 @@ describe('requestAppBack', () => {
541
610
  });
542
611
  });
543
612
 
613
+ describe('resetLifecycleBackendForTest', () => {
614
+ it('clears all backend slots', () => {
615
+ setLifecycleBackend(fakeBackend());
616
+ installLifecycleHostBackend(fakeBackend());
617
+ observeLifecycleHostResult('getState', true);
618
+ resetLifecycleBackendForTest();
619
+ expect(explainLifecycleBackend().layer).toBe('host-not-enabled');
620
+ expect(explainLifecycleBackend().conflict).toBe(false);
621
+ expect(explainLifecycleBackend().viability).toBe('unobserved');
622
+ });
623
+ });
624
+
544
625
  describe('setLifecycleBackend', () => {
545
626
  it('clears back to the web fallback when passed null', () => {
546
627
  setLifecycleBackend(fakeBackend());