masterrecord 0.3.30 → 0.3.32
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/Entity/entityModelBuilder.js +44 -1
- package/Migrations/cli.js +17 -4
- package/Migrations/dependencyGraph.js +108 -0
- package/Migrations/migrationMySQLQuery.js +10 -0
- package/Migrations/migrationPostgresQuery.js +10 -0
- package/Migrations/migrationSQLiteQuery.js +10 -0
- package/Migrations/migrationTemplate.js +176 -0
- package/Migrations/migrations.js +121 -12
- package/Migrations/schema.js +63 -0
- package/context.js +288 -0
- package/package.json +1 -1
- package/readme.md +812 -37
- package/test/seed-data-test.js +212 -0
- package/test/seed-features-integration-test.js +418 -0
- package/test/seed-migration-template-test.js +220 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test: Seed Data Migration Template Generation
|
|
3
|
+
*
|
|
4
|
+
* Verifies that seed data correctly generates ORM-based migration code
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const MigrationTemplate = require('../Migrations/migrationTemplate');
|
|
8
|
+
const os = require('os');
|
|
9
|
+
|
|
10
|
+
console.log("╔════════════════════════════════════════════════════════════════╗");
|
|
11
|
+
console.log("║ Seed Data Migration Template Generation Test ║");
|
|
12
|
+
console.log("╚════════════════════════════════════════════════════════════════╝\n");
|
|
13
|
+
|
|
14
|
+
let passed = 0;
|
|
15
|
+
let failed = 0;
|
|
16
|
+
|
|
17
|
+
function test(description, fn) {
|
|
18
|
+
try {
|
|
19
|
+
fn();
|
|
20
|
+
console.log(`✓ ${description}`);
|
|
21
|
+
passed++;
|
|
22
|
+
} catch (error) {
|
|
23
|
+
console.log(`✗ ${description}`);
|
|
24
|
+
console.log(` Error: ${error.message}`);
|
|
25
|
+
failed++;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function assertContains(haystack, needle, message) {
|
|
30
|
+
if (!haystack.includes(needle)) {
|
|
31
|
+
throw new Error(`${message}: expected to find "${needle}" in output`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function assertNotContains(haystack, needle, message) {
|
|
36
|
+
if (haystack.includes(needle)) {
|
|
37
|
+
throw new Error(`${message}: did not expect to find "${needle}" in output`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Run tests
|
|
42
|
+
console.log("Running tests...\n");
|
|
43
|
+
|
|
44
|
+
test("Single seed record generates single-line create call", () => {
|
|
45
|
+
const MT = new MigrationTemplate('TestMigration');
|
|
46
|
+
|
|
47
|
+
const seedData = [
|
|
48
|
+
{ name: 'Admin', email: 'admin@example.com' }
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
MT.seedData('up', 'User', seedData);
|
|
52
|
+
|
|
53
|
+
const output = MT.get();
|
|
54
|
+
|
|
55
|
+
assertContains(output, 'await table.User.create(', 'Should contain create call');
|
|
56
|
+
assertContains(output, '"name":"Admin"', 'Should contain name field');
|
|
57
|
+
assertContains(output, '"email":"admin@example.com"', 'Should contain email field');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("Multiple seed records generate multiple create calls", () => {
|
|
61
|
+
const MT = new MigrationTemplate('TestMigration');
|
|
62
|
+
|
|
63
|
+
const seedData = [
|
|
64
|
+
{ title: 'Post 1', content: 'Content 1' },
|
|
65
|
+
{ title: 'Post 2', content: 'Content 2' }
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
MT.seedData('up', 'Post', seedData);
|
|
69
|
+
|
|
70
|
+
const output = MT.get();
|
|
71
|
+
|
|
72
|
+
assertContains(output, 'await table.Post.create(', 'Should contain create calls');
|
|
73
|
+
assertContains(output, '"title":"Post 1"', 'Should contain Post 1');
|
|
74
|
+
assertContains(output, '"title":"Post 2"', 'Should contain Post 2');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("Large record generates multi-line formatted create call", () => {
|
|
78
|
+
const MT = new MigrationTemplate('TestMigration');
|
|
79
|
+
|
|
80
|
+
const seedData = [
|
|
81
|
+
{
|
|
82
|
+
user_name: 'admin',
|
|
83
|
+
first_name: 'System',
|
|
84
|
+
last_name: 'Administrator',
|
|
85
|
+
email: 'admin@bookbag.ai',
|
|
86
|
+
system_role: 'system_admin',
|
|
87
|
+
admin_type: 'engineering'
|
|
88
|
+
}
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
MT.seedData('up', 'User', seedData);
|
|
92
|
+
|
|
93
|
+
const output = MT.get();
|
|
94
|
+
|
|
95
|
+
// Large record (> 80 chars) should be multi-line
|
|
96
|
+
assertContains(output, 'await table.User.create(', 'Should contain create call');
|
|
97
|
+
assertContains(output, '"user_name"', 'Should contain user_name field');
|
|
98
|
+
assertContains(output, '"system_role"', 'Should contain system_role field');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("Empty seed data generates nothing", () => {
|
|
102
|
+
const MT = new MigrationTemplate('TestMigration');
|
|
103
|
+
|
|
104
|
+
MT.seedData('up', 'User', []);
|
|
105
|
+
|
|
106
|
+
const output = MT.get();
|
|
107
|
+
|
|
108
|
+
// Should not contain any User create calls
|
|
109
|
+
assertNotContains(output, 'await table.User.create(', 'Should not contain create call');
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("Down migration does not generate seed code", () => {
|
|
113
|
+
const MT = new MigrationTemplate('TestMigration');
|
|
114
|
+
|
|
115
|
+
const seedData = [
|
|
116
|
+
{ name: 'Admin', email: 'admin@example.com' }
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
MT.seedData('down', 'User', seedData);
|
|
120
|
+
|
|
121
|
+
const output = MT.get();
|
|
122
|
+
|
|
123
|
+
// Down migrations should not contain seed data deletion
|
|
124
|
+
// (as per design - seed data not removed in down migrations)
|
|
125
|
+
const downSection = output.split('async down(table)')[1];
|
|
126
|
+
assertNotContains(downSection, 'await table.User.create(', 'Down migration should not create seed data');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("Seed data with special characters is properly escaped", () => {
|
|
130
|
+
const MT = new MigrationTemplate('TestMigration');
|
|
131
|
+
|
|
132
|
+
const seedData = [
|
|
133
|
+
{ name: 'Test "Quote"', description: "It's working" }
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
MT.seedData('up', 'Item', seedData);
|
|
137
|
+
|
|
138
|
+
const output = MT.get();
|
|
139
|
+
|
|
140
|
+
assertContains(output, 'await table.Item.create(', 'Should contain create call');
|
|
141
|
+
// JSON.stringify handles escaping automatically
|
|
142
|
+
assertContains(output, 'Test \\"Quote\\"', 'Should escape double quotes');
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("Seed data with null values is preserved", () => {
|
|
146
|
+
const MT = new MigrationTemplate('TestMigration');
|
|
147
|
+
|
|
148
|
+
const seedData = [
|
|
149
|
+
{ name: 'Test', optional_field: null }
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
MT.seedData('up', 'Item', seedData);
|
|
153
|
+
|
|
154
|
+
const output = MT.get();
|
|
155
|
+
|
|
156
|
+
assertContains(output, 'await table.Item.create(', 'Should contain create call');
|
|
157
|
+
assertContains(output, '"optional_field":null', 'Should preserve null value');
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test("Seed data with boolean values is preserved", () => {
|
|
161
|
+
const MT = new MigrationTemplate('TestMigration');
|
|
162
|
+
|
|
163
|
+
const seedData = [
|
|
164
|
+
{ name: 'Admin', is_active: true, is_deleted: false }
|
|
165
|
+
];
|
|
166
|
+
|
|
167
|
+
MT.seedData('up', 'User', seedData);
|
|
168
|
+
|
|
169
|
+
const output = MT.get();
|
|
170
|
+
|
|
171
|
+
assertContains(output, '"is_active":true', 'Should preserve true value');
|
|
172
|
+
assertContains(output, '"is_deleted":false', 'Should preserve false value');
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("Seed data with numbers is preserved", () => {
|
|
176
|
+
const MT = new MigrationTemplate('TestMigration');
|
|
177
|
+
|
|
178
|
+
const seedData = [
|
|
179
|
+
{ name: 'Product', price: 19.99, quantity: 100, rating: 4.5 }
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
MT.seedData('up', 'Product', seedData);
|
|
183
|
+
|
|
184
|
+
const output = MT.get();
|
|
185
|
+
|
|
186
|
+
assertContains(output, '"price":19.99', 'Should preserve decimal number');
|
|
187
|
+
assertContains(output, '"quantity":100', 'Should preserve integer');
|
|
188
|
+
assertContains(output, '"rating":4.5', 'Should preserve float');
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test("Migration template structure is valid", () => {
|
|
192
|
+
const MT = new MigrationTemplate('TestMigration_123');
|
|
193
|
+
|
|
194
|
+
const seedData = [
|
|
195
|
+
{ name: 'Test User' }
|
|
196
|
+
];
|
|
197
|
+
|
|
198
|
+
MT.seedData('up', 'User', seedData);
|
|
199
|
+
|
|
200
|
+
const output = MT.get();
|
|
201
|
+
|
|
202
|
+
// Verify basic structure
|
|
203
|
+
assertContains(output, "class TestMigration_123 extends masterrecord.schema", 'Should have class definition');
|
|
204
|
+
assertContains(output, "async up(table)", 'Should have up method');
|
|
205
|
+
assertContains(output, "async down(table)", 'Should have down method');
|
|
206
|
+
assertContains(output, "this.init(table)", 'Should initialize table');
|
|
207
|
+
assertContains(output, "module.exports = TestMigration_123", 'Should export class');
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Print summary
|
|
211
|
+
console.log("\n" + "─".repeat(64));
|
|
212
|
+
console.log(`Tests completed: ${passed} passed, ${failed} failed`);
|
|
213
|
+
|
|
214
|
+
if (failed > 0) {
|
|
215
|
+
console.log("\n❌ Some tests failed");
|
|
216
|
+
process.exit(1);
|
|
217
|
+
} else {
|
|
218
|
+
console.log("\n✅ All tests passed!");
|
|
219
|
+
process.exit(0);
|
|
220
|
+
}
|