LibreNMS/lib/typeahead/test/typeahead/dataset_spec.js

497 lines
13 KiB
JavaScript

describe('Dataset', function() {
var www = WWW(), mockSuggestions, mockSuggestionsDisplayFn;
mockSuggestions = [
{ value: 'one', raw: { value: 'one' } },
{ value: 'two', raw: { value: 'two' } },
{ value: 'html', raw: { value: '<b>html</b>' } }
];
mockSuggestionsDisplayFn = [
{ display: '4' },
{ display: '5' },
{ display: '6' }
];
beforeEach(function() {
this.dataset = new Dataset({
name: 'test',
node: $('<div>'),
source: this.source = jasmine.createSpy('source')
}, www);
});
it('should throw an error if source is missing', function() {
expect(noSource).toThrow();
function noSource() { new Dataset({}, www); }
});
it('should throw an error if the name is not a valid class name', function() {
expect(fn).toThrow();
function fn() {
var d = new Dataset({
name: 'a space',
node: $('<div>'),
source: $.noop
}, www);
}
});
describe('#getRoot', function() {
it('should return the root element', function() {
var sel = 'div' + www.selectors.dataset + www.selectors.dataset + '-test';
expect(this.dataset.$el).toBe(sel);
});
});
describe('#update', function() {
it('should render suggestions', function() {
this.source.andCallFake(syncMockSuggestions);
this.dataset.update('woah');
expect(this.dataset.$el).toContainText('one');
expect(this.dataset.$el).toContainText('two');
expect(this.dataset.$el).toContainText('html');
});
it('should escape html chars from display value when using default template', function() {
this.source.andCallFake(syncMockSuggestions);
this.dataset.update('woah');
expect(this.dataset.$el).toContainText('<b>html</b>');
});
it('should respect limit option', function() {
this.dataset.limit = 2;
this.source.andCallFake(syncMockSuggestions);
this.dataset.update('woah');
expect(this.dataset.$el).toContainText('one');
expect(this.dataset.$el).toContainText('two');
expect(this.dataset.$el).not.toContainText('three');
});
it('should allow custom display functions', function() {
this.dataset = new Dataset({
name: 'test',
node: $('<div>'),
display: function(o) { return o.display; },
source: this.source = jasmine.createSpy('source')
}, www);
this.source.andCallFake(syncMockSuggestionsDisplayFn);
this.dataset.update('woah');
expect(this.dataset.$el).toContainText('4');
expect(this.dataset.$el).toContainText('5');
expect(this.dataset.$el).toContainText('6');
});
it('should ignore async invocations of sync', function() {
this.source.andCallFake(asyncSync);
this.dataset.update('woah');
expect(this.dataset.$el).not.toContainText('one');
});
it('should ignore subesequent invocations of sync', function() {
this.source.andCallFake(multipleSync);
this.dataset.update('woah');
expect(this.dataset.$el.find('.tt-suggestion')).toHaveLength(3);
});
it('should trigger asyncRequested when needing/expecting backfill', function() {
var spy = jasmine.createSpy();
this.dataset.async = true;
this.dataset.onSync('asyncRequested', spy);
this.source.andCallFake(fakeGetWithAsyncSuggestions);
this.dataset.update('woah');
expect(spy).toHaveBeenCalled();
});
it('should not trigger asyncRequested when not expecting backfill', function() {
var spy = jasmine.createSpy();
this.dataset.async = false;
this.dataset.onSync('asyncRequested', spy);
this.source.andCallFake(fakeGetWithAsyncSuggestions);
this.dataset.update('woah');
expect(spy).not.toHaveBeenCalled();
});
it('should not trigger asyncRequested when not expecting backfill', function() {
var spy = jasmine.createSpy();
this.dataset.limit = 2;
this.dataset.async = true;
this.dataset.onSync('asyncRequested', spy);
this.source.andCallFake(fakeGetWithAsyncSuggestions);
this.dataset.update('woah');
expect(spy).not.toHaveBeenCalled();
});
it('should trigger asyncCanceled when pending aysnc is canceled', function() {
var spy = jasmine.createSpy();
this.dataset.async = true;
this.dataset.onSync('asyncCanceled', spy);
this.source.andCallFake(fakeGetWithAsyncSuggestions);
this.dataset.update('woah');
this.dataset.cancel();
waits(100);
runs(function() {
expect(spy).toHaveBeenCalled();
});
});
it('should not trigger asyncCanceled when cancel happens after update', function() {
var spy = jasmine.createSpy();
this.dataset.async = true;
this.dataset.onSync('asyncCanceled', spy);
this.source.andCallFake(fakeGetWithAsyncSuggestions);
this.dataset.update('woah');
waits(100);
runs(function() {
this.dataset.cancel();
expect(spy).not.toHaveBeenCalled();
});
});
it('should trigger asyncReceived when aysnc is received', function() {
var spy = jasmine.createSpy();
this.dataset.async = true;
this.dataset.onSync('asyncReceived', spy);
this.source.andCallFake(fakeGetWithAsyncSuggestions);
this.dataset.update('woah');
waits(100);
runs(function() {
expect(spy).toHaveBeenCalled();
});
});
it('should not trigger asyncReceived if canceled', function() {
var spy = jasmine.createSpy();
this.dataset.async = true;
this.dataset.onSync('asyncReceived', spy);
this.source.andCallFake(fakeGetWithAsyncSuggestions);
this.dataset.update('woah');
this.dataset.cancel();
waits(100);
runs(function() {
expect(spy).not.toHaveBeenCalled();
});
});
it('should not modify sync when async is added', function() {
var $test;
this.dataset.async = true;
this.source.andCallFake(fakeGetWithAsyncSuggestions);
this.dataset.update('woah');
$test = this.dataset.$el.find('.tt-suggestion').first();
$test.addClass('test');
waits(100);
runs(function() {
expect($test).toHaveClass('test');
});
});
it('should respect limit option in regard to async', function() {
this.dataset.async = true;
this.source.andCallFake(fakeGetWithAsyncSuggestions);
this.dataset.update('woah');
waits(100);
runs(function() {
expect(this.dataset.$el.find('.tt-suggestion')).toHaveLength(5);
});
});
it('should cancel pending async', function() {
var spy1 = jasmine.createSpy(), spy2 = jasmine.createSpy();
this.dataset.async = true;
this.dataset.onSync('asyncCanceled', spy1);
this.dataset.onSync('asyncReceived', spy2);
this.source.andCallFake(fakeGetWithAsyncSuggestions);
this.dataset.update('woah');
this.dataset.update('woah again');
waits(100);
runs(function() {
expect(spy1.callCount).toBe(1);
expect(spy2.callCount).toBe(1);
});
});
it('should render notFound when no suggestions are available', function() {
this.dataset = new Dataset({
source: this.source,
node: $('<div>'),
templates: {
notFound: '<h2>empty</h2>'
}
}, www);
this.source.andCallFake(syncEmptySuggestions);
this.dataset.update('woah');
expect(this.dataset.$el).toContainText('empty');
});
it('should render pending when no suggestions are available but async is pending', function() {
this.dataset = new Dataset({
source: this.source,
node: $('<div>'),
async: true,
templates: {
pending: '<h2>pending</h2>'
}
}, www);
this.source.andCallFake(syncEmptySuggestions);
this.dataset.update('woah');
expect(this.dataset.$el).toContainText('pending');
});
it('should render header when suggestions are rendered', function() {
this.dataset = new Dataset({
source: this.source,
node: $('<div>'),
templates: {
header: '<h2>header</h2>'
}
}, www);
this.source.andCallFake(syncMockSuggestions);
this.dataset.update('woah');
expect(this.dataset.$el).toContainText('header');
});
it('should render footer when suggestions are rendered', function() {
this.dataset = new Dataset({
source: this.source,
node: $('<div>'),
templates: {
footer: function(c) { return '<p>' + c.query + '</p>'; }
}
}, www);
this.source.andCallFake(syncMockSuggestions);
this.dataset.update('woah');
expect(this.dataset.$el).toContainText('woah');
});
it('should not render header/footer if there is no content', function() {
this.dataset = new Dataset({
source: this.source,
node: $('<div>'),
templates: {
header: '<h2>header</h2>',
footer: '<h2>footer</h2>'
}
}, www);
this.source.andCallFake(syncEmptySuggestions);
this.dataset.update('woah');
expect(this.dataset.$el).not.toContainText('header');
expect(this.dataset.$el).not.toContainText('footer');
});
it('should not render stale suggestions', function() {
this.source.andCallFake(fakeGetWithAsyncSuggestions);
this.dataset.update('woah');
this.source.andCallFake(syncMockSuggestions);
this.dataset.update('nelly');
waits(100);
runs(function() {
expect(this.dataset.$el).toContainText('one');
expect(this.dataset.$el).toContainText('two');
expect(this.dataset.$el).toContainText('html');
expect(this.dataset.$el).not.toContainText('four');
expect(this.dataset.$el).not.toContainText('five');
});
});
it('should not render async suggestions if update was canceled', function() {
this.source.andCallFake(fakeGetWithAsyncSuggestions);
this.dataset.update('woah');
this.dataset.cancel();
waits(100);
runs(function() {
var rendered = this.dataset.$el.find('.tt-suggestion');
expect(rendered).toHaveLength(3);
});
});
it('should render all async suggestions if sync had no content', function() {
this.source.andCallFake(fakeGetWithEmptySyncAndAsyncSuggestions);
this.dataset.update('woah');
waits(100);
runs(function() {
var rendered = this.dataset.$el.find('.tt-suggestion');
expect(rendered).toHaveLength(5);
});
});
it('should trigger rendered after suggestions are rendered', function() {
var spy;
this.dataset.onSync('rendered', spy = jasmine.createSpy());
this.source.andCallFake(syncMockSuggestions);
this.dataset.update('woah');
waitsFor(function() { return spy.callCount; });
});
});
describe('#clear', function() {
it('should clear suggestions', function() {
this.source.andCallFake(syncMockSuggestions);
this.dataset.update('woah');
this.dataset.clear();
expect(this.dataset.$el).toBeEmpty();
});
it('should cancel pending updates', function() {
var spy;
this.source.andCallFake(syncMockSuggestions);
this.dataset.update('woah');
spy = spyOn(this.dataset, 'cancel');
this.dataset.clear();
expect(spy).toHaveBeenCalled();
});
it('should trigger cleared', function() {
var spy;
this.dataset.onSync('cleared', spy = jasmine.createSpy());
this.dataset.clear();
expect(spy).toHaveBeenCalled();
});
});
describe('#isEmpty', function() {
it('should return true when empty', function() {
expect(this.dataset.isEmpty()).toBe(true);
});
it('should return false when not empty', function() {
this.source.andCallFake(syncMockSuggestions);
this.dataset.update('woah');
expect(this.dataset.isEmpty()).toBe(false);
});
});
describe('#destroy', function() {
it('should set dataset element to dummy element', function() {
var $prevEl = this.dataset.$el;
this.dataset.destroy();
expect(this.dataset.$el).not.toBe($prevEl);
});
});
// helper functions
// ----------------
function syncEmptySuggestions(q, sync, async) {
sync([]);
}
function syncMockSuggestions(q, sync, async) {
sync(mockSuggestions);
}
function syncMockSuggestionsDisplayFn(q, sync, async) {
sync(mockSuggestionsDisplayFn);
}
function asyncSync(q, sync, async) {
setTimeout(function() { sync(mockSuggestions); }, 0);
}
function multipleSync(q, sync, async) {
sync(mockSuggestions);
sync(mockSuggestions);
}
function fakeGetWithAsyncSuggestions(query, sync, async) {
sync(mockSuggestions);
setTimeout(function() {
async([
{ value: 'four', raw: { value: 'four' } },
{ value: 'five', raw: { value: 'five' } },
{ value: 'six', raw: { value: 'six' } },
{ value: 'seven', raw: { value: 'seven' } },
{ value: 'eight', raw: { value: 'eight' } },
]);
}, 0);
}
function fakeGetWithEmptySyncAndAsyncSuggestions(query, sync, async) {
sync([]);
setTimeout(function() {
async([
{ value: 'four', raw: { value: 'four' } },
{ value: 'five', raw: { value: 'five' } },
{ value: 'six', raw: { value: 'six' } },
{ value: 'seven', raw: { value: 'seven' } },
{ value: 'eight', raw: { value: 'eight' } },
]);
}, 0);
}
});