modeldb.spec.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import {
  4. ModelDB,
  5. ObservableJSON,
  6. ObservableString,
  7. ObservableUndoableList,
  8. ObservableValue
  9. } from '@jupyterlab/observables';
  10. import { JSONExt } from '@lumino/coreutils';
  11. describe('@jupyterlab/observables', () => {
  12. describe('ObservableValue', () => {
  13. describe('#constructor', () => {
  14. it('should accept no arguments', () => {
  15. const value = new ObservableValue();
  16. expect(value instanceof ObservableValue).toBe(true);
  17. expect(value.get()).toBeNull();
  18. });
  19. it('should accept an initial JSON value', () => {
  20. const value = new ObservableValue('value');
  21. expect(value instanceof ObservableValue).toBe(true);
  22. const value2 = new ObservableValue({ one: 'one', two: 2 });
  23. expect(value2 instanceof ObservableValue).toBe(true);
  24. });
  25. });
  26. describe('#type', () => {
  27. it('should return `Value`', () => {
  28. const value = new ObservableValue();
  29. expect(value.type).toBe('Value');
  30. });
  31. });
  32. describe('#isDisposed', () => {
  33. it('should test whether the value is disposed', () => {
  34. const value = new ObservableValue();
  35. expect(value.isDisposed).toBe(false);
  36. value.dispose();
  37. expect(value.isDisposed).toBe(true);
  38. });
  39. });
  40. describe('#changed', () => {
  41. it('should be emitted when the map changes state', () => {
  42. let called = false;
  43. const value = new ObservableValue();
  44. value.changed.connect(() => {
  45. called = true;
  46. });
  47. value.set('set');
  48. expect(called).toBe(true);
  49. });
  50. it('should have value changed args', () => {
  51. let called = false;
  52. const value = new ObservableValue();
  53. value.changed.connect((sender, args) => {
  54. expect(sender).toBe(value);
  55. expect(args.newValue).toBe('set');
  56. expect(args.oldValue).toBeNull();
  57. called = true;
  58. });
  59. value.set('set');
  60. expect(called).toBe(true);
  61. });
  62. });
  63. describe('#get', () => {
  64. it('should get the value of the object', () => {
  65. const value = new ObservableValue('value');
  66. expect(value.get()).toBe('value');
  67. const value2 = new ObservableValue({ one: 'one', two: 2 });
  68. expect(JSONExt.deepEqual(value2.get(), { one: 'one', two: 2 })).toBe(
  69. true
  70. );
  71. });
  72. });
  73. describe('#set', () => {
  74. it('should set the value of the object', () => {
  75. const value = new ObservableValue();
  76. value.set('value');
  77. expect(value.get()).toBe('value');
  78. });
  79. });
  80. });
  81. describe('ModelDB', () => {
  82. describe('#constructor()', () => {
  83. it('should accept no arguments', () => {
  84. const db = new ModelDB();
  85. expect(db instanceof ModelDB).toBe(true);
  86. });
  87. it('should accept a basePath', () => {
  88. const db = new ModelDB({ basePath: 'base' });
  89. expect(db instanceof ModelDB).toBe(true);
  90. });
  91. it('should accept a baseDB', () => {
  92. const base = new ModelDB();
  93. const db = new ModelDB({ baseDB: base });
  94. expect(db instanceof ModelDB).toBe(true);
  95. });
  96. });
  97. describe('#isDisposed', () => {
  98. it('should test whether it is disposed', () => {
  99. const db = new ModelDB();
  100. expect(db.isDisposed).toBe(false);
  101. db.dispose();
  102. expect(db.isDisposed).toBe(true);
  103. });
  104. });
  105. describe('#basePath', () => {
  106. it('should return an empty string for a model without a baseDB', () => {
  107. const db = new ModelDB();
  108. expect(db.basePath).toBe('');
  109. });
  110. it('should return the base path', () => {
  111. const db = new ModelDB({ basePath: 'base' });
  112. expect(db.basePath).toBe('base');
  113. });
  114. });
  115. describe('#isPrepopulated', () => {
  116. it('should return false for an in-memory database', () => {
  117. const db = new ModelDB();
  118. expect(db.isPrepopulated).toBe(false);
  119. });
  120. });
  121. describe('#isCollaborative', () => {
  122. it('should return false for an in-memory database', () => {
  123. const db = new ModelDB();
  124. expect(db.isCollaborative).toBe(false);
  125. });
  126. });
  127. describe('#connected', () => {
  128. it('should resolve immediately for an in-memory database', () => {
  129. const db = new ModelDB();
  130. return db.connected;
  131. });
  132. });
  133. describe('#get', () => {
  134. it('should get a value that exists at a path', () => {
  135. const db = new ModelDB();
  136. const value = db.createValue('value');
  137. const value2 = db.get('value');
  138. expect(value2).toBe(value);
  139. });
  140. it('should return undefined for a value that does not exist', () => {
  141. const db = new ModelDB();
  142. expect(db.get('value')).toBeUndefined();
  143. });
  144. });
  145. describe('#has', () => {
  146. it('should return true if a value exists at a path', () => {
  147. const db = new ModelDB();
  148. db.createValue('value');
  149. expect(db.has('value')).toBe(true);
  150. });
  151. it('should return false for a value that does not exist', () => {
  152. const db = new ModelDB();
  153. expect(db.has('value')).toBe(false);
  154. });
  155. });
  156. describe('#createString', () => {
  157. it('should create an ObservableString`', () => {
  158. const db = new ModelDB();
  159. const str = db.createString('str');
  160. expect(str instanceof ObservableString).toBe(true);
  161. });
  162. it('should be able to retrieve that string using `get`', () => {
  163. const db = new ModelDB();
  164. const str = db.createString('str');
  165. expect(db.get('str')).toBe(str);
  166. });
  167. });
  168. describe('#createList', () => {
  169. it('should create an ObservableUndoableList`', () => {
  170. const db = new ModelDB();
  171. const str = db.createList('vec');
  172. expect(str instanceof ObservableUndoableList).toBe(true);
  173. });
  174. it('should be able to retrieve that vector using `get`', () => {
  175. const db = new ModelDB();
  176. const vec = db.createList('vec');
  177. expect(db.get('vec')).toBe(vec);
  178. });
  179. });
  180. describe('#createMap', () => {
  181. it('should create an ObservableMap`', () => {
  182. const db = new ModelDB();
  183. const map = db.createMap('map');
  184. expect(map instanceof ObservableJSON).toBe(true);
  185. });
  186. it('should be able to retrieve that map using `get`', () => {
  187. const db = new ModelDB();
  188. const map = db.createMap('map');
  189. expect(db.get('map')).toBe(map);
  190. });
  191. });
  192. describe('#createValue', () => {
  193. it('should create an ObservableValue`', () => {
  194. const db = new ModelDB();
  195. const value = db.createValue('value');
  196. expect(value instanceof ObservableValue).toBe(true);
  197. });
  198. it('should be able to retrieve that value using `get`', () => {
  199. const db = new ModelDB();
  200. const value = db.createString('value');
  201. expect(db.get('value')).toBe(value);
  202. });
  203. });
  204. describe('#setValue', () => {
  205. it('should set a value at a path', () => {
  206. const db = new ModelDB();
  207. const value = db.createValue('value');
  208. db.setValue('value', 'set');
  209. expect(value.get()).toBe('set');
  210. });
  211. });
  212. describe('#getValue', () => {
  213. it('should get a value at a path', () => {
  214. const db = new ModelDB();
  215. const value = db.createValue('value');
  216. value.set('set');
  217. expect(db.getValue('value')).toBe('set');
  218. });
  219. });
  220. describe('#view', () => {
  221. it('should should return a ModelDB', () => {
  222. const db = new ModelDB();
  223. const view = db.view('');
  224. expect(view instanceof ModelDB).toBe(true);
  225. expect(view === db).toBe(false);
  226. });
  227. it('should set the baseDB path on the view', () => {
  228. const db = new ModelDB();
  229. const view = db.view('base');
  230. expect(view.basePath).toBe('base');
  231. });
  232. it('should return a view onto the base ModelDB', () => {
  233. const db = new ModelDB();
  234. const view = db.view('base');
  235. db.createString('base.str1');
  236. expect(db.get('base.str1')).toBe(view.get('str1'));
  237. view.createString('str2');
  238. expect(db.get('base.str2')).toBe(view.get('str2'));
  239. });
  240. it('should be stackable', () => {
  241. const db = new ModelDB();
  242. const view = db.view('one');
  243. const viewView = view.view('two');
  244. expect(view.basePath).toBe('one');
  245. expect(viewView.basePath).toBe('two');
  246. viewView.createString('str');
  247. expect(viewView.get('str')).toBe(view.get('two.str'));
  248. expect(viewView.get('str')).toBe(db.get('one.two.str'));
  249. });
  250. });
  251. describe('#dispose', () => {
  252. it('should dispose of the resources used by the model', () => {
  253. const db = new ModelDB();
  254. const str = db.createString('str');
  255. const view = db.view('base');
  256. const str2 = view.createString('str');
  257. expect(db.isDisposed).toBe(false);
  258. expect(str.isDisposed).toBe(false);
  259. expect(view.isDisposed).toBe(false);
  260. expect(str2.isDisposed).toBe(false);
  261. db.dispose();
  262. expect(db.isDisposed).toBe(true);
  263. expect(str.isDisposed).toBe(true);
  264. expect(view.isDisposed).toBe(true);
  265. expect(str2.isDisposed).toBe(true);
  266. });
  267. it('should not dispose of resources in base databases', () => {
  268. const db = new ModelDB();
  269. const view = db.view('base');
  270. const str = db.createString('str');
  271. const str2 = view.createString('str');
  272. expect(db.isDisposed).toBe(false);
  273. expect(str.isDisposed).toBe(false);
  274. expect(view.isDisposed).toBe(false);
  275. expect(str2.isDisposed).toBe(false);
  276. view.dispose();
  277. expect(view.isDisposed).toBe(true);
  278. expect(str2.isDisposed).toBe(true);
  279. expect(db.isDisposed).toBe(false);
  280. expect(str.isDisposed).toBe(false);
  281. });
  282. it('should be safe to call more than once', () => {
  283. const db = new ModelDB();
  284. expect(db.isDisposed).toBe(false);
  285. db.dispose();
  286. expect(db.isDisposed).toBe(true);
  287. });
  288. });
  289. });
  290. });