@rebasepro/server-postgresql 0.0.1-canary.4d4fb3e → 0.0.1-canary.ca2cb6e
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/dist/common/src/collections/CollectionRegistry.d.ts +8 -0
- package/dist/common/src/util/entities.d.ts +22 -0
- package/dist/common/src/util/relations.d.ts +14 -4
- package/dist/common/src/util/resolutions.d.ts +1 -1
- package/dist/index.es.js +1254 -591
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1254 -591
- package/dist/index.umd.js.map +1 -1
- package/dist/server-postgresql/src/PostgresBackendDriver.d.ts +17 -29
- package/dist/server-postgresql/src/auth/services.d.ts +7 -3
- package/dist/server-postgresql/src/collections/PostgresCollectionRegistry.d.ts +1 -1
- package/dist/server-postgresql/src/connection.d.ts +34 -1
- package/dist/server-postgresql/src/data-transformer.d.ts +26 -4
- package/dist/server-postgresql/src/databasePoolManager.d.ts +2 -2
- package/dist/server-postgresql/src/schema/auth-schema.d.ts +139 -38
- package/dist/server-postgresql/src/schema/doctor-cli.d.ts +2 -0
- package/dist/server-postgresql/src/schema/doctor.d.ts +43 -0
- package/dist/server-postgresql/src/schema/generate-drizzle-schema-logic.d.ts +1 -1
- package/dist/server-postgresql/src/schema/test-schema.d.ts +24 -0
- package/dist/server-postgresql/src/services/EntityFetchService.d.ts +22 -8
- package/dist/server-postgresql/src/services/EntityPersistService.d.ts +1 -1
- package/dist/server-postgresql/src/services/RelationService.d.ts +11 -5
- package/dist/server-postgresql/src/services/entity-helpers.d.ts +16 -2
- package/dist/server-postgresql/src/services/entityService.d.ts +8 -6
- package/dist/server-postgresql/src/services/realtimeService.d.ts +2 -0
- package/dist/server-postgresql/src/utils/drizzle-conditions.d.ts +2 -2
- package/dist/types/src/controllers/auth.d.ts +2 -0
- package/dist/types/src/controllers/client.d.ts +119 -7
- package/dist/types/src/controllers/collection_registry.d.ts +4 -3
- package/dist/types/src/controllers/customization_controller.d.ts +7 -1
- package/dist/types/src/controllers/data.d.ts +34 -7
- package/dist/types/src/controllers/data_driver.d.ts +20 -28
- package/dist/types/src/controllers/database_admin.d.ts +2 -2
- package/dist/types/src/controllers/email.d.ts +34 -0
- package/dist/types/src/controllers/index.d.ts +1 -0
- package/dist/types/src/controllers/local_config_persistence.d.ts +4 -4
- package/dist/types/src/controllers/navigation.d.ts +5 -5
- package/dist/types/src/controllers/registry.d.ts +6 -3
- package/dist/types/src/controllers/side_entity_controller.d.ts +7 -6
- package/dist/types/src/controllers/storage.d.ts +24 -26
- package/dist/types/src/rebase_context.d.ts +8 -4
- package/dist/types/src/types/backend.d.ts +4 -1
- package/dist/types/src/types/builders.d.ts +5 -4
- package/dist/types/src/types/chips.d.ts +1 -1
- package/dist/types/src/types/collections.d.ts +169 -125
- package/dist/types/src/types/cron.d.ts +102 -0
- package/dist/types/src/types/data_source.d.ts +1 -1
- package/dist/types/src/types/entity_actions.d.ts +8 -8
- package/dist/types/src/types/entity_callbacks.d.ts +15 -15
- package/dist/types/src/types/entity_link_builder.d.ts +1 -1
- package/dist/types/src/types/entity_overrides.d.ts +2 -1
- package/dist/types/src/types/entity_views.d.ts +8 -8
- package/dist/types/src/types/export_import.d.ts +3 -3
- package/dist/types/src/types/index.d.ts +1 -0
- package/dist/types/src/types/plugins.d.ts +72 -18
- package/dist/types/src/types/properties.d.ts +118 -33
- package/dist/types/src/types/relations.d.ts +1 -1
- package/dist/types/src/types/slots.d.ts +30 -6
- package/dist/types/src/types/translations.d.ts +44 -0
- package/dist/types/src/types/user_management_delegate.d.ts +1 -0
- package/drizzle-test/0000_woozy_junta.sql +6 -0
- package/drizzle-test/0001_youthful_arachne.sql +1 -0
- package/drizzle-test/0002_lively_dragon_lord.sql +2 -0
- package/drizzle-test/0003_mean_king_cobra.sql +2 -0
- package/drizzle-test/meta/0000_snapshot.json +47 -0
- package/drizzle-test/meta/0001_snapshot.json +48 -0
- package/drizzle-test/meta/0002_snapshot.json +38 -0
- package/drizzle-test/meta/0003_snapshot.json +48 -0
- package/drizzle-test/meta/_journal.json +34 -0
- package/drizzle-test-out/0000_tan_trauma.sql +6 -0
- package/drizzle-test-out/0001_rapid_drax.sql +1 -0
- package/drizzle-test-out/meta/0000_snapshot.json +44 -0
- package/drizzle-test-out/meta/0001_snapshot.json +54 -0
- package/drizzle-test-out/meta/_journal.json +20 -0
- package/drizzle.test.config.ts +10 -0
- package/package.json +88 -89
- package/scratch.ts +41 -0
- package/src/PostgresBackendDriver.ts +63 -79
- package/src/PostgresBootstrapper.ts +7 -8
- package/src/auth/ensure-tables.ts +158 -86
- package/src/auth/services.ts +109 -50
- package/src/cli.ts +259 -16
- package/src/collections/PostgresCollectionRegistry.ts +6 -6
- package/src/connection.ts +70 -48
- package/src/data-transformer.ts +155 -116
- package/src/databasePoolManager.ts +6 -5
- package/src/history/HistoryService.ts +3 -12
- package/src/interfaces.ts +3 -3
- package/src/schema/auth-schema.ts +26 -3
- package/src/schema/doctor-cli.ts +47 -0
- package/src/schema/doctor.ts +595 -0
- package/src/schema/generate-drizzle-schema-logic.ts +204 -57
- package/src/schema/generate-drizzle-schema.ts +6 -6
- package/src/schema/test-schema.ts +11 -0
- package/src/services/BranchService.ts +5 -5
- package/src/services/EntityFetchService.ts +317 -188
- package/src/services/EntityPersistService.ts +15 -17
- package/src/services/RelationService.ts +299 -37
- package/src/services/entity-helpers.ts +39 -13
- package/src/services/entityService.ts +11 -9
- package/src/services/realtimeService.ts +58 -29
- package/src/utils/drizzle-conditions.ts +25 -24
- package/src/websocket.ts +52 -21
- package/test/auth-services.test.ts +131 -39
- package/test/batch-many-to-many-regression.test.ts +573 -0
- package/test/branchService.test.ts +22 -12
- package/test/data-transformer-hardening.test.ts +417 -0
- package/test/data-transformer.test.ts +175 -0
- package/test/doctor.test.ts +182 -0
- package/test/entityService.errors.test.ts +31 -16
- package/test/entityService.relations.test.ts +155 -59
- package/test/entityService.subcollection-search.test.ts +107 -57
- package/test/entityService.test.ts +105 -47
- package/test/generate-drizzle-schema.test.ts +262 -69
- package/test/historyService.test.ts +31 -16
- package/test/n-plus-one-regression.test.ts +314 -0
- package/test/postgresDataDriver.test.ts +260 -168
- package/test/realtimeService.test.ts +70 -39
- package/test/relation-pipeline-gaps.test.ts +637 -0
- package/test/relations.test.ts +492 -39
- package/test-drizzle-bug.ts +18 -0
- package/test-drizzle-out/0000_cultured_freak.sql +7 -0
- package/test-drizzle-out/0001_tiresome_professor_monster.sql +1 -0
- package/test-drizzle-out/meta/0000_snapshot.json +55 -0
- package/test-drizzle-out/meta/0001_snapshot.json +63 -0
- package/test-drizzle-out/meta/_journal.json +20 -0
- package/test-drizzle-prompt.sh +2 -0
- package/test-policy-prompt.sh +3 -0
- package/test-programmatic.ts +30 -0
- package/test-programmatic2.ts +59 -0
- package/test-schema-no-policies.ts +12 -0
- package/test_drizzle_mock.js +2 -2
- package/test_find_changed.mjs +3 -1
- package/test_hash.js +14 -0
- package/tsconfig.json +1 -1
- package/vite.config.ts +5 -5
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { EntityCollection, StringProperty, NumberProperty, DateProperty, ArrayProperty, Property } from "@rebasepro/types";
|
|
2
|
+
import { generateSchema } from "../src/schema/generate-drizzle-schema-logic";
|
|
3
|
+
import { checkCollectionsVsSchema, getExpectedColumnType } from "../src/schema/doctor";
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import { tmpdir } from "os";
|
|
7
|
+
|
|
8
|
+
// Re-export for testing — we need to access the internal helper
|
|
9
|
+
// but since it's not exported, we test it indirectly via checkCollectionsVsSchema
|
|
10
|
+
|
|
11
|
+
describe("Rebase Schema Doctor", () => {
|
|
12
|
+
|
|
13
|
+
describe("checkCollectionsVsSchema", () => {
|
|
14
|
+
const createTempSchemaFile = async (content: string): Promise<string> => {
|
|
15
|
+
const dir = fs.mkdtempSync(path.join(tmpdir(), "doctor-test-"));
|
|
16
|
+
const filePath = path.join(dir, "schema.generated.ts");
|
|
17
|
+
fs.writeFileSync(filePath, content, "utf-8");
|
|
18
|
+
return filePath;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
it("should detect missing schema file", async () => {
|
|
22
|
+
const collections: EntityCollection[] = [{
|
|
23
|
+
slug: "products",
|
|
24
|
+
table: "products",
|
|
25
|
+
name: "Products",
|
|
26
|
+
properties: { name: { type: "string" } }
|
|
27
|
+
}];
|
|
28
|
+
|
|
29
|
+
const result = await checkCollectionsVsSchema(collections, "/nonexistent/path/schema.generated.ts");
|
|
30
|
+
expect(result.passed).toBe(false);
|
|
31
|
+
expect(result.issues).toHaveLength(1);
|
|
32
|
+
expect(result.issues[0].category).toBe("schema_stale");
|
|
33
|
+
expect(result.issues[0].severity).toBe("error");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should pass when schema matches collections", async () => {
|
|
37
|
+
const collections: EntityCollection[] = [{
|
|
38
|
+
slug: "products",
|
|
39
|
+
table: "products",
|
|
40
|
+
name: "Products",
|
|
41
|
+
properties: {
|
|
42
|
+
name: { type: "string" },
|
|
43
|
+
price: { type: "number" }
|
|
44
|
+
}
|
|
45
|
+
}];
|
|
46
|
+
|
|
47
|
+
// Generate the expected schema and write to temp file
|
|
48
|
+
const expectedSchema = await generateSchema(collections);
|
|
49
|
+
const schemaPath = await createTempSchemaFile(expectedSchema);
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const result = await checkCollectionsVsSchema(collections, schemaPath);
|
|
53
|
+
expect(result.passed).toBe(true);
|
|
54
|
+
expect(result.issues).toHaveLength(0);
|
|
55
|
+
} finally {
|
|
56
|
+
fs.rmSync(path.dirname(schemaPath), { recursive: true });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("should detect stale schema when collections have changed", async () => {
|
|
61
|
+
const originalCollections: EntityCollection[] = [{
|
|
62
|
+
slug: "products",
|
|
63
|
+
table: "products",
|
|
64
|
+
name: "Products",
|
|
65
|
+
properties: { name: { type: "string" } }
|
|
66
|
+
}];
|
|
67
|
+
|
|
68
|
+
const updatedCollections: EntityCollection[] = [{
|
|
69
|
+
slug: "products",
|
|
70
|
+
table: "products",
|
|
71
|
+
name: "Products",
|
|
72
|
+
properties: {
|
|
73
|
+
name: { type: "string" },
|
|
74
|
+
price: { type: "number" } // New field added
|
|
75
|
+
}
|
|
76
|
+
}];
|
|
77
|
+
|
|
78
|
+
// Write schema for original, check against updated
|
|
79
|
+
const originalSchema = await generateSchema(originalCollections);
|
|
80
|
+
const schemaPath = await createTempSchemaFile(originalSchema);
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
const result = await checkCollectionsVsSchema(updatedCollections, schemaPath);
|
|
84
|
+
expect(result.passed).toBe(false);
|
|
85
|
+
expect(result.issues.some(i => i.category === "schema_stale")).toBe(true);
|
|
86
|
+
} finally {
|
|
87
|
+
fs.rmSync(path.dirname(schemaPath), { recursive: true });
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("should return error for nonexistent schema file even with empty collections", async () => {
|
|
92
|
+
const result = await checkCollectionsVsSchema([], "/nonexistent/path");
|
|
93
|
+
// Schema file doesn't exist → error regardless of collection count
|
|
94
|
+
expect(result.passed).toBe(false);
|
|
95
|
+
expect(result.issues[0].category).toBe("schema_stale");
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe("column type mapping", () => {
|
|
100
|
+
// We test getExpectedColumnType indirectly through import
|
|
101
|
+
// These are integration-style tests against the mapping logic
|
|
102
|
+
|
|
103
|
+
it("should map string types correctly", () => {
|
|
104
|
+
expect(getExpectedColumnType({ type: "string" })).toBe("character varying");
|
|
105
|
+
expect(getExpectedColumnType({ type: "string",
|
|
106
|
+
columnType: "text" } as StringProperty)).toBe("text");
|
|
107
|
+
expect(getExpectedColumnType({ type: "string",
|
|
108
|
+
columnType: "char" } as StringProperty)).toBe("character");
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("should map number types correctly", () => {
|
|
112
|
+
expect(getExpectedColumnType({ type: "number" })).toBe("numeric");
|
|
113
|
+
expect(getExpectedColumnType({ type: "number",
|
|
114
|
+
validation: { integer: true } } as NumberProperty)).toBe("integer");
|
|
115
|
+
expect(getExpectedColumnType({ type: "number",
|
|
116
|
+
columnType: "real" } as NumberProperty)).toBe("real");
|
|
117
|
+
expect(getExpectedColumnType({ type: "number",
|
|
118
|
+
columnType: "double precision" } as NumberProperty)).toBe("double precision");
|
|
119
|
+
expect(getExpectedColumnType({ type: "number",
|
|
120
|
+
columnType: "bigint" } as NumberProperty)).toBe("bigint");
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("should map boolean type correctly", () => {
|
|
124
|
+
expect(getExpectedColumnType({ type: "boolean" })).toBe("boolean");
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("should map date types correctly", () => {
|
|
128
|
+
expect(getExpectedColumnType({ type: "date" })).toBe("timestamp with time zone");
|
|
129
|
+
expect(getExpectedColumnType({ type: "date",
|
|
130
|
+
columnType: "date" } as DateProperty)).toBe("date");
|
|
131
|
+
expect(getExpectedColumnType({ type: "date",
|
|
132
|
+
columnType: "time" } as DateProperty)).toBe("time without time zone");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("should map json types correctly", () => {
|
|
136
|
+
expect(getExpectedColumnType({ type: "map" })).toBe("jsonb");
|
|
137
|
+
expect(getExpectedColumnType({ type: "array" })).toBe("jsonb");
|
|
138
|
+
expect(getExpectedColumnType({ type: "array",
|
|
139
|
+
columnType: "json" } as ArrayProperty)).toBe("json");
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("should map enum string to USER-DEFINED", () => {
|
|
143
|
+
expect(getExpectedColumnType({
|
|
144
|
+
type: "string",
|
|
145
|
+
enum: { active: "Active",
|
|
146
|
+
inactive: "Inactive" }
|
|
147
|
+
} as StringProperty)).toBe("USER-DEFINED");
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("should return null for relation type", () => {
|
|
151
|
+
expect(getExpectedColumnType({ type: "relation" } as Property)).toBe(null);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
describe("report generation", () => {
|
|
156
|
+
it("should correctly count errors and warnings in summary", () => {
|
|
157
|
+
const issues = [
|
|
158
|
+
{ severity: "error" as const,
|
|
159
|
+
category: "missing_table" as const,
|
|
160
|
+
table: "t1",
|
|
161
|
+
message: "m",
|
|
162
|
+
fix: "f" },
|
|
163
|
+
{ severity: "warning" as const,
|
|
164
|
+
category: "type_mismatch" as const,
|
|
165
|
+
table: "t2",
|
|
166
|
+
message: "m",
|
|
167
|
+
fix: "f" },
|
|
168
|
+
{ severity: "error" as const,
|
|
169
|
+
category: "missing_column" as const,
|
|
170
|
+
table: "t3",
|
|
171
|
+
message: "m",
|
|
172
|
+
fix: "f" }
|
|
173
|
+
];
|
|
174
|
+
|
|
175
|
+
const errors = issues.filter(i => i.severity === "error").length;
|
|
176
|
+
const warnings = issues.filter(i => i.severity === "warning").length;
|
|
177
|
+
|
|
178
|
+
expect(errors).toBe(2);
|
|
179
|
+
expect(warnings).toBe(1);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
@@ -9,7 +9,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
9
9
|
let db: jest.Mocked<NodePgDatabase<any>>;
|
|
10
10
|
|
|
11
11
|
const mockTable = {
|
|
12
|
-
id: { name: "id",
|
|
12
|
+
id: { name: "id",
|
|
13
|
+
dataType: "number" },
|
|
13
14
|
name: { name: "name" },
|
|
14
15
|
_def: { tableName: "test_table" }
|
|
15
16
|
};
|
|
@@ -52,7 +53,7 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
52
53
|
update: jest.fn().mockReturnThis(),
|
|
53
54
|
set: jest.fn().mockReturnThis(),
|
|
54
55
|
delete: jest.fn().mockReturnThis(),
|
|
55
|
-
transaction: jest.fn((callback) => callback(db))
|
|
56
|
+
transaction: jest.fn((callback) => callback(db))
|
|
56
57
|
} as any;
|
|
57
58
|
|
|
58
59
|
// Add a then method to make the db object awaitable when the query chain ends
|
|
@@ -81,7 +82,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
81
82
|
|
|
82
83
|
describe("ID Type Validation", () => {
|
|
83
84
|
it("should handle valid numeric ID strings", async () => {
|
|
84
|
-
const mockEntity = { id: 123,
|
|
85
|
+
const mockEntity = { id: 123,
|
|
86
|
+
name: "Test" };
|
|
85
87
|
db.limit.mockResolvedValue([mockEntity]);
|
|
86
88
|
|
|
87
89
|
const entity = await entityService.fetchEntity("test", "123");
|
|
@@ -95,7 +97,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
95
97
|
});
|
|
96
98
|
|
|
97
99
|
it("should handle zero as valid ID", async () => {
|
|
98
|
-
const mockEntity = { id: 0,
|
|
100
|
+
const mockEntity = { id: 0,
|
|
101
|
+
name: "Test" };
|
|
99
102
|
db.limit.mockResolvedValue([mockEntity]);
|
|
100
103
|
|
|
101
104
|
const entity = await entityService.fetchEntity("test", 0);
|
|
@@ -103,7 +106,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
103
106
|
});
|
|
104
107
|
|
|
105
108
|
it("should handle negative numbers as valid ID", async () => {
|
|
106
|
-
const mockEntity = { id: -1,
|
|
109
|
+
const mockEntity = { id: -1,
|
|
110
|
+
name: "Test" };
|
|
107
111
|
db.limit.mockResolvedValue([mockEntity]);
|
|
108
112
|
|
|
109
113
|
const entity = await entityService.fetchEntity("test", -1);
|
|
@@ -176,7 +180,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
176
180
|
|
|
177
181
|
describe("Concurrent Operations", () => {
|
|
178
182
|
it("should handle multiple simultaneous reads", async () => {
|
|
179
|
-
const mockEntity = { id: 1,
|
|
183
|
+
const mockEntity = { id: 1,
|
|
184
|
+
name: "Test" };
|
|
180
185
|
db.limit.mockResolvedValue([mockEntity]);
|
|
181
186
|
|
|
182
187
|
const promises = Array(10).fill(0).map(() =>
|
|
@@ -193,7 +198,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
193
198
|
|
|
194
199
|
it("should handle race conditions in write operations", async () => {
|
|
195
200
|
db.returning.mockResolvedValue([{ id: 1 }]);
|
|
196
|
-
db.limit.mockResolvedValue([{ id: 1,
|
|
201
|
+
db.limit.mockResolvedValue([{ id: 1,
|
|
202
|
+
name: "Updated" }]);
|
|
197
203
|
|
|
198
204
|
const promises = Array(5).fill(0).map((_, i) =>
|
|
199
205
|
entityService.saveEntity("test", { name: `Update ${i}` }, 1)
|
|
@@ -243,7 +249,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
243
249
|
const incompleteEntity = {}; // Missing required fields
|
|
244
250
|
|
|
245
251
|
db.returning.mockResolvedValue([{ id: 1 }]);
|
|
246
|
-
db.limit.mockResolvedValue([{ id: 1,
|
|
252
|
+
db.limit.mockResolvedValue([{ id: 1,
|
|
253
|
+
name: null }]);
|
|
247
254
|
|
|
248
255
|
// The service should handle validation at the collection level
|
|
249
256
|
// This test verifies the service doesn't crash with incomplete data
|
|
@@ -252,7 +259,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
252
259
|
});
|
|
253
260
|
|
|
254
261
|
it("should handle NULL values in database correctly", async () => {
|
|
255
|
-
const mockEntity = { id: 1,
|
|
262
|
+
const mockEntity = { id: 1,
|
|
263
|
+
name: null };
|
|
256
264
|
db.limit.mockResolvedValue([mockEntity]);
|
|
257
265
|
|
|
258
266
|
const entity = await entityService.fetchEntity("test", 1);
|
|
@@ -263,7 +271,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
263
271
|
const entityWithUndefined = { name: undefined };
|
|
264
272
|
|
|
265
273
|
db.returning.mockResolvedValue([{ id: 1 }]);
|
|
266
|
-
db.limit.mockResolvedValue([{ id: 1,
|
|
274
|
+
db.limit.mockResolvedValue([{ id: 1,
|
|
275
|
+
name: null }]);
|
|
267
276
|
|
|
268
277
|
const entity = await entityService.saveEntity("test", entityWithUndefined);
|
|
269
278
|
expect(entity.id).toBe("1");
|
|
@@ -276,7 +285,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
276
285
|
|
|
277
286
|
// The service should handle this safely through parameterized queries
|
|
278
287
|
// This test should not throw an error because of proper parameterization
|
|
279
|
-
const mockEntity = { id: 1,
|
|
288
|
+
const mockEntity = { id: 1,
|
|
289
|
+
name: "Safe" };
|
|
280
290
|
db.limit.mockResolvedValue([mockEntity]);
|
|
281
291
|
|
|
282
292
|
const entity = await entityService.fetchEntity("test", maliciousId);
|
|
@@ -288,7 +298,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
288
298
|
const entityWithLongValue = { name: veryLongString };
|
|
289
299
|
|
|
290
300
|
db.returning.mockResolvedValue([{ id: 1 }]);
|
|
291
|
-
db.limit.mockResolvedValue([{ id: 1,
|
|
301
|
+
db.limit.mockResolvedValue([{ id: 1,
|
|
302
|
+
name: veryLongString }]);
|
|
292
303
|
|
|
293
304
|
const entity = await entityService.saveEntity("test", entityWithLongValue);
|
|
294
305
|
expect(entity.values.name).toBe(veryLongString);
|
|
@@ -299,7 +310,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
299
310
|
const entityWithSpecialChars = { name: specialChars };
|
|
300
311
|
|
|
301
312
|
db.returning.mockResolvedValue([{ id: 1 }]);
|
|
302
|
-
db.limit.mockResolvedValue([{ id: 1,
|
|
313
|
+
db.limit.mockResolvedValue([{ id: 1,
|
|
314
|
+
name: specialChars }]);
|
|
303
315
|
|
|
304
316
|
const entity = await entityService.saveEntity("test", entityWithSpecialChars);
|
|
305
317
|
expect(entity.values.name).toBe(specialChars);
|
|
@@ -317,7 +329,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
317
329
|
};
|
|
318
330
|
jest.spyOn(collectionRegistry, "getCollectionByPath").mockReturnValue(booleanCollection);
|
|
319
331
|
|
|
320
|
-
const mockEntity = { id: 1,
|
|
332
|
+
const mockEntity = { id: 1,
|
|
333
|
+
active: false };
|
|
321
334
|
db.limit.mockResolvedValue([mockEntity]);
|
|
322
335
|
|
|
323
336
|
const entity = await entityService.fetchEntity("test", 1);
|
|
@@ -334,7 +347,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
334
347
|
};
|
|
335
348
|
jest.spyOn(collectionRegistry, "getCollectionByPath").mockReturnValue(numericCollection);
|
|
336
349
|
|
|
337
|
-
const mockEntity = { id: 1,
|
|
350
|
+
const mockEntity = { id: 1,
|
|
351
|
+
count: 0 };
|
|
338
352
|
db.limit.mockResolvedValue([mockEntity]);
|
|
339
353
|
|
|
340
354
|
const entity = await entityService.fetchEntity("test", 1);
|
|
@@ -342,7 +356,8 @@ describe("EntityService - Error Handling & Edge Cases", () => {
|
|
|
342
356
|
});
|
|
343
357
|
|
|
344
358
|
it("should handle empty string values correctly", async () => {
|
|
345
|
-
const mockEntity = { id: 1,
|
|
359
|
+
const mockEntity = { id: 1,
|
|
360
|
+
name: "" };
|
|
346
361
|
db.limit.mockResolvedValue([mockEntity]);
|
|
347
362
|
|
|
348
363
|
const entity = await entityService.fetchEntity("test", 1);
|