statedb.spec.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import 'jest';
  4. import { StateDB } from '@jupyterlab/statedb';
  5. import { PromiseDelegate, ReadonlyJSONObject } from '@lumino/coreutils';
  6. describe('StateDB', () => {
  7. describe('#constructor()', () => {
  8. it('should create a state database', () => {
  9. const db = new StateDB();
  10. expect(db).toBeInstanceOf(StateDB);
  11. });
  12. it('should allow an overwrite data transformation', async () => {
  13. const connector = new StateDB.Connector();
  14. const key = 'foo';
  15. const correct = 'bar';
  16. const incorrect = 'baz';
  17. expect(await connector.fetch(key)).toBeUndefined();
  18. await connector.save(key, `{ "v": "${incorrect}"}`);
  19. expect(JSON.parse(await connector.fetch(key)).v).toBe(incorrect);
  20. const transform = new PromiseDelegate<StateDB.DataTransform>();
  21. const db = new StateDB({ connector, transform: transform.promise });
  22. const transformation: StateDB.DataTransform = {
  23. type: 'overwrite',
  24. contents: { [key]: correct }
  25. };
  26. transform.resolve(transformation);
  27. await transform.promise;
  28. expect(await db.fetch(key)).toBe(correct);
  29. expect(JSON.parse(await connector.fetch(key)).v).toBe(correct);
  30. });
  31. it('should allow a merge data transformation', async () => {
  32. const connector = new StateDB.Connector();
  33. const k1 = 'foo';
  34. const v1 = 'bar';
  35. const k2 = 'baz';
  36. const v2 = 'qux';
  37. expect(await connector.fetch(k1)).toBeUndefined();
  38. expect(await connector.fetch(k2)).toBeUndefined();
  39. await connector.save(k1, `{ "v": "${v1}"}`);
  40. expect(JSON.parse(await connector.fetch(k1)).v).toBe(v1);
  41. const transform = new PromiseDelegate<StateDB.DataTransform>();
  42. const db = new StateDB({ connector, transform: transform.promise });
  43. const transformation: StateDB.DataTransform = {
  44. type: 'merge',
  45. contents: { [k2]: v2 }
  46. };
  47. transform.resolve(transformation);
  48. await transform.promise;
  49. expect(await db.fetch(k1)).toBe(v1);
  50. expect(await db.fetch(k2)).toBe(v2);
  51. });
  52. });
  53. describe('#changed', () => {
  54. it('should emit changes when the database is updated', async () => {
  55. const db = new StateDB();
  56. const changes: StateDB.Change[] = [
  57. { id: 'foo', type: 'save' },
  58. { id: 'foo', type: 'remove' },
  59. { id: 'bar', type: 'save' },
  60. { id: 'bar', type: 'remove' }
  61. ];
  62. const recorded: StateDB.Change[] = [];
  63. db.changed.connect((_, change) => {
  64. recorded.push(change);
  65. });
  66. await db.save('foo', 0);
  67. await db.remove('foo');
  68. await db.save('bar', 1);
  69. await db.remove('bar');
  70. expect(recorded).toEqual(changes);
  71. });
  72. });
  73. describe('#clear()', () => {
  74. it('should empty the items in a state database', async () => {
  75. const connector = new StateDB.Connector();
  76. const db = new StateDB({ connector });
  77. expect((await connector.list()).ids).toHaveLength(0);
  78. await db.save('foo', 'bar');
  79. expect((await connector.list()).ids).toHaveLength(1);
  80. await db.clear();
  81. expect((await connector.list()).ids).toHaveLength(0);
  82. });
  83. });
  84. describe('#fetch()', () => {
  85. it('should fetch a stored key', async () => {
  86. const db = new StateDB();
  87. const key = 'foo:bar';
  88. const value = { baz: 'qux' };
  89. expect(await db.fetch(key)).toBeUndefined();
  90. await db.save(key, value);
  91. expect(await db.fetch(key)).toEqual(value);
  92. });
  93. });
  94. describe('#list()', () => {
  95. it('should fetch a stored namespace', async () => {
  96. const db = new StateDB();
  97. const keys = [
  98. 'foo:bar',
  99. 'foo:baz',
  100. 'foo:qux',
  101. 'abc:def',
  102. 'abc:ghi',
  103. 'abc:jkl',
  104. 'foo-two:bar',
  105. 'foo-two:baz',
  106. 'foo-two:qux'
  107. ];
  108. await Promise.all(keys.map(key => db.save(key, { value: key })));
  109. let fetched = await db.list('foo');
  110. expect(fetched.ids.length).toBe(3);
  111. expect(fetched.values.length).toBe(3);
  112. let sorted = fetched.ids.sort((a, b) => a.localeCompare(b));
  113. expect(sorted[0]).toBe(keys[0]);
  114. expect(sorted[1]).toBe(keys[1]);
  115. expect(sorted[2]).toBe(keys[2]);
  116. fetched = await db.list('abc');
  117. expect(fetched.ids.length).toBe(3);
  118. expect(fetched.values.length).toBe(3);
  119. sorted = fetched.ids.sort((a, b) => a.localeCompare(b));
  120. expect(sorted[0]).toBe(keys[3]);
  121. expect(sorted[1]).toBe(keys[4]);
  122. expect(sorted[2]).toBe(keys[5]);
  123. });
  124. });
  125. describe('#remove()', () => {
  126. it('should remove a stored key', async () => {
  127. const db = new StateDB();
  128. const key = 'foo:bar';
  129. const value = { baz: 'qux' };
  130. expect(await db.fetch(key)).toBeUndefined();
  131. await db.save(key, value);
  132. expect(await db.fetch(key)).toEqual(value);
  133. await db.remove(key);
  134. expect(await db.fetch(key)).toBeUndefined();
  135. });
  136. });
  137. describe('#save()', () => {
  138. it('should save a key and a value', async () => {
  139. const db = new StateDB();
  140. const key = 'foo:bar';
  141. const value = { baz: 'qux' };
  142. await db.save(key, value);
  143. expect(await db.fetch(key)).toEqual(value);
  144. });
  145. });
  146. describe('#toJSON()', () => {
  147. it('return the full contents of a state database', async () => {
  148. const db = new StateDB();
  149. const contents: ReadonlyJSONObject = {
  150. abc: 'def',
  151. ghi: 'jkl',
  152. mno: 1,
  153. pqr: {
  154. foo: { bar: { baz: 'qux' } }
  155. }
  156. };
  157. await Promise.all(
  158. Object.keys(contents).map(key => db.save(key, contents[key]))
  159. );
  160. const serialized = await db.toJSON();
  161. expect(serialized).toEqual(contents);
  162. });
  163. });
  164. });