widget.spec.ts 7.0 KB

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