holosphere 1.1.5 → 1.1.7
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.
- package/FEDERATION.md +213 -0
- package/README.md +140 -0
- package/babel.config.js +5 -0
- package/examples/README-environmental.md +158 -0
- package/examples/environmentalData.js +380 -0
- package/examples/federation.js +154 -0
- package/examples/queryEnvironmentalData.js +147 -0
- package/examples/references.js +177 -0
- package/federation.js +988 -0
- package/holosphere.d.ts +445 -20
- package/holosphere.js +1083 -998
- package/package.json +3 -6
- package/services/environmentalApi.js +162 -0
- package/services/environmentalApi.test.js +0 -6
- package/test/ai.test.js +268 -76
- package/test/auth.test.js +241 -0
- package/test/delete.test.js +225 -0
- package/test/federation.test.js +163 -356
- package/test/holosphere.test.js +109 -955
- package/test/sea.html +33 -0
- package/test/jest.setup.js +0 -5
- package/test/spacesauth.test.js +0 -335
package/test/federation.test.js
CHANGED
|
@@ -1,363 +1,170 @@
|
|
|
1
1
|
import HoloSphere from '../holosphere.js';
|
|
2
2
|
import { jest } from '@jest/globals';
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
jest.setTimeout(
|
|
6
|
-
|
|
7
|
-
describe('Federation
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
+
});
|
|
11
41
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Create fresh test spaces with retries
|
|
36
|
-
for (let i = 0; i < 3; i++) {
|
|
37
|
-
try {
|
|
38
|
-
await holoSphere.createSpace(space1.spacename, space1.password);
|
|
39
|
-
await holoSphere.createSpace(space2.spacename, space2.password);
|
|
40
|
-
break;
|
|
41
|
-
} catch (error) {
|
|
42
|
-
console.log('Space creation attempt', i + 1, 'failed:', error.message);
|
|
43
|
-
if (i === 2) throw error;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// Verify spaces were created
|
|
49
|
-
const space1Created = await holoSphere.getGlobal('spaces', space1.spacename);
|
|
50
|
-
const space2Created = await holoSphere.getGlobal('spaces', space2.spacename);
|
|
51
|
-
|
|
52
|
-
if (!space1Created || !space2Created) {
|
|
53
|
-
throw new Error('Failed to create test spaces');
|
|
54
|
-
}
|
|
55
|
-
}, 30000);
|
|
56
|
-
|
|
57
|
-
beforeEach(async () => {
|
|
58
|
-
// Clean up any existing federation data
|
|
59
|
-
await holoSphere.deleteAllGlobal('federation');
|
|
60
|
-
|
|
61
|
-
// Clean up any existing test data
|
|
62
|
-
await holoSphere.deleteAll(testHolon, testLens);
|
|
63
|
-
|
|
64
|
-
// Set up base schema for all tests
|
|
65
|
-
const baseSchema = {
|
|
66
|
-
type: 'object',
|
|
67
|
-
properties: {
|
|
68
|
-
id: { type: 'string' },
|
|
69
|
-
name: { type: 'string' },
|
|
70
|
-
data: { type: 'string' },
|
|
71
|
-
federation: {
|
|
72
|
-
type: 'object',
|
|
73
|
-
properties: {
|
|
74
|
-
origin: { type: 'string' },
|
|
75
|
-
timestamp: { type: 'number' }
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
},
|
|
79
|
-
required: ['id']
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
await holoSphere.setSchema(testLens, baseSchema);
|
|
83
|
-
await strictHoloSphere.setSchema(testLens, baseSchema);
|
|
84
|
-
|
|
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
|
+
});
|
|
85
63
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Verify spaces again
|
|
111
|
-
const space1Verified = await holoSphere.getGlobal('spaces', space1.spacename);
|
|
112
|
-
const space2Verified = await holoSphere.getGlobal('spaces', space2.spacename);
|
|
113
|
-
|
|
114
|
-
if (!space1Verified || !space2Verified) {
|
|
115
|
-
throw new Error('Test spaces not found - test environment not properly set up');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Ensure both instances are logged out
|
|
119
|
-
if (holoSphere.currentSpace) {
|
|
120
|
-
await holoSphere.logout();
|
|
121
|
-
}
|
|
122
|
-
if (strictHoloSphere.currentSpace) {
|
|
123
|
-
await strictHoloSphere.logout();
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Login as first space to holoSphere
|
|
127
|
-
await holoSphere.login(space1.spacename, space1.password);
|
|
128
|
-
|
|
129
|
-
}, 20000);
|
|
130
|
-
|
|
131
|
-
test('should create federation relationship between spaces', async () => {
|
|
132
|
-
// Create federation relationship
|
|
133
|
-
await holoSphere.federate(space1.spacename, space2.spacename);
|
|
134
|
-
|
|
135
|
-
// Verify federation was created
|
|
136
|
-
const fedInfo = await holoSphere.getFederation(space1.spacename);
|
|
137
|
-
expect(fedInfo).toBeDefined();
|
|
138
|
-
expect(fedInfo.federation).toContain(space2.spacename);
|
|
139
|
-
}, 10000);
|
|
140
|
-
|
|
141
|
-
test('should establish bidirectional federation', async () => {
|
|
142
|
-
// Create bidirectional federation
|
|
143
|
-
await holoSphere.federate(space1.spacename, space2.spacename);
|
|
144
|
-
|
|
145
|
-
// Login to space1 to verify federation
|
|
146
|
-
await holoSphere.login(space1.spacename, space1.password);
|
|
147
|
-
|
|
148
|
-
// Verify both spaces are federated with each other
|
|
149
|
-
const fedInfo1 = await holoSphere.getFederation(space1.spacename);
|
|
150
|
-
const fedInfo2 = await holoSphere.getFederation(space2.spacename);
|
|
151
|
-
|
|
152
|
-
expect(fedInfo1).toBeDefined();
|
|
153
|
-
expect(fedInfo2).toBeDefined();
|
|
154
|
-
expect(fedInfo1.federation).toContain(space2.spacename);
|
|
155
|
-
expect(fedInfo2.notify).toContain(space1.spacename);
|
|
156
|
-
}, 10000);
|
|
157
|
-
|
|
158
|
-
test('should prevent duplicate federation relationships', async () => {
|
|
159
|
-
// Login to space1
|
|
160
|
-
await holoSphere.login(space1.spacename, space1.password);
|
|
161
|
-
|
|
162
|
-
// Create initial federation
|
|
163
|
-
await holoSphere.federate(space1.spacename, space2.spacename);
|
|
164
|
-
|
|
165
|
-
// Verify federation exists
|
|
166
|
-
const fedInfo = await holoSphere.getFederation(space1.spacename);
|
|
167
|
-
expect(fedInfo).toBeDefined();
|
|
168
|
-
expect(fedInfo.federation).toBeDefined();
|
|
169
|
-
expect(fedInfo.federation).toContain(space2.spacename);
|
|
170
|
-
|
|
171
|
-
// Attempt to create duplicate federation
|
|
172
|
-
await expect(holoSphere.federate(space1.spacename, space2.spacename))
|
|
173
|
-
.rejects.toThrow('Federation already exists');
|
|
174
|
-
}, 15000);
|
|
175
|
-
|
|
176
|
-
test('should handle federation data propagation', async () => {
|
|
177
|
-
// Login to space1
|
|
178
|
-
await holoSphere.login(space1.spacename, space1.password);
|
|
179
|
-
|
|
180
|
-
const testData = {
|
|
181
|
-
id: 'test1',
|
|
182
|
-
name: 'Test Item',
|
|
183
|
-
data: 'federated content'
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
// Set up federation
|
|
187
|
-
await holoSphere.federate(space1.spacename, space2.spacename);
|
|
188
|
-
|
|
189
|
-
// Login to space2 with strict instance
|
|
190
|
-
await strictHoloSphere.login(space2.spacename, space2.password);
|
|
191
|
-
|
|
192
|
-
// Put data in first space
|
|
193
|
-
await holoSphere.put(testHolon, testLens, testData);
|
|
194
|
-
|
|
195
|
-
// Verify data was propagated to federated space
|
|
196
|
-
const federatedData = await strictHoloSphere.get(testHolon, testLens, testData.id);
|
|
197
|
-
expect(federatedData).toBeDefined();
|
|
198
|
-
expect(federatedData).not.toBeNull();
|
|
199
|
-
expect(federatedData.data).toEqual(testData.data);
|
|
200
|
-
expect(federatedData.federation).toBeDefined();
|
|
201
|
-
expect(federatedData.federation.origin).toEqual(space1.spacename);
|
|
202
|
-
expect(federatedData.federation.timestamp).toBeGreaterThan(0);
|
|
203
|
-
}, 20000);
|
|
204
|
-
|
|
205
|
-
test('should handle different getFederated modalities', async () => {
|
|
206
|
-
// Clean up any existing test data first
|
|
207
|
-
await holoSphere.deleteAll(testHolon, testLens);
|
|
208
|
-
await strictHoloSphere.deleteAll(testHolon, testLens);
|
|
209
|
-
|
|
210
|
-
// Set up federation using non-strict instance (already logged in as space1)
|
|
211
|
-
await holoSphere.federate(space1.spacename, space2.spacename);
|
|
212
|
-
|
|
213
|
-
// Login to space2 with strict instance
|
|
214
|
-
await strictHoloSphere.login(space2.spacename, space2.password);
|
|
215
|
-
|
|
216
|
-
// Test data with overlapping IDs and different fields
|
|
217
|
-
const testData1 = {
|
|
218
|
-
id: 'user1',
|
|
219
|
-
name: 'User One',
|
|
220
|
-
received: 10,
|
|
221
|
-
sent: 5,
|
|
222
|
-
wants: ['item1', 'item2'],
|
|
223
|
-
offers: ['service1']
|
|
224
|
-
};
|
|
225
|
-
const testData2 = {
|
|
226
|
-
id: 'user1', // Same ID as testData1
|
|
227
|
-
name: 'User One Updated',
|
|
228
|
-
received: 15,
|
|
229
|
-
sent: 8,
|
|
230
|
-
wants: ['item3'],
|
|
231
|
-
offers: ['service2']
|
|
232
|
-
};
|
|
233
|
-
const testData3 = {
|
|
234
|
-
id: 'user2',
|
|
235
|
-
name: 'User Two',
|
|
236
|
-
received: 20,
|
|
237
|
-
sent: 12,
|
|
238
|
-
wants: ['item4'],
|
|
239
|
-
offers: ['service3']
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
// Put data using both instances and wait between puts
|
|
243
|
-
console.log('Putting test data 1:', JSON.stringify(testData1, null, 2));
|
|
244
|
-
await holoSphere.put(testHolon, testLens, testData1);
|
|
245
|
-
|
|
246
|
-
console.log('Putting test data 2:', JSON.stringify(testData2, null, 2));
|
|
247
|
-
await strictHoloSphere.put(testHolon, testLens, testData2);
|
|
248
|
-
|
|
249
|
-
console.log('Putting test data 3:', JSON.stringify(testData3, null, 2));
|
|
250
|
-
await holoSphere.put(testHolon, testLens, testData3);
|
|
251
|
-
|
|
252
|
-
// Test 1: Simple concatenation without deduplication
|
|
253
|
-
const concatenatedResults = await holoSphere.getFederated(testHolon, testLens, {
|
|
254
|
-
aggregate: false,
|
|
255
|
-
removeDuplicates: false
|
|
256
|
-
});
|
|
257
|
-
console.log('Concatenated results:', JSON.stringify(concatenatedResults, null, 2));
|
|
258
|
-
|
|
259
|
-
// Verify we have all items including duplicates
|
|
260
|
-
expect(concatenatedResults.filter(item => item.id === 'user1').length).toBeGreaterThanOrEqual(1);
|
|
261
|
-
expect(concatenatedResults.filter(item => item.id === 'user2').length).toBe(1);
|
|
262
|
-
|
|
263
|
-
// Test 2: With deduplication
|
|
264
|
-
const dedupedResults = await strictHoloSphere.getFederated(testHolon, testLens, {
|
|
265
|
-
aggregate: false,
|
|
266
|
-
removeDuplicates: true
|
|
267
|
-
});
|
|
268
|
-
console.log('Deduped results:', JSON.stringify(dedupedResults, null, 2));
|
|
269
|
-
expect(dedupedResults.length).toBe(2);
|
|
270
|
-
const user1Deduped = dedupedResults.find(item => item.id === 'user1');
|
|
271
|
-
expect(user1Deduped.name).toBe('User One Updated');
|
|
272
|
-
|
|
273
|
-
// Test 3: With aggregation
|
|
274
|
-
const aggregationOptions = {
|
|
275
|
-
aggregate: true,
|
|
276
|
-
idField: 'id',
|
|
277
|
-
sumFields: ['received', 'sent'],
|
|
278
|
-
concatArrays: ['wants', 'offers'],
|
|
279
|
-
removeDuplicates: true
|
|
280
|
-
};
|
|
281
|
-
console.log('Aggregation options:', JSON.stringify(aggregationOptions, null, 2));
|
|
282
|
-
const aggregatedResults = await holoSphere.getFederated(testHolon, testLens, aggregationOptions);
|
|
283
|
-
console.log('Aggregated results:', JSON.stringify(aggregatedResults, null, 2));
|
|
284
|
-
|
|
285
|
-
// Sort results by ID for consistent testing
|
|
286
|
-
const sortedResults = aggregatedResults.sort((a, b) => a.id.localeCompare(b.id));
|
|
287
|
-
expect(sortedResults.length).toBe(2);
|
|
288
|
-
|
|
289
|
-
const user1Aggregated = sortedResults.find(item => item.id === 'user1');
|
|
290
|
-
expect(user1Aggregated).toBeDefined();
|
|
291
|
-
expect(user1Aggregated.received).toBe(15); // Latest value
|
|
292
|
-
expect(user1Aggregated.sent).toBe(8); // Latest value
|
|
293
|
-
expect(user1Aggregated.wants).toEqual(['item3']); // Latest value
|
|
294
|
-
expect(user1Aggregated.offers).toEqual(['service2']); // Latest value
|
|
295
|
-
|
|
296
|
-
const user2Aggregated = sortedResults.find(item => item.id === 'user2');
|
|
297
|
-
expect(user2Aggregated).toBeDefined();
|
|
298
|
-
expect(user2Aggregated.received).toBe(20);
|
|
299
|
-
expect(user2Aggregated.sent).toBe(12);
|
|
300
|
-
expect(user2Aggregated.wants).toEqual(['item4']);
|
|
301
|
-
expect(user2Aggregated.offers).toEqual(['service3']);
|
|
302
|
-
}, 60000);
|
|
303
|
-
|
|
304
|
-
test('should handle unfederation', async () => {
|
|
305
|
-
// Login to space1
|
|
306
|
-
await holoSphere.login(space1.spacename, space1.password);
|
|
307
|
-
|
|
308
|
-
// Set up federation
|
|
309
|
-
await holoSphere.federate(space1.spacename, space2.spacename);
|
|
310
|
-
|
|
311
|
-
// Verify federation exists
|
|
312
|
-
let fedInfo1 = await holoSphere.getFederation(space1.spacename);
|
|
313
|
-
expect(fedInfo1).toBeDefined();
|
|
314
|
-
expect(fedInfo1.federation).toBeDefined();
|
|
315
|
-
expect(fedInfo1.federation).toContain(space2.spacename);
|
|
316
|
-
|
|
317
|
-
// Remove federation
|
|
318
|
-
await holoSphere.unfederate(space1.spacename, space2.spacename);
|
|
319
|
-
|
|
320
|
-
// Verify federation is removed
|
|
321
|
-
fedInfo1 = await holoSphere.getFederation(space1.spacename);
|
|
322
|
-
const fedInfo2 = await holoSphere.getFederation(space2.spacename);
|
|
323
|
-
|
|
324
|
-
expect(fedInfo1).toBeDefined();
|
|
325
|
-
expect(fedInfo2).toBeDefined();
|
|
326
|
-
expect(fedInfo1.federation || []).not.toContain(space2.spacename);
|
|
327
|
-
expect(fedInfo2.notify || []).not.toContain(space1.spacename);
|
|
328
|
-
}, 20000);
|
|
329
|
-
|
|
330
|
-
afterEach(async () => {
|
|
331
|
-
// Clean up test data
|
|
332
|
-
await holoSphere.deleteAll(testHolon, testLens);
|
|
333
|
-
|
|
334
|
-
// Clean up federation data while still logged in
|
|
335
|
-
await holoSphere.deleteAllGlobal('federation');
|
|
336
|
-
|
|
337
|
-
// Logout from both instances
|
|
338
|
-
if (holoSphere.currentSpace) {
|
|
339
|
-
await holoSphere.logout();
|
|
340
|
-
}
|
|
341
|
-
if (strictHoloSphere.currentSpace) {
|
|
342
|
-
await strictHoloSphere.logout();
|
|
343
|
-
}
|
|
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);
|
|
344
84
|
});
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
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
|
+
|
|
93
|
+
describe('unfederate', () => {
|
|
94
|
+
test('should remove a federation relationship between two spaces', async () => {
|
|
95
|
+
const space1 = `${testPrefix}unfed_space1`;
|
|
96
|
+
const space2 = `${testPrefix}unfed_space2`;
|
|
97
|
+
|
|
98
|
+
// Create federation first
|
|
99
|
+
await holosphere.federate(space1, space2, null, null);
|
|
100
|
+
|
|
101
|
+
// Allow time for federation to be created
|
|
102
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
103
|
+
|
|
104
|
+
// Now remove it
|
|
105
|
+
const result = await holosphere.unfederate(space1, space2, null, null);
|
|
106
|
+
expect(result).toBe(true);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('should handle missing federation gracefully', async () => {
|
|
110
|
+
const space1 = `${testPrefix}missing_fed1`;
|
|
111
|
+
const space2 = `${testPrefix}missing_fed2`;
|
|
112
|
+
|
|
113
|
+
// Try to remove a federation that doesn't exist
|
|
114
|
+
const result = await holosphere.unfederate(space1, space2, null, null);
|
|
115
|
+
|
|
116
|
+
// Should return true even if federation didn't exist
|
|
117
|
+
expect(result).toBe(true);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe('data propagation and cross-space access', () => {
|
|
122
|
+
test('should store data in a space', async () => {
|
|
123
|
+
// Use unique space name
|
|
124
|
+
const space = `${testPrefix}data_space`;
|
|
125
|
+
|
|
126
|
+
// Create test data
|
|
127
|
+
const testData = {
|
|
128
|
+
id: 'test-item',
|
|
129
|
+
title: 'Test Item',
|
|
130
|
+
value: 42
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Store data
|
|
134
|
+
await holosphere.put(space, 'items', testData);
|
|
135
|
+
|
|
136
|
+
// Verify data was stored
|
|
137
|
+
const retrievedData = await holosphere.get(space, 'items', 'test-item');
|
|
138
|
+
expect(retrievedData).toBeDefined();
|
|
139
|
+
expect(retrievedData.id).toBe('test-item');
|
|
140
|
+
expect(retrievedData.value).toBe(42);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
describe('getFederated', () => {
|
|
145
|
+
test('should return empty array when no data exists', async () => {
|
|
146
|
+
const space = `${testPrefix}empty_space`;
|
|
147
|
+
|
|
148
|
+
// Get data from space with no data
|
|
149
|
+
const result = await holosphere.getFederated(space, 'nonexistent');
|
|
150
|
+
|
|
151
|
+
// Should return empty array
|
|
152
|
+
expect(Array.isArray(result)).toBe(true);
|
|
153
|
+
expect(result.length).toBe(0);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe('propagate', () => {
|
|
158
|
+
test('should handle propagation to non-federated space gracefully', async () => {
|
|
159
|
+
const space = `${testPrefix}no_fed_space`;
|
|
160
|
+
const data = { id: 'test-item', value: 42 };
|
|
161
|
+
|
|
162
|
+
// Try to propagate to a space with no federation
|
|
163
|
+
const result = await holosphere.propagate(space, 'items', data);
|
|
164
|
+
|
|
165
|
+
// Should have a message property but not fail
|
|
166
|
+
expect(result).toBeDefined();
|
|
167
|
+
expect(result.message).toBeDefined();
|
|
362
168
|
});
|
|
363
|
-
});
|
|
169
|
+
});
|
|
170
|
+
});
|