test("fullName", ()=>{ /** * Get the name of the test-case prefixed by the parent test-cases (if any). **/ api.protoMethod(); assert.same(TH.test.tc.fullName(), 'koru/test/test-case sub-test-case'); });
test("whereNot", ()=>{ /** * Add one or more where-nots to the query. If any where-not * test matches then the query does not match record * @param {string|object} params field or directive to match * on. If is object then whereNot is called for each key. * @param {object|primative} [value] corresponding to `params` **/ api.protoMethod('whereNot'); let st = new Query(TestModel).where('gender', 'm'); assert.same(st.count(), 2); st.whereNot({age: 5}); assert.equals(st.fetchField('age'), [10]); st = new Query(TestModel).where('gender', 'm'); st.whereNot('age', [5, 7]); assert.equals(st.fetchField('age'), [10]); assert.equals(st.whereNot('age', [5, 10]).fetchField('age'), []); assert.equals(st.whereNot('name', 'foo').fetchField('name'), []); });
test("resend", ()=>{ /** * Iterating over the queue returns messages in msgId order. **/ api.protoMethod('resend'); const session = { _msgId: 0, sendBinary(type, data) { assert.same(type, 'M'); ans.push(data); }, checkMsgId() {}, }; const queue = new sut(); queue.push(session, ['50'+Random.id(), 'list']); queue.push(session, ['6'+Random.id(), 'get', 423]); queue.push(session, ['8'+Random.id(), 'get', 5]); const ans = []; queue.resend(session); assert.same(session._msgId.toString(36), '50'); assert.equals(ans, [[TH.match(/^6/), 'get', 423], [TH.match(/^8/), 'get', 5], [TH.match(/^50/), 'list']]); });
test("topTestCase", ()=>{ /** * Retrieve the top most `TestCase` **/ api.protoMethod(); assert.same(TH.test.tc.topTestCase().fullName(), 'koru/test/test-case'); });
test("already Idle", ()=>{ /** * waitIdle waits until `this.count` drops to zero. **/ api.protoMethod('waitIdle'); //[ const check = new IdleCheck(); check.waitIdle(v.stub = stub()); assert.called(v.stub); //] });
test("reduce", ()=>{ /** * Run `reducer` on each member returning a single value **/ api.protoMethod(); //[ const iter = new Enumerable({*[Symbol.iterator]() {yield 1; yield 3}}); assert.same(iter.reduce((sum, value) => sum+value, 5), 9); assert.same(iter.reduce((sum, value) => sum-value), -2); //] });
test("map", ()=>{ /** * Map (and filter) an iterator to another value. If the `mapper` return `undefined` then the * value is filtered out of the results **/ api.protoMethod(); //[ const iter = new Enumerable({*[Symbol.iterator]() {yield 1; yield 5; yield 3}}); const mapped = iter.map(i => i == 5 ? undefined : 2*i); assert.equals(mapped.count(), 2); assert.equals(Array.from(mapped), [2, 6]); assert.equals(iter.map(i => 2*i)[Symbol.iterator]().next(), {done: false, value: 2}); //] });
test("onChange", ()=>{ /** * Observe changes to documents matching query * * See {#koru/observable#add} **/ api.protoMethod('onChange'); const onChange = TestModel.onChange; intercept(TestModel, 'onChange', func =>{ const handle = onChange.call(TestModel, func); v.stopSpy = spy(handle, 'stop'); return handle; }); api.example(_=>{ const query = TestModel.query.where(doc => doc.name.startsWith('F')); const oc = stub(); const handle = query.onChange(oc); const fred = TestModel.create({name: 'Fred'}); assert.calledWith(oc, DocChange.add(fred)); oc.reset(); const emma = TestModel.create({name: 'Emma'}); refute.called(oc); emma.$update('name', 'Fiona'); assert.calledWith(oc, DocChange.add(emma.$reload())); emma.$update('name', 'Fi'); assert.calledWith(oc, DocChange.change(emma.$reload(), {name: 'Fiona'})); fred.$update('name', 'Eric'); assert.calledWith(oc, DocChange.delete(fred.$reload())); /** stop cancels observer **/ handle.stop(); oc.reset(); fred.$update('name', 'Freddy'); refute.called(oc); }); assert.called(v.stopSpy); });
test("clone", ()=>{ /** * Clone the change. This is a shallow copy of the change---doc and undo are assigned; not * copied. **/ api.protoMethod(); //[ change = DocChange.change( new Book({_id: 'book1', title: 'Animal Farm'}), {title: 'Fanimal Arm'}); const copy = change.clone(); refute.same(copy, change); assert.same(copy.doc, change.doc); assert.same(copy.undo, change.undo); assert.same(copy.was, change.was); // was is cached //] });
test("subDocKeys", ()=>{ /** * Create a iterator over the property names for each property that is different between two * objects. **/ api.protoMethod(); //[ const book = new Book({_id: 'book1', title: 'Animal Farm', index: { d: {dog: [123,234], donkey: [56,456]}, p: {pig: [3, 34]} }}); const undo = Changes.applyAll(book.attributes, {index: { d: {dog: [123,234]}, h: {horse: [23,344]}, p: {pig: [3, 34]}, }}); change = DocChange.change(book, undo); assert.equals(Array.from(change.subDocKeys('index')).sort(), ['d', 'h']); //] change._set(book, {index: {g: false}}); assert.equals(Array.from(change.subDocKeys('index')).sort(), ['d', 'g', 'h', 'p']); change._set(book, {$partial: {index: ['$replace', null]}}); assert.equals(Array.from(change.subDocKeys('index')).sort(), ['d', 'h', 'p']); change._set(book, {foo: {a: 1, b: 2}}); assert.equals(Array.from(change.subDocKeys('foo')).sort(), ['a', 'b']); assert.equals(Array.from( DocChange.change(book, {}).subDocKeys('index') ).sort(), ['d', 'h', 'p']); assert.equals(Array.from( DocChange.change(book, {$partial: {title: null}}).subDocKeys('index') ).sort(), []); });
test("hasSomeFields", ()=>{ /** * Test if any of the `fields` have been changed **/ api.protoMethod(); //[ const dc = DocChange.change( new Book({ _id: 'book1', title: 'Animal Farm', Author: 'George Orwell', pages: 112, }), {title: 'Fanimal Arm', pages: 432}); assert.isTrue(dc.hasSomeFields('author', 'title')); assert.isTrue(dc.hasSomeFields('pages', 'title')); assert.isTrue(dc.hasSomeFields('author', 'pages')); assert.isFalse(dc.hasSomeFields('author')); assert.isFalse(dc.hasSomeFields('author', 'index')); //] });
test("hasField", ()=>{ /** * Test if a field has been changed. **/ api.protoMethod(); //[ const dc = DocChange.change( new Book({_id: 'book1', title: 'Animal Farm', pages: 112}), {title: 'Fanimal Arm'}); assert.isTrue(dc.hasField('title')); assert.isFalse(dc.hasField('pages')); // does not need to be a Model document const add = DocChange.add({name: 'Simon'}); assert.isTrue(add.hasField('name')); assert.isFalse(add.hasField('location')); assert.isTrue(DocChange.delete({name: 'Simon'}).hasField('name')); const change = DocChange.change({name: 'Simon', location: 'home'}, {location: 'work'}); assert.isFalse(change.hasField('name')); assert.isTrue(change.hasField('location')); //] });
test("$in", ()=>{ api.protoMethod('where'); assert.equals(TestModel.where('age', {$in: [10, 5]}).map(d => d.age).sort(), [10, 5]); assert.equals(TestModel.where('age', {$in: [5, 6]}).map(d => d.age).sort(), [5]); assert.equals(TestModel.where('age', [5, 6]).map(d => d.age).sort(), [5]); });
test("$ne", ()=>{ api.protoMethod('where'); assert.equals(TestModel.where('age', {$ne: 5}).map(d => d.age), [10]); assert.equals(TestModel.where('age', {$nin: [5, 6]}).map(d => d.age), [10]); assert.equals(TestModel.where({age: {$ne: 5}}).map(d => d.age), [10]); });
test("where func", ()=>{ api.protoMethod('where'); assert.same(v.TestModel.query.where(doc => doc.name !== 'foo').count(), 0); assert.same(v.TestModel.query.where(doc => doc.name === 'foo').count(), 1); });
test("example", ()=>{ api.protoMethod(); //[ const book = new Book({_id: 'book1', title: 'Animal Farm', index: { d: {dog: [123,234], donkey: [56,456]}, p: {pig: [3, 34]} }}); const undo = Changes.applyAll(book.attributes, {index: { d: {dog: [123,234], deer: [34]}, h: {horse: [23,344]}, p: {pig: [3, 34]}, }}); change = DocChange.change(book, undo); let count = 0; for (const dc of change.subDocs('index')) { if (dc._id === 'd') { ++count; assert.isTrue(dc.isChange); assert.same(dc.doc, book.index.d); assert.equals(dc.undo, {$partial: { deer: null, donkey: ['$replace', [56, 456]], }}); } else { ++count; assert.same(dc._id, 'h'); assert.isTrue(dc.isAdd); assert.same(dc.doc, book.index.h); } } assert.same(count, 2); //] change._set(book, {index: {g: false}}); let ans, dc; ans = map(change.subDocs('index')); assert.equals(ans.map(dc => dc._id), ['d', 'g', 'h', 'p']); assert.equals(ans.map(dc => dc.type), ['add', 'del', 'add', 'add']); assert.equals(ans.map(dc => dc.doc), [ {dog: [123, 234], deer: [34]}, false, {horse: [23, 344]}, {pig: [3, 34]}]); change._set(book, {$partial: {index: ['$replace', null]}}); ans = map(change.subDocs('index')); assert.equals(ans.map(dc => dc._id), ['d', 'h', 'p']); assert.equals(ans.map(dc => dc.type), ['add', 'add', 'add']); assert.equals(ans.map(dc => dc.doc), [ {dog: [123, 234], deer: [34]}, {horse: [23, 344]}, {pig: [3, 34]}]); change._set(book, {foo: {a: 1, b: 2}}); ans = map(change.subDocs('foo')); assert.equals(ans.map(dc => dc._id), ['a', 'b']); assert.equals(ans.map(dc => dc.type), ['del', 'del']); assert.equals(ans.map(dc => dc.doc), [1, 2]); change._set(book, {$partial: {index: ['h', null]}}); ans = map(change.subDocs('index')); dc = ans[0]; assert.equals(ans.map(dc => dc._id), ['h']); assert.equals(dc.type, 'add'); assert.equals(dc.doc, {horse: [23, 344]}); change._set(book, {$partial: {index: ['h', {hog: [12]}]}}); ans = map(change.subDocs('index')); dc = ans[0]; assert.equals(ans.map(dc => dc._id), ['h']); assert.equals(dc.type, 'chg'); assert.equals(dc.undo, {hog: [12]}); change._set(book, {$partial: {index: ['h', {hog: [12]}]}}); change._set(book, {$partial: {foo: ['a', 123]}}); assert.equals(map(change.subDocs('index')), []); ans = map(change.subDocs('foo')); dc = ans[0]; assert.equals(ans.map(dc => dc._id), ['a']); assert.equals(dc.type, 'del'); assert.equals(dc.doc, 123); });