layoutrestorer.spec.ts 6.6 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 { DockPanel, 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 mode: DockPanel.Mode = 'single-document';
  53. const dehydrated: ILabShell.ILayout = {
  54. mainArea: { currentWidget, dock: null, mode },
  55. leftArea: { collapsed: true, currentWidget: null, widgets: null },
  56. rightArea: { collapsed: true, currentWidget: null, widgets: null }
  57. };
  58. restorer.add(currentWidget, 'test-one');
  59. ready.resolve(void 0);
  60. await restorer.restored;
  61. await restorer.save(dehydrated);
  62. const layout = await restorer.fetch();
  63. expect(layout.mainArea?.currentWidget).toBe(currentWidget);
  64. expect(layout.mainArea?.mode).toBe(mode);
  65. });
  66. });
  67. describe('#fetch()', () => {
  68. it('should always return a value', async () => {
  69. const restorer = new LayoutRestorer({
  70. connector: new StateDB(),
  71. first: Promise.resolve(void 0),
  72. registry: new CommandRegistry()
  73. });
  74. const layout = await restorer.fetch();
  75. expect(layout).not.toBe(null);
  76. });
  77. it('should fetch saved data', async () => {
  78. const ready = new PromiseDelegate<void>();
  79. const restorer = new LayoutRestorer({
  80. connector: new StateDB(),
  81. first: ready.promise,
  82. registry: new CommandRegistry()
  83. });
  84. const currentWidget = new Widget();
  85. // The `fresh` attribute is only here to check against the return value.
  86. const dehydrated: ILabShell.ILayout = {
  87. fresh: false,
  88. mainArea: { currentWidget: null, dock: null, mode: null },
  89. leftArea: {
  90. currentWidget,
  91. collapsed: true,
  92. widgets: [currentWidget]
  93. },
  94. rightArea: { collapsed: true, currentWidget: null, widgets: null }
  95. };
  96. restorer.add(currentWidget, 'test-one');
  97. ready.resolve(void 0);
  98. await restorer.restored;
  99. await restorer.save(dehydrated);
  100. const layout = await restorer.fetch();
  101. expect(layout).toEqual(dehydrated);
  102. });
  103. });
  104. describe('#restore()', () => {
  105. it('should restore the widgets in a tracker', async () => {
  106. const tracker = new WidgetTracker({ namespace: 'foo-widget' });
  107. const registry = new CommandRegistry();
  108. const state = new StateDB();
  109. const ready = new PromiseDelegate<void>();
  110. const restorer = new LayoutRestorer({
  111. connector: state,
  112. first: ready.promise,
  113. registry
  114. });
  115. let called = false;
  116. const key = `${tracker.namespace}:${tracker.namespace}`;
  117. registry.addCommand(tracker.namespace, {
  118. execute: () => {
  119. called = true;
  120. }
  121. });
  122. await state.save(key, { data: null });
  123. ready.resolve(undefined);
  124. await restorer.restore(tracker, {
  125. name: () => tracker.namespace,
  126. command: tracker.namespace
  127. });
  128. await restorer.restored;
  129. expect(called).toBe(true);
  130. });
  131. });
  132. describe('#save()', () => {
  133. it('should not run before `first` promise', async () => {
  134. const restorer = new LayoutRestorer({
  135. connector: new StateDB(),
  136. first: new Promise(() => {
  137. // no op
  138. }),
  139. registry: new CommandRegistry()
  140. });
  141. const dehydrated: ILabShell.ILayout = {
  142. mainArea: { currentWidget: null, dock: null, mode: null },
  143. leftArea: { currentWidget: null, collapsed: true, widgets: null },
  144. rightArea: { collapsed: true, currentWidget: null, widgets: null }
  145. };
  146. await expect(restorer.save(dehydrated)).rejects.toThrow(
  147. '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, mode: 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. });