Skip to content

Commit

Permalink
fix(render): pass renderer.render to default render function (#940)
Browse files Browse the repository at this point in the history
  • Loading branch information
sarahdayan authored Apr 8, 2022
1 parent 8b737cb commit 55f53d1
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 54 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { SearchClient } from 'algoliasearch/lite';
import type { BaseItem } from '@algolia/autocomplete-core';
import type { AutocompleteOptions } from '@algolia/autocomplete-js';
import type { AutocompleteOptions, Render } from '@algolia/autocomplete-js';

import {
createElement,
ReactElement,
Fragment,
useEffect,
useMemo,
Expand Down Expand Up @@ -228,13 +227,7 @@ export function Autocomplete({
});
}
},
renderer: {
createElement,
Fragment,
},
render({ children }, root) {
render(children as ReactElement, root);
},
renderer: { createElement, Fragment, render: render as Render },
});

return () => autocompleteInstance.destroy();
Expand Down
5 changes: 1 addition & 4 deletions examples/react-instantsearch/src/Autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ export function Autocomplete(props) {

const search = autocomplete({
container: containerRef.current,
renderer: { createElement, Fragment },
render({ children }, root) {
render(children, root);
},
renderer: { createElement, Fragment, render },
...props,
});

Expand Down
4 changes: 1 addition & 3 deletions examples/vue-instantsearch/src/Autocomplete.vue
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,7 @@ export default {
renderer: {
createElement,
Fragment,
},
render({ children }, root) {
render(children, root);
render,
},
});
},
Expand Down
4 changes: 1 addition & 3 deletions examples/vue/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,7 @@ export default {
renderer: {
createElement,
Fragment,
},
render({ children }, root) {
render(children, root);
render,
},
});
});
Expand Down
122 changes: 91 additions & 31 deletions packages/autocomplete-js/src/__tests__/renderer.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { warnCache } from '@algolia/autocomplete-shared';
import { fireEvent, waitFor } from '@testing-library/dom';
import {
createElement as preactCreateElement,
Fragment as PreactFragment,
Expand All @@ -17,6 +18,8 @@ describe('renderer', () => {
});

test('defaults to the Preact implementation', () => {
expect.assertions(3);

const container = document.createElement('div');
const panelContainer = document.createElement('div');

Expand Down Expand Up @@ -47,19 +50,14 @@ describe('renderer', () => {
expect(Fragment).toBe(PreactFragment);
expect(render).toBe(preactRender);

render(createElement(Fragment, null, 'testSource'), root);
},
renderNoResults({ createElement, Fragment, render }, root) {
expect(createElement).toBe(preactCreateElement);
expect(Fragment).toBe(PreactFragment);
expect(render).toBe(preactRender);

render(createElement(Fragment, null, 'testSource'), root);
},
});
});

test('accepts a custom renderer', () => {
expect.assertions(6);

const container = document.createElement('div');
const panelContainer = document.createElement('div');
const CustomFragment = (props: any) => props.children;
Expand Down Expand Up @@ -106,26 +104,6 @@ describe('renderer', () => {
expect.any(Object)
);
},
renderNoResults(
{ children, createElement, Fragment, render, html },
root
) {
expect(createElement).toBe(mockCreateElement);
expect(Fragment).toBe(CustomFragment);
expect(render).toBe(mockRender);
expect(mockCreateElement).toHaveBeenCalled();

mockCreateElement.mockClear();

render(html`<div>${children}</div>`, root);

expect(mockCreateElement).toHaveBeenCalledTimes(1);
expect(mockCreateElement).toHaveBeenLastCalledWith(
'div',
null,
expect.any(Object)
);
},
renderer: {
createElement: mockCreateElement,
Fragment: CustomFragment,
Expand All @@ -135,6 +113,8 @@ describe('renderer', () => {
});

test('defaults `render` when not specified in the renderer', () => {
expect.assertions(1);

const container = document.createElement('div');
const panelContainer = document.createElement('div');
const CustomFragment = (props: any) => props.children;
Expand Down Expand Up @@ -168,16 +148,96 @@ describe('renderer', () => {

preactRender(createElement(Fragment, null, 'testSource'), root);
},
renderNoResults({ createElement, Fragment, render }, root) {
expect(render).toBe(preactRender);
renderer: {
createElement: mockCreateElement,
Fragment: CustomFragment,
},
});
});

preactRender(createElement(Fragment, null, 'testSource'), root);
test('uses a custom `render` via `renderer`', async () => {
const container = document.createElement('div');
const panelContainer = document.createElement('div');

document.body.appendChild(panelContainer);

const CustomFragment = (props: any) => props.children;
const mockCreateElement = jest.fn(preactCreateElement);
const mockRender = jest.fn().mockImplementation(preactRender);

autocomplete<{ label: string }>({
container,
panelContainer,
id: 'autocomplete-0',
getSources() {
return [
{
sourceId: 'testSource',
getItems() {
return [{ label: '1' }];
},
templates: {
item({ item }) {
return item.label;
},
},
},
];
},
renderer: {
createElement: mockCreateElement,
Fragment: CustomFragment,
render: mockRender,
createElement: mockCreateElement,
},
});

const input = container.querySelector<HTMLInputElement>('.aa-Input');

fireEvent.input(input, { target: { value: 'apple' } });

await waitFor(() => {
expect(
panelContainer.querySelector<HTMLElement>('.aa-Panel')
).toBeInTheDocument();
expect(mockRender).toHaveBeenCalled();
expect(panelContainer).toMatchInlineSnapshot(`
<div>
<div
class="aa-Panel"
data-testid="panel"
style="top: 0px; left: 0px; right: 0px; max-width: unset;"
>
<div
class="aa-PanelLayout aa-Panel--scrollable"
>
<section
class="aa-Source"
data-autocomplete-source-id="testSource"
>
<ul
aria-labelledby="autocomplete-0-label"
class="aa-List"
id="autocomplete-0-list"
role="listbox"
>
<li
aria-selected="false"
class="aa-Item"
id="autocomplete-0-item-0"
role="option"
>
1
</li>
</ul>
</section>
</div>
<div
class="aa-GradientBottom"
/>
</div>
</div>
`);
});
});

test('warns about renderer mismatch when specifying an incomplete renderer', () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/autocomplete-js/src/getDefaultOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ const defaultClassNames: AutocompleteClassNames = {
submitButton: 'aa-SubmitButton',
};

const defaultRender: AutocompleteRender<any> = ({ children }, root) => {
const defaultRender: AutocompleteRender<any> = ({ children, render }, root) => {
render(children, root);
};

const defaultRenderer: AutocompleteRenderer = {
const defaultRenderer: Required<AutocompleteRenderer> = {
createElement: preactCreateElement,
Fragment: PreactFragment,
render,
Expand Down
2 changes: 1 addition & 1 deletion packages/autocomplete-js/src/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type RenderProps<TItem extends BaseItem> = {
panelContainer: HTMLElement;
propGetters: AutocompletePropGetters<TItem>;
state: AutocompleteState<TItem>;
renderer: AutocompleteRenderer;
renderer: Required<AutocompleteRenderer>;
};

export function renderSearchBox<TItem extends BaseItem>({
Expand Down
2 changes: 1 addition & 1 deletion packages/autocomplete-js/src/types/AutocompleteRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export type AutocompleteRender<TItem extends BaseItem> = (
createElement: Pragma;
Fragment: PragmaFrag;
html: HTMLTemplate;
render?: Render;
render: Render;
},
root: HTMLElement
) => void;

0 comments on commit 55f53d1

Please sign in to comment.