terminal.spec.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import 'jest';
  4. import { Terminal as TerminalNS, TerminalManager } from '@jupyterlab/services';
  5. import { Message, MessageLoop } from '@lumino/messaging';
  6. import { Widget } from '@lumino/widgets';
  7. import { Terminal } from '../src';
  8. import {
  9. framePromise,
  10. testEmission,
  11. JupyterServer
  12. } from '@jupyterlab/testutils';
  13. const server = new JupyterServer();
  14. beforeAll(async () => {
  15. await server.start();
  16. });
  17. afterAll(async () => {
  18. await server.shutdown();
  19. });
  20. class LogTerminal extends Terminal {
  21. methods: string[] = [];
  22. protected onAfterAttach(msg: Message): void {
  23. super.onAfterAttach(msg);
  24. this.methods.push('onAfterAttach');
  25. }
  26. protected onAfterShow(msg: Message): void {
  27. super.onAfterShow(msg);
  28. this.methods.push('onAfterShow');
  29. }
  30. protected onResize(msg: Widget.ResizeMessage): void {
  31. super.onResize(msg);
  32. this.methods.push('onResize');
  33. }
  34. protected onUpdateRequest(msg: Message): void {
  35. super.onUpdateRequest(msg);
  36. this.methods.push('onUpdateRequest');
  37. }
  38. protected onFitRequest(msg: Message): void {
  39. super.onFitRequest(msg);
  40. this.methods.push('onFitRequest');
  41. }
  42. protected onActivateRequest(msg: Message): void {
  43. super.onActivateRequest(msg);
  44. this.methods.push('onActivateRequest');
  45. }
  46. }
  47. describe('terminal/index', () => {
  48. describe('Terminal', () => {
  49. let widget: LogTerminal;
  50. let session: TerminalNS.ITerminalConnection;
  51. let manager: TerminalManager;
  52. beforeAll(async () => {
  53. manager = new TerminalManager();
  54. session = await manager.startNew();
  55. });
  56. beforeEach(() => {
  57. widget = new LogTerminal(session, { autoFit: false });
  58. Widget.attach(widget, document.body);
  59. return framePromise();
  60. });
  61. afterEach(() => {
  62. widget.dispose();
  63. });
  64. describe('#constructor()', () => {
  65. it('should create a terminal widget', () => {
  66. expect(widget).toBeInstanceOf(Terminal);
  67. });
  68. });
  69. describe('#session', () => {
  70. it('should be the constructor value', () => {
  71. expect(widget.session).toBe(session);
  72. });
  73. it('should set the title when ready', async () => {
  74. if (session.connectionStatus !== 'connected') {
  75. await testEmission(session.connectionStatusChanged, {
  76. find: (_, status) => status === 'connected'
  77. });
  78. }
  79. expect(widget.title.label).toContain(session.name);
  80. });
  81. });
  82. describe('#fontSize', () => {
  83. it('should be 13 by default', () => {
  84. expect(widget.getOption('fontSize')).toBe(13);
  85. });
  86. it('should trigger an update request', async () => {
  87. widget.setOption('fontSize', 14);
  88. expect(widget.getOption('fontSize')).toBe(14);
  89. await framePromise();
  90. expect(widget.methods).toContain('onUpdateRequest');
  91. });
  92. });
  93. describe('#scrollback', () => {
  94. it('should be 1000 by default', () => {
  95. expect(widget.getOption('scrollback')).toBe(1000);
  96. });
  97. });
  98. describe('#theme', () => {
  99. it('should be set to inherit by default', () => {
  100. expect(widget.getOption('theme')).toBe('inherit');
  101. });
  102. it('should be light if we change it', () => {
  103. widget.setOption('theme', 'light');
  104. expect(widget.getOption('theme')).toBe('light');
  105. });
  106. });
  107. describe('#dispose()', () => {
  108. it('should dispose of the resources used by the widget', () => {
  109. expect(widget.isDisposed).toBe(false);
  110. widget.dispose();
  111. expect(widget.isDisposed).toBe(true);
  112. widget.dispose();
  113. expect(widget.isDisposed).toBe(true);
  114. });
  115. });
  116. describe('#refresh()', () => {
  117. it('should refresh the widget', () => {
  118. return widget.refresh();
  119. });
  120. });
  121. describe('#processMessage()', () => {
  122. it('should handle fit requests', () => {
  123. widget.processMessage(Widget.Msg.FitRequest);
  124. expect(widget.methods).toContain('onFitRequest');
  125. });
  126. });
  127. describe('#onAfterAttach()', () => {
  128. it('should post an update request', async () => {
  129. Widget.detach(widget);
  130. Widget.attach(widget, document.body);
  131. await framePromise();
  132. expect(widget.methods).toContain('onUpdateRequest');
  133. });
  134. });
  135. describe('#onAfterShow()', () => {
  136. it('should post an update request', async () => {
  137. widget.hide();
  138. Widget.detach(widget);
  139. Widget.attach(widget, document.body);
  140. await framePromise();
  141. widget.methods = [];
  142. widget.show();
  143. await framePromise();
  144. expect(widget.methods).toContain('onUpdateRequest');
  145. });
  146. });
  147. describe('#onResize()', () => {
  148. it('should trigger an update request', async () => {
  149. const msg = Widget.ResizeMessage.UnknownSize;
  150. MessageLoop.sendMessage(widget, msg);
  151. expect(widget.methods).toContain('onResize');
  152. await framePromise();
  153. expect(widget.methods).toContain('onUpdateRequest');
  154. });
  155. });
  156. describe('#onUpdateRequest()', () => {
  157. it('should attach the terminal', () => {
  158. Widget.detach(widget);
  159. Widget.attach(widget, document.body);
  160. MessageLoop.sendMessage(widget, Widget.Msg.UpdateRequest);
  161. expect(widget.methods).toContain('onUpdateRequest');
  162. expect(widget.node.firstElementChild!.classList).toContain(
  163. 'jp-Terminal-body'
  164. );
  165. });
  166. });
  167. describe('#onFitRequest', () => {
  168. it('should send a resize request', () => {
  169. MessageLoop.sendMessage(widget, Widget.Msg.FitRequest);
  170. expect(widget.methods).toContain('onResize');
  171. });
  172. });
  173. describe('#onActivateRequest', () => {
  174. it('should focus the terminal element', () => {
  175. Widget.detach(widget);
  176. Widget.attach(widget, document.body);
  177. expect(widget.node.contains(document.activeElement)).toBe(false);
  178. MessageLoop.sendMessage(widget, Widget.Msg.ActivateRequest);
  179. expect(widget.methods).toContain('onActivateRequest');
  180. expect(widget.node.contains(document.activeElement)).toBe(true);
  181. });
  182. });
  183. });
  184. });