filehandler.spec.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. 'use strict';
  4. import expect = require('expect.js');
  5. import {
  6. IContentsModel, IContentsManager, IContentsOpts, ICheckpointModel,
  7. IAjaxSettings, ContentsManager
  8. } from 'jupyter-js-services';
  9. import {
  10. sendMessage
  11. } from 'phosphor-messaging';
  12. import {
  13. Widget
  14. } from 'phosphor-widget';
  15. import {
  16. AbstractFileHandler
  17. } from '../../../lib/filehandler/handler';
  18. import {
  19. MockContentsManager
  20. } from '../mock';
  21. import {
  22. acceptDialog
  23. } from '../utils';
  24. class FileHandler extends AbstractFileHandler<Widget> {
  25. methods: string[] = [];
  26. protected getSaveOptions(widget: Widget, path: string): Promise<IContentsOpts> {
  27. this.methods.push('getSaveOptions');
  28. return Promise.resolve({ path, content: 'baz', name,
  29. type: 'file', format: 'text' });
  30. }
  31. protected createWidget(path: string): Widget {
  32. this.methods.push('createWidget');
  33. return new Widget();
  34. }
  35. protected populateWidget(widget: Widget, model: IContentsModel): Promise<IContentsModel> {
  36. this.methods.push('populateWidget');
  37. return Promise.resolve(model);
  38. }
  39. protected getFetchOptions(path: string): IContentsOpts {
  40. this.methods.push('getFetchOptions');
  41. return super.getFetchOptions(path);
  42. }
  43. protected getTitleText(path: string): string {
  44. this.methods.push('getTitleText');
  45. return super.getTitleText(path);
  46. }
  47. protected beforeClose(widget: Widget): Promise<void> {
  48. this.methods.push('beforeClose');
  49. return super.beforeClose(widget);
  50. }
  51. }
  52. describe('jupyter-ui', () => {
  53. describe('AbstractFileHandler', () => {
  54. describe('#constructor()', () => {
  55. it('should accept a contents manager', () => {
  56. let manager = new MockContentsManager();
  57. let handler = new FileHandler(manager);
  58. expect(handler instanceof AbstractFileHandler).to.be(true);
  59. });
  60. });
  61. describe('#opened', () => {
  62. it('should be emitted when an item is opened', () => {
  63. let manager = new MockContentsManager();
  64. let handler = new FileHandler(manager);
  65. let called = false;
  66. handler.opened.connect((h, widget) => {
  67. expect(widget instanceof Widget).to.be(true);
  68. called = true;
  69. });
  70. handler.open('foo.txt');
  71. expect(called).to.be(true);
  72. });
  73. });
  74. describe('#finished', () => {
  75. it('should be emitted when a widget is populated', (done) => {
  76. let manager = new MockContentsManager();
  77. let handler = new FileHandler(manager);
  78. handler.finished.connect((h, widget) => {
  79. expect(widget instanceof Widget).to.be(true);
  80. done();
  81. });
  82. handler.open('foo.txt');
  83. });
  84. });
  85. describe('#fileExtensions', () => {
  86. it('should be an empty list by default', () => {
  87. let manager = new MockContentsManager();
  88. let handler = new FileHandler(manager);
  89. expect(handler.fileExtensions).to.eql([]);
  90. });
  91. it('should be read only', () => {
  92. let manager = new MockContentsManager();
  93. let handler = new FileHandler(manager);
  94. expect(() => { handler.fileExtensions = []; }).to.throwError();
  95. });
  96. });
  97. describe('#findWidget()', () => {
  98. it('should find a widget given a path', () => {
  99. let manager = new MockContentsManager();
  100. let handler = new FileHandler(manager);
  101. let widget = handler.open('foo.txt');
  102. expect(handler.findWidget('foo.txt')).to.be(widget);
  103. });
  104. it('should return `undefined` if the path is invalid', () => {
  105. let manager = new MockContentsManager();
  106. let handler = new FileHandler(manager);
  107. let widget = handler.open('foo.txt');
  108. expect(handler.findWidget('bar.txt')).to.be(void 0);
  109. });
  110. });
  111. describe('#findPath()', () => {
  112. it('should find a path given a widget', () => {
  113. let manager = new MockContentsManager();
  114. let handler = new FileHandler(manager);
  115. let widget = handler.open('foo.txt');
  116. expect(handler.findPath(widget)).to.be('foo.txt');
  117. });
  118. it('should return `undefined` if the widget is invalid', (done) => {
  119. let manager = new MockContentsManager();
  120. let handler = new FileHandler(manager);
  121. let widget = handler.open('foo.txt');
  122. handler.close('foo.txt').then(() => {
  123. expect(handler.findPath(widget)).to.be(void 0);
  124. done();
  125. });
  126. });
  127. });
  128. describe('#open()', () => {
  129. it('should open a file by path and return a widget', () => {
  130. let manager = new MockContentsManager();
  131. let handler = new FileHandler(manager);
  132. let widget = handler.open('foo.txt');
  133. expect(widget instanceof Widget).to.be(true);
  134. });
  135. it('should return an existing widget if it is already open', () => {
  136. let manager = new MockContentsManager();
  137. let handler = new FileHandler(manager);
  138. let widget = handler.open('foo.txt');
  139. expect(handler.open('foo.txt')).to.be(widget);
  140. });
  141. it('should clear the dirty state when finished', (done) => {
  142. let manager = new MockContentsManager();
  143. let handler = new FileHandler(manager);
  144. let widget = handler.open('foo.txt');
  145. handler.finished.connect(() => {
  146. expect(handler.isDirty('foo.txt')).to.be(false);
  147. done();
  148. });
  149. });
  150. it('should set the title', () => {
  151. let manager = new MockContentsManager();
  152. let handler = new FileHandler(manager);
  153. let widget = handler.open('foo.txt');
  154. expect(widget.title.text).to.be('foo.txt');
  155. });
  156. });
  157. describe('#rename()', () => {
  158. it('should rename the file', () => {
  159. let manager = new MockContentsManager();
  160. let handler = new FileHandler(manager);
  161. let widget = handler.open('foo.txt');
  162. handler.rename('foo.txt', 'bar.txt');
  163. expect(handler.findWidget('bar.txt')).to.be(widget);
  164. });
  165. it('should update the title', () => {
  166. let manager = new MockContentsManager();
  167. let handler = new FileHandler(manager);
  168. let widget = handler.open('foo.txt');
  169. handler.rename('foo.txt', 'bar.txt');
  170. expect(widget.title.text).to.be('bar.txt');
  171. });
  172. });
  173. describe('#save()', () => {
  174. it('should resolve to the file contents', (done) => {
  175. let manager = new MockContentsManager();
  176. let handler = new FileHandler(manager);
  177. let widget = handler.open('foo.txt');
  178. handler.save('foo.txt').then(contents => {
  179. expect(contents.content).to.be('baz');
  180. done();
  181. });
  182. });
  183. it('should clear the dirty flag', (done) => {
  184. let manager = new MockContentsManager();
  185. let handler = new FileHandler(manager);
  186. let widget = handler.open('foo.txt');
  187. handler.setDirty('foo.txt', true);
  188. handler.save('foo.txt').then(contents => {
  189. expect(handler.isDirty('foo.txt')).to.be(false);
  190. done();
  191. });
  192. });
  193. });
  194. describe('#revert()', () => {
  195. it('should resolve to the original file contents', (done) => {
  196. let manager = new MockContentsManager();
  197. let handler = new FileHandler(manager);
  198. let widget = handler.open('foo.txt');
  199. handler.revert('foo.txt').then(contents => {
  200. expect(contents.content).to.be(manager.DEFAULT_TEXT);
  201. done();
  202. });
  203. });
  204. it('should clear the dirty flag', (done) => {
  205. let manager = new MockContentsManager();
  206. let handler = new FileHandler(manager);
  207. let widget = handler.open('foo.txt');
  208. handler.setDirty('foo.txt', true);
  209. handler.revert('foo.txt').then(contents => {
  210. expect(handler.isDirty('foo.txt')).to.be(false);
  211. done();
  212. });
  213. });
  214. });
  215. describe('#close()', () => {
  216. it('should close a file by path', (done) => {
  217. let manager = new MockContentsManager();
  218. let handler = new FileHandler(manager);
  219. let widget = handler.open('foo.txt');
  220. widget.attach(document.body);
  221. handler.close('foo.txt').then(result => {
  222. expect(result).to.be(true);
  223. expect(widget.isAttached).to.be(false);
  224. done();
  225. });
  226. });
  227. it('should return false if the path is invalid', (done) => {
  228. let manager = new MockContentsManager();
  229. let handler = new FileHandler(manager);
  230. handler.close('foo.txt').then(result => {
  231. expect(result).to.be(false);
  232. done();
  233. });
  234. });
  235. it('should prompt the user if the file is dirty', (done) => {
  236. let manager = new MockContentsManager();
  237. let handler = new FileHandler(manager);
  238. handler.open('foo.txt');
  239. handler.setDirty('foo.txt', true);
  240. handler.close('foo.txt').then(result => {
  241. expect(result).to.be(true);
  242. done();
  243. });
  244. acceptDialog();
  245. });
  246. });
  247. describe('#closeAll()', () => {
  248. it('should class all files', (done) => {
  249. let manager = new MockContentsManager();
  250. let handler = new FileHandler(manager);
  251. let widget0 = handler.open('foo.txt');
  252. let widget1 = handler.open('bar.txt');
  253. widget0.attach(document.body);
  254. handler.closeAll().then(() => {
  255. expect(widget0.isAttached).to.be(false);
  256. expect(handler.findWidget('bar.txt')).to.be(void 0);
  257. done();
  258. });
  259. });
  260. });
  261. describe('#isDirty()', () => {
  262. it('should default to false', () => {
  263. let manager = new MockContentsManager();
  264. let handler = new FileHandler(manager);
  265. let widget0 = handler.open('foo.txt');
  266. expect(handler.isDirty('foo.txt')).to.be(false);
  267. });
  268. it('should return `undefined` if the path is invalid', () => {
  269. let manager = new MockContentsManager();
  270. let handler = new FileHandler(manager);
  271. let widget0 = handler.open('foo.txt');
  272. expect(handler.isDirty('bar.txt')).to.be(void 0);
  273. });
  274. });
  275. describe('#setDirty()', () => {
  276. it('should set the dirty state of a file', () => {
  277. let manager = new MockContentsManager();
  278. let handler = new FileHandler(manager);
  279. let widget0 = handler.open('foo.txt');
  280. handler.setDirty('foo.txt', true);
  281. expect(handler.isDirty('foo.txt')).to.be(true);
  282. handler.setDirty('foo.txt', false);
  283. expect(handler.isDirty('foo.txt')).to.be(false);
  284. });
  285. it('should affect the className of the title', () => {
  286. let manager = new MockContentsManager();
  287. let handler = new FileHandler(manager);
  288. let widget = handler.open('foo.txt');
  289. expect(widget.title.className.indexOf('jp-mod-dirty')).to.be(-1);
  290. handler.setDirty('foo.txt', true);
  291. expect(widget.title.className.indexOf('jp-mod-dirty')).to.not.be(-1);
  292. });
  293. it('should be a no-op for an invalid path', () => {
  294. let manager = new MockContentsManager();
  295. let handler = new FileHandler(manager);
  296. let widget0 = handler.open('foo.txt');
  297. handler.setDirty('bar.txt', true);
  298. });
  299. });
  300. describe('#filterMessage()', () => {
  301. it('should filter close messages for contained widgets', () => {
  302. let manager = new MockContentsManager();
  303. let handler = new FileHandler(manager);
  304. let widget = handler.open('foo.txt');
  305. let value = handler.filterMessage(widget, Widget.MsgCloseRequest);
  306. expect(value).to.be(true);
  307. value = handler.filterMessage(widget, Widget.MsgUpdateRequest);
  308. expect(value).to.be(false);
  309. });
  310. });
  311. describe('#getFetchOptions()', () => {
  312. it('should get the options use to fetch contents from disk', () => {
  313. let manager = new MockContentsManager();
  314. let handler = new FileHandler(manager);
  315. let widget0 = handler.open('foo.txt');
  316. expect(handler.methods.indexOf('getFetchOptions')).to.not.be(-1);
  317. });
  318. it('should be called during a revert', () => {
  319. let manager = new MockContentsManager();
  320. let handler = new FileHandler(manager);
  321. let widget0 = handler.open('foo.txt');
  322. handler.methods = [];
  323. handler.revert('foo.txt');
  324. expect(handler.methods.indexOf('getFetchOptions')).to.not.be(-1);
  325. });
  326. });
  327. describe('#getSaveOptions()', () => {
  328. it('should get the options used to save the widget', () => {
  329. let manager = new MockContentsManager();
  330. let handler = new FileHandler(manager);
  331. let widget0 = handler.open('foo.txt');
  332. handler.save('foo.txt');
  333. expect(handler.methods.indexOf('getSaveOptions')).to.not.be(-1);
  334. });
  335. });
  336. describe('#createWidget()', () => {
  337. it('should be used to create the initial widget given a path', () => {
  338. let manager = new MockContentsManager();
  339. let handler = new FileHandler(manager);
  340. let widget0 = handler.open('foo.txt');
  341. expect(handler.methods.indexOf('createWidget')).to.not.be(-1);
  342. });
  343. });
  344. describe('#populateWidget()', () => {
  345. it('should be called to populate a widget while opening', (done) => {
  346. let manager = new MockContentsManager();
  347. let handler = new FileHandler(manager);
  348. let widget0 = handler.open('foo.txt');
  349. handler.finished.connect(() => {
  350. expect(handler.methods.indexOf('populateWidget')).to.not.be(-1);
  351. done();
  352. });
  353. });
  354. it('should be called when reverting', (done) => {
  355. let manager = new MockContentsManager();
  356. let handler = new FileHandler(manager);
  357. let widget0 = handler.open('foo.txt');
  358. let called = false;
  359. handler.finished.connect(() => {
  360. handler.methods = [];
  361. handler.revert('foo.txt').then(() => {
  362. expect(handler.methods.indexOf('populateWidget')).to.not.be(-1);
  363. done();
  364. });
  365. });
  366. });
  367. });
  368. describe('#getTitleText()', () => {
  369. it('should set the appropriate title text based on a path', () => {
  370. let manager = new MockContentsManager();
  371. let handler = new FileHandler(manager);
  372. let widget0 = handler.open('foo.txt');
  373. expect(handler.methods.indexOf('getTitleText')).to.not.be(-1);
  374. });
  375. it('should be called when renaming', () => {
  376. let manager = new MockContentsManager();
  377. let handler = new FileHandler(manager);
  378. let widget0 = handler.open('foo.txt');
  379. handler.methods = [];
  380. handler.rename('foo.txt', 'bar.txt');
  381. expect(handler.methods.indexOf('getTitleText')).to.not.be(-1);
  382. });
  383. });
  384. describe('#beforeClose()', () => {
  385. it('should call before closing', (done) => {
  386. let manager = new MockContentsManager();
  387. let handler = new FileHandler(manager);
  388. let widget = handler.open('foo.txt');
  389. widget.attach(document.body);
  390. handler.close('foo.txt').then(result => {
  391. expect(result).to.be(true);
  392. expect(handler.methods.indexOf('beforeClose')).to.not.be(-1);
  393. done();
  394. });
  395. });
  396. });
  397. });
  398. });