mock.spec.ts 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import 'jest';
  4. import * as Mock from '../src/mock';
  5. import { KernelMessage } from '@jupyterlab/services';
  6. import { toArray } from '@lumino/algorithm';
  7. describe('mock', () => {
  8. describe('createSimpleSessionContext()', () => {
  9. it('should create a session context', () => {
  10. const context = Mock.createSimpleSessionContext();
  11. expect(context.session!.kernel!.name).toEqual(Mock.DEFAULT_NAME);
  12. });
  13. it('should accept a session model', () => {
  14. const context = Mock.createSimpleSessionContext({
  15. name: 'hi',
  16. path: 'foo',
  17. type: 'bar',
  18. kernel: { name: 'fizz' }
  19. });
  20. expect(context.name).toEqual('hi');
  21. expect(context.path).toEqual('foo');
  22. expect(context.type).toEqual('bar');
  23. expect(context.session!.kernel!.name).toEqual('fizz');
  24. });
  25. });
  26. describe('updateKernelStatus()', () => {
  27. it('should update the kernel status', () => {
  28. const context = Mock.createSimpleSessionContext();
  29. let called = false;
  30. context.statusChanged.connect((_, status) => {
  31. if (status === 'dead') {
  32. called = true;
  33. }
  34. });
  35. Mock.updateKernelStatus(context, 'dead');
  36. expect(context.session!.kernel!.status).toEqual('dead');
  37. expect(called).toEqual(true);
  38. });
  39. });
  40. describe('emitIopubMessage', () => {
  41. it('should emit an iopub message', () => {
  42. const context = Mock.createSimpleSessionContext();
  43. const source = KernelMessage.createMessage({
  44. channel: 'iopub',
  45. msgType: 'execute_input',
  46. session: 'foo',
  47. username: 'bar',
  48. msgId: 'fizz',
  49. content: {
  50. code: 'hello, world!',
  51. execution_count: 0
  52. }
  53. });
  54. let called = false;
  55. context.iopubMessage.connect((_, msg) => {
  56. expect(msg).toBe(source);
  57. called = true;
  58. });
  59. Mock.emitIopubMessage(context, source);
  60. expect(called).toBe(true);
  61. });
  62. });
  63. describe('cloneKernel()', () => {
  64. it('should clone a kernel', () => {
  65. const kernel0 = new Mock.KernelMock({});
  66. const kernel1 = Mock.cloneKernel(kernel0);
  67. expect(kernel0.id).toBe(kernel1.id);
  68. expect(kernel0.clientId).not.toBe(kernel1.clientId);
  69. });
  70. });
  71. describe('KernelMock', () => {
  72. describe('.constructor()', () => {
  73. it('should create a mock kernel', () => {
  74. const kernel = new Mock.KernelMock({});
  75. expect(kernel.name).toBe(Mock.DEFAULT_NAME);
  76. });
  77. it('should take options', () => {
  78. const kernel = new Mock.KernelMock({ model: { name: 'foo' } });
  79. expect(kernel.name).toBe('foo');
  80. });
  81. });
  82. describe('.spec()', () => {
  83. it('should resolve with a kernel spec', async () => {
  84. const kernel = new Mock.KernelMock({});
  85. const spec = await kernel.spec;
  86. expect(spec!.name).toBe(Mock.DEFAULT_NAME);
  87. });
  88. });
  89. describe('.dispose()', () => {
  90. it('should be a no-op', () => {
  91. const kernel = new Mock.KernelMock({});
  92. kernel.dispose();
  93. });
  94. });
  95. describe('.clone()', () => {
  96. it('should clone the kernel', () => {
  97. const kernel0 = new Mock.KernelMock({});
  98. const kernel1 = kernel0.clone();
  99. expect(kernel0.id).toBe(kernel1.id);
  100. expect(kernel0.clientId).not.toBe(kernel1.clientId);
  101. });
  102. });
  103. describe('.info', () => {
  104. it('should resolve with undefined', async () => {
  105. const kernel = new Mock.KernelMock({});
  106. const info = await kernel.info;
  107. expect(info).toBeUndefined();
  108. });
  109. });
  110. describe('.shutdown()', () => {
  111. it('should be a no-op', async () => {
  112. const kernel = new Mock.KernelMock({});
  113. await kernel.shutdown();
  114. });
  115. });
  116. describe('.requestHistory()', () => {
  117. it('should get the history info', async () => {
  118. const kernel = new Mock.KernelMock({});
  119. const reply = await kernel.requestHistory({} as any);
  120. expect(reply.content.status).toBe('ok');
  121. });
  122. });
  123. describe('.restart()', () => {
  124. it('should be a no-op', async () => {
  125. const kernel = new Mock.KernelMock({});
  126. await kernel.restart();
  127. });
  128. });
  129. describe('.requestExecute()', () => {
  130. it('should request execution', async () => {
  131. const kernel = new Mock.KernelMock({});
  132. let called = false;
  133. kernel.iopubMessage.connect((_, msg) => {
  134. if (msg.header.msg_type === 'execute_input') {
  135. called = true;
  136. }
  137. });
  138. const future = kernel.requestExecute({ code: 'foo ' });
  139. await future.done;
  140. expect(called).toBe(true);
  141. });
  142. });
  143. });
  144. describe('SessionConnectionMock', () => {
  145. describe('.constructor()', () => {
  146. it('should create a new SessionConnectionMock', () => {
  147. const session = new Mock.SessionConnectionMock({}, null);
  148. expect(session.kernel!.name).toBe(Mock.DEFAULT_NAME);
  149. });
  150. it('should take options', () => {
  151. const kernel = new Mock.KernelMock({});
  152. const session = new Mock.SessionConnectionMock(
  153. { model: { name: 'foo' } },
  154. kernel
  155. );
  156. expect(session.kernel).toBe(kernel);
  157. expect(session.name).toBe('foo');
  158. });
  159. });
  160. describe('.dispose()', () => {
  161. it('should be a no-op', () => {
  162. const session = new Mock.SessionConnectionMock({}, null);
  163. session.dispose();
  164. });
  165. });
  166. describe('.changeKernel()', () => {
  167. it('should change the kernel', async () => {
  168. const session = new Mock.SessionConnectionMock({}, null);
  169. const oldId = session.kernel!.id;
  170. const kernel = await session.changeKernel({ name: Mock.DEFAULT_NAME });
  171. expect(kernel!.id).not.toBe(oldId);
  172. });
  173. });
  174. describe('.shutdown()', () => {
  175. it('should be a no-op', async () => {
  176. const session = new Mock.SessionConnectionMock({}, null);
  177. await session.shutdown();
  178. });
  179. });
  180. describe('.setPath()', () => {
  181. it('should set the path', async () => {
  182. const session = new Mock.SessionConnectionMock({}, null);
  183. let called = false;
  184. session.propertyChanged.connect((_, args) => {
  185. if (args === 'path') {
  186. called = true;
  187. }
  188. });
  189. await session.setPath('foo');
  190. expect(session.path).toBe('foo');
  191. expect(called).toBe(true);
  192. });
  193. });
  194. describe('.setType()', () => {
  195. it('should set the type', async () => {
  196. const session = new Mock.SessionConnectionMock({}, null);
  197. let called = false;
  198. session.propertyChanged.connect((_, args) => {
  199. if (args === 'type') {
  200. called = true;
  201. }
  202. });
  203. await session.setType('foo');
  204. expect(session.type).toBe('foo');
  205. expect(called).toBe(true);
  206. });
  207. });
  208. describe('.setName()', () => {
  209. it('should set the name', async () => {
  210. const session = new Mock.SessionConnectionMock({}, null);
  211. let called = false;
  212. session.propertyChanged.connect((_, args) => {
  213. if (args === 'name') {
  214. called = true;
  215. }
  216. });
  217. await session.setName('foo');
  218. expect(session.name).toBe('foo');
  219. expect(called).toBe(true);
  220. });
  221. });
  222. });
  223. describe('SessionContextMock', () => {
  224. describe('.constructor()', () => {
  225. it('should create a new context', () => {
  226. const context = new Mock.SessionContextMock({}, null);
  227. expect(context.session!.kernel!.name).toBe(Mock.DEFAULT_NAME);
  228. });
  229. it('should accept options', () => {
  230. const session = new Mock.SessionConnectionMock({}, null);
  231. const context = new Mock.SessionContextMock({ path: 'foo' }, session);
  232. expect(context.session).toBe(session);
  233. expect(context.path).toBe('foo');
  234. });
  235. });
  236. describe('.dispose()', () => {
  237. it('should be a no-op', () => {
  238. const context = new Mock.SessionContextMock({}, null);
  239. context.dispose();
  240. });
  241. });
  242. describe('.initialize()', () => {
  243. it('should be a no-op', async () => {
  244. const context = new Mock.SessionContextMock({}, null);
  245. await context.initialize();
  246. });
  247. });
  248. describe('.ready', () => {
  249. it('should be a no-op', async () => {
  250. const context = new Mock.SessionContextMock({}, null);
  251. await context.ready;
  252. });
  253. });
  254. describe('.changeKernel()', () => {
  255. it('should change the kernel', async () => {
  256. const context = new Mock.SessionContextMock({}, null);
  257. const oldId = context.session!.kernel!.id;
  258. const kernel = await context.changeKernel({ name: Mock.DEFAULT_NAME });
  259. expect(kernel!.id).not.toBe(oldId);
  260. });
  261. });
  262. describe('.shutdown()', () => {
  263. it('should be a no-op', async () => {
  264. const context = new Mock.SessionContextMock({}, null);
  265. await context.shutdown();
  266. });
  267. });
  268. });
  269. describe('ContentsManagerMock', () => {
  270. describe('.constructor()', () => {
  271. it('should create a new mock', () => {
  272. const manager = new Mock.ContentsManagerMock();
  273. expect(manager.localPath('foo')).toBe('foo');
  274. });
  275. });
  276. describe('.newUntitled', () => {
  277. it('should create a new text file', async () => {
  278. const manager = new Mock.ContentsManagerMock();
  279. let called = false;
  280. manager.fileChanged.connect((_, args) => {
  281. if (args.type === 'new') {
  282. called = true;
  283. }
  284. });
  285. const contents = await manager.newUntitled();
  286. expect(contents.type).toBe('file');
  287. expect(called).toBe(true);
  288. });
  289. it('should create a new notebook', async () => {
  290. const manager = new Mock.ContentsManagerMock();
  291. const contents = await manager.newUntitled({ type: 'notebook' });
  292. expect(contents.type).toBe('notebook');
  293. });
  294. });
  295. describe('.createCheckpoint()', () => {
  296. it('should create a checkpoint', async () => {
  297. const manager = new Mock.ContentsManagerMock();
  298. const content = await manager.newUntitled();
  299. const checkpoint = await manager.createCheckpoint(content.path);
  300. expect(checkpoint.id).toBeTruthy();
  301. });
  302. });
  303. describe('.listCheckpoints()', () => {
  304. it('should list the checkpoints', async () => {
  305. const manager = new Mock.ContentsManagerMock();
  306. const content = await manager.newUntitled();
  307. const checkpoint = await manager.createCheckpoint(content.path);
  308. const checkpoints = await manager.listCheckpoints(content.path);
  309. expect(checkpoints[0].id).toBe(checkpoint.id);
  310. });
  311. });
  312. describe('.deleteCheckpoint', () => {
  313. it('should delete a checkpoints', async () => {
  314. const manager = new Mock.ContentsManagerMock();
  315. const content = await manager.newUntitled();
  316. const checkpoint = await manager.createCheckpoint(content.path);
  317. await manager.deleteCheckpoint(content.path, checkpoint.id);
  318. const checkpoints = await manager.listCheckpoints(content.path);
  319. expect(checkpoints.length).toBe(0);
  320. });
  321. });
  322. describe('.restoreCheckpoint()', () => {
  323. it('should restore the contents', async () => {
  324. const manager = new Mock.ContentsManagerMock();
  325. const content = await manager.newUntitled();
  326. await manager.save(content.path, { content: 'foo' });
  327. const checkpoint = await manager.createCheckpoint(content.path);
  328. await manager.save(content.path, { content: 'bar' });
  329. await manager.restoreCheckpoint(content.path, checkpoint.id);
  330. const newContent = await manager.get(content.path);
  331. expect(newContent.content).toBe('foo');
  332. });
  333. });
  334. describe('.getModelDBFactory()', () => {
  335. it('should return null', () => {
  336. const manager = new Mock.ContentsManagerMock();
  337. expect(manager.getModelDBFactory('foo')).toBe(null);
  338. });
  339. });
  340. describe('.normalize()', () => {
  341. it('should normalize a path', () => {
  342. const manager = new Mock.ContentsManagerMock();
  343. expect(manager.normalize('foo/bar/../baz')).toBe('foo/baz');
  344. });
  345. });
  346. describe('.localPath', () => {
  347. it('should get the local path of a file', () => {
  348. const manager = new Mock.ContentsManagerMock();
  349. const defaultDrive = manager.driveName('foo');
  350. expect(manager.localPath(`${defaultDrive}foo/bar`)).toBe('foo/bar');
  351. });
  352. });
  353. describe('.get()', () => {
  354. it('should get the file contents', async () => {
  355. const manager = new Mock.ContentsManagerMock();
  356. const content = await manager.newUntitled();
  357. await manager.save(content.path, { content: 'foo' });
  358. const newContent = await manager.get(content.path);
  359. expect(newContent.content).toBe('foo');
  360. });
  361. });
  362. describe('.driveName()', () => {
  363. it('should get the drive name of the path', () => {
  364. const manager = new Mock.ContentsManagerMock();
  365. const defaultDrive = manager.driveName('foo');
  366. expect(manager.driveName(`${defaultDrive}/bar`)).toBe(defaultDrive);
  367. });
  368. });
  369. describe('.rename()', () => {
  370. it('should rename the file', async () => {
  371. const manager = new Mock.ContentsManagerMock();
  372. let called = false;
  373. manager.fileChanged.connect((_, args) => {
  374. if (args.type === 'rename') {
  375. expect(args.newValue!.path).toBe('foo');
  376. called = true;
  377. }
  378. });
  379. const contents = await manager.newUntitled();
  380. await manager.rename(contents.path, 'foo');
  381. expect(called).toBe(true);
  382. });
  383. });
  384. describe('.delete()', () => {
  385. it('should delete the file', async () => {
  386. const manager = new Mock.ContentsManagerMock();
  387. let called = false;
  388. manager.fileChanged.connect((_, args) => {
  389. if (args.type === 'delete') {
  390. expect(args.newValue).toBe(null);
  391. called = true;
  392. }
  393. });
  394. const contents = await manager.newUntitled();
  395. await manager.delete(contents.path);
  396. expect(called).toBe(true);
  397. });
  398. });
  399. describe('.save()', () => {
  400. it('should save the file', async () => {
  401. const manager = new Mock.ContentsManagerMock();
  402. let called = false;
  403. manager.fileChanged.connect((_, args) => {
  404. if (args.type === 'save') {
  405. expect(args.newValue!.content).toBe('bar');
  406. called = true;
  407. }
  408. });
  409. const contents = await manager.newUntitled();
  410. await manager.save(contents.path, { content: 'bar' });
  411. expect(called).toBe(true);
  412. });
  413. });
  414. describe('.dispose()', () => {
  415. it('should be a no-op', () => {
  416. const manager = new Mock.ContentsManagerMock();
  417. manager.dispose();
  418. });
  419. });
  420. });
  421. describe('SessionManagerMock', () => {
  422. describe('.constructor()', () => {
  423. it('should create a new session manager', () => {
  424. const manager = new Mock.SessionManagerMock();
  425. expect(manager.isReady).toBe(true);
  426. });
  427. });
  428. describe('.startNew()', () => {
  429. it('should start a new session', async () => {
  430. const manager = new Mock.SessionManagerMock();
  431. const session = await manager.startNew({
  432. path: 'foo',
  433. name: 'foo',
  434. type: 'bar',
  435. kernel: { name: Mock.DEFAULT_NAME }
  436. });
  437. expect(session.kernel!.name).toBe(Mock.DEFAULT_NAME);
  438. });
  439. });
  440. describe('.connectTo()', () => {
  441. it('should connect to a session', async () => {
  442. const manager = new Mock.SessionManagerMock();
  443. const session = await manager.connectTo({
  444. model: {
  445. id: 'fizz',
  446. path: 'foo',
  447. type: 'bar',
  448. name: 'baz',
  449. kernel: { name: Mock.DEFAULT_NAME, id: 'fuzz' }
  450. }
  451. });
  452. expect(session.kernel!.name).toBe(Mock.DEFAULT_NAME);
  453. });
  454. });
  455. describe('.stopIfNeeded()', () => {
  456. it('should remove a running kernel', async () => {
  457. const manager = new Mock.SessionManagerMock();
  458. const session = await manager.startNew({
  459. path: 'foo',
  460. name: 'foo',
  461. type: 'bar',
  462. kernel: { name: Mock.DEFAULT_NAME }
  463. });
  464. expect(toArray(manager.running()).length).toBe(1);
  465. await manager.stopIfNeeded(session.path);
  466. expect(toArray(manager.running()).length).toBe(0);
  467. });
  468. });
  469. describe('.refreshRunning()', () => {
  470. it('should be a no-op', async () => {
  471. const manager = new Mock.SessionManagerMock();
  472. await manager.refreshRunning();
  473. });
  474. });
  475. describe('.running()', () => {
  476. it('should be an iterable of running sessions', async () => {
  477. const manager = new Mock.SessionManagerMock();
  478. await manager.startNew({
  479. path: 'foo',
  480. name: 'foo',
  481. type: 'bar',
  482. kernel: { name: Mock.DEFAULT_NAME }
  483. });
  484. expect(toArray(manager.running()).length).toBe(1);
  485. });
  486. });
  487. });
  488. describe('KernelSpecManagerMock', () => {
  489. describe('.constructor', () => {
  490. it('should create a new mock', () => {
  491. const manager = new Mock.KernelSpecManagerMock();
  492. expect(manager.isReady).toBe(true);
  493. });
  494. });
  495. describe('.specs', () => {
  496. it('should be the kernel specs', () => {
  497. const manager = new Mock.KernelSpecManagerMock();
  498. expect(manager.specs!.default).toBe(Mock.DEFAULT_NAME);
  499. });
  500. });
  501. describe('.refreshSpecs()', () => {
  502. it('should be a no-op', async () => {
  503. const manager = new Mock.KernelSpecManagerMock();
  504. await manager.refreshSpecs();
  505. });
  506. });
  507. });
  508. describe('ServiceManagerMock', () => {
  509. describe('.constructor()', () => {
  510. it('should create a new mock', () => {
  511. const manager = new Mock.ServiceManagerMock();
  512. expect(manager.isReady).toBe(true);
  513. });
  514. });
  515. describe('.ready', () => {
  516. it('should resolve', async () => {
  517. const manager = new Mock.ServiceManagerMock();
  518. await manager.ready;
  519. });
  520. });
  521. describe('.contents', () => {
  522. it('should be a contents manager', () => {
  523. const manager = new Mock.ServiceManagerMock();
  524. expect(manager.contents.normalize).toBeTruthy();
  525. });
  526. });
  527. describe('.sessions', () => {
  528. it('should be a sessions manager', () => {
  529. const manager = new Mock.ServiceManagerMock();
  530. expect(manager.sessions.isReady).toBe(true);
  531. });
  532. });
  533. describe('.kernelspecs', () => {
  534. it('should be a kernelspecs manager', () => {
  535. const manager = new Mock.ServiceManagerMock();
  536. expect(manager.kernelspecs.isReady).toBe(true);
  537. });
  538. });
  539. describe('.dispose()', () => {
  540. it('should be a no-op', () => {
  541. const manager = new Mock.ServiceManagerMock();
  542. manager.dispose();
  543. });
  544. });
  545. });
  546. describe('MockShellFuture', () => {
  547. it('should create a new mock', async () => {
  548. const msg = KernelMessage.createMessage({
  549. channel: 'shell',
  550. msgType: 'execute_reply',
  551. session: 'foo',
  552. username: 'bar',
  553. msgId: 'fizz',
  554. content: {
  555. user_expressions: {},
  556. execution_count: 0,
  557. status: 'ok'
  558. }
  559. });
  560. const future = new Mock.MockShellFuture(msg);
  561. const reply = await future.done;
  562. expect(reply).toBe(msg);
  563. future.dispose();
  564. });
  565. });
  566. describe('createFileContext()', () => {
  567. it('should create a context without a kernel', async () => {
  568. const context = Mock.createFileContext();
  569. await context.initialize(true);
  570. await context.sessionContext.initialize();
  571. expect(context.sessionContext.session).toBe(null);
  572. });
  573. it('should create a context with a kernel', async () => {
  574. const context = Mock.createFileContext(true);
  575. await context.initialize(true);
  576. await context.sessionContext.initialize();
  577. expect(context.sessionContext.session!.kernel!.name).toBe(
  578. Mock.DEFAULT_NAME
  579. );
  580. });
  581. });
  582. });