UNPKG

vue-instantsearch

Version:

👀 Lightning-fast Algolia search for Vue apps

383 lines (315 loc) • 9.34 kB
import { isVue3, version as vueVersion } from '../../util/vue-compat'; import { mount, nextTick } from '../../../test/utils'; import instantsearch from 'instantsearch.js/es'; import InstantSearch from '../InstantSearch'; import { version } from '../../../package.json'; import { warn } from '../../util/warn'; jest.mock('../../util/warn'); beforeEach(() => { jest.clearAllMocks(); }); it('passes props to InstantSearch.js', () => { const searchClient = {}; const insightsClient = jest.fn(); const searchFunction = helper => helper.search(); mount(InstantSearch, { propsData: { searchClient, insightsClient, indexName: 'something', routing: { router: {}, stateMapping: {}, }, stalledSearchDelay: 250, searchFunction, }, }); expect(instantsearch).toHaveBeenCalledWith({ indexName: 'something', routing: { router: {}, stateMapping: {}, }, searchClient, insightsClient, searchFunction, stalledSearchDelay: 250, }); }); it('throws on usage of appId or apiKey', () => { global.console.error = jest.fn(); global.console.warn = jest.fn(); mount(InstantSearch, { propsData: { searchClient: {}, apiKey: 'bla', appId: 'blabla', indexName: 'something', }, }); expect(warn) .toHaveBeenCalledWith(`Vue InstantSearch: You used the prop api-key or app-id. These have been replaced by search-client. See more info here: https://www.algolia.com/doc/api-reference/widgets/instantsearch/vue/#widget-param-search-client`); if (isVue3) { expect(global.console.warn.mock.calls[0][0]).toMatchInlineSnapshot( `"[Vue warn]: Invalid prop: custom validator check failed for prop \\"apiKey\\"."` ); expect(global.console.warn.mock.calls[1][0]).toMatchInlineSnapshot( `"[Vue warn]: Invalid prop: custom validator check failed for prop \\"appId\\"."` ); } else { expect(global.console.error.mock.calls[0][0]).toMatchInlineSnapshot(` "[Vue warn]: Invalid prop: custom validator check failed for prop \\"apiKey\\". found in ---> <AisInstantSearch> <Root>" `); expect(global.console.error.mock.calls[1][0]).toMatchInlineSnapshot(` "[Vue warn]: Invalid prop: custom validator check failed for prop \\"appId\\". found in ---> <AisInstantSearch> <Root>" `); } }); it('calls `start` on the next tick', async () => { const wrapper = mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'something', }, }); await nextTick(); expect(wrapper.vm.instantSearchInstance.start).toHaveBeenCalledTimes(1); }); it('renders correctly (empty)', () => { const wrapper = mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'bla', }, }); expect(wrapper.html()).toMatchSnapshot(); }); it('renders correctly (with slot used)', () => { const wrapper = mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'bla', }, slots: { default: '<div>Hi there, this is the main slot</div>', }, }); expect(wrapper.html()).toMatchSnapshot(); }); it('Allows a change in `index-name`', async () => { const wrapper = mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'bla', }, }); await wrapper.setProps({ indexName: 'doggie_bowl', }); const helper = wrapper.vm.instantSearchInstance.helper; expect(helper.setIndex).toHaveBeenCalledTimes(1); expect(helper.setIndex).toHaveBeenCalledWith('doggie_bowl'); expect(helper.search).toHaveBeenCalledTimes(1); }); it('Allows a change in `search-client`', async () => { const wrapper = mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'bla', }, }); const newClient = { cats: 'rule', dogs: 'drool' }; await wrapper.setProps({ searchClient: newClient, }); const helper = wrapper.vm.instantSearchInstance.helper; expect(helper.setClient).toHaveBeenCalledTimes(1); expect(helper.setClient).toHaveBeenCalledWith(newClient); expect(helper.search).toHaveBeenCalledTimes(1); }); it('Allows a change in `search-function`', async () => { const oldValue = () => {}; const newValue = () => {}; const wrapper = mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'bla', searchFunction: oldValue, }, }); expect(wrapper.vm.instantSearchInstance._searchFunction).toEqual(oldValue); await wrapper.setProps({ searchFunction: newValue, }); expect(wrapper.vm.instantSearchInstance._searchFunction).toEqual(newValue); }); it('Allows a change in `stalled-search-delay`', async () => { const wrapper = mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'bla', searchFunction: () => {}, stalledSearchDelay: 200, }, }); expect(wrapper.vm.instantSearchInstance._stalledSearchDelay).toEqual(200); await wrapper.setProps({ stalledSearchDelay: 50, }); expect(wrapper.vm.instantSearchInstance._stalledSearchDelay).toEqual(50); }); it('does not allow `routing` to be a boolean', () => { global.console.error = jest.fn(); global.console.warn = jest.fn(); mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'bla', routing: true, }, }); if (isVue3) { expect(global.console.warn.mock.calls[0][0]).toMatchInlineSnapshot( `"[Vue warn]: Invalid prop: custom validator check failed for prop \\"routing\\"."` ); } else { expect(global.console.error.mock.calls[0][0]).toMatchInlineSnapshot(` "[Vue warn]: Invalid prop: custom validator check failed for prop \\"routing\\". found in ---> <AisInstantSearch> <Root>" `); } expect(warn) .toHaveBeenCalledWith(`The \`routing\` option expects an object with \`router\` and/or \`stateMapping\`. See https://www.algolia.com/doc/api-reference/widgets/instantsearch/vue/#widget-param-routing`); }); it('warns when `routing` does not have `router` or `stateMapping`', () => { mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'indexName', routing: {}, }, }); expect(warn) .toHaveBeenCalledWith(`The \`routing\` option expects an object with \`router\` and/or \`stateMapping\`. See https://www.algolia.com/doc/api-reference/widgets/instantsearch/vue/#widget-param-routing`); }); it('does not warn when `routing` have either `router` or `stateMapping`', () => { mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'indexName', routing: { router: {} }, }, }); mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'indexName', routing: { stateMapping: {} }, }, }); expect(warn).toHaveBeenCalledTimes(0); }); it('Does not allow a change in `routing`', () => { const wrapper = mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'bla', }, }); expect( wrapper.setProps({ routing: false, }) ).rejects.toMatchInlineSnapshot(` [Error: routing configuration can not be changed dynamically at this point. Please open a new issue: https://github.com/algolia/vue-instantsearch/issues/new?template=feature.md] `); }); it('will call client.addAlgoliaAgent if present', () => { const client = { addAlgoliaAgent: jest.fn() }; mount(InstantSearch, { propsData: { searchClient: client, indexName: 'bla', }, }); expect(client.addAlgoliaAgent).toHaveBeenCalledTimes(2); expect(client.addAlgoliaAgent).toHaveBeenCalledWith(`Vue (${vueVersion})`); expect(client.addAlgoliaAgent).toHaveBeenCalledWith( `Vue InstantSearch (${version})` ); }); it('will not call client.addAlgoliaAgent if not function (so nothing to assert)', () => { expect(() => mount(InstantSearch, { propsData: { searchClient: { addAlgoliaAgent: true }, indexName: 'bla', }, }) ).not.toThrow(); }); it('disposes the instantsearch instance on unmount', async () => { const wrapper = mount(InstantSearch, { propsData: { searchClient: {}, indexName: 'something', }, }); await nextTick(); expect(wrapper.vm.instantSearchInstance.started).toBe(true); wrapper.destroy(); expect(wrapper.vm.instantSearchInstance.started).toBe(false); expect(wrapper.vm.instantSearchInstance.dispose).toHaveBeenCalledTimes(1); }); it('provides the instantsearch instance', done => { let instantSearchInstance; const ParentComponent = { ...InstantSearch, created() { instantSearchInstance = this.instantSearchInstance; }, }; const ChildComponent = { inject: ['$_ais_instantSearchInstance'], mounted() { this.$nextTick(() => { expect(typeof this.$_ais_instantSearchInstance).toBe('object'); expect(this.$_ais_instantSearchInstance).toBe(instantSearchInstance); done(); }); }, render() { return null; }, }; mount({ components: { ParentComponent, ChildComponent }, data() { return { props: { searchClient: {}, indexName: 'something', }, }; }, template: ` <ParentComponent v-bind="props"> <ChildComponent /> </ParentComponent> `, }); });