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.
@@ -0,0 +1,241 @@
1
+ import Gun from 'gun';
2
+ import HoloSphere from '../holosphere.js';
3
+ import * as h3 from 'h3-js';
4
+ import { jest } from '@jest/globals';
5
+
6
+ // Increase timeout for all tests
7
+ jest.setTimeout(3000);
8
+
9
+ describe('HoloSphere Authentication and Authorization', () => {
10
+ let holoSphere;
11
+ let strictHoloSphere;
12
+ const testPassword = 'TestPass123!';
13
+ const testHolon = 'test-holon';
14
+ const testLens = 'test-lens';
15
+
16
+ beforeAll(async () => {
17
+ holoSphere = new HoloSphere('test-app', false, null);
18
+ strictHoloSphere = new HoloSphere('test-app-strict', true, null);
19
+ });
20
+
21
+ afterEach(async () => {
22
+ // Clean up test data
23
+ try {
24
+ if (holoSphere) {
25
+ await holoSphere.deleteAll(testHolon, testLens);
26
+ }
27
+ if (strictHoloSphere) {
28
+ await strictHoloSphere.deleteAll(testHolon, testLens);
29
+ }
30
+ } catch (error) {
31
+ console.error('Error in afterEach cleanup:', error);
32
+ }
33
+ });
34
+
35
+ afterAll(async () => {
36
+ // Clean up all test data
37
+ await holoSphere.deleteAll(testHolon, testLens);
38
+ await holoSphere.deleteAllGlobal('testTable');
39
+
40
+ // Close Gun connections
41
+ if (holoSphere.gun) {
42
+ holoSphere.gun.off();
43
+ }
44
+ if (strictHoloSphere.gun) {
45
+ strictHoloSphere.gun.off();
46
+ }
47
+
48
+ // Wait for connections to close
49
+ await new Promise(resolve => setTimeout(resolve, 1000));
50
+ });
51
+
52
+ describe('Authentication System', () => {
53
+ it('should authenticate with password and store/retrieve data', async () => {
54
+ const testData = { id: 'test1', value: 'private-data' };
55
+
56
+ // Test storing with authentication
57
+ await holoSphere.put(testHolon, testLens, testData, testPassword);
58
+
59
+ // Test retrieving with authentication
60
+ const result = await holoSphere.get(testHolon, testLens, testData.id, testPassword);
61
+ expect(result).toBeDefined();
62
+ expect(result.value).toBe(testData.value);
63
+ });
64
+
65
+ it('should handle authentication errors gracefully', async () => {
66
+ const testData = { id: 'test2', value: 'private-data' };
67
+
68
+ // Store data with correct password
69
+ await holoSphere.put(testHolon, testLens, testData, testPassword);
70
+
71
+ // Try to retrieve with wrong password
72
+ const result = await holoSphere.get(testHolon, testLens, testData.id, 'wrong_password');
73
+ expect(result).toBeNull();
74
+ }, 10000);
75
+ });
76
+
77
+ describe('Schema Validation', () => {
78
+ it('should only validate schema in strict mode', async () => {
79
+ const schema = {
80
+ type: 'object',
81
+ properties: {
82
+ id: { type: 'string' },
83
+ value: { type: 'number' }
84
+ },
85
+ required: ['id', 'value']
86
+ };
87
+
88
+ // Set schema for both instances
89
+ await holoSphere.setSchema(testLens, schema);
90
+ await strictHoloSphere.setSchema(testLens, schema);
91
+
92
+ const invalidData = { id: 'invalid' }; // Missing required 'value' field
93
+
94
+ // Should work in non-strict mode
95
+ await expect(holoSphere.put(testHolon, testLens, invalidData)).resolves.toBeTruthy();
96
+
97
+ // Should fail in strict mode
98
+ await expect(strictHoloSphere.put(testHolon, testLens, invalidData))
99
+ .rejects.toThrow('Schema validation failed');
100
+ }, 10000);
101
+
102
+ it('should require schema in strict mode', async () => {
103
+ const testData = { id: 'test', value: 123 };
104
+
105
+ // Should work in non-strict mode without schema
106
+ await expect(holoSphere.put(testHolon, testLens, testData)).resolves.toBeTruthy();
107
+
108
+ // Delete any existing schema
109
+ await strictHoloSphere.putGlobal('schemas', { id: testLens, schema: null });
110
+
111
+ // Should fail in strict mode without schema
112
+ try {
113
+ await strictHoloSphere.put(testHolon, testLens, testData);
114
+ fail('Should have thrown an error');
115
+ } catch (error) {
116
+ expect(error.message).toBe('Schema required in strict mode');
117
+ }
118
+ }, 10000);
119
+ });
120
+
121
+ describe('Private Data Operations', () => {
122
+ it('should store and retrieve private data with password', async () => {
123
+ const testData = { id: 'test3', value: 123 };
124
+
125
+ await holoSphere.put(testHolon, testLens, testData, testPassword);
126
+
127
+ const result = await holoSphere.get(testHolon, testLens, testData.id, testPassword);
128
+ expect(result).toEqual(testData);
129
+ });
130
+
131
+ it('should handle public data access', async () => {
132
+ const testData = { id: 'public', value: 456 };
133
+
134
+ await holoSphere.put(testHolon, testLens, testData);
135
+
136
+ const result = await holoSphere.get(testHolon, testLens, testData.id);
137
+ expect(result).toEqual(testData);
138
+ });
139
+
140
+ it('should prevent unauthorized access to private data', async () => {
141
+ const testData = { id: 'private', value: 789 };
142
+
143
+ // Store with password
144
+ await holoSphere.put(testHolon, testLens, testData, testPassword);
145
+
146
+ // Try to retrieve without password
147
+ const result = await holoSphere.get(testHolon, testLens, testData.id);
148
+ expect(result).toBeNull();
149
+ });
150
+
151
+ it('should handle deletion of private data', async () => {
152
+ const testData = { id: 'delete', value: 101 };
153
+
154
+ await holoSphere.put(testHolon, testLens, testData, testPassword);
155
+ await holoSphere.delete(testHolon, testLens, testData.id, testPassword);
156
+
157
+ const result = await holoSphere.get(testHolon, testLens, testData.id, testPassword);
158
+ expect(result).toBeNull();
159
+ });
160
+
161
+ it('should handle multiple private data versions', async () => {
162
+ const versions = [
163
+ { id: 'version1', value: 1 },
164
+ { id: 'version2', value: 2 },
165
+ { id: 'version3', value: 3 }
166
+ ];
167
+
168
+ // Clean up any existing data first
169
+ await holoSphere.deleteAll(testHolon, testLens, testPassword);
170
+
171
+ // Store each version
172
+ for (const data of versions) {
173
+ await holoSphere.put(testHolon, testLens, data, testPassword);
174
+ }
175
+
176
+ // Wait a bit for data to settle
177
+ await new Promise(resolve => setTimeout(resolve, 1000));
178
+
179
+ const results = await holoSphere.getAll(testHolon, testLens, testPassword);
180
+ expect(results.length).toBe(versions.length);
181
+ for (const version of versions) {
182
+ expect(results).toContainEqual(expect.objectContaining(version));
183
+ }
184
+ }, 10000);
185
+ });
186
+
187
+ describe('Global Data Operations', () => {
188
+ it('should handle private global data', async () => {
189
+ const testData = { id: 'global', value: 111 };
190
+
191
+ await holoSphere.putGlobal('testTable', testData, testPassword);
192
+
193
+ const result = await holoSphere.getGlobal('testTable', testData.id, testPassword);
194
+ expect(result).toEqual(testData);
195
+ });
196
+
197
+ it('should handle public global data', async () => {
198
+ const testData = { id: 'public_global', value: 222 };
199
+
200
+ await holoSphere.putGlobal('testTable', testData);
201
+
202
+ const result = await holoSphere.getGlobal('testTable', testData.id);
203
+ expect(result).toEqual(testData);
204
+ });
205
+
206
+ it('should handle getAllGlobal with private data', async () => {
207
+ const testData = [
208
+ { id: 'global1', value: 1 },
209
+ { id: 'global2', value: 2 }
210
+ ];
211
+
212
+ // Clean up any existing data first
213
+ await holoSphere.deleteAllGlobal('testTable', testPassword);
214
+
215
+ // Store each item
216
+ for (const data of testData) {
217
+ await holoSphere.putGlobal('testTable', data, testPassword);
218
+ }
219
+
220
+ // Wait a bit for data to settle
221
+ await new Promise(resolve => setTimeout(resolve, 1000));
222
+
223
+ const results = await holoSphere.getAllGlobal('testTable', testPassword);
224
+ expect(results.length).toBe(testData.length);
225
+ for (const data of testData) {
226
+ expect(results).toContainEqual(expect.objectContaining(data));
227
+ }
228
+ }, 10000);
229
+
230
+ it('should handle deleteGlobal with private data', async () => {
231
+ const testData = { id: 'delete_global', value: 333 };
232
+
233
+ await holoSphere.putGlobal('testTable', testData, testPassword);
234
+
235
+ await holoSphere.deleteGlobal('testTable', testData.id, testPassword);
236
+
237
+ const result = await holoSphere.getGlobal('testTable', testData.id, testPassword);
238
+ expect(result).toBeNull();
239
+ });
240
+ });
241
+ });
@@ -0,0 +1,225 @@
1
+ import HoloSphere from '../holosphere.js';
2
+ import { jest } from '@jest/globals';
3
+
4
+ // Configure Jest
5
+ jest.setTimeout(30000); // 30 second timeout
6
+
7
+ describe('HoloSphere Deletion Tests', () => {
8
+ const testAppName = 'test-app-deletion';
9
+ const testHolon = 'testHolonDeletion';
10
+ const testLens = 'testLensDeletion';
11
+ const testGlobalTable = 'testGlobalTable';
12
+ const testPassword = 'testPassword1234';
13
+ let holoSphere;
14
+
15
+ beforeAll(async () => {
16
+ holoSphere = new HoloSphere(testAppName, false, null);
17
+ });
18
+
19
+ afterAll(async () => {
20
+ // Clean up all test data
21
+ await holoSphere.deleteAll(testHolon, testLens);
22
+ await holoSphere.deleteAllGlobal(testGlobalTable);
23
+
24
+ // Close Gun connections
25
+ if (holoSphere) {
26
+ await holoSphere.close();
27
+ }
28
+
29
+ // Wait for connections to close
30
+ await new Promise(resolve => setTimeout(resolve, 1000));
31
+ });
32
+
33
+ describe('Basic Deletion', () => {
34
+ test('should delete a single item properly', async () => {
35
+ // Create test data
36
+ const testData = { id: 'delete-test-1', value: 'delete me' };
37
+
38
+ // Store data
39
+ await holoSphere.put(testHolon, testLens, testData);
40
+
41
+ // Verify data exists
42
+ const storedData = await holoSphere.get(testHolon, testLens, testData.id);
43
+ expect(storedData).toBeDefined();
44
+ expect(storedData.value).toBe(testData.value);
45
+
46
+ // Delete data
47
+ const deleteResult = await holoSphere.delete(testHolon, testLens, testData.id);
48
+ expect(deleteResult).toBe(true);
49
+
50
+ // Verify data is deleted
51
+ const deletedData = await holoSphere.get(testHolon, testLens, testData.id);
52
+ expect(deletedData).toBeNull();
53
+ });
54
+
55
+ test('should delete a node properly', async () => {
56
+ // Create test node data
57
+ const nodeData = { value: 'node-to-delete' };
58
+ const nodeKey = 'test-node-key';
59
+
60
+ // Store node
61
+ await holoSphere.putNode(testHolon, testLens, { id: nodeKey, value: nodeData });
62
+
63
+ // Verify node exists
64
+ const storedNode = await holoSphere.getNode(testHolon, testLens, 'value');
65
+ expect(storedNode).toBeDefined();
66
+
67
+ // Delete node
68
+ const deleteResult = await holoSphere.deleteNode(testHolon, testLens, 'value');
69
+ expect(deleteResult).toBe(true);
70
+
71
+ // Verify node is deleted
72
+ const deletedNode = await holoSphere.getNode(testHolon, testLens, 'value');
73
+ expect(deletedNode).toBeNull();
74
+ });
75
+ });
76
+
77
+ describe('Bulk Deletion', () => {
78
+ test('should delete all items in a lens', async () => {
79
+ // Create multiple test items
80
+ const items = [
81
+ { id: 'bulk-delete-1', value: 'bulk 1' },
82
+ { id: 'bulk-delete-2', value: 'bulk 2' },
83
+ { id: 'bulk-delete-3', value: 'bulk 3' }
84
+ ];
85
+
86
+ // Store all items
87
+ for (const item of items) {
88
+ await holoSphere.put(testHolon, testLens, item);
89
+ }
90
+
91
+ // Verify items exist
92
+ const allItems = await holoSphere.getAll(testHolon, testLens);
93
+ expect(allItems.length).toBeGreaterThanOrEqual(items.length);
94
+
95
+ // Delete all items
96
+ const deleteAllResult = await holoSphere.deleteAll(testHolon, testLens);
97
+ expect(deleteAllResult).toBe(true);
98
+
99
+ // Verify all items are deleted
100
+ const remainingItems = await holoSphere.getAll(testHolon, testLens);
101
+ expect(remainingItems.length).toBe(0);
102
+ });
103
+ });
104
+
105
+ describe('Global Table Deletion', () => {
106
+ test('should delete global items properly', async () => {
107
+ // Create global test data
108
+ const globalData = { id: 'global-delete-test', value: 'global delete me' };
109
+
110
+ // Store global data
111
+ await holoSphere.putGlobal(testGlobalTable, globalData);
112
+
113
+ // Verify global data exists
114
+ const storedGlobalData = await holoSphere.getGlobal(testGlobalTable, globalData.id);
115
+ expect(storedGlobalData).toBeDefined();
116
+ expect(storedGlobalData.value).toBe(globalData.value);
117
+
118
+ // Delete global data
119
+ const deleteResult = await holoSphere.deleteGlobal(testGlobalTable, globalData.id);
120
+ expect(deleteResult).toBe(true);
121
+
122
+ // Verify global data is deleted
123
+ const deletedGlobalData = await holoSphere.getGlobal(testGlobalTable, globalData.id);
124
+ expect(deletedGlobalData).toBeNull();
125
+ });
126
+
127
+ test('should delete all global items in a table', async () => {
128
+ // Create multiple global test items
129
+ const items = [
130
+ { id: 'global-bulk-1', value: 'global bulk 1' },
131
+ { id: 'global-bulk-2', value: 'global bulk 2' },
132
+ { id: 'global-bulk-3', value: 'global bulk 3' }
133
+ ];
134
+
135
+ // Store all global items
136
+ for (const item of items) {
137
+ await holoSphere.putGlobal(testGlobalTable, item);
138
+ }
139
+
140
+ // Verify global items exist
141
+ const allGlobalItems = await holoSphere.getAllGlobal(testGlobalTable);
142
+ expect(allGlobalItems.length).toBeGreaterThanOrEqual(items.length);
143
+
144
+ // Delete all global items
145
+ const deleteAllResult = await holoSphere.deleteAllGlobal(testGlobalTable);
146
+ expect(deleteAllResult).toBe(true);
147
+
148
+ // Verify all global items are deleted
149
+ const remainingGlobalItems = await holoSphere.getAllGlobal(testGlobalTable);
150
+ expect(remainingGlobalItems.length).toBe(0);
151
+ });
152
+ });
153
+
154
+ describe('Private Data Deletion', () => {
155
+ test('should delete private data properly', async () => {
156
+ // Create private test data
157
+ const privateData = { id: 'private-delete-test', value: 'private delete me' };
158
+
159
+ // Store private data
160
+ await holoSphere.put(testHolon, testLens, privateData, testPassword);
161
+
162
+ // Verify private data exists
163
+ const storedPrivateData = await holoSphere.get(testHolon, testLens, privateData.id, testPassword);
164
+ expect(storedPrivateData).toBeDefined();
165
+ expect(storedPrivateData.value).toBe(privateData.value);
166
+
167
+ // Delete private data
168
+ const deleteResult = await holoSphere.delete(testHolon, testLens, privateData.id, testPassword);
169
+ expect(deleteResult).toBe(true);
170
+
171
+ // Verify private data is deleted
172
+ const deletedPrivateData = await holoSphere.get(testHolon, testLens, privateData.id, testPassword);
173
+ expect(deletedPrivateData).toBeNull();
174
+ });
175
+
176
+ test('should delete all private items in a lens', async () => {
177
+ // Create multiple private test items
178
+ const items = [
179
+ { id: 'private-bulk-1', value: 'private bulk 1' },
180
+ { id: 'private-bulk-2', value: 'private bulk 2' },
181
+ { id: 'private-bulk-3', value: 'private bulk 3' }
182
+ ];
183
+
184
+ // Store all private items
185
+ for (const item of items) {
186
+ await holoSphere.put(testHolon, testLens, item, testPassword);
187
+ }
188
+
189
+ // Verify private items exist
190
+ const allPrivateItems = await holoSphere.getAll(testHolon, testLens, testPassword);
191
+ expect(allPrivateItems.length).toBeGreaterThanOrEqual(items.length);
192
+
193
+ // Delete all private items
194
+ const deleteAllResult = await holoSphere.deleteAll(testHolon, testLens, testPassword);
195
+ expect(deleteAllResult).toBe(true);
196
+
197
+ // Verify all private items are deleted
198
+ const remainingPrivateItems = await holoSphere.getAll(testHolon, testLens, testPassword);
199
+ expect(remainingPrivateItems.length).toBe(0);
200
+ });
201
+ });
202
+
203
+ describe('Edge Cases', () => {
204
+ test('should handle deletion of non-existent items gracefully', async () => {
205
+ // Try to delete non-existent item
206
+ const deleteResult = await holoSphere.delete(testHolon, testLens, 'non-existent-id');
207
+ expect(deleteResult).toBe(true); // Gun returns success even for non-existent items
208
+
209
+ // Try to delete non-existent global item
210
+ const deleteGlobalResult = await holoSphere.deleteGlobal(testGlobalTable, 'non-existent-global-id');
211
+ expect(deleteGlobalResult).toBe(true);
212
+ });
213
+
214
+ test('should handle invalid parameters gracefully', async () => {
215
+ // Test with missing parameters
216
+ await expect(holoSphere.delete(null, testLens, 'test-id')).rejects.toThrow();
217
+ await expect(holoSphere.delete(testHolon, null, 'test-id')).rejects.toThrow();
218
+ await expect(holoSphere.delete(testHolon, testLens, null)).rejects.toThrow();
219
+
220
+ // Test with missing global parameters
221
+ await expect(holoSphere.deleteGlobal(null, 'test-id')).rejects.toThrow();
222
+ await expect(holoSphere.deleteGlobal(testGlobalTable, null)).rejects.toThrow();
223
+ });
224
+ });
225
+ });