vue-instantsearch 4.1.1 → 4.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/package.json +7 -6
  3. package/src/components/DynamicWidgets.js +11 -1
  4. package/src/components/ExperimentalDynamicWidgets.js +10 -0
  5. package/src/components/__tests__/DynamicWidgets.js +45 -0
  6. package/src/components/__tests__/ExperimentalDynamicWidgets.js +41 -0
  7. package/src/mixins/widget.js +1 -1
  8. package/src/util/__tests__/createServerRootMixin.test.js +217 -61
  9. package/src/util/createServerRootMixin.js +40 -108
  10. package/src/util/testutils/helper.js +2 -2
  11. package/src/widgets.js +3 -0
  12. package/vue2/cjs/index.js +1 -1
  13. package/vue2/cjs/index.js.map +1 -1
  14. package/vue2/es/package.json.js +1 -1
  15. package/vue2/es/src/components/DynamicWidgets.js +1 -1
  16. package/vue2/es/src/components/DynamicWidgets.js.map +1 -1
  17. package/vue2/es/src/components/ExperimentalDynamicWidgets.js +2 -0
  18. package/vue2/es/src/components/ExperimentalDynamicWidgets.js.map +1 -0
  19. package/vue2/es/src/instantsearch.js +1 -1
  20. package/vue2/es/src/mixins/widget.js +1 -1
  21. package/vue2/es/src/mixins/widget.js.map +1 -1
  22. package/vue2/es/src/util/createServerRootMixin.js +1 -1
  23. package/vue2/es/src/util/createServerRootMixin.js.map +1 -1
  24. package/vue2/es/src/widgets.js +1 -1
  25. package/vue2/umd/index.js +1 -1
  26. package/vue2/umd/index.js.map +1 -1
  27. package/vue3/cjs/index.js +1 -1
  28. package/vue3/cjs/index.js.map +1 -1
  29. package/vue3/es/package.json.js +1 -1
  30. package/vue3/es/src/components/DynamicWidgets.js +1 -1
  31. package/vue3/es/src/components/DynamicWidgets.js.map +1 -1
  32. package/vue3/es/src/components/ExperimentalDynamicWidgets.js +2 -0
  33. package/vue3/es/src/components/ExperimentalDynamicWidgets.js.map +1 -0
  34. package/vue3/es/src/instantsearch.js +1 -1
  35. package/vue3/es/src/mixins/widget.js +1 -1
  36. package/vue3/es/src/mixins/widget.js.map +1 -1
  37. package/vue3/es/src/util/createServerRootMixin.js +1 -1
  38. package/vue3/es/src/util/createServerRootMixin.js.map +1 -1
  39. package/vue3/es/src/widgets.js +1 -1
  40. package/vue3/umd/index.js +1 -1
  41. package/vue3/umd/index.js.map +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,41 @@
1
+ ## [4.3.2](https://github.com/algolia/vue-instantsearch/compare/v4.3.1...v4.3.2) (2022-01-31)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **ssr:** extend component correctly if at root (vue2) ([#1104](https://github.com/algolia/vue-instantsearch/issues/1104)) ([08b7124](https://github.com/algolia/vue-instantsearch/commit/08b71244c3bf7cf2cbd8183a671d1a589af75798)), closes [#1054](https://github.com/algolia/vue-instantsearch/issues/1054)
7
+
8
+
9
+
10
+ ## [4.3.1](https://github.com/algolia/vue-instantsearch/compare/v4.3.0...v4.3.1) (2022-01-11)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **dependencies:** update instantsearch.js requirement ([a36ae2b](https://github.com/algolia/vue-instantsearch/commit/a36ae2b964110f3e4bc98c39895dd31b79527701)), closes [#1096](https://github.com/algolia/vue-instantsearch/issues/1096)
16
+
17
+
18
+
19
+ # [4.3.0](https://github.com/algolia/vue-instantsearch/compare/v4.2.0...v4.3.0) (2021-12-16)
20
+
21
+
22
+ ### Features
23
+
24
+ * **dynamicWidgets:** pass parameters to connector ([#1093](https://github.com/algolia/vue-instantsearch/issues/1093)) ([247ed0f](https://github.com/algolia/vue-instantsearch/commit/247ed0f101b5dabd5eebf35a7b8c3a2504eef2e2))
25
+
26
+
27
+
28
+ # [4.2.0](https://github.com/algolia/vue-instantsearch/compare/v4.1.1...v4.2.0) (2021-12-13)
29
+
30
+
31
+ ### Features
32
+
33
+ * **dynamicWidgets:** release as production ([#1086](https://github.com/algolia/vue-instantsearch/issues/1086)) ([9e0902b](https://github.com/algolia/vue-instantsearch/commit/9e0902bc7a3afe3eb2211b78e681e65b3677dd78))
34
+ * **instantsearch:** update version ([dbf485f](https://github.com/algolia/vue-instantsearch/commit/dbf485f6263d9821aaf169e682ff1ab94157d15f))
35
+ * **ssr:** prevent initial network request ([#1090](https://github.com/algolia/vue-instantsearch/issues/1090)) ([d97eea2](https://github.com/algolia/vue-instantsearch/commit/d97eea21fbd059b0ca0634a6984a6a8b02acdd3d))
36
+
37
+
38
+
1
39
  ## [4.1.1](https://github.com/algolia/vue-instantsearch/compare/v4.1.0...v4.1.1) (2021-10-27)
2
40
 
3
41
 
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "autocomplete"
17
17
  ],
18
18
  "license": "MIT",
19
- "version": "4.1.1",
19
+ "version": "4.3.2",
20
20
  "files": [
21
21
  "vue2",
22
22
  "vue3",
@@ -48,8 +48,7 @@
48
48
  "release": "shipjs prepare"
49
49
  },
50
50
  "dependencies": {
51
- "algoliasearch-helper": "^3.6.2",
52
- "instantsearch.js": "^4.32.0",
51
+ "instantsearch.js": "^4.37.2",
53
52
  "mitt": "^2.1.0"
54
53
  },
55
54
  "peerDependencies": {
@@ -76,12 +75,14 @@
76
75
  "@vue/test-utils2": "npm:@vue/test-utils@2.0.0-rc.11",
77
76
  "@wdio/cli": "^5.11.13",
78
77
  "@wdio/jasmine-framework": "^5.11.0",
78
+ "@wdio/junit-reporter": "^5.11.7",
79
79
  "@wdio/local-runner": "^5.11.13",
80
80
  "@wdio/sauce-service": "^5.11.1",
81
81
  "@wdio/selenium-standalone-service": "^5.11.2",
82
82
  "@wdio/spec-reporter": "^5.11.7",
83
83
  "@wdio/static-server-service": "^5.11.0",
84
84
  "algoliasearch": "4.0.1",
85
+ "algoliasearch-helper": "3.7.0",
85
86
  "babel-eslint": "10.0.1",
86
87
  "babel-jest": "23.6.0",
87
88
  "babel-preset-es2015": "6.24.1",
@@ -95,7 +96,7 @@
95
96
  "eslint-plugin-jest": "22.3.0",
96
97
  "eslint-plugin-prettier": "3.0.0",
97
98
  "eslint-plugin-vue": "4.7.1",
98
- "instantsearch-e2e-tests": "algolia/instantsearch-e2e-tests#v1.3.0",
99
+ "instantsearch-e2e-tests": "algolia/instantsearch-e2e-tests#v2.0.1",
99
100
  "instantsearch.css": "7.3.1",
100
101
  "jest": "23.6.0",
101
102
  "jest-serializer-html": "7.1.0",
@@ -132,11 +133,11 @@
132
133
  "bundlesize": [
133
134
  {
134
135
  "path": "./vue2/umd/index.js",
135
- "maxSize": "55.25 kB"
136
+ "maxSize": "56.00 kB"
136
137
  },
137
138
  {
138
139
  "path": "./vue3/umd/index.js",
139
- "maxSize": "56.75 kB"
140
+ "maxSize": "57.00 kB"
140
141
  },
141
142
  {
142
143
  "path": "./vue2/cjs/index.js",
@@ -40,7 +40,7 @@ function getWidgetAttribute(vnode) {
40
40
  }
41
41
 
42
42
  export default {
43
- name: 'AisExperimentalDynamicWidgets',
43
+ name: 'AisDynamicWidgets',
44
44
  mixins: [
45
45
  createWidgetMixin({ connector: connectDynamicWidgets }),
46
46
  createSuitMixin({ name: 'DynamicWidgets' }),
@@ -50,6 +50,14 @@ export default {
50
50
  type: Function,
51
51
  default: undefined,
52
52
  },
53
+ facets: {
54
+ type: Array,
55
+ default: undefined,
56
+ },
57
+ maxValuesPerFacet: {
58
+ type: Number,
59
+ default: undefined,
60
+ },
53
61
  },
54
62
  render: renderCompat(function(h) {
55
63
  const components = new Map();
@@ -91,6 +99,8 @@ export default {
91
99
  widgetParams() {
92
100
  return {
93
101
  transformItems: this.transformItems,
102
+ facets: this.facets,
103
+ maxValuesPerFacet: this.maxValuesPerFacet,
94
104
  // we do not pass "widgets" to the connector, since Vue is in charge of rendering
95
105
  widgets: [],
96
106
  };
@@ -0,0 +1,10 @@
1
+ import AisDynamicWidgets from './DynamicWidgets';
2
+ import { warn } from '../util/warn';
3
+
4
+ // @MAJOR remove this file
5
+ export default Object.assign({}, AisDynamicWidgets, {
6
+ name: 'AisExperimentalDynamicWidgets',
7
+ mounted() {
8
+ warn('Use AisDynamicWidgets instead of AisExperimentalDynamicWidgets.');
9
+ },
10
+ });
@@ -46,6 +46,51 @@ const MockHierarchicalMenu = {
46
46
  `,
47
47
  };
48
48
 
49
+ it('passes arguments to connector', () => {
50
+ __setState(null);
51
+
52
+ const transformItems = items => items;
53
+ const facets = ['test'];
54
+ const maxValuesPerFacet = 100;
55
+ const wrapper = mount({
56
+ data() {
57
+ return { props: { transformItems, facets, maxValuesPerFacet } };
58
+ },
59
+ template: `
60
+ <DynamicWidgets v-bind="props">
61
+ <MockRefinementList attribute="test1"/>
62
+ <MockMenu attribute="test2"/>
63
+ <AisPanel>
64
+ <MockHierarchicalMenu :attributes="['test3', 'test4']" />
65
+ </AisPanel>
66
+ </DynamicWidgets>
67
+ `,
68
+ components: {
69
+ DynamicWidgets,
70
+ MockRefinementList,
71
+ MockMenu,
72
+ MockHierarchicalMenu,
73
+ AisPanel,
74
+ },
75
+ });
76
+
77
+ const dynamicWidgets = wrapper.findComponent(DynamicWidgets);
78
+
79
+ expect(dynamicWidgets.props()).toEqual({
80
+ classNames: undefined,
81
+ transformItems,
82
+ facets: ['test'],
83
+ maxValuesPerFacet: 100,
84
+ });
85
+
86
+ expect(dynamicWidgets.vm.widgetParams).toEqual({
87
+ transformItems,
88
+ facets: ['test'],
89
+ maxValuesPerFacet: 100,
90
+ widgets: [],
91
+ });
92
+ });
93
+
49
94
  it('renders all children without state', () => {
50
95
  __setState(null);
51
96
 
@@ -0,0 +1,41 @@
1
+ import { mount } from '../../../test/utils';
2
+ import ExperimentalDynamicWidgets from '../ExperimentalDynamicWidgets';
3
+ import { warn } from '../../util/warn';
4
+ import { __setState } from '../../mixins/widget';
5
+ import DynamicWidgets from '../DynamicWidgets';
6
+
7
+ jest.mock('../../mixins/widget');
8
+ jest.mock('../../util/warn', () => ({ warn: jest.fn() }));
9
+
10
+ it('warns on mount', () => {
11
+ __setState(null);
12
+
13
+ mount({
14
+ template: '<ExperimentalDynamicWidgets />',
15
+ components: {
16
+ ExperimentalDynamicWidgets,
17
+ },
18
+ });
19
+ expect(warn).toHaveBeenCalledTimes(1);
20
+ expect(warn.mock.calls[0][0]).toMatchInlineSnapshot(
21
+ `"Use AisDynamicWidgets instead of AisExperimentalDynamicWidgets."`
22
+ );
23
+ });
24
+
25
+ it('behaves the same as DynamicWidgets', () => {
26
+ Object.keys(ExperimentalDynamicWidgets).forEach(key => {
27
+ if (key === 'name') {
28
+ // name is different
29
+ expect(ExperimentalDynamicWidgets[key]).toBe(
30
+ 'AisExperimentalDynamicWidgets'
31
+ );
32
+ } else if (key === 'mounted') {
33
+ // mounted has the warning
34
+ expect(ExperimentalDynamicWidgets[key]).toEqual(expect.any(Function));
35
+ } else if (key[0] === '_') {
36
+ // private Vue behavior, not tested
37
+ } else {
38
+ expect(ExperimentalDynamicWidgets[key]).toEqual(DynamicWidgets[key]);
39
+ }
40
+ });
41
+ });
@@ -31,7 +31,7 @@ export const createWidgetMixin = ({ connector } = {}) => ({
31
31
  this.getParentIndex().addWidgets([this.widget]);
32
32
 
33
33
  if (
34
- this.instantSearchInstance.__initialSearchResults &&
34
+ this.instantSearchInstance._initialResults &&
35
35
  !this.instantSearchInstance.started
36
36
  ) {
37
37
  if (typeof this.instantSearchInstance.__forceRender !== 'function') {
@@ -11,9 +11,9 @@ import { createFakeClient } from '../testutils/client';
11
11
  import { createSerializedState } from '../testutils/helper';
12
12
  import { isVue3, isVue2, Vue2, renderCompat } from '../vue-compat';
13
13
  import {
14
- SearchResults,
15
- SearchParameters,
16
14
  AlgoliaSearchHelper,
15
+ SearchParameters,
16
+ SearchResults,
17
17
  } from 'algoliasearch-helper';
18
18
 
19
19
  jest.unmock('instantsearch.js/es');
@@ -57,9 +57,11 @@ describe('createServerRootMixin', () => {
57
57
  }),
58
58
  ],
59
59
  })
60
- ).toThrowErrorMatchingInlineSnapshot(
61
- `"createServerRootMixin requires \`searchClient\` and \`indexName\` in the first argument"`
62
- );
60
+ ).toThrowErrorMatchingInlineSnapshot(`
61
+ "The \`searchClient\` option is required.
62
+
63
+ See documentation: https://www.algolia.com/doc/api-reference/widgets/instantsearch/js/"
64
+ `);
63
65
  });
64
66
 
65
67
  it('requires indexName', () => {
@@ -72,9 +74,11 @@ describe('createServerRootMixin', () => {
72
74
  }),
73
75
  ],
74
76
  })
75
- ).toThrowErrorMatchingInlineSnapshot(
76
- `"createServerRootMixin requires \`searchClient\` and \`indexName\` in the first argument"`
77
- );
77
+ ).toThrowErrorMatchingInlineSnapshot(`
78
+ "The \`indexName\` option is required.
79
+
80
+ See documentation: https://www.algolia.com/doc/api-reference/widgets/instantsearch/js/"
81
+ `);
78
82
  });
79
83
 
80
84
  it('creates an instantsearch instance on "data"', () => {
@@ -301,14 +305,13 @@ Array [
301
305
  renderToString,
302
306
  });
303
307
  expect(state).toEqual({
304
- __identifier: 'stringified',
305
308
  hello: {
306
- _rawResults: [
309
+ results: [
307
310
  {
308
311
  query: '',
309
312
  },
310
313
  ],
311
- _state: {
314
+ state: {
312
315
  disjunctiveFacets: [],
313
316
  disjunctiveFacetsRefinements: {},
314
317
  facets: [],
@@ -534,7 +537,7 @@ Array [
534
537
  this.instantsearch.mainIndex.getWidgets().map(w => w.$$type)
535
538
  ).toEqual(['ais.configure']);
536
539
 
537
- expect(res.hello._state.hitsPerPage).toBe(100);
540
+ expect(res.hello.state.hitsPerPage).toBe(100);
538
541
  })
539
542
  // jest throws an error we need to catch, since stuck in the flow
540
543
  .catch(e => {
@@ -656,11 +659,149 @@ Array [
656
659
 
657
660
  await renderToString(wrapper);
658
661
  });
662
+
663
+ it('searches only once', async () => {
664
+ const searchClient = createFakeClient();
665
+ const app = {
666
+ mixins: [
667
+ forceIsServerMixin,
668
+ createServerRootMixin({
669
+ searchClient,
670
+ indexName: 'hello',
671
+ }),
672
+ ],
673
+ render: renderCompat(h =>
674
+ /**
675
+ * This code triggers this warning in Vue 3:
676
+ * > Non-function value encountered for default slot. Prefer function slots for better performance.
677
+ *
678
+ * To fix it, replace the third argument
679
+ * > [h(...), h(...)]
680
+ * with
681
+ * > { default: () => [h(...), h(...)] }
682
+ *
683
+ * but it's not important (and not compatible in vue2), we're leaving it as-is.
684
+ */
685
+ h(InstantSearchSsr, {}, [
686
+ h(Configure, {
687
+ attrs: {
688
+ hitsPerPage: 100,
689
+ },
690
+ }),
691
+ h(SearchBox),
692
+ ])
693
+ ),
694
+ serverPrefetch() {
695
+ return this.instantsearch.findResultsState({
696
+ component: this,
697
+ renderToString,
698
+ });
699
+ },
700
+ };
701
+
702
+ const wrapper = createSSRApp({
703
+ mixins: [forceIsServerMixin],
704
+ render: renderCompat(h => h(app)),
705
+ });
706
+
707
+ await renderToString(wrapper);
708
+
709
+ expect(searchClient.search).toHaveBeenCalledTimes(1);
710
+ expect(searchClient.search.mock.calls[0][0]).toMatchInlineSnapshot(`
711
+ Array [
712
+ Object {
713
+ "indexName": "hello",
714
+ "params": Object {
715
+ "facets": Array [],
716
+ "hitsPerPage": 100,
717
+ "query": "",
718
+ "tagFilters": "",
719
+ },
720
+ },
721
+ ]
722
+ `);
723
+ });
724
+
725
+ it('works when component is at root (and therefore has no $vnode)', async () => {
726
+ const searchClient = createFakeClient();
727
+ let mainIndex;
728
+
729
+ const app = {
730
+ render: renderCompat(h =>
731
+ /**
732
+ * This code triggers this warning in Vue 3:
733
+ * > Non-function value encountered for default slot. Prefer function slots for better performance.
734
+ *
735
+ * To fix it, replace the third argument
736
+ * > [h(...), h(...)]
737
+ * with
738
+ * > { default: () => [h(...), h(...)] }
739
+ *
740
+ * but it's not important (and not compatible in vue2), we're leaving it as-is.
741
+ */
742
+ h(InstantSearchSsr, {}, [
743
+ h(Configure, {
744
+ attrs: {
745
+ hitsPerPage: 100,
746
+ },
747
+ }),
748
+ h(SearchBox),
749
+ ])
750
+ ),
751
+ };
752
+
753
+ const wrapper = createSSRApp({
754
+ mixins: [
755
+ forceIsServerMixin,
756
+ createServerRootMixin({
757
+ searchClient,
758
+ indexName: 'hello',
759
+ }),
760
+ ],
761
+ serverPrefetch() {
762
+ return this.instantsearch.findResultsState({
763
+ component: this,
764
+ renderToString,
765
+ });
766
+ },
767
+ created() {
768
+ mainIndex = this.instantsearch.mainIndex;
769
+ },
770
+ render: renderCompat(h => h(app)),
771
+ });
772
+
773
+ await renderToString(wrapper);
774
+
775
+ expect(mainIndex.getWidgetState()).toMatchInlineSnapshot(`
776
+ Object {
777
+ "hello": Object {
778
+ "configure": Object {
779
+ "hitsPerPage": 100,
780
+ },
781
+ },
782
+ }
783
+ `);
784
+
785
+ expect(searchClient.search).toHaveBeenCalledTimes(1);
786
+ expect(searchClient.search.mock.calls[0][0]).toMatchInlineSnapshot(`
787
+ Array [
788
+ Object {
789
+ "indexName": "hello",
790
+ "params": Object {
791
+ "facets": Array [],
792
+ "hitsPerPage": 100,
793
+ "query": "",
794
+ "tagFilters": "",
795
+ },
796
+ },
797
+ ]
798
+ `);
799
+ });
659
800
  }
660
801
  });
661
802
 
662
803
  describe('hydrate', () => {
663
- it('sets __initialSearchResults', () => {
804
+ it('sets _initialResults', () => {
664
805
  const serialized = createSerializedState();
665
806
 
666
807
  const app = {
@@ -683,7 +824,6 @@ Array [
683
824
  // in test, beforeCreated doesn't have $data yet, but IRL it does
684
825
  created() {
685
826
  this.instantsearch.hydrate({
686
- __identifier: 'stringified',
687
827
  hello: serialized,
688
828
  });
689
829
  },
@@ -693,57 +833,20 @@ Array [
693
833
  vm: { instantsearch },
694
834
  } = mount(app);
695
835
 
696
- expect(instantsearch.__initialSearchResults).toEqual(
697
- expect.objectContaining({ hello: expect.any(SearchResults) })
836
+ expect(instantsearch._initialResults).toEqual(
837
+ expect.objectContaining({
838
+ hello: {
839
+ state: expect.any(Object),
840
+ results: expect.any(Object),
841
+ },
842
+ })
698
843
  );
699
844
 
700
- expect(instantsearch.__initialSearchResults.hello).toEqual(
845
+ expect(instantsearch._initialResults.hello).toEqual(
701
846
  expect.objectContaining(serialized)
702
847
  );
703
848
  });
704
849
 
705
- it('accepts non-stringified results', () => {
706
- const serialized = createSerializedState();
707
- const nonSerialized = new SearchResults(
708
- new SearchParameters(serialized._state),
709
- serialized._rawResults
710
- );
711
-
712
- const app = {
713
- mixins: [
714
- createServerRootMixin({
715
- searchClient: createFakeClient(),
716
- indexName: 'movies',
717
- }),
718
- ],
719
- render: renderCompat(h =>
720
- h(InstantSearchSsr, {}, [
721
- h(Configure, {
722
- attrs: {
723
- hitsPerPage: 100,
724
- },
725
- }),
726
- h(SearchBox),
727
- ])
728
- ),
729
- created() {
730
- this.instantsearch.hydrate({
731
- movies: nonSerialized,
732
- });
733
-
734
- expect(this.instantsearch.__initialSearchResults).toEqual(
735
- expect.objectContaining({ movies: expect.any(SearchResults) })
736
- );
737
-
738
- expect(this.instantsearch.__initialSearchResults.movies).toEqual(
739
- nonSerialized
740
- );
741
- },
742
- };
743
-
744
- mount(app);
745
- });
746
-
747
850
  it('inits the main index', () => {
748
851
  const serialized = createSerializedState();
749
852
 
@@ -773,7 +876,6 @@ Array [
773
876
  expect(instantsearch.mainIndex.getHelper()).toBe(null);
774
877
 
775
878
  instantsearch.hydrate({
776
- __identifier: 'stringified',
777
879
  hello: serialized,
778
880
  });
779
881
 
@@ -812,7 +914,6 @@ Array [
812
914
  expect(instantsearch.mainHelper).toBe(null);
813
915
 
814
916
  instantsearch.hydrate({
815
- __identifier: 'stringified',
816
917
  hello: serialized,
817
918
  });
818
919
 
@@ -834,6 +935,7 @@ Array [
834
935
  created() {
835
936
  instantSearchInstance = this.instantsearch;
836
937
  },
938
+ render() {},
837
939
  });
838
940
 
839
941
  const widget = {
@@ -894,6 +996,58 @@ Object {
894
996
  );
895
997
  });
896
998
 
999
+ it('uses the results passed to hydrate for rendering', () => {
1000
+ let instantSearchInstance;
1001
+ mount({
1002
+ mixins: [
1003
+ createServerRootMixin({
1004
+ searchClient: createFakeClient(),
1005
+ indexName: 'lol',
1006
+ }),
1007
+ ],
1008
+ created() {
1009
+ instantSearchInstance = this.instantsearch;
1010
+ },
1011
+ render() {},
1012
+ });
1013
+
1014
+ const widget = {
1015
+ init: jest.fn(),
1016
+ render: jest.fn(),
1017
+ };
1018
+
1019
+ const resultsState = createSerializedState();
1020
+ const state = new SearchParameters(resultsState.state);
1021
+ const results = new SearchResults(state, resultsState.results);
1022
+
1023
+ instantSearchInstance.hydrate({
1024
+ lol: resultsState,
1025
+ });
1026
+
1027
+ instantSearchInstance.__forceRender(
1028
+ widget,
1029
+ instantSearchInstance.mainIndex
1030
+ );
1031
+
1032
+ expect(widget.init).toHaveBeenCalledTimes(0);
1033
+ expect(widget.render).toHaveBeenCalledTimes(1);
1034
+
1035
+ const renderArgs = widget.render.mock.calls[0][0];
1036
+
1037
+ expect(renderArgs).toEqual(
1038
+ expect.objectContaining({
1039
+ state,
1040
+ results,
1041
+ scopedResults: [
1042
+ expect.objectContaining({
1043
+ indexId: 'lol',
1044
+ results,
1045
+ }),
1046
+ ],
1047
+ })
1048
+ );
1049
+ });
1050
+
897
1051
  describe('createURL', () => {
898
1052
  it('returns # if instantsearch has no routing', () => {
899
1053
  let instantSearchInstance;
@@ -907,6 +1061,7 @@ Object {
907
1061
  created() {
908
1062
  instantSearchInstance = this.instantsearch;
909
1063
  },
1064
+ render() {},
910
1065
  });
911
1066
 
912
1067
  const widget = {
@@ -940,6 +1095,7 @@ Object {
940
1095
  created() {
941
1096
  instantSearchInstance = this.instantsearch;
942
1097
  },
1098
+ render() {},
943
1099
  });
944
1100
 
945
1101
  const widget = {