import { Watcher } from '../src/watcher.js'; describe('A watcher', () => { const selector = {}; const opts = {}; it('initially does nothing.', () => { const db = { changes: () => fail('Watcher should not call changes until the first subscription.') }; const w = Watcher(db, selector, opts); expect().nothing(); }); it('calls PouchDB.change API on the first subscription.', () => { let state = 0; const db = { changes: options => { expect(state).toEqual(1); expect(options.live).toEqual(true); expect(options.since).toEqual('now'); expect(options.selector).toBe(selector); return db; }, on: (eventName, callback) => { expect(['change', 'error'].indexOf(eventName) !== -1).toBeTruthy(); return db; }, cancel: () => {} }; const w = Watcher(db, selector, opts); state = 1; w(() => fail('Subscription callback should not be called until data changes.')); }); it('cancels change subscription when the last subscriber unsubscribes', () => { let state = 0; const db = { changes: options => { expect(state).toEqual(1); expect(options.live).toEqual(true); expect(options.since).toEqual('now'); expect(options.selector).toBe(selector); return db; }, on: (eventName, callback) => { expect(['change', 'error'].indexOf(eventName) !== -1).toBeTruthy(); return db; }, cancel: () => { expect(state).toEqual(2); state = 3; } }; const w = Watcher(db, selector, opts); state = 1; const unsub = w(() => fail('Subscription callback should not be called until data changes.')); state = 2; unsub(); expect(state).toEqual(3); }); it('passes change events to subscribers.', () => { let state = 0; const changes = { 234: { id: 234, deleted: false, doc: { _id: 234 } }, 34: { id: 34, deleted: true, doc: { _id: 34 } }, 4564565: { id: 4564565, deleted: false, doc: { _id: 4564565 } } }; let sub = null; const db = { changes: options => { expect(state).toEqual(1); expect(options.live).toEqual(true); expect(options.since).toEqual('now'); expect(options.selector).toBe(selector); return db; }, on: (eventName, callback) => { if (eventName == 'change') { sub = callback; } expect(['change', 'error'].indexOf(eventName) !== -1).toBeTruthy(); return db; }, cancel: () => (sub = null) }; const w = Watcher(db, selector, opts); state = 1; w((id, deleted, doc) => { expect(changes.hasOwnProperty(id)).toBeTruthy(); expect(changes[id].doc).toBe(doc); expect(changes[id].deleted).toEqual(deleted); }); Object.values(changes).forEach(sub); }); it('dumps subscribers when an error event happens.', () => { let state = 0; const changes = { 234: { id: 234, deleted: false, doc: { _id: 234 } }, 34: { id: 34, deleted: true, doc: { _id: 34 } }, 4564565: { id: 4564565, deleted: false, doc: { _id: 4564565 } } }; let sub = null; let errorSub = null; const db = { changes: options => { expect(state).toEqual(1); expect(options.live).toEqual(true); expect(options.since).toEqual('now'); expect(options.selector).toBe(selector); return db; }, on: (eventName, callback) => { if (eventName == 'change') { sub = callback; } if (eventName == 'error') { errorSub = callback; } expect(['change', 'error'].indexOf(eventName) !== -1).toBeTruthy(); return db; }, cancel: () => { sub = null; errorSub = null; } }; const w = Watcher(db, selector, opts); state = 1; w(() => fail('Subscription callback should not be called until data changes.')); const error = new Error('TestError'); try { errorSub(error); } catch (e) { expect(e).toBe(error); } Object.values(changes).forEach(sub); }); });