Skip to content
This repository has been archived by the owner on Dec 30, 2022. It is now read-only.

fix(ssr): forward slots of the AisInstantSearchSsr component #898

Merged
merged 5 commits into from
Dec 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions src/util/__tests__/createServerRootMixin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,163 @@ Array [

await renderToString(wrapper);
});

it('forwards slots', async done => {
const searchClient = createFakeClient();

expect.assertions(2);

const App = Vue.component('App', {
mixins: [
forceIsServerMixin,
createServerRootMixin({
searchClient,
indexName: 'hello',
}),
],
render(h) {
return h(InstantSearchSsr, {}, this.$slots.default);
},
serverPrefetch() {
return (
this.instantsearch
.findResultsState(this)
.then(res => {
expect(
this.instantsearch.mainIndex.getWidgets().map(w => w.$$type)
).toEqual(['ais.configure']);

expect(res.hello._state.hitsPerPage).toBe(100);
})
// jest throws an error we need to catch, since stuck in the flow
.catch(e => {
done.fail(e);
})
);
},
});

const wrapper = new Vue({
mixins: [forceIsServerMixin],
render(h) {
return h(App, [
h('template', { slot: 'default' }, [
h(Configure, {
attrs: {
hitsPerPage: 100,
},
}),
]),
]);
},
});

await renderToString(wrapper);
done();
});

// TODO: forwarding of scoped slots doesn't yet work.
it.skip('forwards scoped slots', async done => {
const searchClient = createFakeClient();

expect.assertions(2);

const App = Vue.component('App', {
mixins: [
forceIsServerMixin,
createServerRootMixin({
searchClient,
indexName: 'hello',
}),
],
render(h) {
return h(InstantSearchSsr, {}, [
this.$scopedSlots.default({ test: true }),
]);
},
serverPrefetch() {
return (
this.instantsearch
.findResultsState(this)
.then(res => {
expect(
this.instantsearch.mainIndex.getWidgets().map(w => w.$$type)
).toEqual(['ais.configure']);

expect(res.hello._state.hitsPerPage).toBe(100);
})
// jest throws an error we need to catch, since stuck in the flow
.catch(e => {
done.fail(e);
})
);
},
});

const wrapper = new Vue({
mixins: [forceIsServerMixin],
render(h) {
return h(App, {
scopedSlots: {
default({ test }) {
if (test) {
return h(Configure, {
attrs: {
hitsPerPage: 100,
},
});
}
return null;
},
},
});
},
});

await renderToString(wrapper);
done();
});

it('forwards root', async () => {
const searchClient = createFakeClient();

// there are two renders of App, each with an assertion
expect.assertions(2);

const App = Vue.component('App', {
mixins: [
forceIsServerMixin,
createServerRootMixin({
searchClient,
indexName: 'hello',
}),
],
render(h) {
expect(this.$root).toBe(wrapper);

return h(InstantSearchSsr, {}, [
h(Configure, {
attrs: {
hitsPerPage: 100,
},
}),
h(SearchBox),
]);
},
serverPrefetch() {
return this.instantsearch.findResultsState(this);
},
});

const wrapper = new Vue({
mixins: [forceIsServerMixin],
render(h) {
return h(App);
},
});

await renderToString(wrapper);
});
});

describe('hydrate', () => {
Expand Down
11 changes: 11 additions & 0 deletions src/util/createServerRootMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ function augmentInstantSearch(instantSearchOptions, searchClient, indexName) {
propsData: componentInstance.$options.propsData,
});

// https://stackoverflow.com/a/48195006/3185307
app.$slots = componentInstance.$slots;
Haroenv marked this conversation as resolved.
Show resolved Hide resolved

app.$root = componentInstance.$root;

app.$options.serverPrefetch = [];

app.instantsearch.helper = helper;
Expand Down Expand Up @@ -160,6 +165,12 @@ function augmentInstantSearch(instantSearchOptions, searchClient, indexName) {

const results = search.__initialSearchResults[parent.getIndexId()];

// this happens when a different InstantSearch gets rendered initially,
// after the hydrate finished. There's thus no initial results available.
if (!results) {
return;
}

const state = results._state;

// helper gets created in init, but that means it doesn't get the injected
Expand Down