From 6780cbcfb13c3632326ac62a732b768e26c2c343 Mon Sep 17 00:00:00 2001 From: Pixelastic Date: Thu, 17 Dec 2015 16:24:38 +0100 Subject: [PATCH 1/2] test(DocSearch): Add tests for constructor --- src/lib/DocSearch.js | 8 ++++++-- test/DocSearch-test.js | 11 +++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/lib/DocSearch.js b/src/lib/DocSearch.js index ab493d07..ce4358d8 100644 --- a/src/lib/DocSearch.js +++ b/src/lib/DocSearch.js @@ -44,6 +44,12 @@ class DocSearch { this.algoliaOptions = algoliaOptions; this.autocompleteOptions = autocompleteOptions; + this.apiKey = apiKey; + this.indexName = indexName; + this.input = this.getInputFromSelector(inputSelector); + this.algoliaOptions = algoliaOptions; + this.autocompleteOptions = autocompleteOptions; + this.client = algoliasearch('BH4D9OD16A', this.apiKey); this.client.addAlgoliaAgent('docsearch.js ' + version); this.autocomplete = autocomplete(this.input, autocompleteOptions, [{ @@ -68,8 +74,6 @@ class DocSearch { } if (!DocSearch.getInputFromSelector(args.inputSelector)) { - throw new Error(`Error: No input element in the page matches ${args.inputSelector}`); - } } /** diff --git a/test/DocSearch-test.js b/test/DocSearch-test.js index 3aeafb1a..aef41582 100644 --- a/test/DocSearch-test.js +++ b/test/DocSearch-test.js @@ -227,6 +227,17 @@ describe('DocSearch', () => { // Given let selector = '.i-do-not-exist > at #all'; + DocSearch.prototype.checkArguments = checkArguments; + DocSearch.prototype.getInputFromSelector = getInputFromSelector; + + DocSearch.__Rewire__('algoliasearch', AlgoliaSearch); + DocSearch.__Rewire__('autocomplete', AutoComplete); + }); + + it('should call checkArguments', () => { + // Given + let options = defaultOptions; + // When let actual = getInputFromSelector(selector); From 7b6c219a7ebd82d6501306d23d037697603fcc83 Mon Sep 17 00:00:00 2001 From: Pixelastic Date: Fri, 18 Dec 2015 16:28:24 +0100 Subject: [PATCH 2/2] test(getAutocompleteSource): Add tests for source I had to change some methods to static to be able to tests them without instantiating a new DocSearch. I also used better `restore` methods of sinon.js. I did not manage to correctly test the promise returned by the method returned by getAutocompleteSource. I would have like to test that when resolved it correctly call reformatHits on the data as well as call the callback on the reformated hits but got confused in spying/stubbing/mocking the promise. --- src/lib/DocSearch.js | 14 +++--- test/DocSearch-test.js | 108 +++++++++++++++++++++++++++++------------ 2 files changed, 83 insertions(+), 39 deletions(-) diff --git a/src/lib/DocSearch.js b/src/lib/DocSearch.js index ce4358d8..d494e5b7 100644 --- a/src/lib/DocSearch.js +++ b/src/lib/DocSearch.js @@ -44,19 +44,17 @@ class DocSearch { this.algoliaOptions = algoliaOptions; this.autocompleteOptions = autocompleteOptions; - this.apiKey = apiKey; - this.indexName = indexName; - this.input = this.getInputFromSelector(inputSelector); - this.algoliaOptions = algoliaOptions; - this.autocompleteOptions = autocompleteOptions; - this.client = algoliasearch('BH4D9OD16A', this.apiKey); this.client.addAlgoliaAgent('docsearch.js ' + version); this.autocomplete = autocomplete(this.input, autocompleteOptions, [{ source: this.getAutocompleteSource(), templates: { suggestion: this.getSuggestionTemplate(), - footer: '' + footer: ` + + ` } }]); this.autocomplete.on('autocomplete:selected', this.handleSelected); @@ -74,6 +72,8 @@ class DocSearch { } if (!DocSearch.getInputFromSelector(args.inputSelector)) { + throw new Error(`Error: No input element in the page matches ${args.inputSelector}`); + } } /** diff --git a/test/DocSearch-test.js b/test/DocSearch-test.js index aef41582..092c442b 100644 --- a/test/DocSearch-test.js +++ b/test/DocSearch-test.js @@ -34,10 +34,6 @@ describe('DocSearch', () => { let algoliasearch; let AutoComplete; let autocomplete; - let checkArguments; - let getInputFromSelector; - let checkArgumentsInitial; - let getInputFromSelectorInitial; let defaultOptions; beforeEach(() => { @@ -50,28 +46,24 @@ describe('DocSearch', () => { on: sinon.spy() }; AutoComplete = sinon.stub().returns(autocomplete); - - checkArgumentsInitial = DocSearch.checkArguments; - checkArguments = sinon.spy(); - getInputFromSelectorInitial = DocSearch.getInputFromSelector; - getInputFromSelector = sinon.stub(); defaultOptions = { indexName: 'indexName', apiKey: 'apiKey', inputSelector: '#input' }; - DocSearch.checkArguments = checkArguments; - DocSearch.getInputFromSelector = getInputFromSelector; + sinon.spy(DocSearch, 'checkArguments'); + sinon.stub(DocSearch, 'getInputFromSelector').returns(true); DocSearch.__Rewire__('algoliasearch', AlgoliaSearch); DocSearch.__Rewire__('autocomplete', AutoComplete); }); afterEach(() => { - // Cleanup the stubs on static methods - DocSearch.checkArguments = checkArgumentsInitial; - DocSearch.getInputFromSelector = getInputFromSelectorInitial; + DocSearch.checkArguments.restore(); + DocSearch.getInputFromSelector.restore(); + DocSearch.__ResetDependency__('algoliasearch'); + DocSearch.__ResetDependency__('autocomplete'); }); it('should call checkArguments', () => { @@ -82,7 +74,7 @@ describe('DocSearch', () => { new DocSearch(options); // Then - expect(checkArguments.calledOnce).toBe(true); + expect(DocSearch.checkArguments.calledOnce).toBe(true); }); it('should pass main options as instance properties', () => { // Given @@ -98,7 +90,7 @@ describe('DocSearch', () => { it('should pass the input element as an instance property', () => { // Given let options = defaultOptions; - getInputFromSelector.returns($('foo')); + DocSearch.getInputFromSelector.returns($('foo')); // When let actual = new DocSearch(options); @@ -123,7 +115,7 @@ describe('DocSearch', () => { expect(actual.algoliaOptions).toEqual('algoliaOptions'); expect(actual.autocompleteOptions).toEqual('autocompleteOptions'); }); - it('should instanciate algoliasearch with the correct values', () => { + it('should instantiate algoliasearch with the correct values', () => { // Given let options = defaultOptions; @@ -144,14 +136,14 @@ describe('DocSearch', () => { // Then expect(algoliasearch.addAlgoliaAgent.calledOnce).toBe(true); }); - it('should instanciate autocomplete.js', () => { + it('should instantiate autocomplete.js', () => { // Given let options = { ...defaultOptions, autocompleteOptions: 'bar' }; let $input = $(''); - getInputFromSelector.returns($input); + DocSearch.getInputFromSelector.returns($input); // When new DocSearch(options); @@ -179,6 +171,12 @@ describe('DocSearch', () => { checkArguments = DocSearch.checkArguments; }); + afterEach(() => { + if (DocSearch.getInputFromSelector.restore) { + DocSearch.getInputFromSelector.restore(); + } + }); + it('should throw an error if no apiKey defined', () => { // Given let options = { @@ -207,8 +205,7 @@ describe('DocSearch', () => { apiKey: 'apiKey', indexName: 'indexName' }; - let getInputFromSelector = sinon.stub().returns(false); - DocSearch.prototype.getInputFromSelector = getInputFromSelector; + sinon.stub(DocSearch, 'getInputFromSelector').returns(false); // When expect(() => { @@ -227,17 +224,6 @@ describe('DocSearch', () => { // Given let selector = '.i-do-not-exist > at #all'; - DocSearch.prototype.checkArguments = checkArguments; - DocSearch.prototype.getInputFromSelector = getInputFromSelector; - - DocSearch.__Rewire__('algoliasearch', AlgoliaSearch); - DocSearch.__Rewire__('autocomplete', AutoComplete); - }); - - it('should call checkArguments', () => { - // Given - let options = defaultOptions; - // When let actual = getInputFromSelector(selector); @@ -265,4 +251,62 @@ describe('DocSearch', () => { expect($.zepto.isZ(actual)).toBe(true); }); }); + + describe('getAutocompleteSource', () => { + let client; + let AlgoliaSearch; + let docsearch; + beforeEach(() => { + client = { + algolia: 'client', + addAlgoliaAgent: sinon.spy(), + search: sinon.stub().returns({ + then: sinon.spy() + }) + }; + AlgoliaSearch = sinon.stub().returns(client); + DocSearch.__Rewire__('algoliasearch', AlgoliaSearch); + + docsearch = new DocSearch({ + indexName: 'indexName', + apiKey: 'apiKey', + inputSelector: '#input', + algoliaOptions: 'algoliaOptions' + }); + }); + + afterEach(() => { + DocSearch.__ResetDependency__('algoliasearch'); + }); + + it('returns a function', () => { + // Given + let actual = docsearch.getAutocompleteSource(); + + // When + + // Then + expect(actual).toBeA('function'); + }); + + describe('the returned function', () => { + it('calls the Agolia client with the correct parameters', () => { + // Given + let actual = docsearch.getAutocompleteSource(); + + // When + actual('query'); + + // Then + expect(client.search.calledOnce).toBe(true); + // expect(resolvedQuery.calledOnce).toBe(true); + let expectedArguments = { + indexName: 'indexName', + query: 'query', + params: 'algoliaOptions' + }; + expect(client.search.calledWith([expectedArguments])).toBe(true); + }); + }); + }); });