meadow 2.0.23 → 2.0.26
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/README.md +110 -141
- package/docs/README.md +34 -230
- package/docs/_cover.md +14 -0
- package/docs/_sidebar.md +44 -12
- package/docs/_topbar.md +5 -0
- package/docs/api/doCount.md +109 -0
- package/docs/api/doCreate.md +132 -0
- package/docs/api/doDelete.md +101 -0
- package/docs/api/doRead.md +122 -0
- package/docs/api/doReads.md +136 -0
- package/docs/api/doUndelete.md +98 -0
- package/docs/api/doUpdate.md +129 -0
- package/docs/api/getRoleName.md +84 -0
- package/docs/api/loadFromPackage.md +153 -0
- package/docs/api/marshalRecordFromSourceToObject.md +92 -0
- package/docs/api/query.md +133 -0
- package/docs/api/rawQueries.md +197 -0
- package/docs/api/reference.md +117 -0
- package/docs/api/setAuthorizer.md +103 -0
- package/docs/api/setDefault.md +90 -0
- package/docs/api/setDefaultIdentifier.md +84 -0
- package/docs/api/setDomain.md +56 -0
- package/docs/api/setIDUser.md +91 -0
- package/docs/api/setJsonSchema.md +92 -0
- package/docs/api/setProvider.md +87 -0
- package/docs/api/setSchema.md +107 -0
- package/docs/api/setScope.md +68 -0
- package/docs/api/validateObject.md +119 -0
- package/docs/architecture.md +316 -0
- package/docs/audit-tracking.md +226 -0
- package/docs/configuration.md +317 -0
- package/docs/providers/meadow-endpoints.md +306 -0
- package/docs/providers/mongodb.md +319 -0
- package/docs/providers/postgresql.md +312 -0
- package/docs/providers/rocksdb.md +297 -0
- package/docs/query-dsl.md +269 -0
- package/docs/quick-start.md +384 -0
- package/docs/raw-queries.md +193 -0
- package/docs/retold-catalog.json +61 -1
- package/docs/retold-keyword-index.json +15860 -4839
- package/docs/soft-deletes.md +224 -0
- package/package.json +36 -9
- package/scripts/bookstore-seed-postgresql.sql +135 -0
- package/scripts/dgraph-test-db.sh +144 -0
- package/scripts/meadow-test-cleanup.sh +5 -1
- package/scripts/mongodb-test-db.sh +98 -0
- package/scripts/postgresql-test-db.sh +124 -0
- package/scripts/solr-test-db.sh +135 -0
- package/source/Meadow.js +5 -0
- package/source/providers/Meadow-Provider-DGraph.js +679 -0
- package/source/providers/Meadow-Provider-MongoDB.js +527 -0
- package/source/providers/Meadow-Provider-PostgreSQL.js +361 -0
- package/source/providers/Meadow-Provider-RocksDB.js +1300 -0
- package/source/providers/Meadow-Provider-Solr.js +726 -0
- package/test/Meadow-Provider-DGraph_tests.js +741 -0
- package/test/Meadow-Provider-MongoDB_tests.js +661 -0
- package/test/Meadow-Provider-PostgreSQL_tests.js +787 -0
- package/test/Meadow-Provider-RocksDB_tests.js +887 -0
- package/test/Meadow-Provider-Solr_tests.js +679 -0
|
@@ -0,0 +1,741 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Meadow "DGraph" Provider
|
|
3
|
+
*
|
|
4
|
+
* These tests expect a DGraph instance.....
|
|
5
|
+
*
|
|
6
|
+
* @license MIT
|
|
7
|
+
*
|
|
8
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
var Chai = require("chai");
|
|
12
|
+
var Expect = Chai.expect;
|
|
13
|
+
|
|
14
|
+
const libMeadowConnectionDGraph = require('meadow-connection-dgraph');
|
|
15
|
+
|
|
16
|
+
var tmpFableSettings = (
|
|
17
|
+
{
|
|
18
|
+
"Product": "MeadowDGraphTestBookstore",
|
|
19
|
+
"ProductVersion": "1.0.0",
|
|
20
|
+
|
|
21
|
+
"UUID":
|
|
22
|
+
{
|
|
23
|
+
"DataCenter": 0,
|
|
24
|
+
"Worker": 0
|
|
25
|
+
},
|
|
26
|
+
"LogStreams":
|
|
27
|
+
[
|
|
28
|
+
{
|
|
29
|
+
"streamtype": "console"
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
|
|
33
|
+
"DGraph":
|
|
34
|
+
{
|
|
35
|
+
"Server": "127.0.0.1",
|
|
36
|
+
"Port": 38080
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
var libFable = new (require('fable'))(tmpFableSettings);
|
|
41
|
+
|
|
42
|
+
libFable.serviceManager.addServiceType('MeadowDGraphProvider', libMeadowConnectionDGraph);
|
|
43
|
+
libFable.serviceManager.instantiateServiceProvider('MeadowDGraphProvider');
|
|
44
|
+
|
|
45
|
+
var _AnimalJsonSchema = (
|
|
46
|
+
{
|
|
47
|
+
title: "Animal",
|
|
48
|
+
description: "A creature that lives in a meadow.",
|
|
49
|
+
type: "object",
|
|
50
|
+
properties: {
|
|
51
|
+
IDAnimal: {
|
|
52
|
+
description: "The unique identifier for an animal",
|
|
53
|
+
type: "integer"
|
|
54
|
+
},
|
|
55
|
+
Name: {
|
|
56
|
+
description: "The animal's name",
|
|
57
|
+
type: "string"
|
|
58
|
+
},
|
|
59
|
+
Type: {
|
|
60
|
+
description: "The type of the animal",
|
|
61
|
+
type: "string"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
required: ["IDAnimal", "Name", "CreatingIDUser"]
|
|
65
|
+
});
|
|
66
|
+
var _AnimalSchema = (
|
|
67
|
+
[
|
|
68
|
+
{ Column: "IDAnimal", Type: "AutoIdentity" },
|
|
69
|
+
{ Column: "GUIDAnimal", Type: "AutoGUID" },
|
|
70
|
+
{ Column: "CreateDate", Type: "CreateDate" },
|
|
71
|
+
{ Column: "CreatingIDUser", Type: "CreateIDUser" },
|
|
72
|
+
{ Column: "UpdateDate", Type: "UpdateDate" },
|
|
73
|
+
{ Column: "UpdatingIDUser", Type: "UpdateIDUser" },
|
|
74
|
+
{ Column: "Deleted", Type: "Deleted" },
|
|
75
|
+
{ Column: "DeletingIDUser", Type: "DeleteIDUser" },
|
|
76
|
+
{ Column: "DeleteDate", Type: "DeleteDate" },
|
|
77
|
+
{ Column: "Name", Type: "String" },
|
|
78
|
+
{ Column: "Type", Type: "String" }
|
|
79
|
+
]);
|
|
80
|
+
var _AnimalDefault = (
|
|
81
|
+
{
|
|
82
|
+
IDAnimal: null,
|
|
83
|
+
GUIDAnimal: '',
|
|
84
|
+
|
|
85
|
+
CreateDate: false,
|
|
86
|
+
CreatingIDUser: 0,
|
|
87
|
+
UpdateDate: false,
|
|
88
|
+
UpdatingIDUser: 0,
|
|
89
|
+
Deleted: 0,
|
|
90
|
+
DeleteDate: false,
|
|
91
|
+
DeletingIDUser: 0,
|
|
92
|
+
|
|
93
|
+
Name: 'Unknown',
|
|
94
|
+
Type: 'Unclassified'
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Helper to drop all DGraph data via the HTTP API
|
|
98
|
+
var dropAllDGraphData = function (fCallback)
|
|
99
|
+
{
|
|
100
|
+
var http = require('http');
|
|
101
|
+
var tmpOptions = {
|
|
102
|
+
hostname: '127.0.0.1',
|
|
103
|
+
port: 38080,
|
|
104
|
+
path: '/alter',
|
|
105
|
+
method: 'POST',
|
|
106
|
+
headers: { 'Content-Type': 'application/json' }
|
|
107
|
+
};
|
|
108
|
+
var tmpReq = http.request(tmpOptions, function (pRes)
|
|
109
|
+
{
|
|
110
|
+
pRes.on('data', function () {});
|
|
111
|
+
pRes.on('end', function () { fCallback(); });
|
|
112
|
+
});
|
|
113
|
+
tmpReq.on('error', function (pError) { fCallback(pError); });
|
|
114
|
+
tmpReq.write(JSON.stringify({ drop_all: true }));
|
|
115
|
+
tmpReq.end();
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// Helper to apply DGraph schema via the HTTP API
|
|
119
|
+
var applyDGraphSchema = function (fCallback)
|
|
120
|
+
{
|
|
121
|
+
var http = require('http');
|
|
122
|
+
var tmpSchema = [
|
|
123
|
+
'IDAnimal: int @index(int) .',
|
|
124
|
+
'GUIDAnimal: string .',
|
|
125
|
+
'CreateDate: string .',
|
|
126
|
+
'CreatingIDUser: int .',
|
|
127
|
+
'UpdateDate: string .',
|
|
128
|
+
'UpdatingIDUser: int .',
|
|
129
|
+
'Deleted: int @index(int) .',
|
|
130
|
+
'DeleteDate: string .',
|
|
131
|
+
'DeletingIDUser: int .',
|
|
132
|
+
'Name: string @index(exact, term) .',
|
|
133
|
+
'Type: string @index(exact, term) .',
|
|
134
|
+
'MeadowCounter.scope: string @index(exact) .',
|
|
135
|
+
'MeadowCounter.sequence: int .',
|
|
136
|
+
'',
|
|
137
|
+
'type FableTest {',
|
|
138
|
+
' IDAnimal',
|
|
139
|
+
' GUIDAnimal',
|
|
140
|
+
' CreateDate',
|
|
141
|
+
' CreatingIDUser',
|
|
142
|
+
' UpdateDate',
|
|
143
|
+
' UpdatingIDUser',
|
|
144
|
+
' Deleted',
|
|
145
|
+
' DeleteDate',
|
|
146
|
+
' DeletingIDUser',
|
|
147
|
+
' Name',
|
|
148
|
+
' Type',
|
|
149
|
+
'}',
|
|
150
|
+
'',
|
|
151
|
+
'type MeadowCounter {',
|
|
152
|
+
' MeadowCounter.scope',
|
|
153
|
+
' MeadowCounter.sequence',
|
|
154
|
+
'}'
|
|
155
|
+
].join('\n');
|
|
156
|
+
|
|
157
|
+
var tmpOptions = {
|
|
158
|
+
hostname: '127.0.0.1',
|
|
159
|
+
port: 38080,
|
|
160
|
+
path: '/alter',
|
|
161
|
+
method: 'POST',
|
|
162
|
+
headers: { 'Content-Type': 'application/octet-stream' }
|
|
163
|
+
};
|
|
164
|
+
var tmpReq = http.request(tmpOptions, function (pRes)
|
|
165
|
+
{
|
|
166
|
+
pRes.on('data', function () {});
|
|
167
|
+
pRes.on('end', function () { fCallback(); });
|
|
168
|
+
});
|
|
169
|
+
tmpReq.on('error', function (pError) { fCallback(pError); });
|
|
170
|
+
tmpReq.write(tmpSchema);
|
|
171
|
+
tmpReq.end();
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
suite
|
|
175
|
+
(
|
|
176
|
+
'Meadow-Provider-DGraph',
|
|
177
|
+
function ()
|
|
178
|
+
{
|
|
179
|
+
var _SpooledUp = false;
|
|
180
|
+
|
|
181
|
+
var newMeadow = function ()
|
|
182
|
+
{
|
|
183
|
+
return require('../source/Meadow.js')
|
|
184
|
+
.new(libFable, 'FableTest')
|
|
185
|
+
.setProvider('DGraph')
|
|
186
|
+
.setSchema(_AnimalSchema)
|
|
187
|
+
.setJsonSchema(_AnimalJsonSchema)
|
|
188
|
+
.setDefaultIdentifier('IDAnimal')
|
|
189
|
+
.setDefault(_AnimalDefault)
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
suiteSetup
|
|
193
|
+
(
|
|
194
|
+
function (fDone)
|
|
195
|
+
{
|
|
196
|
+
this.timeout(30000);
|
|
197
|
+
if (!_SpooledUp)
|
|
198
|
+
{
|
|
199
|
+
// Drop all data and re-apply schema
|
|
200
|
+
dropAllDGraphData(function (pDropError)
|
|
201
|
+
{
|
|
202
|
+
if (pDropError)
|
|
203
|
+
{
|
|
204
|
+
libFable.log.error(`Error dropping DGraph data: ${pDropError}`);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
applyDGraphSchema(function (pSchemaError)
|
|
208
|
+
{
|
|
209
|
+
if (pSchemaError)
|
|
210
|
+
{
|
|
211
|
+
libFable.log.error(`Error applying DGraph schema: ${pSchemaError}`);
|
|
212
|
+
return fDone(pSchemaError);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
libFable.MeadowDGraphProvider.connectAsync(
|
|
216
|
+
(pError) =>
|
|
217
|
+
{
|
|
218
|
+
if (pError)
|
|
219
|
+
{
|
|
220
|
+
libFable.log.error(`Error connecting to DGraph: ${pError}`);
|
|
221
|
+
return fDone(pError);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
var tmpClient = libFable.MeadowDGraphProvider.pool;
|
|
225
|
+
var tmpNow = new Date().toISOString();
|
|
226
|
+
|
|
227
|
+
// Seed 5 animals and the counter using a single mutation
|
|
228
|
+
var tmpTxn = tmpClient.newTxn();
|
|
229
|
+
var tmpSeedData = [
|
|
230
|
+
{ 'dgraph.type': 'FableTest', IDAnimal: 1, GUIDAnimal: '00000000-0000-0000-0000-000000000000', CreateDate: tmpNow, CreatingIDUser: 1, UpdateDate: tmpNow, UpdatingIDUser: 1, Deleted: 0, DeleteDate: '', DeletingIDUser: 0, Name: 'Foo Foo', Type: 'Bunny' },
|
|
231
|
+
{ 'dgraph.type': 'FableTest', IDAnimal: 2, GUIDAnimal: '00000000-0000-0000-0000-000000000000', CreateDate: tmpNow, CreatingIDUser: 1, UpdateDate: tmpNow, UpdatingIDUser: 1, Deleted: 0, DeleteDate: '', DeletingIDUser: 0, Name: 'Red Riding Hood', Type: 'Girl' },
|
|
232
|
+
{ 'dgraph.type': 'FableTest', IDAnimal: 3, GUIDAnimal: '00000000-0000-0000-0000-000000000000', CreateDate: tmpNow, CreatingIDUser: 1, UpdateDate: tmpNow, UpdatingIDUser: 1, Deleted: 0, DeleteDate: '', DeletingIDUser: 0, Name: 'Red', Type: 'Dog' },
|
|
233
|
+
{ 'dgraph.type': 'FableTest', IDAnimal: 4, GUIDAnimal: '00000000-0000-0000-0000-000000000000', CreateDate: tmpNow, CreatingIDUser: 1, UpdateDate: tmpNow, UpdatingIDUser: 1, Deleted: 0, DeleteDate: '', DeletingIDUser: 0, Name: 'Spot', Type: 'Dog' },
|
|
234
|
+
{ 'dgraph.type': 'FableTest', IDAnimal: 5, GUIDAnimal: '00000000-0000-0000-0000-000000000000', CreateDate: tmpNow, CreatingIDUser: 1, UpdateDate: tmpNow, UpdatingIDUser: 1, Deleted: 0, DeleteDate: '', DeletingIDUser: 0, Name: 'Gertrude', Type: 'Frog' },
|
|
235
|
+
{ 'dgraph.type': 'MeadowCounter', 'MeadowCounter.scope': 'FableTest.IDAnimal', 'MeadowCounter.sequence': 5 }
|
|
236
|
+
];
|
|
237
|
+
|
|
238
|
+
tmpTxn.mutate({ setJson: tmpSeedData })
|
|
239
|
+
.then(function ()
|
|
240
|
+
{
|
|
241
|
+
return tmpTxn.commit();
|
|
242
|
+
})
|
|
243
|
+
.then(function ()
|
|
244
|
+
{
|
|
245
|
+
_SpooledUp = true;
|
|
246
|
+
fDone();
|
|
247
|
+
})
|
|
248
|
+
.catch(function (pMutateError)
|
|
249
|
+
{
|
|
250
|
+
try { tmpTxn.discard(); } catch (e) {}
|
|
251
|
+
fDone(pMutateError);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
else
|
|
259
|
+
{
|
|
260
|
+
fDone();
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
suiteTeardown((fDone) =>
|
|
266
|
+
{
|
|
267
|
+
dropAllDGraphData(function ()
|
|
268
|
+
{
|
|
269
|
+
fDone();
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
suite
|
|
274
|
+
(
|
|
275
|
+
'Object Sanity',
|
|
276
|
+
function ()
|
|
277
|
+
{
|
|
278
|
+
test
|
|
279
|
+
(
|
|
280
|
+
'The DGraph class should initialize itself into a happy little object.',
|
|
281
|
+
function ()
|
|
282
|
+
{
|
|
283
|
+
var testMeadow = require('../source/Meadow.js').new(libFable).setProvider('DGraph');
|
|
284
|
+
Expect(testMeadow).to.be.an('object', 'Meadow should initialize as an object directly from the require statement.');
|
|
285
|
+
}
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
suite
|
|
290
|
+
(
|
|
291
|
+
'Query Processing',
|
|
292
|
+
function ()
|
|
293
|
+
{
|
|
294
|
+
test
|
|
295
|
+
(
|
|
296
|
+
'Create a record in the database',
|
|
297
|
+
function (fDone)
|
|
298
|
+
{
|
|
299
|
+
var testMeadow = newMeadow().setIDUser(90210);
|
|
300
|
+
|
|
301
|
+
var tmpQuery = testMeadow.query.clone().setLogLevel(5)
|
|
302
|
+
.addRecord({ Name: 'Blastoise', Type: 'Pokemon' });
|
|
303
|
+
|
|
304
|
+
testMeadow.doCreate(tmpQuery,
|
|
305
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
306
|
+
{
|
|
307
|
+
// We should have a record ....
|
|
308
|
+
Expect(pRecord.Name)
|
|
309
|
+
.to.equal('Blastoise');
|
|
310
|
+
Expect(pRecord.CreatingIDUser)
|
|
311
|
+
.to.equal(90210);
|
|
312
|
+
fDone();
|
|
313
|
+
}
|
|
314
|
+
)
|
|
315
|
+
}
|
|
316
|
+
);
|
|
317
|
+
test
|
|
318
|
+
(
|
|
319
|
+
'Read a record from the database',
|
|
320
|
+
function (fDone)
|
|
321
|
+
{
|
|
322
|
+
var testMeadow = newMeadow();
|
|
323
|
+
|
|
324
|
+
var tmpQuery = testMeadow.query
|
|
325
|
+
.addFilter('IDAnimal', 1);
|
|
326
|
+
|
|
327
|
+
testMeadow.doRead(tmpQuery,
|
|
328
|
+
function (pError, pQuery, pRecord)
|
|
329
|
+
{
|
|
330
|
+
// We should have a record ....
|
|
331
|
+
Expect(pRecord.IDAnimal)
|
|
332
|
+
.to.equal(1);
|
|
333
|
+
Expect(pRecord.Name)
|
|
334
|
+
.to.equal('Foo Foo');
|
|
335
|
+
fDone();
|
|
336
|
+
}
|
|
337
|
+
)
|
|
338
|
+
}
|
|
339
|
+
);
|
|
340
|
+
test
|
|
341
|
+
(
|
|
342
|
+
'Read all records from the database',
|
|
343
|
+
function (fDone)
|
|
344
|
+
{
|
|
345
|
+
var testMeadow = newMeadow();
|
|
346
|
+
|
|
347
|
+
testMeadow.doReads(testMeadow.query.addSort({Column: 'IDAnimal'}),
|
|
348
|
+
function (pError, pQuery, pRecords)
|
|
349
|
+
{
|
|
350
|
+
// We should have records ....
|
|
351
|
+
Expect(pRecords[0].IDAnimal)
|
|
352
|
+
.to.equal(1);
|
|
353
|
+
Expect(pRecords[0].Name)
|
|
354
|
+
.to.equal('Foo Foo');
|
|
355
|
+
Expect(pRecords[1].IDAnimal)
|
|
356
|
+
.to.equal(2);
|
|
357
|
+
Expect(pRecords[1].Name)
|
|
358
|
+
.to.equal('Red Riding Hood');
|
|
359
|
+
fDone();
|
|
360
|
+
}
|
|
361
|
+
)
|
|
362
|
+
}
|
|
363
|
+
);
|
|
364
|
+
test
|
|
365
|
+
(
|
|
366
|
+
'Update a record in the database',
|
|
367
|
+
function (fDone)
|
|
368
|
+
{
|
|
369
|
+
var testMeadow = newMeadow();
|
|
370
|
+
|
|
371
|
+
var tmpQuery = testMeadow.query
|
|
372
|
+
.addRecord({ IDAnimal: 2, Type: 'Human' });
|
|
373
|
+
|
|
374
|
+
testMeadow.doUpdate(tmpQuery,
|
|
375
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
376
|
+
{
|
|
377
|
+
// We should have a record ....
|
|
378
|
+
Expect(pRecord.Type)
|
|
379
|
+
.to.equal('Human');
|
|
380
|
+
fDone();
|
|
381
|
+
}
|
|
382
|
+
)
|
|
383
|
+
}
|
|
384
|
+
);
|
|
385
|
+
test
|
|
386
|
+
(
|
|
387
|
+
'Delete a record in the database',
|
|
388
|
+
function (fDone)
|
|
389
|
+
{
|
|
390
|
+
var testMeadow = newMeadow();
|
|
391
|
+
|
|
392
|
+
var tmpQuery = testMeadow.query.addFilter('IDAnimal', 3);
|
|
393
|
+
|
|
394
|
+
testMeadow.doDelete(tmpQuery,
|
|
395
|
+
function (pError, pQuery, pRecord)
|
|
396
|
+
{
|
|
397
|
+
// It returns the number of rows deleted
|
|
398
|
+
Expect(pRecord)
|
|
399
|
+
.to.equal(1);
|
|
400
|
+
fDone();
|
|
401
|
+
}
|
|
402
|
+
)
|
|
403
|
+
}
|
|
404
|
+
);
|
|
405
|
+
test
|
|
406
|
+
(
|
|
407
|
+
'Undelete a record in the database',
|
|
408
|
+
function (fDone)
|
|
409
|
+
{
|
|
410
|
+
var testMeadow = newMeadow();
|
|
411
|
+
|
|
412
|
+
var tmpDeleteQuery = testMeadow.query.addFilter('IDAnimal', 5);
|
|
413
|
+
|
|
414
|
+
// Make sure the record is deleted!
|
|
415
|
+
testMeadow.doDelete(tmpDeleteQuery,
|
|
416
|
+
function (pDeleteError, pDeleteQuery, pDeleteRecord)
|
|
417
|
+
{
|
|
418
|
+
var tmpQuery = testMeadow.query.addFilter('IDAnimal', 5);
|
|
419
|
+
testMeadow.doUndelete(tmpQuery,
|
|
420
|
+
function (pError, pQuery, pRecord)
|
|
421
|
+
{
|
|
422
|
+
// It returns the number of rows undeleted
|
|
423
|
+
Expect(pRecord)
|
|
424
|
+
.to.equal(1);
|
|
425
|
+
fDone();
|
|
426
|
+
});
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
);
|
|
430
|
+
test
|
|
431
|
+
(
|
|
432
|
+
'Count all records from the database',
|
|
433
|
+
function (fDone)
|
|
434
|
+
{
|
|
435
|
+
var testMeadow = newMeadow();
|
|
436
|
+
|
|
437
|
+
Expect(testMeadow.query.parameters.result.executed)
|
|
438
|
+
.to.equal(false);
|
|
439
|
+
testMeadow.doCount(testMeadow.query,
|
|
440
|
+
function (pError, pQuery, pRecord)
|
|
441
|
+
{
|
|
442
|
+
// There should be 5 records (5 seeded + 1 created - 1 deleted = 5 non-deleted)
|
|
443
|
+
Expect(pRecord)
|
|
444
|
+
.to.equal(5);
|
|
445
|
+
Expect(pQuery.parameters.result.executed)
|
|
446
|
+
.to.equal(true);
|
|
447
|
+
fDone();
|
|
448
|
+
}
|
|
449
|
+
)
|
|
450
|
+
}
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
);
|
|
454
|
+
suite
|
|
455
|
+
(
|
|
456
|
+
'Logged Query Processing',
|
|
457
|
+
function ()
|
|
458
|
+
{
|
|
459
|
+
test
|
|
460
|
+
(
|
|
461
|
+
'Create a record in the database',
|
|
462
|
+
function (fDone)
|
|
463
|
+
{
|
|
464
|
+
var testMeadow = newMeadow();
|
|
465
|
+
|
|
466
|
+
var tmpQuery = testMeadow.query
|
|
467
|
+
.setLogLevel(5)
|
|
468
|
+
.addRecord({ Name: 'MewTwo', Type: 'Pokemon' });
|
|
469
|
+
|
|
470
|
+
testMeadow.doCreate(tmpQuery,
|
|
471
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
472
|
+
{
|
|
473
|
+
// We should have a record ....
|
|
474
|
+
Expect(pRecord.Name)
|
|
475
|
+
.to.equal('MewTwo');
|
|
476
|
+
fDone();
|
|
477
|
+
}
|
|
478
|
+
)
|
|
479
|
+
}
|
|
480
|
+
);
|
|
481
|
+
test
|
|
482
|
+
(
|
|
483
|
+
'Read a record from the database',
|
|
484
|
+
function (fDone)
|
|
485
|
+
{
|
|
486
|
+
var testMeadow = newMeadow();
|
|
487
|
+
|
|
488
|
+
var tmpQuery = testMeadow.query
|
|
489
|
+
.setLogLevel(5)
|
|
490
|
+
.addFilter('IDAnimal', 1);
|
|
491
|
+
|
|
492
|
+
testMeadow.doRead(tmpQuery,
|
|
493
|
+
function (pError, pQuery, pRecord)
|
|
494
|
+
{
|
|
495
|
+
// We should have a record ....
|
|
496
|
+
Expect(pRecord.IDAnimal)
|
|
497
|
+
.to.equal(1);
|
|
498
|
+
Expect(pRecord.Name)
|
|
499
|
+
.to.equal('Foo Foo');
|
|
500
|
+
fDone();
|
|
501
|
+
}
|
|
502
|
+
)
|
|
503
|
+
}
|
|
504
|
+
);
|
|
505
|
+
test
|
|
506
|
+
(
|
|
507
|
+
'Read all records from the database',
|
|
508
|
+
function (fDone)
|
|
509
|
+
{
|
|
510
|
+
var testMeadow = newMeadow();
|
|
511
|
+
|
|
512
|
+
testMeadow.doReads(testMeadow.query.setLogLevel(5).addSort({Column: 'IDAnimal'}),
|
|
513
|
+
function (pError, pQuery, pRecords)
|
|
514
|
+
{
|
|
515
|
+
// We should have records ....
|
|
516
|
+
Expect(pRecords[0].IDAnimal)
|
|
517
|
+
.to.equal(1);
|
|
518
|
+
Expect(pRecords[0].Name)
|
|
519
|
+
.to.equal('Foo Foo');
|
|
520
|
+
Expect(pRecords[1].IDAnimal)
|
|
521
|
+
.to.equal(2);
|
|
522
|
+
Expect(pRecords[1].Name)
|
|
523
|
+
.to.equal('Red Riding Hood');
|
|
524
|
+
Expect(pRecords[1].Type)
|
|
525
|
+
.to.equal('Human');
|
|
526
|
+
fDone();
|
|
527
|
+
}
|
|
528
|
+
)
|
|
529
|
+
}
|
|
530
|
+
);
|
|
531
|
+
test
|
|
532
|
+
(
|
|
533
|
+
'Update a record in the database',
|
|
534
|
+
function (fDone)
|
|
535
|
+
{
|
|
536
|
+
var testMeadow = newMeadow();
|
|
537
|
+
|
|
538
|
+
var tmpQuery = testMeadow.query
|
|
539
|
+
.setLogLevel(5)
|
|
540
|
+
.addRecord({ IDAnimal: 2, Type: 'HumanGirl' });
|
|
541
|
+
|
|
542
|
+
testMeadow.doUpdate(tmpQuery,
|
|
543
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
544
|
+
{
|
|
545
|
+
// We should have a record ....
|
|
546
|
+
Expect(pRecord.Type)
|
|
547
|
+
.to.equal('HumanGirl');
|
|
548
|
+
fDone();
|
|
549
|
+
}
|
|
550
|
+
)
|
|
551
|
+
}
|
|
552
|
+
);
|
|
553
|
+
test
|
|
554
|
+
(
|
|
555
|
+
'Delete a record in the database',
|
|
556
|
+
function (fDone)
|
|
557
|
+
{
|
|
558
|
+
var testMeadow = newMeadow();
|
|
559
|
+
|
|
560
|
+
var tmpQuery = testMeadow.query
|
|
561
|
+
.setLogLevel(5)
|
|
562
|
+
.addFilter('IDAnimal', 4);
|
|
563
|
+
|
|
564
|
+
testMeadow.doDelete(tmpQuery,
|
|
565
|
+
function (pError, pQuery, pRecord)
|
|
566
|
+
{
|
|
567
|
+
// It returns the number of rows deleted
|
|
568
|
+
Expect(pRecord)
|
|
569
|
+
.to.equal(1);
|
|
570
|
+
fDone();
|
|
571
|
+
}
|
|
572
|
+
)
|
|
573
|
+
}
|
|
574
|
+
);
|
|
575
|
+
test
|
|
576
|
+
(
|
|
577
|
+
'Count all records from the database',
|
|
578
|
+
function (fDone)
|
|
579
|
+
{
|
|
580
|
+
var testMeadow = newMeadow();
|
|
581
|
+
|
|
582
|
+
testMeadow.doCount(testMeadow.query.setLogLevel(5),
|
|
583
|
+
function (pError, pQuery, pRecord)
|
|
584
|
+
{
|
|
585
|
+
// DGraph auto-filters Deleted=0, so count is non-deleted records only
|
|
586
|
+
Expect(pRecord)
|
|
587
|
+
.to.equal(5);
|
|
588
|
+
fDone();
|
|
589
|
+
}
|
|
590
|
+
)
|
|
591
|
+
}
|
|
592
|
+
);
|
|
593
|
+
test
|
|
594
|
+
(
|
|
595
|
+
'Create a record in the database with a defined creating user',
|
|
596
|
+
function (fDone)
|
|
597
|
+
{
|
|
598
|
+
var testMeadow = newMeadow();
|
|
599
|
+
var tmpQuery = testMeadow.query
|
|
600
|
+
.setIDUser(800)
|
|
601
|
+
.addRecord({ Name: 'MewSix', GUIDAnimal: '0x123456', Type: 'Pokemon' });
|
|
602
|
+
|
|
603
|
+
testMeadow.doCreate(tmpQuery,
|
|
604
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
605
|
+
{
|
|
606
|
+
// We should have a record ....
|
|
607
|
+
Expect(pRecord.Name)
|
|
608
|
+
.to.equal('MewSix');
|
|
609
|
+
Expect(pRecord.CreatingIDUser)
|
|
610
|
+
.to.equal(800);
|
|
611
|
+
fDone();
|
|
612
|
+
}
|
|
613
|
+
)
|
|
614
|
+
}
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
);
|
|
618
|
+
suite
|
|
619
|
+
(
|
|
620
|
+
'The Bad Kind of Query Processing',
|
|
621
|
+
function ()
|
|
622
|
+
{
|
|
623
|
+
test
|
|
624
|
+
(
|
|
625
|
+
'Create a record in the database with no record',
|
|
626
|
+
function (fDone)
|
|
627
|
+
{
|
|
628
|
+
var testMeadow = newMeadow().setDefaultIdentifier('Type');
|
|
629
|
+
|
|
630
|
+
testMeadow.doCreate(testMeadow.query,
|
|
631
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
632
|
+
{
|
|
633
|
+
Expect(pError)
|
|
634
|
+
.to.equal('No record submitted');
|
|
635
|
+
fDone();
|
|
636
|
+
}
|
|
637
|
+
)
|
|
638
|
+
}
|
|
639
|
+
);
|
|
640
|
+
test
|
|
641
|
+
(
|
|
642
|
+
'Read a record from the database with no data returned',
|
|
643
|
+
function (fDone)
|
|
644
|
+
{
|
|
645
|
+
var testMeadow = newMeadow();
|
|
646
|
+
|
|
647
|
+
var tmpQuery = testMeadow.query
|
|
648
|
+
.addFilter('IDAnimal', 5000);
|
|
649
|
+
testMeadow.doRead(tmpQuery,
|
|
650
|
+
function (pError, pQuery, pRecord)
|
|
651
|
+
{
|
|
652
|
+
Expect(pRecord)
|
|
653
|
+
.to.equal(false);
|
|
654
|
+
fDone();
|
|
655
|
+
}
|
|
656
|
+
)
|
|
657
|
+
}
|
|
658
|
+
);
|
|
659
|
+
test
|
|
660
|
+
(
|
|
661
|
+
'Read records from the database with no data returned',
|
|
662
|
+
function (fDone)
|
|
663
|
+
{
|
|
664
|
+
var testMeadow = newMeadow();
|
|
665
|
+
|
|
666
|
+
var tmpQuery = testMeadow.query
|
|
667
|
+
.addFilter('IDAnimal', 5000);
|
|
668
|
+
|
|
669
|
+
testMeadow.doReads(tmpQuery,
|
|
670
|
+
function (pError, pQuery, pRecord)
|
|
671
|
+
{
|
|
672
|
+
Expect(pRecord.length)
|
|
673
|
+
.to.equal(0);
|
|
674
|
+
fDone();
|
|
675
|
+
}
|
|
676
|
+
)
|
|
677
|
+
}
|
|
678
|
+
);
|
|
679
|
+
test
|
|
680
|
+
(
|
|
681
|
+
'Update a record in the database without passing a record in',
|
|
682
|
+
function (fDone)
|
|
683
|
+
{
|
|
684
|
+
var testMeadow = newMeadow();
|
|
685
|
+
|
|
686
|
+
testMeadow.doUpdate(testMeadow.query,
|
|
687
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
688
|
+
{
|
|
689
|
+
Expect(pError)
|
|
690
|
+
.to.equal('No record submitted');
|
|
691
|
+
fDone();
|
|
692
|
+
}
|
|
693
|
+
)
|
|
694
|
+
}
|
|
695
|
+
);
|
|
696
|
+
test
|
|
697
|
+
(
|
|
698
|
+
'Update a record in the database with a bad record passed in (no default identifier)',
|
|
699
|
+
function (fDone)
|
|
700
|
+
{
|
|
701
|
+
var testMeadow = newMeadow();
|
|
702
|
+
|
|
703
|
+
var tmpQuery = testMeadow.query
|
|
704
|
+
.addRecord({ Name: 'Bill' });
|
|
705
|
+
|
|
706
|
+
testMeadow.doUpdate(tmpQuery,
|
|
707
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
708
|
+
{
|
|
709
|
+
Expect(pError)
|
|
710
|
+
.to.equal('Automated update missing default identifier');
|
|
711
|
+
fDone();
|
|
712
|
+
}
|
|
713
|
+
)
|
|
714
|
+
}
|
|
715
|
+
);
|
|
716
|
+
test
|
|
717
|
+
(
|
|
718
|
+
'Update a record in the database that does not exist',
|
|
719
|
+
function (fDone)
|
|
720
|
+
{
|
|
721
|
+
var testMeadow = newMeadow();
|
|
722
|
+
|
|
723
|
+
var tmpQuery = testMeadow.query
|
|
724
|
+
.addRecord({ IDAnimal: 983924 });
|
|
725
|
+
|
|
726
|
+
testMeadow.doUpdate(tmpQuery,
|
|
727
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
728
|
+
{
|
|
729
|
+
// DGraph returns 0 (not an object) when no nodes match,
|
|
730
|
+
// so Meadow-Update Step 2 returns 'No record updated.'
|
|
731
|
+
Expect(pError)
|
|
732
|
+
.to.equal('No record updated.');
|
|
733
|
+
fDone();
|
|
734
|
+
}
|
|
735
|
+
)
|
|
736
|
+
}
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
);
|