sorla-db 1.1.0 → 1.2.0

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.
@@ -1,62 +0,0 @@
1
- const chai = require('chai')
2
- const expect = chai.expect
3
- const sorla = require('../src/sorla.js')
4
-
5
- describe('SORLA databases and collections', () => {
6
- it('useDb creates the database when needed and selects it', () => {
7
- const srla = new sorla();
8
- expect(srla.dbExists('shop')).to.equal(false);
9
- srla.useDb('shop');
10
- expect(srla.dbExists('shop')).to.equal(true);
11
- expect(srla.db.name).to.equal('shop');
12
- expect(srla.countDb()).to.equal(1);
13
- });
14
-
15
- it('createDb returns the position, or false when the name exists', () => {
16
- const srla = new sorla();
17
- expect(srla.createDb('a')).to.equal(0);
18
- expect(srla.createDb('b')).to.equal(1);
19
- expect(srla.createDb('a')).to.equal(false);
20
- });
21
-
22
- it('keeps databases and their collections isolated', () => {
23
- const srla = new sorla();
24
- srla.useDb('one');
25
- srla.db.createCollection('items');
26
- srla.db.items.insertOne({ n: 1 });
27
- srla.useDb('two');
28
- srla.db.createCollection('items');
29
- expect(srla.db.items.count()).to.equal(0);
30
- srla.useDb('one');
31
- expect(srla.db.items.count()).to.equal(1);
32
- });
33
-
34
- it('instances do not share data', () => {
35
- const a = new sorla();
36
- const b = new sorla();
37
- a.useDb('x');
38
- expect(b.dbExists('x')).to.equal(false);
39
- });
40
-
41
- it('rejects duplicated collection names', () => {
42
- const srla = new sorla();
43
- srla.useDb('dupes');
44
- srla.db.createCollection('items');
45
- expect(() => srla.db.createCollection('items')).to.throw('Collection already exists');
46
- expect(srla.db.countCollections()).to.equal(1);
47
- });
48
-
49
- it('collection count, first, last and all', () => {
50
- const srla = new sorla();
51
- srla.useDb('basics');
52
- srla.db.createCollection('items');
53
- const items = srla.db.items;
54
- expect(items.count()).to.equal(0);
55
- items.insertOne({ n: 1 });
56
- items.insertOne({ n: 2 });
57
- expect(items.count()).to.equal(2);
58
- expect(items.first.n).to.equal(1);
59
- expect(items.last.n).to.equal(2);
60
- expect(items.all.length).to.equal(2);
61
- });
62
- });
@@ -1,116 +0,0 @@
1
- const chai = require('chai')
2
- const expect = chai.expect
3
- const sorla = require('../src/sorla.js')
4
-
5
- const UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
6
-
7
- describe('SORLA inserting documents', () => {
8
- let srla;
9
- let counter = 0;
10
- const fresh = () => {
11
- const name = `insert${++counter}`;
12
- srla.db.createCollection(name);
13
- return srla.db[name];
14
- };
15
-
16
- beforeAll(() => {
17
- srla = new sorla();
18
- srla.useDb('inserts');
19
- // insertMany logs the count of invalid documents on every call
20
- jest.spyOn(console, 'info').mockImplementation(() => {});
21
- });
22
-
23
- afterAll(() => jest.restoreAllMocks());
24
-
25
- it('generates a uuid v4 _id when the document has none', () => {
26
- const collection = fresh();
27
- collection.insertOne({ name: 'Ana' });
28
- expect(collection.first._id).to.match(UUID_V4);
29
- });
30
-
31
- it('generates unique ids', () => {
32
- const collection = fresh();
33
- for(let i = 0; i < 500; i++) collection.insertOne({ i });
34
- const ids = new Set(collection.all.map(doc => doc._id));
35
- expect(ids.size).to.equal(500);
36
- });
37
-
38
- it('keeps a provided _id', () => {
39
- const collection = fresh();
40
- collection.insertOne({ _id: 'custom-1', name: 'Ana' });
41
- expect(collection.findOne({ _id: 'custom-1' }).name).to.equal('Ana');
42
- });
43
-
44
- it('keeps values of every type', () => {
45
- const collection = fresh();
46
- collection.insertOne({ text: 'a', number: 1.5, flag: false, list: [1, 'b'], nested: { deep: { value: 3 } }, empty: '' });
47
- const doc = collection.first;
48
- expect(doc).to.include({ text: 'a', number: 1.5, flag: false, empty: '' });
49
- expect(doc.list).to.deep.equal([1, 'b']);
50
- expect(doc.nested.deep.value).to.equal(3);
51
- });
52
-
53
- it('insertMany inserts in order and counts', () => {
54
- const collection = fresh();
55
- collection.insertMany([{ n: 1 }, { n: 2 }, { n: 3 }]);
56
- expect(collection.count()).to.equal(3);
57
- expect(collection.all.map(doc => doc.n)).to.deep.equal([1, 2, 3]);
58
- expect(collection.last.n).to.equal(3);
59
- });
60
-
61
- it('calls the callbacks', () => {
62
- const collection = fresh();
63
- let calls = 0;
64
- collection.insertOne({ n: 1 }, () => calls++);
65
- collection.insertMany([{ n: 2 }], () => calls++);
66
- expect(calls).to.equal(2);
67
- });
68
-
69
- it('rejects documents that are not objects', () => {
70
- const collection = fresh();
71
- expect(() => collection.insertOne('text')).to.throw('Invalid document type');
72
- expect(() => collection.insertOne(['a'])).to.throw('Invalid document type');
73
- expect(() => collection.insertMany('text')).to.throw();
74
- expect(() => collection.insertMany([{ a: 1 }, 'b'])).to.throw('Documents must be an array of objects');
75
- });
76
-
77
- it('rejects keys with $ or .', () => {
78
- const collection = fresh();
79
- expect(() => collection.insertOne({ $name: 'a' })).to.throw('Invalid document keys');
80
- expect(() => collection.insertOne({ 'a.b': 1 })).to.throw('Invalid document keys');
81
- expect(() => collection.insertOne({ nested: { 'a.b': 1 } })).to.throw('Invalid document keys');
82
- expect(() => collection.insertOne({ list: [{ 'a.b': 1 }] })).to.throw('Invalid document keys');
83
- expect(collection.count()).to.equal(0);
84
- });
85
-
86
- // ---- known bugs: these document current behavior and will start failing once fixed
87
-
88
- it.failing('accepts null values (Object.keys(null) in _validateKeys)', () => {
89
- const collection = fresh();
90
- collection.insertOne({ name: 'Ana', nickname: null });
91
- expect(collection.first.nickname).to.equal(null);
92
- });
93
-
94
- it.failing('validates every nested object, not only the first one', () => {
95
- const collection = fresh();
96
- expect(() => collection.insertOne({ first: { ok: 1 }, second: { 'a.b': 1 } })).to.throw('Invalid document keys');
97
- });
98
-
99
- it.failing('rejects a duplicated _id', () => {
100
- const collection = fresh();
101
- collection.insertOne({ _id: 'same' });
102
- expect(() => collection.insertOne({ _id: 'same' })).to.throw();
103
- });
104
-
105
- it.failing('insertMany explains why a non array is rejected (it calls reduce before validating)', () => {
106
- const collection = fresh();
107
- expect(() => collection.insertMany('text')).to.throw('Documents must be an array of objects');
108
- });
109
-
110
- it.failing('does not mutate the inserted object', () => {
111
- const collection = fresh();
112
- const input = { name: 'Ana' };
113
- collection.insertOne(input);
114
- expect(input).to.not.have.property('_id');
115
- });
116
- });
@@ -1,94 +0,0 @@
1
- const chai = require('chai')
2
- const expect = chai.expect
3
- const sorla = require('../src/sorla.js')
4
-
5
- describe('SORLA nested logical queries', () => {
6
- let people;
7
-
8
- beforeAll(() => {
9
- const srla = new sorla();
10
- srla.useDb('nestedQueries');
11
- srla.db.createCollection('people');
12
- srla.db.people.insertOne({ name: 'Ana', age: 25, city: 'A', tags: ['admin'] });
13
- srla.db.people.insertOne({ name: 'Bruno', age: 31, city: 'B', tags: [] });
14
- srla.db.people.insertOne({ name: 'Carla', age: 42, city: 'C', tags: ['admin', 'dev'] });
15
- srla.db.people.insertOne({ name: 'Davi', age: 35, city: 'A' });
16
- srla.db.people.insertOne({ name: 'Eva', age: 19, city: 'D', tags: ['dev'] });
17
- people = srla.db.people;
18
- });
19
-
20
- const names = cursor => {
21
- const result = [];
22
- while(cursor.hasNext()) result.push(cursor.next()._data.name);
23
- return result;
24
- };
25
-
26
- it('combines $and with a nested $or', () => {
27
- const docs = people.find({
28
- $and: [
29
- { age: { $gte: 30 } },
30
- { $or: [{ name: 'Carla' }, { city: { $in: ['A', 'B'] } }] }
31
- ]
32
- });
33
- expect(names(docs)).to.deep.equal(['Bruno', 'Carla', 'Davi']);
34
- });
35
-
36
- it('nests groups at any depth', () => {
37
- const docs = people.find({
38
- $or: [
39
- { $and: [{ city: 'A' }, { $or: [{ age: { $lt: 30 } }, { name: 'Davi' }] }] },
40
- { $and: [{ city: 'D' }, { age: { $lt: 20 } }] }
41
- ]
42
- });
43
- expect(names(docs)).to.deep.equal(['Ana', 'Davi', 'Eva']);
44
- });
45
-
46
- it('evaluates every operator of a field inside $or', () => {
47
- const docs = people.find({ $or: [{ age: { $gte: 30, $lte: 35 } }, { name: 'Eva' }] });
48
- expect(names(docs)).to.deep.equal(['Bruno', 'Davi', 'Eva']);
49
- });
50
-
51
- it('evaluates every operator of a field at the top level', () => {
52
- expect(names(people.find({ age: { $gt: 20, $lt: 40, $ne: 31 } }))).to.deep.equal(['Ana', 'Davi']);
53
- });
54
-
55
- it('supports $nor with nested groups', () => {
56
- const docs = people.find({ $nor: [{ city: 'A' }, { $and: [{ age: { $gt: 40 } }, { city: 'C' }] }] });
57
- expect(names(docs)).to.deep.equal(['Bruno', 'Eva']);
58
- });
59
-
60
- it('$not inverts the whole condition, with one or more operators', () => {
61
- expect(names(people.find({ age: { $not: { $gte: 30 } } }))).to.deep.equal(['Ana', 'Eva']);
62
- expect(names(people.find({ age: { $not: { $gte: 30, $lte: 35 } } }))).to.deep.equal(['Ana', 'Carla', 'Eva']);
63
- });
64
-
65
- it('$not can be combined with other operators and logical groups', () => {
66
- const docs = people.find({ $and: [{ city: { $not: { $eq: 'A' } } }, { $or: [{ age: { $lt: 20 } }, { name: 'Bruno' }] }] });
67
- expect(names(docs)).to.deep.equal(['Bruno', 'Eva']);
68
- });
69
-
70
- it('matches array fields with $in', () => {
71
- expect(names(people.find({ $or: [{ tags: { $in: ['dev'] } }, { age: 31 }] }))).to.deep.equal(['Bruno', 'Carla', 'Eva']);
72
- });
73
-
74
- it('a field missing in the document matches $ne and $nin', () => {
75
- expect(names(people.find({ tags: { $ne: 'x' }, city: 'A' }))).to.deep.equal(['Ana', 'Davi']);
76
- expect(names(people.find({ name: { $nin: ['Ana', 'Bruno'] }, age: { $lt: 40 } }))).to.deep.equal(['Davi', 'Eva']);
77
- });
78
-
79
- it('accepts null values in conditions', () => {
80
- expect(people.find({ name: null }).length).to.equal(0);
81
- expect(people.find({ $or: [{ name: null }, { name: 'Ana' }] }).length).to.equal(1);
82
- });
83
-
84
- it('findOne works with nested queries', () => {
85
- const doc = people.findOne({ $and: [{ $or: [{ city: 'C' }, { city: 'D' }] }, { age: { $gt: 40 } }] });
86
- expect(doc.name).to.equal('Carla');
87
- });
88
-
89
- it('rejects invalid queries with a clear error', () => {
90
- expect(() => people.find({ $or: { name: 'Ana' } })).to.throw('The $or operator must be an array');
91
- expect(() => people.find({ age: { $between: [1, 2] } })).to.throw('Unknown operator $between');
92
- expect(() => people.find({ $not: { age: 1 } })).to.throw('$not operator must be used inside a field condition');
93
- });
94
- });
@@ -1,165 +0,0 @@
1
- /**
2
- * Compares find() against a straightforward reference implementation of the query semantics,
3
- * over hand written queries and hundreds of randomly generated nested ones (seeded, so a failure
4
- * always reproduces). This catches logic bugs, not just crashes.
5
- */
6
- const chai = require('chai')
7
- const expect = chai.expect
8
- const sorla = require('../src/sorla.js')
9
-
10
- // deterministic PRNG (mulberry32)
11
- function prng(seed) {
12
- return () => {
13
- seed |= 0; seed = seed + 0x6D2B79F5 | 0;
14
- let t = Math.imul(seed ^ seed >>> 15, 1 | seed);
15
- t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
16
- return ((t ^ t >>> 14) >>> 0) / 4294967296;
17
- };
18
- }
19
-
20
- const NAMES = ['Ana', 'Bruno', 'Carla', 'Davi', 'Eva', 'Fábio'];
21
- const CITIES = ['A', 'B', 'C', 'D'];
22
- const TAGS = ['admin', 'dev', 'ops'];
23
-
24
- function buildDocuments(random, count) {
25
- const pick = list => list[Math.floor(random() * list.length)];
26
- return Array.from({ length: count }, (_, n) => {
27
- const doc = { n, name: pick(NAMES), city: pick(CITIES), score: Math.round(random() * 1000) / 10, active: random() > 0.5 };
28
- if(random() > 0.15) doc.age = 18 + Math.floor(random() * 50); // sometimes missing
29
- if(random() > 0.3) doc.tags = TAGS.filter(() => random() > 0.5); // array, sometimes missing
30
- // nickname is often missing; null values cannot be stored yet (see feature_insert.test.js)
31
- if(random() > 0.5) doc.nickname = pick(NAMES);
32
- return doc;
33
- });
34
- }
35
-
36
- // ---- reference semantics, written independently of src/
37
- const compare = {
38
- $eq: (v, q) => !Array.isArray(q) && v === q,
39
- $ne: (v, q) => !Array.isArray(q) && v !== q,
40
- $gt: (v, q) => !Array.isArray(q) && v > q,
41
- $gte: (v, q) => !Array.isArray(q) && v >= q,
42
- $lt: (v, q) => !Array.isArray(q) && v < q,
43
- $lte: (v, q) => !Array.isArray(q) && v <= q,
44
- $in: (v, q) => Array.isArray(v) ? v.some(item => q.includes(item)) : q.includes(v),
45
- $nin: (v, q) => !(Array.isArray(v) ? v.some(item => q.includes(item)) : q.includes(v))
46
- };
47
-
48
- function refCondition(value, condition) {
49
- const isOps = condition !== null && typeof condition === 'object' && !Array.isArray(condition)
50
- && Object.keys(condition).length > 0 && Object.keys(condition).every(k => k.startsWith('$'));
51
- if(!isOps) return value === condition;
52
- return Object.entries(condition).every(([op, arg]) => op === '$not' ? !refCondition(value, arg) : compare[op](value, arg));
53
- }
54
-
55
- function refMatch(doc, query) {
56
- return Object.entries(query).every(([key, value]) => {
57
- if(key === '$and') return value.every(q => refMatch(doc, q));
58
- if(key === '$or') return value.some(q => refMatch(doc, q));
59
- if(key === '$nor') return !value.some(q => refMatch(doc, q));
60
- return refCondition(doc[key], value);
61
- });
62
- }
63
-
64
- // ---- random nested queries
65
- function randomQueryGenerator(random) {
66
- const pick = list => list[Math.floor(random() * list.length)];
67
- const fields = {
68
- name: () => pick(NAMES),
69
- city: () => pick(CITIES),
70
- age: () => 18 + Math.floor(random() * 50),
71
- score: () => Math.round(random() * 1000) / 10,
72
- active: () => random() > 0.5,
73
- tags: () => pick(TAGS),
74
- nickname: () => random() > 0.3 ? pick(NAMES) : null
75
- };
76
-
77
- function condition(field) {
78
- const value = fields[field];
79
- const roll = random();
80
- if(roll < 0.2) return value(); // plain equality
81
- const ops = {};
82
- const count = 1 + Math.floor(random() * 2);
83
- for(let i = 0; i < count; i++) {
84
- const op = pick(['$eq', '$ne', '$gt', '$gte', '$lt', '$lte', '$in', '$nin']);
85
- ops[op] = op === '$in' || op === '$nin' ? [value(), value()] : value();
86
- }
87
- return roll > 0.85 ? { $not: ops } : ops;
88
- }
89
-
90
- function node(depth) {
91
- const query = {};
92
- const fieldNames = Object.keys(fields).sort(() => random() - 0.5).slice(0, 1 + Math.floor(random() * 2));
93
- for(const field of fieldNames) query[field] = condition(field);
94
- if(depth < 3 && random() > 0.4) {
95
- const logical = pick(['$and', '$or', '$nor']);
96
- query[logical] = Array.from({ length: 1 + Math.floor(random() * 3) }, () => node(depth + 1));
97
- }
98
- return query;
99
- }
100
-
101
- return () => node(0);
102
- }
103
-
104
- describe('SORLA find() matches the reference query semantics', () => {
105
- let collection;
106
- let documents;
107
-
108
- beforeAll(() => {
109
- documents = buildDocuments(prng(2026), 120);
110
- const srla = new sorla();
111
- srla.useDb('equivalence');
112
- srla.db.createCollection('people');
113
- // insertOne mutates the object (adds _id), keep the reference documents clean
114
- for(const doc of documents) srla.db.people.insertOne(structuredClone(doc));
115
- collection = srla.db.people;
116
- });
117
-
118
- const found = query => {
119
- const cursor = collection.find(query);
120
- const ids = [];
121
- while(cursor.hasNext()) ids.push(cursor.next()._data.n);
122
- return ids;
123
- };
124
- const expected = query => documents.filter(doc => refMatch(doc, query)).map(doc => doc.n);
125
-
126
- const handWritten = [
127
- {},
128
- { city: 'A' },
129
- { age: { $gte: 30, $lt: 40 } },
130
- { tags: { $in: ['ops'] } },
131
- { nickname: null },
132
- { nickname: { $ne: null } },
133
- { age: { $nin: [20, 21, 22] }, active: true },
134
- { $or: [{ city: 'A' }, { city: 'B', age: { $gt: 50 } }] },
135
- { $and: [{ age: { $gte: 30 } }, { $or: [{ name: 'Ana' }, { city: { $in: ['A', 'B'] } }] }] },
136
- { $nor: [{ active: true }, { score: { $lt: 50 } }] },
137
- { score: { $not: { $gte: 20, $lte: 80 } } },
138
- { $or: [{ $and: [{ city: 'C' }, { $nor: [{ age: { $lt: 30 } }] }] }, { tags: { $in: ['admin'] }, active: false }] }
139
- ];
140
-
141
- handWritten.forEach((query, i) => {
142
- it(`hand written query #${i + 1}: ${JSON.stringify(query)}`, () => {
143
- expect(found(query)).to.deep.equal(expected(query));
144
- });
145
- });
146
-
147
- it('500 random nested queries give the same documents as the reference', () => {
148
- const next = randomQueryGenerator(prng(42));
149
- let nonEmpty = 0;
150
- for(let i = 0; i < 500; i++) {
151
- const query = next();
152
- const want = expected(query);
153
- if(want.length) nonEmpty++;
154
- expect(found(query), JSON.stringify(query)).to.deep.equal(want);
155
- }
156
- // the generator must produce meaningful queries, not only empty results
157
- expect(nonEmpty).to.be.greaterThan(100);
158
- });
159
-
160
- it('findOne returns the first matching document', () => {
161
- const query = { $and: [{ city: 'B' }, { $or: [{ active: true }, { age: { $gt: 40 } }] }] };
162
- const first = expected(query)[0];
163
- expect(collection.findOne(query).n).to.equal(first);
164
- });
165
- });
@@ -1,36 +0,0 @@
1
- const chai = require('chai')
2
- const expect = chai.expect
3
- const faker = require('faker')
4
- const sorla = require('../src/sorla.js')
5
- const collection = require('../src/collections/collection.js');
6
-
7
- describe('SORLA Database Unit Test', () => {
8
- beforeAll(() => {
9
- this.srla = new sorla();
10
- this.dbname = faker.random.word();
11
- this.srla.createDb(this.dbname);
12
- this.srla.useDb(this.dbname);
13
- });
14
-
15
- it('Should create a new collection with specified name', () => {
16
- this.srla.db.createCollection('collection1');
17
- expect(this.srla.db.countCollections()).to.equal(1);
18
- expect(this.srla.db.collection1).to.not.be.undefined;
19
- expect(this.srla.db.collection1).to.be.an.instanceof(collection);
20
- });
21
-
22
- it('Should create a new collection with specified name, second collection', () => {
23
- this.srla.db.createCollection('collection2');
24
- expect(this.srla.db.countCollections()).to.equal(2);
25
- expect(this.srla.db.collection2).to.not.be.undefined;
26
- expect(this.srla.db.collection2).to.be.an.instanceof(collection);
27
- });
28
-
29
- it('Should return a collection undefined when not exists', () => {
30
- expect(this.srla.db.collection3).to.be.undefined;
31
- });
32
-
33
- it('Should avoid create a collection with name that exists in database class', () => {
34
- expect(() => this.srla.db.createCollection('_name')).to.throw();
35
- });
36
- });
@@ -1,39 +0,0 @@
1
- const chai = require('chai');
2
- const expect = chai.expect;
3
- const faker = require('faker');
4
- const documents = require('../src/documents/document.js');
5
-
6
- describe('testing document capabilities', () => {
7
- it('checking capabilities of getting a field inside a object', () => {
8
- const doc = new documents({
9
- name: 'Anderson',
10
- test: {
11
- inscription: 123
12
- }
13
- });
14
-
15
- expect(doc.name).to.equal('Anderson');
16
- });
17
-
18
- it('checking capabilities of getting a field inside a object', () => {
19
- const doc = new documents({
20
- name: 'Anderson',
21
- test: {
22
- inscription: 123
23
- }
24
- });
25
-
26
- expect(doc.test.inscription).to.equal(123);
27
- });
28
-
29
- it('checking capabilities of getting a field inside a object', () => {
30
- const doc = new documents({
31
- name: 'Anderson',
32
- test: {
33
- inscription: 123
34
- }
35
- });
36
-
37
- expect(doc['test.inscription']).to.equal(123);
38
- });
39
- });
@@ -1,78 +0,0 @@
1
- const chai = require('chai')
2
- const expect = chai.expect
3
- const operators = require('../src/query_language/operators.js')
4
-
5
- describe('SORLA comparison operators', () => {
6
- const op = new operators();
7
-
8
- it('recognizes logical and comparison operators', () => {
9
- for(const name of ['$and', '$or', '$not', '$nor'])
10
- expect(op.isLogicalOperator(name)).to.equal(true);
11
- for(const name of ['$eq', '$ne', '$gt', '$gte', '$lt', '$lte', '$in', '$nin'])
12
- expect(op.isOperator(name)).to.equal(true);
13
- expect(op.isAnyOperator('$regex')).to.equal(false);
14
- expect(op.isAnyOperator('name')).to.equal(false);
15
- });
16
-
17
- it('$eq is strict', () => {
18
- expect(op.$eq(1, 1)).to.equal(true);
19
- expect(op.$eq('1', 1)).to.equal(false);
20
- expect(op.$eq(null, null)).to.equal(true);
21
- expect(op.$eq(undefined, null)).to.equal(false);
22
- expect(op.$eq(true, 1)).to.equal(false);
23
- expect(op.$eq([1], [1]), 'arrays are not compared').to.equal(false);
24
- });
25
-
26
- it('$ne is the negation of $eq for scalars', () => {
27
- expect(op.$ne(1, 2)).to.equal(true);
28
- expect(op.$ne(1, 1)).to.equal(false);
29
- expect(op.$ne(undefined, 1), 'missing field').to.equal(true);
30
- });
31
-
32
- it('range operators compare numbers, strings and ISO dates', () => {
33
- expect(op.$gt(5, 3)).to.equal(true);
34
- expect(op.$gte(3, 3)).to.equal(true);
35
- expect(op.$lt(2, 3)).to.equal(true);
36
- expect(op.$lte(3, 3)).to.equal(true);
37
- expect(op.$gt('b', 'a')).to.equal(true);
38
- expect(op.$lt('2026-01-31', '2026-02-01')).to.equal(true);
39
- expect(op.$gt(undefined, 0), 'missing field').to.equal(false);
40
- expect(op.$lt(undefined, 10), 'missing field').to.equal(false);
41
- });
42
-
43
- it('range operators reject arrays as the operand', () => {
44
- for(const name of ['$gt', '$gte', '$lt', '$lte', '$eq', '$ne'])
45
- expect(op[name](1, [1, 2]), name).to.equal(false);
46
- });
47
-
48
- it('$in and $nin work with scalar and array fields', () => {
49
- expect(op.$in('a', ['a', 'b'])).to.equal(true);
50
- expect(op.$in('c', ['a', 'b'])).to.equal(false);
51
- expect(op.$in(['x', 'b'], ['a', 'b']), 'array field shares a value').to.equal(true);
52
- expect(op.$in(['x'], ['a', 'b'])).to.equal(false);
53
- expect(op.$in(1, ['1']), 'strict').to.equal(false);
54
- expect(op.$nin('c', ['a', 'b'])).to.equal(true);
55
- expect(op.$nin(undefined, ['a']), 'missing field').to.equal(true);
56
- });
57
-
58
- it('$in and $nin require an array', () => {
59
- expect(() => op.$in('a', 'a')).to.throw('$in operator must be an array');
60
- expect(() => op.$nin('a', 'a')).to.throw('$nin operator must be an array');
61
- });
62
-
63
- it('matchesCondition treats plain values as equality and objects of operators as conditions', () => {
64
- expect(op.matchesCondition(5, 5)).to.equal(true);
65
- expect(op.matchesCondition(5, { $gt: 1, $lt: 10 })).to.equal(true);
66
- expect(op.matchesCondition(5, { $gt: 1, $lt: 4 })).to.equal(false);
67
- expect(op.matchesCondition(5, { $not: { $gt: 10 } })).to.equal(true);
68
- expect(op.matchesCondition({ a: 1 }, { a: 1 }), 'objects are not deep compared').to.equal(false);
69
- });
70
-
71
- it('isOperatorObject only accepts non empty objects made of operators', () => {
72
- expect(op.isOperatorObject({ $gt: 1 })).to.equal(true);
73
- expect(op.isOperatorObject({ $gt: 1, name: 2 })).to.equal(false);
74
- expect(op.isOperatorObject({})).to.equal(false);
75
- expect(op.isOperatorObject(null)).to.equal(false);
76
- expect(op.isOperatorObject([1])).to.equal(false);
77
- });
78
- });
@@ -1,42 +0,0 @@
1
- const chai = require('chai')
2
- const expect = chai.expect
3
- const faker = require('faker')
4
-
5
- const sorla = require('../src/sorla.js')
6
-
7
- describe('SORLA Unit Test', () => {
8
- it('Should create a new database with random name', () => {
9
- const srla = new sorla();
10
- const dbname = faker.random.word();
11
- srla.createDb(dbname);
12
- srla.useDb(dbname);
13
-
14
- expect(srla.countDb()).to.equal(1);
15
- expect(srla.dbExists(dbname)).to.equal(true);
16
- expect(srla.db.name).to.equal(dbname);
17
- });
18
-
19
- it('Should not create a new database with the same name', () => {
20
- const srla = new sorla();
21
- const dbname = faker.random.word();
22
- srla.createDb(dbname);
23
-
24
- expect(srla.createDb(dbname)).to.equal(false);
25
- });
26
-
27
- it('Should created more than one database', () => {
28
- const srla = new sorla();
29
- for(let i=0; i<2; i++)
30
- {
31
- const dbname = faker.random.word();
32
- srla.createDb(dbname);
33
- }
34
-
35
- expect(srla.countDb()).to.equal(2);
36
- });
37
-
38
- it('Should not have any database created', () => {
39
- const srla = new sorla();
40
- expect(srla.countDb()).to.equal(0);
41
- });
42
- });
@@ -1,25 +0,0 @@
1
- const chai = require('chai');
2
- const expect = chai.expect;
3
-
4
- const sorla = require('../src/sorla.js');
5
-
6
- describe('Sorla Class', () => {
7
- it('should create a new database', () => {
8
- const srla = new sorla();
9
- srla.createDb('test');
10
- expect(srla.countDb()).to.equal(1);
11
- });
12
-
13
- it('should not create a new database with the same name', () => {
14
- const srla = new sorla();
15
- srla.createDb('test');
16
- expect(srla.createDb('test')).to.equal(false);
17
- });
18
-
19
- it('should created a new database and select it', () => {
20
- const srla = new sorla();
21
- const dbname = 'test';
22
- srla.useDb(dbname);
23
- expect(srla.db.name).to.equal(dbname);
24
- });
25
- });
package/webpack.config.js DELETED
@@ -1,11 +0,0 @@
1
- const path = require('path');
2
-
3
- module.exports = {
4
- mode: "production",
5
- target: "web",
6
- entry: './src/sorla.js',
7
- output: {
8
- path: path.resolve(__dirname, 'dist'),
9
- filename: 'sorla.min.js'
10
- }
11
- }