widget.spec.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright (c) Jupyter Development Team.
  2. import 'jest';
  3. // Distributed under the terms of the Modified BSD License.
  4. import { LoggerRegistry, LogConsolePanel } from '@jupyterlab/logconsole';
  5. import {
  6. RenderMimeRegistry,
  7. IRenderMimeRegistry,
  8. standardRendererFactories as initialFactories
  9. } from '@jupyterlab/rendermime';
  10. import { Signal, ISignal } from '@lumino/signaling';
  11. import { Widget } from '@lumino/widgets';
  12. class SignalLogger<SENDER, ARGS> {
  13. constructor(signal: ISignal<SENDER, ARGS>) {
  14. signal.connect(this.slot, this);
  15. }
  16. slot(sender: SENDER, args: ARGS) {
  17. this.args.push(args);
  18. }
  19. clear() {
  20. this.args.length = 0;
  21. }
  22. dispose() {
  23. Signal.disconnectAll(this);
  24. }
  25. args: ARGS[] = [];
  26. }
  27. function anyAncestor(el: Element, test: (el: Element) => boolean) {
  28. while (el) {
  29. if (test(el)) {
  30. return true;
  31. }
  32. if (!el.parentElement || el === el.parentNode) {
  33. break;
  34. }
  35. el = el.parentElement;
  36. }
  37. return false;
  38. }
  39. function isHiddenLumino(el: Element) {
  40. return el.classList.contains('lm-mod-hidden');
  41. }
  42. describe('LogConsolePanel', () => {
  43. let defaultRendermime: IRenderMimeRegistry;
  44. let registry: LoggerRegistry;
  45. let logConsole: LogConsolePanel;
  46. beforeEach(() => {
  47. defaultRendermime = new RenderMimeRegistry({ initialFactories });
  48. registry = new LoggerRegistry({
  49. defaultRendermime,
  50. maxLength: 10
  51. });
  52. logConsole = new LogConsolePanel(registry);
  53. });
  54. afterEach(() => {
  55. registry.dispose();
  56. logConsole.dispose();
  57. });
  58. describe('#constructor()', () => {
  59. it('should create a console with initial parameters', () => {
  60. expect(logConsole).toBeInstanceOf(LogConsolePanel);
  61. expect(logConsole.loggerRegistry).toBe(registry);
  62. });
  63. });
  64. describe('#loggerRegistry', () => {
  65. it('returns the logger registry', () => {
  66. expect(logConsole.loggerRegistry).toBe(registry);
  67. });
  68. });
  69. describe('#source', () => {
  70. it('sets the current source', () => {
  71. expect(logConsole.source).toBe(null);
  72. registry.getLogger('A');
  73. logConsole.source = 'A';
  74. expect(logConsole.source).toBe('A');
  75. });
  76. it('displays output only from the current source', () => {
  77. const loggerA = registry.getLogger('A');
  78. const loggerB = registry.getLogger('B');
  79. loggerA.log({
  80. type: 'html',
  81. data: '<div id="A"></div>',
  82. level: 'warning'
  83. });
  84. loggerB.log({
  85. type: 'html',
  86. data: '<div id="B"></div>',
  87. level: 'warning'
  88. });
  89. logConsole.source = 'A';
  90. const nodeA = logConsole.node.querySelector('#A')!;
  91. const nodeB = logConsole.node.querySelector('#B')!;
  92. expect(nodeA).not.toBeNull();
  93. expect(anyAncestor(nodeA, isHiddenLumino)).toBe(false);
  94. expect(nodeB).not.toBeNull();
  95. expect(anyAncestor(nodeB, isHiddenLumino)).toBe(true);
  96. logConsole.source = 'B';
  97. expect(anyAncestor(nodeA, isHiddenLumino)).toBe(true);
  98. expect(anyAncestor(nodeB, isHiddenLumino)).toBe(false);
  99. });
  100. it('emits a source changed signal if changed', () => {
  101. const s = new SignalLogger(logConsole.sourceChanged);
  102. logConsole.source = 'A';
  103. logConsole.source = null;
  104. expect(s.args).toEqual([
  105. { name: 'source', oldValue: null, newValue: 'A' },
  106. { name: 'source', oldValue: 'A', newValue: null }
  107. ]);
  108. s.dispose();
  109. });
  110. it('has no effect if not changed', () => {
  111. const s = new SignalLogger(logConsole.sourceChanged);
  112. logConsole.source = null;
  113. expect(s.args).toEqual([]);
  114. registry.getLogger('A');
  115. logConsole.source = 'A';
  116. s.clear();
  117. logConsole.source = 'A';
  118. expect(s.args).toEqual([]);
  119. s.dispose();
  120. });
  121. });
  122. describe('#sourceVersion', () => {
  123. it('gives the version for the current source', () => {
  124. const A = registry.getLogger('A');
  125. A.log({ type: 'text', data: 'message', level: 'warning' });
  126. A.log({ type: 'text', data: 'message', level: 'warning' });
  127. logConsole.source = 'A';
  128. expect(logConsole.sourceVersion).toBe(A.version);
  129. });
  130. it('is null if the source is null', () => {
  131. expect(logConsole.source).toBe(null);
  132. expect(logConsole.sourceVersion).toBe(null);
  133. });
  134. });
  135. describe('#logger', () => {
  136. it('gives the logger for the current source', () => {
  137. const A = registry.getLogger('A');
  138. A.log({ type: 'text', data: 'message', level: 'warning' });
  139. A.log({ type: 'text', data: 'message', level: 'warning' });
  140. logConsole.source = 'A';
  141. expect(logConsole.logger).toBe(A);
  142. });
  143. it('is null if the source is null', () => {
  144. expect(logConsole.source).toBe(null);
  145. expect(logConsole.logger).toBe(null);
  146. });
  147. });
  148. describe('#sourceDisplayed', () => {
  149. it('emits when console is attached', () => {
  150. const s = new SignalLogger(logConsole.sourceDisplayed);
  151. const loggerA = registry.getLogger('A');
  152. loggerA.log({ type: 'text', data: 'A1', level: 'warning' });
  153. logConsole.source = 'A';
  154. expect(s.args).toEqual([]);
  155. Widget.attach(logConsole, document.body);
  156. expect(s.args).toEqual([{ source: 'A', version: 1 }]);
  157. s.dispose();
  158. });
  159. it('emits when console is shown', () => {
  160. const s = new SignalLogger(logConsole.sourceDisplayed);
  161. const loggerA = registry.getLogger('A');
  162. loggerA.log({ type: 'text', data: 'A1', level: 'warning' });
  163. logConsole.source = 'A';
  164. logConsole.hide();
  165. Widget.attach(logConsole, document.body);
  166. expect(s.args).toEqual([]);
  167. logConsole.show();
  168. expect(s.args).toEqual([{ source: 'A', version: 1 }]);
  169. s.dispose();
  170. });
  171. it('emits when source is selected', () => {
  172. const s = new SignalLogger(logConsole.sourceDisplayed);
  173. const loggerA = registry.getLogger('A');
  174. const loggerB = registry.getLogger('B');
  175. loggerA.log({ type: 'text', data: 'A1', level: 'warning' });
  176. loggerB.log({ type: 'text', data: 'B1', level: 'warning' });
  177. Widget.attach(logConsole, document.body);
  178. expect(s.args).toEqual([]);
  179. logConsole.source = 'A';
  180. expect(s.args).toEqual([{ source: 'A', version: 1 }]);
  181. s.clear();
  182. loggerB.log({ type: 'text', data: 'B2', level: 'warning' });
  183. expect(s.args).toEqual([]);
  184. logConsole.source = 'B';
  185. expect(s.args).toEqual([{ source: 'B', version: 2 }]);
  186. s.dispose();
  187. });
  188. it('emits when logging to displayed source', () => {
  189. const s = new SignalLogger(logConsole.sourceDisplayed);
  190. const loggerA = registry.getLogger('A');
  191. loggerA.log({ type: 'text', data: 'A1', level: 'warning' });
  192. Widget.attach(logConsole, document.body);
  193. expect(s.args).toEqual([]);
  194. logConsole.source = 'A';
  195. expect(s.args).toEqual([{ source: 'A', version: 1 }]);
  196. s.clear();
  197. loggerA.log({ type: 'text', data: 'A2', level: 'warning' });
  198. expect(s.args).toEqual([{ source: 'A', version: 2 }]);
  199. s.dispose();
  200. });
  201. });
  202. });