model.spec.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import expect = require('expect.js');
  4. import {
  5. MockKernel
  6. } from 'jupyter-js-services/lib/mockkernel';
  7. import {
  8. ListChangeType
  9. } from 'phosphor-observablelist';
  10. import {
  11. deepEqual
  12. } from '../../../../lib/notebook/common/json';
  13. import {
  14. OutputAreaModel
  15. } from '../../../../lib/notebook/output-area/model';
  16. import {
  17. nbformat
  18. } from '../../../../lib/notebook/notebook/nbformat';
  19. /**
  20. * The default outputs used for testing.
  21. */
  22. export
  23. const DEFAULT_OUTPUTS: nbformat.IOutput[] = [
  24. {
  25. name: 'stdout',
  26. output_type: 'stream',
  27. text: [
  28. 'hello world\n',
  29. '0\n',
  30. '1\n',
  31. '2\n'
  32. ]
  33. },
  34. {
  35. name: 'stderr',
  36. output_type: 'stream',
  37. text: [
  38. 'output to stderr\n'
  39. ]
  40. },
  41. {
  42. name: 'stderr',
  43. output_type: 'stream',
  44. text: [
  45. 'output to stderr2\n'
  46. ]
  47. },
  48. {
  49. output_type: 'execute_result',
  50. execution_count: 1,
  51. data: { 'text/plain': 'foo' },
  52. metadata: {}
  53. },
  54. {
  55. output_type: 'display_data',
  56. data: { 'text/plain': 'hello, world' },
  57. metadata: {}
  58. },
  59. {
  60. output_type: 'error',
  61. ename: 'foo',
  62. evalue: 'bar',
  63. traceback: ['fizz', 'buzz']
  64. }
  65. ];
  66. describe('notebook/output-area/model', () => {
  67. describe('OutputAreaModel', () => {
  68. describe('#constructor()', () => {
  69. it('should create an output area model', () => {
  70. let model = new OutputAreaModel();
  71. expect(model).to.be.an(OutputAreaModel);
  72. });
  73. });
  74. describe('#changed', () => {
  75. it('should be emitted when the model changes', () => {
  76. let model = new OutputAreaModel();
  77. let called = false;
  78. model.changed.connect((sender, args) => {
  79. expect(sender).to.be(model);
  80. expect(args.type).to.be(ListChangeType.Add);
  81. expect(args.oldIndex).to.be(-1);
  82. expect(args.newIndex).to.be(0);
  83. expect(args.oldValue).to.be(void 0);
  84. expect(deepEqual(args.newValue as nbformat.IOutput, DEFAULT_OUTPUTS[0]));
  85. called = true;
  86. });
  87. model.add(DEFAULT_OUTPUTS[0]);
  88. expect(called).to.be(true);
  89. });
  90. });
  91. describe('#length', () => {
  92. it('should get the length of the items in the model', () => {
  93. let model = new OutputAreaModel();
  94. expect(model.length).to.be(0);
  95. model.add(DEFAULT_OUTPUTS[0]);
  96. expect(model.length).to.be(1);
  97. });
  98. it('should be read-only', () => {
  99. let model = new OutputAreaModel();
  100. expect(() => { model.length = 0; }).to.throwError();
  101. });
  102. });
  103. describe('#isDisposed', () => {
  104. it('should test whether the model is disposed', () => {
  105. let model = new OutputAreaModel();
  106. expect(model.isDisposed).to.be(false);
  107. model.dispose();
  108. expect(model.isDisposed).to.be(true);
  109. });
  110. it('should be read-only', () => {
  111. let model = new OutputAreaModel();
  112. expect(() => { model.isDisposed = true; }).to.throwError();
  113. });
  114. });
  115. describe('#dispose()', () => {
  116. it('should dispose of the resources used by the model', () => {
  117. let model = new OutputAreaModel();
  118. model.add(DEFAULT_OUTPUTS[0]);
  119. model.dispose();
  120. expect(model.isDisposed).to.be(true);
  121. expect(model.length).to.be(0);
  122. });
  123. it('should be safe to call more than once', () => {
  124. let model = new OutputAreaModel();
  125. model.dispose();
  126. model.dispose();
  127. expect(model.isDisposed).to.be(true);
  128. });
  129. });
  130. describe('#get()', () => {
  131. it('should get the item at the specified index', () => {
  132. let model = new OutputAreaModel();
  133. model.add(DEFAULT_OUTPUTS[0]);
  134. let output = model.get(0);
  135. expect(output).to.not.be(DEFAULT_OUTPUTS[0]);
  136. expect(output.output_type).to.be(DEFAULT_OUTPUTS[0].output_type);
  137. });
  138. it('should return `undefined` if out of range', () => {
  139. let model = new OutputAreaModel();
  140. model.add(DEFAULT_OUTPUTS[0]);
  141. expect(model.get(1)).to.be(void 0);
  142. });
  143. });
  144. describe('#add()', () => {
  145. it('should add an output', () => {
  146. let model = new OutputAreaModel();
  147. model.add(DEFAULT_OUTPUTS[0]);
  148. expect(model.length).to.be(1);
  149. });
  150. it('should consolidate consecutive stream outputs of the same kind', () => {
  151. let model = new OutputAreaModel();
  152. model.add(DEFAULT_OUTPUTS[0]);
  153. model.add(DEFAULT_OUTPUTS[1]);
  154. expect(model.length).to.be(2);
  155. model.add(DEFAULT_OUTPUTS[2]);
  156. expect(model.length).to.be(2);
  157. });
  158. });
  159. describe('#clear()', () => {
  160. it('should clear all of the output', () => {
  161. let model = new OutputAreaModel();
  162. for (let output of DEFAULT_OUTPUTS) {
  163. model.add(output);
  164. }
  165. model.clear();
  166. expect(model.length).to.be(0);
  167. });
  168. it('should wait for next add if requested', () => {
  169. let model = new OutputAreaModel();
  170. model.add(DEFAULT_OUTPUTS[0]);
  171. model.clear(true);
  172. expect(model.length).to.be(1);
  173. model.add(DEFAULT_OUTPUTS[1]);
  174. expect(model.length).to.be(1);
  175. });
  176. });
  177. describe('#execute()', () => {
  178. it('should execute code on a kernel and send outputs to the model', (done) => {
  179. let kernel = new MockKernel();
  180. let model = new OutputAreaModel();
  181. expect(model.length).to.be(0);
  182. model.execute('foo', kernel).then(reply => {
  183. expect(reply.content.execution_count).to.be(1);
  184. expect(reply.content.status).to.be('ok');
  185. expect(model.length).to.be(1);
  186. done();
  187. });
  188. });
  189. it('should clear existing outputs', (done) => {
  190. let kernel = new MockKernel();
  191. let model = new OutputAreaModel();
  192. for (let output of DEFAULT_OUTPUTS) {
  193. model.add(output);
  194. }
  195. model.execute('foo', kernel).then(reply => {
  196. expect(reply.content.execution_count).to.be(1);
  197. expect(model.length).to.be(1);
  198. done();
  199. });
  200. });
  201. });
  202. });
  203. });