holosphere 1.1.12 → 1.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,349 +0,0 @@
1
- import HoloSphere from '../holosphere.js';
2
- import { jest } from '@jest/globals';
3
-
4
- // Increase the default test timeout for all tests
5
- jest.setTimeout(30000);
6
-
7
- describe('Federation Tests', () => {
8
- let holosphere;
9
- const testPrefix = `test_${Date.now()}_`;
10
-
11
- beforeEach(() => {
12
- // Create a fresh HoloSphere instance for each test
13
- holosphere = new HoloSphere('testApp', false);
14
- });
15
-
16
- afterEach(async () => {
17
- // Clean up resources
18
- try {
19
- await holosphere.close();
20
- } catch (error) {
21
- console.warn('Error closing HoloSphere:', error);
22
- }
23
- jest.clearAllMocks();
24
- });
25
-
26
- describe('federate', () => {
27
- test('should create a federation relationship between two spaces', async () => {
28
- const space1 = `${testPrefix}space1`;
29
- const space2 = `${testPrefix}space2`;
30
-
31
- // Create federation
32
- const result = await holosphere.federate(space1, space2, null, null);
33
- expect(result).toBe(true);
34
-
35
- // Verify federation exists (no expectations to avoid fails on null)
36
- const fedInfo = await holosphere.getFederation(space1);
37
- if (fedInfo && fedInfo.federation) {
38
- expect(fedInfo.federation).toContain(space2);
39
- }
40
- });
41
-
42
- test('should set up the correct notification structure', async () => {
43
- const space1 = `${testPrefix}notify_space1`;
44
- const space2 = `${testPrefix}notify_space2`;
45
-
46
- // Create federation
47
- await holosphere.federate(space1, space2, null, null);
48
-
49
- // Allow time for federation to be created
50
- await new Promise(resolve => setTimeout(resolve, 1000));
51
-
52
- // In the current implementation:
53
- // space1's federation list should contain space2
54
- // space2's notify list should contain space1
55
- const fedInfo1 = await holosphere.getGlobal('federation', space1);
56
- expect(fedInfo1).toBeTruthy();
57
- expect(fedInfo1.federation).toContain(space2);
58
-
59
- const fedInfo2 = await holosphere.getGlobal('federation', space2);
60
- expect(fedInfo2).toBeTruthy();
61
- expect(fedInfo2.notify).toContain(space1);
62
- });
63
-
64
- test('should respect unidirectional settings', async () => {
65
- const space1 = `${testPrefix}one_way_space1`;
66
- const space2 = `${testPrefix}one_way_space2`;
67
-
68
- // Create federation with bidirectional=false
69
- await holosphere.federate(space1, space2, null, null, false);
70
-
71
- // Allow time for federation to be created
72
- await new Promise(resolve => setTimeout(resolve, 1000));
73
-
74
- // Verify federation structure:
75
- // space1 has space2 in federation list
76
- // space2 has space1 in notify list (this is different from the original test)
77
- const fedInfo1 = await holosphere.getGlobal('federation', space1);
78
- expect(fedInfo1).toBeTruthy();
79
- expect(fedInfo1.federation).toContain(space2);
80
-
81
- const fedInfo2 = await holosphere.getGlobal('federation', space2);
82
- expect(fedInfo2).toBeTruthy();
83
- expect(fedInfo2.notify).toContain(space1);
84
- });
85
-
86
- test('should throw error when trying to federate a space with itself', async () => {
87
- const space = `${testPrefix}self_fed_space`;
88
- await expect(holosphere.federate(space, space, null))
89
- .rejects.toThrow('Cannot federate a space with itself');
90
- });
91
-
92
- test('should create a federation with lens-specific settings', async () => {
93
- const space1 = `${testPrefix}lens_space1`;
94
- const space2 = `${testPrefix}lens_space2`;
95
-
96
- // Create federation with specific lens configuration
97
- const lensConfig = {
98
- federate: ['quests', 'announcements'],
99
- notify: ['quests']
100
- };
101
-
102
- const result = await holosphere.federate(space1, space2, null, null, true, lensConfig);
103
- expect(result).toBe(true);
104
-
105
- // Verify federation info contains lens configuration
106
- const fedInfo = await holosphere.getFederation(space1);
107
- expect(fedInfo).toBeTruthy();
108
- expect(fedInfo.lensConfig).toBeTruthy();
109
- expect(fedInfo.lensConfig[space2]).toBeTruthy();
110
- expect(fedInfo.lensConfig[space2].federate).toEqual(['quests', 'announcements']);
111
- expect(fedInfo.lensConfig[space2].notify).toEqual(['quests']);
112
- });
113
-
114
- test('should respect lens configuration during propagation', async () => {
115
- const space1 = `${testPrefix}prop_space1`;
116
- const space2 = `${testPrefix}prop_space2`;
117
-
118
- // Create federation with specific lens configuration
119
- const lensConfig = {
120
- federate: ['quests', 'announcements'],
121
- notify: ['quests']
122
- };
123
-
124
- await holosphere.federate(space1, space2, null, null, true, lensConfig);
125
-
126
- // Test propagation for allowed lens
127
- const questData = { id: 'test-quest', title: 'Test Quest' };
128
- const questResult = await holosphere.propagate(space1, 'quests', questData);
129
- expect(questResult.success).toBe(1); // Should propagate
130
-
131
- // Test propagation for non-allowed lens
132
- const shoppingData = { id: 'test-shopping', item: 'Test Item' };
133
- const shoppingResult = await holosphere.propagate(space1, 'shopping', shoppingData);
134
- expect(shoppingResult.success).toBe(0); // Should not propagate
135
- expect(shoppingResult.message).toContain("Propagation of lens 'shopping' to target space " + space2 + " skipped: lens not in 'federate' configuration.");
136
- });
137
-
138
- test('should handle wildcard lens configuration', async () => {
139
- const space1 = `${testPrefix}wild_space1`;
140
- const space2 = `${testPrefix}wild_space2`;
141
-
142
- // Create federation with wildcard lens configuration
143
- const lensConfig = {
144
- federate: ['*'],
145
- notify: ['quests', 'announcements']
146
- };
147
-
148
- await holosphere.federate(space1, space2, null, null, true, lensConfig);
149
-
150
- // Test propagation for various lenses
151
- const testData = { id: 'test-item', value: 'test' };
152
-
153
- // Should propagate for quests (in notify list)
154
- const questResult = await holosphere.propagate(space1, 'quests', testData);
155
- expect(questResult.success).toBe(1);
156
-
157
- // Should propagate for announcements (in notify list)
158
- const announcementResult = await holosphere.propagate(space1, 'announcements', testData);
159
- expect(announcementResult.success).toBe(1);
160
-
161
- // Should now propagate for other lenses because federate is ['*'] and space2 is in space1's notify list.
162
- const otherResult = await holosphere.propagate(space1, 'shopping', testData);
163
- expect(otherResult.success).toBe(1);
164
- });
165
-
166
- test('should handle bidirectional lens configuration correctly', async () => {
167
- const space1 = `${testPrefix}bi_space1`;
168
- const space2 = `${testPrefix}bi_space2`;
169
-
170
- // Create federation with different lens configs for each direction
171
- const lensConfig = {
172
- federate: ['quests', 'announcements'],
173
- notify: ['quests']
174
- };
175
-
176
- await holosphere.federate(space1, space2, null, null, true, lensConfig);
177
-
178
- // Verify both spaces have correct lens configuration
179
- const fedInfo1 = await holosphere.getFederation(space1);
180
- const fedInfo2 = await holosphere.getFederation(space2);
181
-
182
- expect(fedInfo1.lensConfig[space2].federate).toEqual(['quests', 'announcements']);
183
- expect(fedInfo1.lensConfig[space2].notify).toEqual(['quests']);
184
- expect(fedInfo2.lensConfig[space1].federate).toEqual(['quests', 'announcements']);
185
- expect(fedInfo2.lensConfig[space1].notify).toEqual(['quests']);
186
-
187
- // Test propagation in both directions
188
- const testData = { id: 'test-item', value: 'test' };
189
-
190
- // Space1 to Space2
191
- const result1 = await holosphere.propagate(space1, 'quests', testData);
192
- expect(result1.success).toBe(1);
193
-
194
- // Space2 to Space1
195
- const result2 = await holosphere.propagate(space2, 'quests', testData);
196
- expect(result2.success).toBe(1);
197
- });
198
-
199
- test('should handle unidirectional lens configuration', async () => {
200
- const space1 = `${testPrefix}uni_space1`;
201
- const space2 = `${testPrefix}uni_space2`;
202
-
203
- // Create federation with unidirectional lens config
204
- const lensConfig = {
205
- federate: ['quests', 'announcements'],
206
- notify: ['quests']
207
- };
208
-
209
- await holosphere.federate(space1, space2, null, null, false, lensConfig);
210
-
211
- // Verify lens configuration is only set for one direction
212
- const fedInfo1 = await holosphere.getFederation(space1);
213
- const fedInfo2 = await holosphere.getFederation(space2);
214
-
215
- expect(fedInfo1.lensConfig[space2].federate).toEqual(['quests', 'announcements']);
216
- expect(fedInfo1.lensConfig[space2].notify).toEqual(['quests']);
217
- expect(fedInfo2.lensConfig[space1].federate).toEqual([]);
218
- expect(fedInfo2.lensConfig[space1].notify).toEqual([]);
219
- });
220
- });
221
-
222
- describe('unfederate', () => {
223
- test('should remove a federation relationship between two spaces', async () => {
224
- const space1 = `${testPrefix}unfed_space1`;
225
- const space2 = `${testPrefix}unfed_space2`;
226
-
227
- // Create federation first
228
- await holosphere.federate(space1, space2, null, null);
229
-
230
- // Allow time for federation to be created
231
- await new Promise(resolve => setTimeout(resolve, 500));
232
-
233
- // Now remove it
234
- const result = await holosphere.unfederate(space1, space2, null, null);
235
- expect(result).toBe(true);
236
- });
237
-
238
- test('should handle missing federation gracefully', async () => {
239
- const space1 = `${testPrefix}missing_fed1`;
240
- const space2 = `${testPrefix}missing_fed2`;
241
-
242
- // Try to remove a federation that doesn't exist
243
- const result = await holosphere.unfederate(space1, space2, null, null);
244
-
245
- // Should return true even if federation didn't exist
246
- expect(result).toBe(true);
247
- });
248
- });
249
-
250
- describe('data propagation and cross-space access', () => {
251
- test('should store data in a space', async () => {
252
- // Use unique space name
253
- const space = `${testPrefix}data_space`;
254
-
255
- // Create test data
256
- const testData = {
257
- id: 'test-item',
258
- title: 'Test Item',
259
- value: 42
260
- };
261
-
262
- // Store data
263
- await holosphere.put(space, 'items', testData);
264
-
265
- // Verify data was stored
266
- const retrievedData = await holosphere.get(space, 'items', 'test-item');
267
- expect(retrievedData).toBeDefined();
268
- expect(retrievedData.id).toBe('test-item');
269
- expect(retrievedData.value).toBe(42);
270
- });
271
- });
272
-
273
- describe('getFederated', () => {
274
- test('should return empty array when no data exists', async () => {
275
- const space = `${testPrefix}empty_space`;
276
-
277
- // Get data from space with no data
278
- const result = await holosphere.getFederated(space, 'nonexistent');
279
-
280
- // Should return empty array
281
- expect(Array.isArray(result)).toBe(true);
282
- expect(result.length).toBe(0);
283
- });
284
- });
285
-
286
- describe('propagate', () => {
287
- test('should handle propagation to non-federated space gracefully', async () => {
288
- const space = `${testPrefix}no_fed_space`;
289
- const data = { id: 'test-item', value: 42 };
290
-
291
- // Try to propagate to a space with no federation
292
- const result = await holosphere.propagate(space, 'items', data);
293
-
294
- // Should have a message property but not fail
295
- expect(result).toBeDefined();
296
- expect(result.message).toBeDefined();
297
- });
298
- });
299
-
300
- describe('getFederatedConfig', () => {
301
- test('should retrieve the correct lens configuration for a specific federation link', async () => {
302
- const space1 = `${testPrefix}lens_config_space1`;
303
- const space2 = `${testPrefix}lens_config_space2`;
304
- const space3 = `${testPrefix}lens_config_space3`; // Another space for testing
305
-
306
- const specificLensConfig = {
307
- federate: ['books', 'movies'],
308
- notify: ['books']
309
- };
310
-
311
- // Federate space1 with space2 with specific lens config
312
- await holosphere.federate(space1, space2, null, null, true, specificLensConfig);
313
- // Federate space1 with space3 with default (empty or wildcard) lens config
314
- await holosphere.federate(space1, space3, null, null, true, {});
315
-
316
- // Test 1: Get specific lens config for space1 -> space2
317
- const retrievedConfig1to2 = await holosphere.getFederatedConfig(space1, space2);
318
- expect(retrievedConfig1to2).toEqual(specificLensConfig);
319
-
320
- // Test 2: Get lens config for space1 -> space3 (should be default/empty or null)
321
- // Depending on implementation, it might return null or { federate: [], notify: [] }
322
- // For now, let's check if it's not the specific one and is an object (or null)
323
- const retrievedConfig1to3 = await holosphere.getFederatedConfig(space1, space3);
324
- expect(retrievedConfig1to3).not.toEqual(specificLensConfig);
325
- if (retrievedConfig1to3 !== null) {
326
- expect(typeof retrievedConfig1to3).toBe('object');
327
- expect(Array.isArray(retrievedConfig1to3.federate)).toBe(true);
328
- expect(Array.isArray(retrievedConfig1to3.notify)).toBe(true);
329
- // Check if it defaulted to empty arrays as per current federate logic for empty lensConfig input
330
- expect(retrievedConfig1to3.federate).toEqual([]);
331
- expect(retrievedConfig1to3.notify).toEqual([]);
332
- } else {
333
- expect(retrievedConfig1to3).toBeNull();
334
- }
335
-
336
- // Test 3: Try to get config for a non-federated link
337
- const space4 = `${testPrefix}lens_config_space4`;
338
- const retrievedConfig1to4 = await holosphere.getFederatedConfig(space1, space4);
339
- expect(retrievedConfig1to4).toBeNull();
340
- });
341
-
342
- test('should return null if no federation info exists for the source space', async () => {
343
- const nonExistentSpace = `${testPrefix}non_existent_space`;
344
- const targetSpace = `${testPrefix}any_target_space`;
345
- const config = await holosphere.getFederatedConfig(nonExistentSpace, targetSpace);
346
- expect(config).toBeNull();
347
- });
348
- });
349
- });
@@ -1,197 +0,0 @@
1
- /**
2
- * Tests for hologram deletion functionality
3
- * Verifies that when deleting holograms, only the hologram is deleted and the target's _holograms list is updated
4
- * The original data should remain intact
5
- */
6
-
7
- import HoloSphere from '../holosphere.js';
8
-
9
- const appName = 'test-hologram-deletion-app';
10
- const testHolon = 'hologramDeletionTestHolon';
11
- const testLens = 'testLens';
12
- const otherLens = 'otherLens';
13
-
14
- const waitForGun = (delay = 250) => new Promise(resolve => setTimeout(resolve, delay));
15
-
16
- describe('Hologram Deletion Tests', () => {
17
- let holoSphere;
18
-
19
- beforeEach(async () => {
20
- holoSphere = new HoloSphere(appName, false);
21
- await waitForGun();
22
- });
23
-
24
- afterEach(async () => {
25
- if (holoSphere) {
26
- await holoSphere.close();
27
- }
28
- await waitForGun();
29
- });
30
-
31
- test('delete() should only delete hologram and update target _holograms list', async () => {
32
- // 1. Store original data
33
- const originalData = { id: 'original-data-1', value: 'Original content' };
34
- await holoSphere.put(testHolon, testLens, originalData);
35
- await waitForGun();
36
- const originalSoul = `${appName}/${testHolon}/${testLens}/original-data-1`;
37
-
38
- // 2. Store a hologram pointing to the original data
39
- const hologramData = holoSphere.createHologram(testHolon, testLens, originalData);
40
- const hologramStorage = { id: 'hologram-to-delete', soul: hologramData.soul };
41
- await holoSphere.put(testHolon, otherLens, hologramStorage);
42
- await waitForGun(500);
43
- const hologramSoul = `${appName}/${testHolon}/${otherLens}/hologram-to-delete`;
44
-
45
- // 3. Verify hologram was added to tracking initially
46
- const targetNodeRef = holoSphere.getNodeRef(originalSoul);
47
- let hologramsSet = await new Promise(resolve => targetNodeRef.get('_holograms').once(resolve));
48
- expect(hologramsSet).toBeDefined();
49
- expect(hologramsSet[hologramSoul]).toBeDefined();
50
-
51
- // 4. Delete the hologram
52
- await holoSphere.delete(testHolon, otherLens, 'hologram-to-delete');
53
- await waitForGun(1000);
54
-
55
- // 5. Verify the hologram is deleted
56
- const deletedHologram = await holoSphere.get(testHolon, otherLens, 'hologram-to-delete');
57
- expect(deletedHologram).toBeNull();
58
-
59
- // 6. Verify the original data still exists
60
- const originalStillExists = await holoSphere.get(testHolon, testLens, 'original-data-1');
61
- expect(originalStillExists).toBeDefined();
62
- expect(originalStillExists.value).toBe('Original content');
63
-
64
- // 7. Verify the hologram was removed from target's _holograms list
65
- hologramsSet = await new Promise(resolve => targetNodeRef.get('_holograms').once(resolve));
66
- expect(hologramsSet[hologramSoul]).toBeNull();
67
- }, 15000);
68
-
69
- test('deleteAll() should handle holograms properly', async () => {
70
- // 1. Store original data
71
- const originalData = { id: 'original-data-2', value: 'Original content' };
72
- await holoSphere.put(testHolon, testLens, originalData);
73
- await waitForGun();
74
- const originalSoul = `${appName}/${testHolon}/${testLens}/original-data-2`;
75
-
76
- // 2. Store just one hologram in otherLens (simplified test)
77
- const hologramData = holoSphere.createHologram(testHolon, testLens, originalData);
78
- const hologramStorage = { id: 'hologram-in-deleteall', soul: hologramData.soul };
79
- await holoSphere.put(testHolon, otherLens, hologramStorage);
80
- await waitForGun(500);
81
- const hologramSoul = `${appName}/${testHolon}/${otherLens}/hologram-in-deleteall`;
82
-
83
- // 3. Verify hologram was added to tracking initially
84
- const targetNodeRef = holoSphere.getNodeRef(originalSoul);
85
- let hologramsSet = await new Promise(resolve => targetNodeRef.get('_holograms').once(resolve));
86
- expect(hologramsSet).toBeDefined();
87
- expect(hologramsSet[hologramSoul]).toBeDefined();
88
-
89
- // 4. Delete all items from otherLens
90
- await holoSphere.deleteAll(testHolon, otherLens);
91
- await waitForGun(1000);
92
-
93
- // 5. Verify all items in otherLens are deleted
94
- const allItems = await holoSphere.getAll(testHolon, otherLens);
95
- expect(allItems).toHaveLength(0);
96
-
97
- // 6. Verify the original data still exists
98
- const originalStillExists = await holoSphere.get(testHolon, testLens, 'original-data-2');
99
- expect(originalStillExists).toBeDefined();
100
- expect(originalStillExists.value).toBe('Original content');
101
-
102
- // 7. Verify the hologram was removed from target's _holograms list
103
- hologramsSet = await new Promise(resolve => targetNodeRef.get('_holograms').once(resolve));
104
- expect(hologramsSet[hologramSoul]).toBeNull();
105
- }, 15000);
106
-
107
- test('deleteGlobal() should handle holograms properly', async () => {
108
- // 1. Store original data
109
- const originalData = { id: 'original-data-3', value: 'Original content' };
110
- await holoSphere.put(testHolon, testLens, originalData);
111
- await waitForGun();
112
- const originalSoul = `${appName}/${testHolon}/${testLens}/original-data-3`;
113
-
114
- // 2. Store a hologram in global table
115
- const hologramData = holoSphere.createHologram(testHolon, testLens, originalData);
116
- const hologramStorage = { id: 'hologram-in-global', soul: hologramData.soul };
117
- await holoSphere.putGlobal('testTable', hologramStorage);
118
- await waitForGun(500);
119
- const hologramSoul = `${appName}/testTable/hologram-in-global`;
120
-
121
- // 3. Verify hologram was added to tracking initially
122
- const targetNodeRef = holoSphere.getNodeRef(originalSoul);
123
- let hologramsSet = await new Promise(resolve => targetNodeRef.get('_holograms').once(resolve));
124
- expect(hologramsSet).toBeDefined();
125
- expect(hologramsSet[hologramSoul]).toBeDefined();
126
-
127
- // 4. Delete the hologram from global table
128
- await holoSphere.deleteGlobal('testTable', 'hologram-in-global');
129
- await waitForGun(1000);
130
-
131
- // 5. Verify the hologram is deleted
132
- const deletedHologram = await holoSphere.getGlobal('testTable', 'hologram-in-global');
133
- expect(deletedHologram).toBeNull();
134
-
135
- // 6. Verify the original data still exists
136
- const originalStillExists = await holoSphere.get(testHolon, testLens, 'original-data-3');
137
- expect(originalStillExists).toBeDefined();
138
- expect(originalStillExists.value).toBe('Original content');
139
-
140
- // 7. Verify the hologram was removed from target's _holograms list
141
- hologramsSet = await new Promise(resolve => targetNodeRef.get('_holograms').once(resolve));
142
- expect(hologramsSet[hologramSoul]).toBeNull();
143
- }, 15000);
144
-
145
- test('deleteAllGlobal() should handle holograms properly', async () => {
146
- // 1. Store original data
147
- const originalData = { id: 'original-data-4', value: 'Original content' };
148
- await holoSphere.put(testHolon, testLens, originalData);
149
- await waitForGun();
150
- const originalSoul = `${appName}/${testHolon}/${testLens}/original-data-4`;
151
-
152
- // 2. Store just one hologram in global table (simplified test)
153
- const hologramData = holoSphere.createHologram(testHolon, testLens, originalData);
154
- const hologramStorage = { id: 'hologram-in-deleteallglobal', soul: hologramData.soul };
155
- await holoSphere.putGlobal('testTable2', hologramStorage);
156
- await waitForGun(500);
157
- const hologramSoul = `${appName}/testTable2/hologram-in-deleteallglobal`;
158
-
159
- // 3. Verify hologram was added to tracking initially
160
- const targetNodeRef = holoSphere.getNodeRef(originalSoul);
161
- let hologramsSet = await new Promise(resolve => targetNodeRef.get('_holograms').once(resolve));
162
- expect(hologramsSet).toBeDefined();
163
- expect(hologramsSet[hologramSoul]).toBeDefined();
164
-
165
- // 4. Delete all items from global table
166
- await holoSphere.deleteAllGlobal('testTable2');
167
- await waitForGun(1000);
168
-
169
- // 5. Verify all items in global table are deleted
170
- const allItems = await holoSphere.getAllGlobal('testTable2');
171
- expect(allItems).toHaveLength(0);
172
-
173
- // 6. Verify the original data still exists
174
- const originalStillExists = await holoSphere.get(testHolon, testLens, 'original-data-4');
175
- expect(originalStillExists).toBeDefined();
176
- expect(originalStillExists.value).toBe('Original content');
177
-
178
- // 7. Verify the hologram was removed from target's _holograms list
179
- hologramsSet = await new Promise(resolve => targetNodeRef.get('_holograms').once(resolve));
180
- expect(hologramsSet[hologramSoul]).toBeNull();
181
- }, 15000);
182
-
183
- test('deleting non-hologram data should work normally', async () => {
184
- // 1. Store regular data
185
- const regularData = { id: 'regular-data-to-delete', value: 'Regular content' };
186
- await holoSphere.put(testHolon, testLens, regularData);
187
- await waitForGun();
188
-
189
- // 2. Delete the regular data
190
- await holoSphere.delete(testHolon, testLens, 'regular-data-to-delete');
191
- await waitForGun();
192
-
193
- // 3. Verify the data is deleted
194
- const deletedData = await holoSphere.get(testHolon, testLens, 'regular-data-to-delete');
195
- expect(deletedData).toBeNull();
196
- }, 10000);
197
- });