-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create tests for savedobject.js in prep of refactoring and changes #9127
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import MapperService from 'ui/index_patterns/_mapper'; | ||
import stubbedLogstashFields from 'fixtures/logstash_fields'; | ||
import sinon from 'auto-release-sinon'; | ||
|
||
export function stubMapper(Private, mockLogstashFields = Private(stubbedLogstashFields)) { | ||
let stubbedMapper = Private(MapperService); | ||
|
||
sinon.stub(stubbedMapper, 'getFieldsForIndexPattern', function () { | ||
return Promise.resolve(mockLogstashFields.filter((field) => { return field.scripted === false; })); | ||
}); | ||
|
||
sinon.stub(stubbedMapper, 'clearCache', function () { | ||
return Promise.resolve(); | ||
}); | ||
|
||
return stubbedMapper; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
/** | ||
* Tests functionality in ui/public/courier/saved_object/saved_object.js | ||
*/ | ||
|
||
import ngMock from 'ng_mock'; | ||
import expect from 'expect.js'; | ||
import sinon from 'auto-release-sinon'; | ||
|
||
import BluebirdPromise from 'bluebird'; | ||
import SavedObjectFactory from '../saved_object/saved_object'; | ||
import { stubMapper } from 'test_utils/stub_mapper'; | ||
import IndexPatternFactory from 'ui/index_patterns/_index_pattern'; | ||
|
||
describe('Saved Object', function () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This relates to #9161, I've seen a number of tests that would've used 'ui/courier/saved_object' for the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know if there is a rule for this, but I think I prefer not specifying the path, otherwise you'd have to update the test if you move the file and I could see that easily being forgotten. |
||
require('test_utils/no_digest_promises').activateForSuite(); | ||
|
||
let savedObjectFactory; | ||
let IndexPattern; | ||
let esStub; | ||
|
||
beforeEach(ngMock.module('kibana')); | ||
beforeEach(ngMock.inject(function ($injector, Private) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason we're injecting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fetch.js does something similar to what I did, getting es from the injector. Happy to write it another way that makes more sense but I'm not sure how to 'just inject es'. If you can give me a little code snippet to explain your suggestion I can add it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you could change this to the following:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah, awesome, done! |
||
savedObjectFactory = Private(SavedObjectFactory); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like I've more commonly seen this being imported as So instead of having:
it'd become:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, much better. I was confused with the factory and private stuff, making this overly complicated. Done! |
||
IndexPattern = Private(IndexPatternFactory); | ||
esStub = $injector.get('es'); | ||
|
||
mockEsService(); | ||
stubMapper(Private); | ||
})); | ||
|
||
/** | ||
* Some default es stubbing to avoid timeouts and allow a default type of 'dashboard'. | ||
*/ | ||
function mockEsService() { | ||
// Allows the type 'dashboard' to be used. | ||
// Unfortunately we need to use bluebird here instead of native promises because there is | ||
// a call to finally. | ||
sinon.stub(esStub.indices, 'getFieldMapping').returns(BluebirdPromise.resolve({ | ||
'.kibana' : { | ||
'mappings': { | ||
'dashboard': {} | ||
} | ||
} | ||
})); | ||
|
||
// Necessary to avoid a timeout condition. | ||
sinon.stub(esStub.indices, 'putMapping').returns(BluebirdPromise.resolve()); | ||
}; | ||
|
||
/** | ||
* Stubs some of the es retrieval calls so it returns the given response. | ||
* @param {Object} mockDocResponse | ||
*/ | ||
function stubESResponse(mockDocResponse) { | ||
sinon.stub(esStub, 'mget').returns(BluebirdPromise.resolve({ docs: [mockDocResponse] })); | ||
sinon.stub(esStub, 'index').returns(BluebirdPromise.resolve(mockDocResponse)); | ||
} | ||
|
||
/** | ||
* Creates a new saved object with the given configuration. Does not call init. | ||
* @param {Object} config | ||
* @returns {SavedObject} an instance of SavedObject | ||
*/ | ||
function createSavedObject(config = {}) { | ||
let savedObject = {}; | ||
savedObjectFactory.call(savedObject, config); | ||
return savedObject; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor nit: can we move these functions above the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. indeed, done! |
||
|
||
describe ('config', function () { | ||
|
||
it('afterESResp is called', function () { | ||
let afterESRespCallback = sinon.spy(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Throughout the tests, there's an inconsistent usage of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Learn something new every day. Changed to const! |
||
const config = { | ||
type: 'dashboard', | ||
afterESResp: afterESRespCallback | ||
}; | ||
|
||
let savedObject = createSavedObject(config); | ||
return savedObject.init().then(() => { | ||
expect(afterESRespCallback.called).to.be(true); | ||
}); | ||
}); | ||
|
||
it('init is called', function () { | ||
let initCallback = sinon.spy(); | ||
const config = { | ||
type: 'dashboard', | ||
init: initCallback | ||
}; | ||
|
||
let savedObject = createSavedObject(config); | ||
return savedObject.init().then(() => { | ||
expect(initCallback.called).to.be(true); | ||
}); | ||
}); | ||
|
||
it('searchSource creates index when true', function () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we create an assertion for when it's false? describe('searchSource', () => {
describe('when true, blah blah', () => {
});
describe('when false, blah blah', () => {
});
}); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
const indexPatternId = 'testIndexPattern'; | ||
let afterESRespCallback = sinon.spy(); | ||
|
||
const config = { | ||
type: 'dashboard', | ||
afterESResp: afterESRespCallback, | ||
searchSource: true, | ||
indexPattern: indexPatternId | ||
}; | ||
|
||
const mockDocResponse = { | ||
_source: {}, | ||
_index: indexPatternId, | ||
_type: 'test-type', | ||
_id: indexPatternId, | ||
found: true | ||
}; | ||
|
||
stubESResponse(mockDocResponse); | ||
|
||
let savedObject = createSavedObject(config); | ||
expect(!!savedObject.searchSource.get('index')).to.be(false); | ||
|
||
return savedObject.init().then(() => { | ||
expect(afterESRespCallback.called).to.be(true); | ||
const index = savedObject.searchSource.get('index'); | ||
expect(index instanceof IndexPattern).to.be(true); | ||
expect(index.id).to.equal(indexPatternId); | ||
}); | ||
}); | ||
|
||
describe('type', function () { | ||
it('that is not specified throws an error', function () { | ||
let config = {}; | ||
|
||
let savedObject = createSavedObject(config); | ||
try { | ||
savedObject.init(); | ||
expect(false).to.be(true); | ||
} catch (err) { | ||
expect(err).to.not.be(null); | ||
} | ||
}); | ||
|
||
it('that is invalid invalid throws an error', function () { | ||
let config = {type: 'notypeexists'}; | ||
|
||
let savedObject = createSavedObject(config); | ||
try { | ||
savedObject.init(); | ||
expect(false).to.be(true); | ||
} catch (err) { | ||
expect(err).to.not.be(null); | ||
} | ||
}); | ||
|
||
it('that is valid passes', function () { | ||
let config = {type: 'dashboard'}; | ||
return createSavedObject(config).init(); | ||
}); | ||
}); | ||
|
||
describe('defaults', function () { | ||
it('applied to object with no id', function () { | ||
let config = { | ||
defaults: {testDefault: 'hi'}, | ||
type: 'dashboard' | ||
}; | ||
|
||
let savedObject = createSavedObject(config); | ||
return savedObject.init().then(() => { | ||
expect(savedObject.searchSource).to.be(undefined); | ||
expect(savedObject.defaults.testDefault).to.be(config.defaults.testDefault); | ||
}); | ||
}); | ||
|
||
it('applied to source if an id is given', function () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a few more assertions:
I'm just thinking we should document this (kinda odd) behavior in case anything depends on it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
const myId = 'myid'; | ||
const customDefault = 'hi'; | ||
const initialOverwriteMeValue = 'this should get overwritten by the server response'; | ||
|
||
let config = { | ||
defaults: { | ||
overwriteMe: initialOverwriteMeValue, | ||
customDefault: customDefault | ||
}, | ||
type: 'dashboard', | ||
id: myId | ||
}; | ||
|
||
const serverValue = 'this should override the initial default value given'; | ||
|
||
const mockDocResponse = { | ||
_source: { | ||
overwriteMe: serverValue | ||
}, | ||
_index: myId, | ||
_type: 'dashboard', | ||
_id: myId, | ||
found: true | ||
}; | ||
|
||
stubESResponse(mockDocResponse); | ||
|
||
let savedObject = createSavedObject(config); | ||
return savedObject.init().then(() => { | ||
expect(!!savedObject._source).to.be(true); | ||
expect(savedObject.defaults.overwriteMe).to.be(initialOverwriteMeValue); | ||
expect(savedObject._source.overwriteMe).to.be(serverValue); | ||
expect(savedObject._source.customDefault).to.be(customDefault); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might also be good to add tests for other instance methods There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added one for applyESResp. Save I'd prefer to get in the save/rename flow since I know what to test there. As for the others, it feels like I'd just be testing implementation details as opposed to expected results, so at least with my current understanding of this code, it doesn't seem super beneficial. (e.g. for delete, I could test that es.delete is called, but not that the item is actually deleted). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be slightly simplified:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! & done.