terminal.spec.ts 6.1 KB

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