layoutrestorer.spec.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import 'jest';
  4. import { ILabShell, LayoutRestorer } from '@jupyterlab/application';
  5. import { WidgetTracker } from '@jupyterlab/apputils';
  6. import { StateDB } from '@jupyterlab/statedb';
  7. import { CommandRegistry } from '@lumino/commands';
  8. import { PromiseDelegate } from '@lumino/coreutils';
  9. import { Widget } from '@lumino/widgets';
  10. describe('apputils', () => {
  11. describe('LayoutRestorer', () => {
  12. describe('#constructor()', () => {
  13. it('should construct a new layout restorer', () => {
  14. const restorer = new LayoutRestorer({
  15. connector: new StateDB(),
  16. first: Promise.resolve<void>(void 0),
  17. registry: new CommandRegistry()
  18. });
  19. expect(restorer).toBeInstanceOf(LayoutRestorer);
  20. });
  21. });
  22. describe('#restored', () => {
  23. it('should be a promise available right away', () => {
  24. const restorer = new LayoutRestorer({
  25. connector: new StateDB(),
  26. first: Promise.resolve<void>(void 0),
  27. registry: new CommandRegistry()
  28. });
  29. expect(restorer.restored).toBeInstanceOf(Promise);
  30. });
  31. it('should resolve when restorer is done', async () => {
  32. const ready = new PromiseDelegate<void>();
  33. const restorer = new LayoutRestorer({
  34. connector: new StateDB(),
  35. first: ready.promise,
  36. registry: new CommandRegistry()
  37. });
  38. const promise = restorer.restored;
  39. ready.resolve(void 0);
  40. await promise;
  41. });
  42. });
  43. describe('#add()', () => {
  44. it('should add a widget to be tracked by the restorer', async () => {
  45. const ready = new PromiseDelegate<void>();
  46. const restorer = new LayoutRestorer({
  47. connector: new StateDB(),
  48. first: ready.promise,
  49. registry: new CommandRegistry()
  50. });
  51. const currentWidget = new Widget();
  52. const dehydrated: ILabShell.ILayout = {
  53. mainArea: { currentWidget, dock: null },
  54. leftArea: { collapsed: true, currentWidget: null, widgets: null },
  55. rightArea: { collapsed: true, currentWidget: null, widgets: null }
  56. };
  57. restorer.add(currentWidget, 'test-one');
  58. ready.resolve(void 0);
  59. await restorer.restored;
  60. await restorer.save(dehydrated);
  61. const layout = await restorer.fetch();
  62. expect(layout.mainArea?.currentWidget).toBe(currentWidget);
  63. });
  64. });
  65. describe('#fetch()', () => {
  66. it('should always return a value', async () => {
  67. const restorer = new LayoutRestorer({
  68. connector: new StateDB(),
  69. first: Promise.resolve(void 0),
  70. registry: new CommandRegistry()
  71. });
  72. const layout = await restorer.fetch();
  73. expect(layout).not.toBe(null);
  74. });
  75. it('should fetch saved data', async () => {
  76. const ready = new PromiseDelegate<void>();
  77. const restorer = new LayoutRestorer({
  78. connector: new StateDB(),
  79. first: ready.promise,
  80. registry: new CommandRegistry()
  81. });
  82. const currentWidget = new Widget();
  83. // The `fresh` attribute is only here to check against the return value.
  84. const dehydrated: ILabShell.ILayout = {
  85. fresh: false,
  86. mainArea: { currentWidget: null, dock: null },
  87. leftArea: {
  88. currentWidget,
  89. collapsed: true,
  90. widgets: [currentWidget]
  91. },
  92. rightArea: { collapsed: true, currentWidget: null, widgets: null }
  93. };
  94. restorer.add(currentWidget, 'test-one');
  95. ready.resolve(void 0);
  96. await restorer.restored;
  97. await restorer.save(dehydrated);
  98. const layout = await restorer.fetch();
  99. expect(layout).toEqual(dehydrated);
  100. });
  101. });
  102. describe('#restore()', () => {
  103. it('should restore the widgets in a tracker', async () => {
  104. const tracker = new WidgetTracker({ namespace: 'foo-widget' });
  105. const registry = new CommandRegistry();
  106. const state = new StateDB();
  107. const ready = new PromiseDelegate<void>();
  108. const restorer = new LayoutRestorer({
  109. connector: state,
  110. first: ready.promise,
  111. registry
  112. });
  113. let called = false;
  114. const key = `${tracker.namespace}:${tracker.namespace}`;
  115. registry.addCommand(tracker.namespace, {
  116. execute: () => {
  117. called = true;
  118. }
  119. });
  120. await state.save(key, { data: null });
  121. ready.resolve(undefined);
  122. await restorer.restore(tracker, {
  123. name: () => tracker.namespace,
  124. command: tracker.namespace
  125. });
  126. await restorer.restored;
  127. expect(called).toBe(true);
  128. });
  129. });
  130. describe('#save()', () => {
  131. it('should not run before `first` promise', async () => {
  132. const restorer = new LayoutRestorer({
  133. connector: new StateDB(),
  134. first: new Promise(() => {
  135. // no op
  136. }),
  137. registry: new CommandRegistry()
  138. });
  139. const dehydrated: ILabShell.ILayout = {
  140. mainArea: { currentWidget: null, dock: null },
  141. leftArea: { currentWidget: null, collapsed: true, widgets: null },
  142. rightArea: { collapsed: true, currentWidget: null, widgets: null }
  143. };
  144. try {
  145. await restorer.save(dehydrated);
  146. } catch (e) {
  147. expect(e).toBe('save() was called prematurely.');
  148. }
  149. });
  150. it('should save data', async () => {
  151. const ready = new PromiseDelegate<void>();
  152. const restorer = new LayoutRestorer({
  153. connector: new StateDB(),
  154. first: ready.promise,
  155. registry: new CommandRegistry()
  156. });
  157. const currentWidget = new Widget();
  158. // The `fresh` attribute is only here to check against the return value.
  159. const dehydrated: ILabShell.ILayout = {
  160. fresh: false,
  161. mainArea: { currentWidget: null, dock: null },
  162. leftArea: {
  163. currentWidget,
  164. collapsed: true,
  165. widgets: [currentWidget]
  166. },
  167. rightArea: { collapsed: true, currentWidget: null, widgets: null }
  168. };
  169. restorer.add(currentWidget, 'test-one');
  170. ready.resolve(void 0);
  171. await restorer.restored;
  172. await restorer.save(dehydrated);
  173. const layout = await restorer.fetch();
  174. expect(layout).toEqual(dehydrated);
  175. });
  176. });
  177. });
  178. });