@rebasepro/server-postgresql 0.0.1-canary.4d4fb3e
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/LICENSE +6 -0
- package/README.md +106 -0
- package/build-errors.txt +37 -0
- package/dist/common/src/collections/CollectionRegistry.d.ts +48 -0
- package/dist/common/src/collections/index.d.ts +1 -0
- package/dist/common/src/data/buildRebaseData.d.ts +14 -0
- package/dist/common/src/index.d.ts +3 -0
- package/dist/common/src/util/builders.d.ts +57 -0
- package/dist/common/src/util/callbacks.d.ts +6 -0
- package/dist/common/src/util/collections.d.ts +11 -0
- package/dist/common/src/util/common.d.ts +2 -0
- package/dist/common/src/util/conditions.d.ts +26 -0
- package/dist/common/src/util/entities.d.ts +36 -0
- package/dist/common/src/util/enums.d.ts +3 -0
- package/dist/common/src/util/index.d.ts +16 -0
- package/dist/common/src/util/navigation_from_path.d.ts +34 -0
- package/dist/common/src/util/navigation_utils.d.ts +20 -0
- package/dist/common/src/util/parent_references_from_path.d.ts +6 -0
- package/dist/common/src/util/paths.d.ts +14 -0
- package/dist/common/src/util/permissions.d.ts +5 -0
- package/dist/common/src/util/references.d.ts +2 -0
- package/dist/common/src/util/relations.d.ts +12 -0
- package/dist/common/src/util/resolutions.d.ts +72 -0
- package/dist/common/src/util/storage.d.ts +24 -0
- package/dist/index.es.js +10635 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +10643 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/server-postgresql/src/PostgresBackendDriver.d.ts +112 -0
- package/dist/server-postgresql/src/PostgresBootstrapper.d.ts +40 -0
- package/dist/server-postgresql/src/auth/ensure-tables.d.ts +6 -0
- package/dist/server-postgresql/src/auth/services.d.ts +188 -0
- package/dist/server-postgresql/src/cli.d.ts +1 -0
- package/dist/server-postgresql/src/collections/PostgresCollectionRegistry.d.ts +43 -0
- package/dist/server-postgresql/src/connection.d.ts +7 -0
- package/dist/server-postgresql/src/data-transformer.d.ts +36 -0
- package/dist/server-postgresql/src/databasePoolManager.d.ts +20 -0
- package/dist/server-postgresql/src/history/HistoryService.d.ts +71 -0
- package/dist/server-postgresql/src/history/ensure-history-table.d.ts +7 -0
- package/dist/server-postgresql/src/index.d.ts +13 -0
- package/dist/server-postgresql/src/interfaces.d.ts +18 -0
- package/dist/server-postgresql/src/schema/auth-schema.d.ts +767 -0
- package/dist/server-postgresql/src/schema/generate-drizzle-schema-logic.d.ts +2 -0
- package/dist/server-postgresql/src/schema/generate-drizzle-schema.d.ts +1 -0
- package/dist/server-postgresql/src/services/BranchService.d.ts +47 -0
- package/dist/server-postgresql/src/services/EntityFetchService.d.ts +195 -0
- package/dist/server-postgresql/src/services/EntityPersistService.d.ts +41 -0
- package/dist/server-postgresql/src/services/RelationService.d.ts +92 -0
- package/dist/server-postgresql/src/services/entity-helpers.d.ts +24 -0
- package/dist/server-postgresql/src/services/entityService.d.ts +102 -0
- package/dist/server-postgresql/src/services/index.d.ts +4 -0
- package/dist/server-postgresql/src/services/realtimeService.d.ts +186 -0
- package/dist/server-postgresql/src/utils/drizzle-conditions.d.ts +116 -0
- package/dist/server-postgresql/src/websocket.d.ts +5 -0
- package/dist/types/src/controllers/analytics_controller.d.ts +7 -0
- package/dist/types/src/controllers/auth.d.ts +117 -0
- package/dist/types/src/controllers/client.d.ts +58 -0
- package/dist/types/src/controllers/collection_registry.d.ts +44 -0
- package/dist/types/src/controllers/customization_controller.d.ts +54 -0
- package/dist/types/src/controllers/data.d.ts +141 -0
- package/dist/types/src/controllers/data_driver.d.ts +168 -0
- package/dist/types/src/controllers/database_admin.d.ts +11 -0
- package/dist/types/src/controllers/dialogs_controller.d.ts +36 -0
- package/dist/types/src/controllers/effective_role.d.ts +4 -0
- package/dist/types/src/controllers/index.d.ts +17 -0
- package/dist/types/src/controllers/local_config_persistence.d.ts +20 -0
- package/dist/types/src/controllers/navigation.d.ts +213 -0
- package/dist/types/src/controllers/registry.d.ts +51 -0
- package/dist/types/src/controllers/side_dialogs_controller.d.ts +67 -0
- package/dist/types/src/controllers/side_entity_controller.d.ts +89 -0
- package/dist/types/src/controllers/snackbar.d.ts +24 -0
- package/dist/types/src/controllers/storage.d.ts +173 -0
- package/dist/types/src/index.d.ts +4 -0
- package/dist/types/src/rebase_context.d.ts +101 -0
- package/dist/types/src/types/backend.d.ts +533 -0
- package/dist/types/src/types/builders.d.ts +14 -0
- package/dist/types/src/types/chips.d.ts +5 -0
- package/dist/types/src/types/collections.d.ts +812 -0
- package/dist/types/src/types/data_source.d.ts +64 -0
- package/dist/types/src/types/entities.d.ts +145 -0
- package/dist/types/src/types/entity_actions.d.ts +98 -0
- package/dist/types/src/types/entity_callbacks.d.ts +173 -0
- package/dist/types/src/types/entity_link_builder.d.ts +7 -0
- package/dist/types/src/types/entity_overrides.d.ts +9 -0
- package/dist/types/src/types/entity_views.d.ts +61 -0
- package/dist/types/src/types/export_import.d.ts +21 -0
- package/dist/types/src/types/index.d.ts +22 -0
- package/dist/types/src/types/locales.d.ts +4 -0
- package/dist/types/src/types/modify_collections.d.ts +5 -0
- package/dist/types/src/types/plugins.d.ts +225 -0
- package/dist/types/src/types/properties.d.ts +1091 -0
- package/dist/types/src/types/property_config.d.ts +70 -0
- package/dist/types/src/types/relations.d.ts +336 -0
- package/dist/types/src/types/slots.d.ts +228 -0
- package/dist/types/src/types/translations.d.ts +826 -0
- package/dist/types/src/types/user_management_delegate.d.ts +120 -0
- package/dist/types/src/types/websockets.d.ts +78 -0
- package/dist/types/src/users/index.d.ts +2 -0
- package/dist/types/src/users/roles.d.ts +22 -0
- package/dist/types/src/users/user.d.ts +46 -0
- package/jest-all.log +3128 -0
- package/jest.log +49 -0
- package/package.json +93 -0
- package/src/PostgresBackendDriver.ts +1024 -0
- package/src/PostgresBootstrapper.ts +232 -0
- package/src/auth/ensure-tables.ts +309 -0
- package/src/auth/services.ts +740 -0
- package/src/cli.ts +347 -0
- package/src/collections/PostgresCollectionRegistry.ts +96 -0
- package/src/connection.ts +62 -0
- package/src/data-transformer.ts +569 -0
- package/src/databasePoolManager.ts +84 -0
- package/src/history/HistoryService.ts +257 -0
- package/src/history/ensure-history-table.ts +45 -0
- package/src/index.ts +13 -0
- package/src/interfaces.ts +60 -0
- package/src/schema/auth-schema.ts +146 -0
- package/src/schema/generate-drizzle-schema-logic.ts +618 -0
- package/src/schema/generate-drizzle-schema.ts +151 -0
- package/src/services/BranchService.ts +237 -0
- package/src/services/EntityFetchService.ts +1447 -0
- package/src/services/EntityPersistService.ts +351 -0
- package/src/services/RelationService.ts +1012 -0
- package/src/services/entity-helpers.ts +121 -0
- package/src/services/entityService.ts +209 -0
- package/src/services/index.ts +13 -0
- package/src/services/realtimeService.ts +1005 -0
- package/src/utils/drizzle-conditions.ts +999 -0
- package/src/websocket.ts +487 -0
- package/test/auth-services.test.ts +569 -0
- package/test/branchService.test.ts +357 -0
- package/test/drizzle-conditions.test.ts +895 -0
- package/test/entityService.errors.test.ts +352 -0
- package/test/entityService.relations.test.ts +912 -0
- package/test/entityService.subcollection-search.test.ts +516 -0
- package/test/entityService.test.ts +977 -0
- package/test/generate-drizzle-schema.test.ts +795 -0
- package/test/historyService.test.ts +126 -0
- package/test/postgresDataDriver.test.ts +556 -0
- package/test/realtimeService.test.ts +276 -0
- package/test/relations.test.ts +662 -0
- package/test_drizzle_mock.js +3 -0
- package/test_find_changed.mjs +30 -0
- package/test_output.txt +3145 -0
- package/tsconfig.json +49 -0
- package/tsconfig.prod.json +20 -0
- package/vite.config.ts +82 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { EntityService } from "../src/services/entityService";
|
|
2
|
+
import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
3
|
+
import { EntityCollection } from "@rebasepro/types";
|
|
4
|
+
import { PostgresCollectionRegistry } from "../src/collections/PostgresCollectionRegistry";
|
|
5
|
+
const collectionRegistry = new PostgresCollectionRegistry();
|
|
6
|
+
|
|
7
|
+
describe("EntityService - Error Handling & Edge Cases", () => {
|
|
8
|
+
let entityService: EntityService;
|
|
9
|
+
let db: jest.Mocked<NodePgDatabase<any>>;
|
|
10
|
+
|
|
11
|
+
const mockTable = {
|
|
12
|
+
id: { name: "id", dataType: "number" },
|
|
13
|
+
name: { name: "name" },
|
|
14
|
+
_def: { tableName: "test_table" }
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const testCollection: EntityCollection = {
|
|
18
|
+
slug: "test",
|
|
19
|
+
name: "Test Collection",
|
|
20
|
+
table: "test_table",
|
|
21
|
+
properties: {
|
|
22
|
+
id: { type: "number" },
|
|
23
|
+
name: { type: "string" }
|
|
24
|
+
},
|
|
25
|
+
idField: "id"
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
jest.clearAllMocks();
|
|
30
|
+
|
|
31
|
+
jest.spyOn(collectionRegistry, "getCollectionByPath").mockImplementation(path => {
|
|
32
|
+
if (path === "test" || path === "test_table") return testCollection;
|
|
33
|
+
return undefined;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
jest.spyOn(collectionRegistry, "getTable").mockImplementation(tableName => {
|
|
37
|
+
if (tableName === "test_table") return mockTable as any;
|
|
38
|
+
return undefined;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
db = {
|
|
42
|
+
select: jest.fn().mockReturnThis(),
|
|
43
|
+
from: jest.fn().mockReturnThis(),
|
|
44
|
+
where: jest.fn().mockReturnThis(),
|
|
45
|
+
$dynamic: jest.fn().mockReturnThis(),
|
|
46
|
+
limit: jest.fn().mockReturnThis(),
|
|
47
|
+
orderBy: jest.fn().mockReturnThis(),
|
|
48
|
+
innerJoin: jest.fn().mockReturnThis(),
|
|
49
|
+
insert: jest.fn().mockReturnThis(),
|
|
50
|
+
values: jest.fn().mockReturnThis(),
|
|
51
|
+
returning: jest.fn().mockResolvedValue([]),
|
|
52
|
+
update: jest.fn().mockReturnThis(),
|
|
53
|
+
set: jest.fn().mockReturnThis(),
|
|
54
|
+
delete: jest.fn().mockReturnThis(),
|
|
55
|
+
transaction: jest.fn((callback) => callback(db)),
|
|
56
|
+
} as any;
|
|
57
|
+
|
|
58
|
+
// Add a then method to make the db object awaitable when the query chain ends
|
|
59
|
+
(db as any).then = jest.fn((resolve) => resolve([]));
|
|
60
|
+
|
|
61
|
+
entityService = new EntityService(db, collectionRegistry);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("Collection Registry Errors", () => {
|
|
65
|
+
it("should throw error when collection is not found", async () => {
|
|
66
|
+
await expect(
|
|
67
|
+
entityService.fetchEntity("nonexistent", 1)
|
|
68
|
+
).rejects.toThrow("Collection not found: nonexistent");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("should throw error when table is not found for collection", async () => {
|
|
72
|
+
jest.spyOn(collectionRegistry, "getTable").mockReturnValue(undefined);
|
|
73
|
+
|
|
74
|
+
await expect(
|
|
75
|
+
entityService.fetchEntity("test", 1)
|
|
76
|
+
).rejects.toThrow("Table not found for collection");
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe("ID Type Validation", () => {
|
|
83
|
+
it("should handle valid numeric ID strings", async () => {
|
|
84
|
+
const mockEntity = { id: 123, name: "Test" };
|
|
85
|
+
db.limit.mockResolvedValue([mockEntity]);
|
|
86
|
+
|
|
87
|
+
const entity = await entityService.fetchEntity("test", "123");
|
|
88
|
+
expect(entity?.id).toBe("123");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("should throw error for invalid numeric ID", async () => {
|
|
92
|
+
await expect(
|
|
93
|
+
entityService.fetchEntity("test", "invalid-number")
|
|
94
|
+
).rejects.toThrow("Invalid numeric ID: invalid-number");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("should handle zero as valid ID", async () => {
|
|
98
|
+
const mockEntity = { id: 0, name: "Test" };
|
|
99
|
+
db.limit.mockResolvedValue([mockEntity]);
|
|
100
|
+
|
|
101
|
+
const entity = await entityService.fetchEntity("test", 0);
|
|
102
|
+
expect(entity?.id).toBe("0");
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("should handle negative numbers as valid ID", async () => {
|
|
106
|
+
const mockEntity = { id: -1, name: "Test" };
|
|
107
|
+
db.limit.mockResolvedValue([mockEntity]);
|
|
108
|
+
|
|
109
|
+
const entity = await entityService.fetchEntity("test", -1);
|
|
110
|
+
expect(entity?.id).toBe("-1");
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe("Database Operation Errors", () => {
|
|
115
|
+
it("should propagate database connection errors on fetch", async () => {
|
|
116
|
+
const dbError = new Error("Connection timeout");
|
|
117
|
+
db.limit.mockRejectedValue(dbError);
|
|
118
|
+
|
|
119
|
+
await expect(
|
|
120
|
+
entityService.fetchEntity("test", 1)
|
|
121
|
+
).rejects.toThrow("Connection timeout");
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("should propagate database errors on save", async () => {
|
|
125
|
+
const dbError = new Error("Constraint violation");
|
|
126
|
+
db.returning.mockRejectedValue(dbError);
|
|
127
|
+
|
|
128
|
+
await expect(
|
|
129
|
+
entityService.saveEntity("test", { name: "Test" })
|
|
130
|
+
).rejects.toThrow("Constraint violation");
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("should propagate database errors on delete", async () => {
|
|
134
|
+
const dbError = new Error("Foreign key constraint");
|
|
135
|
+
// Fix: Mock the delete method since deleteEntity doesn't use returning()
|
|
136
|
+
db.delete.mockReturnValue({
|
|
137
|
+
where: jest.fn().mockRejectedValue(dbError)
|
|
138
|
+
} as any);
|
|
139
|
+
|
|
140
|
+
await expect(
|
|
141
|
+
entityService.deleteEntity("test", 1)
|
|
142
|
+
).rejects.toThrow("Foreign key constraint");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("should handle transaction rollback scenarios", async () => {
|
|
146
|
+
const transactionError = new Error("Transaction failed");
|
|
147
|
+
db.transaction.mockImplementation((callback) => {
|
|
148
|
+
throw transactionError;
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
await expect(
|
|
152
|
+
entityService.saveEntity("test", { name: "Test" })
|
|
153
|
+
).rejects.toThrow("Transaction failed");
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe("Path Validation", () => {
|
|
158
|
+
it("should reject paths with even number of segments", async () => {
|
|
159
|
+
await expect(
|
|
160
|
+
entityService.fetchCollection("collection/id", {})
|
|
161
|
+
).rejects.toThrow("Invalid relation path: collection/id");
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("should reject single segment paths (not nested)", async () => {
|
|
165
|
+
// Single collection paths should work fine, but let's test the path parsing logic
|
|
166
|
+
const entities = await entityService.fetchCollection("test", {});
|
|
167
|
+
expect(entities).toBeDefined(); // Should work for single collection
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("should reject empty path segments", async () => {
|
|
171
|
+
await expect(
|
|
172
|
+
entityService.fetchCollection("collection//relation", {})
|
|
173
|
+
).rejects.toThrow("Invalid relation path");
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
describe("Concurrent Operations", () => {
|
|
178
|
+
it("should handle multiple simultaneous reads", async () => {
|
|
179
|
+
const mockEntity = { id: 1, name: "Test" };
|
|
180
|
+
db.limit.mockResolvedValue([mockEntity]);
|
|
181
|
+
|
|
182
|
+
const promises = Array(10).fill(0).map(() =>
|
|
183
|
+
entityService.fetchEntity("test", 1)
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
const results = await Promise.all(promises);
|
|
187
|
+
|
|
188
|
+
expect(results).toHaveLength(10);
|
|
189
|
+
results.forEach(result => {
|
|
190
|
+
expect(result?.id).toBe("1");
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it("should handle race conditions in write operations", async () => {
|
|
195
|
+
db.returning.mockResolvedValue([{ id: 1 }]);
|
|
196
|
+
db.limit.mockResolvedValue([{ id: 1, name: "Updated" }]);
|
|
197
|
+
|
|
198
|
+
const promises = Array(5).fill(0).map((_, i) =>
|
|
199
|
+
entityService.saveEntity("test", { name: `Update ${i}` }, 1)
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
const results = await Promise.all(promises);
|
|
203
|
+
|
|
204
|
+
expect(results).toHaveLength(5);
|
|
205
|
+
// All should succeed due to transaction handling
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe("Memory and Performance", () => {
|
|
210
|
+
it("should handle large result sets without memory issues", async () => {
|
|
211
|
+
const largeResultSet = Array(1000).fill(0).map((_, i) => ({
|
|
212
|
+
id: i,
|
|
213
|
+
name: `Entity ${i}`
|
|
214
|
+
}));
|
|
215
|
+
db.orderBy.mockResolvedValue(largeResultSet);
|
|
216
|
+
|
|
217
|
+
const entities = await entityService.fetchCollection("test", {});
|
|
218
|
+
|
|
219
|
+
expect(entities).toHaveLength(1000);
|
|
220
|
+
expect(entities[0].values.name).toBe("Entity 0");
|
|
221
|
+
expect(entities[999].values.name).toBe("Entity 999");
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("should handle pagination correctly for large datasets", async () => {
|
|
225
|
+
const mockEntities = Array(50).fill(0).map((_, i) => ({
|
|
226
|
+
id: i + 1,
|
|
227
|
+
name: `Entity ${i + 1}`
|
|
228
|
+
}));
|
|
229
|
+
// Override the then method to return our mock data for this specific test
|
|
230
|
+
(db as any).then = jest.fn((resolve) => resolve(mockEntities.slice(0, 20)));
|
|
231
|
+
|
|
232
|
+
const entities = await entityService.fetchCollection("test", {
|
|
233
|
+
limit: 20
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
expect(entities).toHaveLength(20);
|
|
237
|
+
expect(db.limit).toHaveBeenCalledWith(20);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
describe("Data Integrity", () => {
|
|
242
|
+
it("should validate required fields are present", async () => {
|
|
243
|
+
const incompleteEntity = {}; // Missing required fields
|
|
244
|
+
|
|
245
|
+
db.returning.mockResolvedValue([{ id: 1 }]);
|
|
246
|
+
db.limit.mockResolvedValue([{ id: 1, name: null }]);
|
|
247
|
+
|
|
248
|
+
// The service should handle validation at the collection level
|
|
249
|
+
// This test verifies the service doesn't crash with incomplete data
|
|
250
|
+
const entity = await entityService.saveEntity("test", incompleteEntity);
|
|
251
|
+
expect(entity.id).toBe("1");
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it("should handle NULL values in database correctly", async () => {
|
|
255
|
+
const mockEntity = { id: 1, name: null };
|
|
256
|
+
db.limit.mockResolvedValue([mockEntity]);
|
|
257
|
+
|
|
258
|
+
const entity = await entityService.fetchEntity("test", 1);
|
|
259
|
+
expect(entity?.values.name).toBeNull();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("should handle undefined values in input data", async () => {
|
|
263
|
+
const entityWithUndefined = { name: undefined };
|
|
264
|
+
|
|
265
|
+
db.returning.mockResolvedValue([{ id: 1 }]);
|
|
266
|
+
db.limit.mockResolvedValue([{ id: 1, name: null }]);
|
|
267
|
+
|
|
268
|
+
const entity = await entityService.saveEntity("test", entityWithUndefined);
|
|
269
|
+
expect(entity.id).toBe("1");
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
describe("Security and Validation", () => {
|
|
274
|
+
it("should handle SQL injection attempts in IDs safely", async () => {
|
|
275
|
+
const maliciousId = "1; DROP TABLE test_table;--";
|
|
276
|
+
|
|
277
|
+
// The service should handle this safely through parameterized queries
|
|
278
|
+
// This test should not throw an error because of proper parameterization
|
|
279
|
+
const mockEntity = { id: 1, name: "Safe" };
|
|
280
|
+
db.limit.mockResolvedValue([mockEntity]);
|
|
281
|
+
|
|
282
|
+
const entity = await entityService.fetchEntity("test", maliciousId);
|
|
283
|
+
expect(entity).toBeDefined(); // Should work safely
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it("should handle extremely long input values", async () => {
|
|
287
|
+
const veryLongString = "a".repeat(10000);
|
|
288
|
+
const entityWithLongValue = { name: veryLongString };
|
|
289
|
+
|
|
290
|
+
db.returning.mockResolvedValue([{ id: 1 }]);
|
|
291
|
+
db.limit.mockResolvedValue([{ id: 1, name: veryLongString }]);
|
|
292
|
+
|
|
293
|
+
const entity = await entityService.saveEntity("test", entityWithLongValue);
|
|
294
|
+
expect(entity.values.name).toBe(veryLongString);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it("should handle special characters in string values", async () => {
|
|
298
|
+
const specialChars = "!@#$%^&*()_+-=[]{}|;':\",./<>?`~";
|
|
299
|
+
const entityWithSpecialChars = { name: specialChars };
|
|
300
|
+
|
|
301
|
+
db.returning.mockResolvedValue([{ id: 1 }]);
|
|
302
|
+
db.limit.mockResolvedValue([{ id: 1, name: specialChars }]);
|
|
303
|
+
|
|
304
|
+
const entity = await entityService.saveEntity("test", entityWithSpecialChars);
|
|
305
|
+
expect(entity.values.name).toBe(specialChars);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
describe("Edge Case Data Types", () => {
|
|
310
|
+
it("should handle boolean false values correctly", async () => {
|
|
311
|
+
const booleanCollection = {
|
|
312
|
+
...testCollection,
|
|
313
|
+
properties: {
|
|
314
|
+
id: { type: "number" },
|
|
315
|
+
active: { type: "boolean" }
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
jest.spyOn(collectionRegistry, "getCollectionByPath").mockReturnValue(booleanCollection);
|
|
319
|
+
|
|
320
|
+
const mockEntity = { id: 1, active: false };
|
|
321
|
+
db.limit.mockResolvedValue([mockEntity]);
|
|
322
|
+
|
|
323
|
+
const entity = await entityService.fetchEntity("test", 1);
|
|
324
|
+
expect(entity?.values.active).toBe(false);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it("should handle zero values correctly", async () => {
|
|
328
|
+
const numericCollection = {
|
|
329
|
+
...testCollection,
|
|
330
|
+
properties: {
|
|
331
|
+
id: { type: "number" },
|
|
332
|
+
count: { type: "number" }
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
jest.spyOn(collectionRegistry, "getCollectionByPath").mockReturnValue(numericCollection);
|
|
336
|
+
|
|
337
|
+
const mockEntity = { id: 1, count: 0 };
|
|
338
|
+
db.limit.mockResolvedValue([mockEntity]);
|
|
339
|
+
|
|
340
|
+
const entity = await entityService.fetchEntity("test", 1);
|
|
341
|
+
expect(entity?.values.count).toBe(0);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
it("should handle empty string values correctly", async () => {
|
|
345
|
+
const mockEntity = { id: 1, name: "" };
|
|
346
|
+
db.limit.mockResolvedValue([mockEntity]);
|
|
347
|
+
|
|
348
|
+
const entity = await entityService.fetchEntity("test", 1);
|
|
349
|
+
expect(entity?.values.name).toBe("");
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
});
|