Skip to content

Commit

Permalink
fix(lifecycle): save configuration done in widget.init
Browse files Browse the repository at this point in the history
Before this commit, every configuration done in widget.init would not
be remembered when going back in the browser history.

Scenario: You built a custom widget using helper.setQueryParameter in
widget.init. Then you load "/", widget.init() sets some helper params,
you go to page 2, you click on <= back. Before this commit we would
forget what was done in widget.init(). Now it works.

This was needed to fix the "rootPath" option of the hierarchicalMenu.
The rootPath option triggers a state change from inside the helper
(which may have been a bad idea after all) => it was not remembered
when going back to empty url.

Thanks to @maxiloc for the bug report and big help solving this!
  • Loading branch information
vvo committed Apr 26, 2016
1 parent 624da3f commit 07d1fea
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 7 deletions.
1 change: 1 addition & 0 deletions dev/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ search.addWidget(
link: 'facet-value',
count: 'facet-count pull-right'
},
rootPath: 'Cameras & Camcorders > Digital Camera Accessories',
templates: {
header: 'Hierarchical categories'
}
Expand Down
2 changes: 1 addition & 1 deletion dev/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ <h1><a href="./">Instant search demo</a> <small>using instantsearch.js</small></
</div>
</div>
</div>
<div id="pagination" class="text-center"></div>
<h3>Results overview</h3>
<div id="hits-table"></div>
<h3>Results</h3>
<div id="hits"></div>
<div id="pagination" class="text-center"></div>
</div>
</div>
</div>
Expand Down
13 changes: 10 additions & 3 deletions src/lib/InstantSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,15 @@ Usage: instantsearch({
start() {
if (!this.widgets) throw new Error('No widgets were added to instantsearch.js');

let syncWidget;

if (this.urlSync) {
let syncWidget = urlSyncWidget(this.urlSync);
syncWidget = urlSyncWidget(this.urlSync);
this._createURL = syncWidget.createURL.bind(syncWidget);
this._onHistoryChange = syncWidget.onHistoryChange.bind(syncWidget);
this.widgets.push(syncWidget);
} else {
this._createURL = defaultCreateURL;
this._onHistoryChange = function() {};
this._onHistoryChange = () => {};
}

this.searchParameters = this.widgets.reduce(enhanceConfiguration, this.searchParameters);
Expand All @@ -128,6 +129,12 @@ Usage: instantsearch({
this.helper = helper;

this._init(helper.state, helper);

if (this.urlSync) {
helper.setState(enhanceConfiguration(helper.state, syncWidget));
syncWidget.init({helper});
}

helper.on('result', this._render.bind(this, helper));
helper.search();
}
Expand Down
29 changes: 26 additions & 3 deletions src/lib/__tests__/InstantSearch-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe('InstantSearch lifecycle', () => {
let searchParameters;
let search;
let helperSearchSpy;
let urlSync;

beforeEach(() => {
client = {algolia: 'client', addAlgoliaAgent: () => {}};
Expand All @@ -33,10 +34,18 @@ describe('InstantSearch lifecycle', () => {
helperSearchSpy = sinon.spy();
helper.search = helperSearchSpy;
helper.getState = sinon.stub().returns({});
helper.setState = sinon.spy();
helper.state = {
setQueryParameters: function(params) { return new SearchParameters(params); }
};

urlSync = {
createURL: sinon.spy(),
onHistoryChange: () => {},
getConfiguration: sinon.spy(),
init: () => {}
};

algoliasearch = sinon.stub().returns(client);
algoliasearchHelper = sinon.stub().returns(helper);

Expand All @@ -51,6 +60,7 @@ describe('InstantSearch lifecycle', () => {
another: {config: 'parameter'}
};

InstantSearch.__Rewire__('urlSyncWidget', () => urlSync);
InstantSearch.__Rewire__('algoliasearch', algoliasearch);
InstantSearch.__Rewire__('algoliasearchHelper', algoliasearchHelper);

Expand All @@ -64,6 +74,7 @@ describe('InstantSearch lifecycle', () => {
});

afterEach(() => {
InstantSearch.__ResetDependency__('urlSyncWidget');
InstantSearch.__ResetDependency__('algoliasearch');
InstantSearch.__ResetDependency__('algoliasearchHelper');
});
Expand Down Expand Up @@ -111,7 +122,9 @@ describe('InstantSearch lifecycle', () => {
beforeEach(() => {
widget = {
getConfiguration: sinon.stub().returns({some: 'modified', another: {different: 'parameter'}}),
init: sinon.spy(),
init: sinon.spy(() => {
helper.state.sendMeToUrlSync = true;
}),
render: sinon.spy()
};
search.addWidget(widget);
Expand Down Expand Up @@ -160,6 +173,14 @@ describe('InstantSearch lifecycle', () => {
expect(args.onHistoryChange).toBe(search._onHistoryChange);
});

it('calls urlSync.getConfiguration after every widget', () => {
expect(urlSync.getConfiguration.calledOnce).toBe(true, 'urlSync.getConfiguration called once');
expect(widget.init.calledAfter(widget.getConfiguration))
.toBe(true, 'urlSync.getConfiguration was called after widget.init');
expect(urlSync.getConfiguration.getCall(0).args[0].sendMeToUrlSync)
.toBe(true, 'state modifications done in widget.init should be sent to urlSync.getConfiguration');
});

it('does not call widget.render', () => {
expect(widget.render.notCalled).toBe(true);
});
Expand Down Expand Up @@ -235,8 +256,10 @@ describe('InstantSearch lifecycle', () => {
search.start();
});

it('creates a URL', () => {
expect(search.createURL({hitsPerPage: 42})).toEqual('?q=&hPP=42&idx=&p=0');
it('has a createURL method', () => {
search.createURL({hitsPerPage: 542});
expect(urlSync.createURL.calledOnce).toBe(true);
expect(urlSync.createURL.getCall(0).args[0].hitsPerPage).toBe(542);
});

it('emits render when all render are done (using on)', () => {
Expand Down

0 comments on commit 07d1fea

Please sign in to comment.