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

feat(Highlight): support array of strings #715

Merged
merged 19 commits into from
Dec 19, 2017
Merged

Conversation

marielaures
Copy link
Member

@marielaures marielaures commented Dec 12, 2017

Summary

This PR fixes #22.

Before this, the Highlight widget was only compatible with strings.
Now we've added support for arrays of strings.

Result

The Highlight widget is used in the same way for attribute names that point to either a string or an array of strings.

In the following example we have two Highlight widgets, the first one for attributeName="name" where hit.name is a string, and the second one for attributeName="tags" where hit.tags is an array of strings (tags: ["Ancient Egypt", "Online Course", "History"] ):

<Highlight attributeName="name" hit={hit} />
<Highlight attributeName="tags" hit={hit} />

highlightarray

@algobot
Copy link
Contributor

algobot commented Dec 12, 2017

Deploy preview ready!

Built with commit 268a5ac

https://deploy-preview-715--react-instantsearch.netlify.com

string
>): Promise<*> {
function computeFiles(
[filesGlob, replaceFilesGlob]: Array<string, string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like a different version of prettier was run over the code base

Highlighter.defaultProps = {
tagName: 'em',
nonHighlightedTagName: 'span',
separator: ',',
Copy link
Contributor

@Haroenv Haroenv Dec 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default should be ,<space>

Copy link
Collaborator

@samouss samouss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @marielaures! 🙂

I left few comments, but no blockers for me.

@@ -1,35 +1,75 @@
import PropTypes from 'prop-types';
import React from 'react';
import classNames from './classNames.js';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need the .js at the end of the import.

@@ -11,4 +11,6 @@ Highlight.propTypes = {
attributeName: PropTypes.string.isRequired,
highlight: PropTypes.func.isRequired,
tagName: PropTypes.string,
nonHighlightedTagName: PropTypes.string,
separator: PropTypes.string,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should match the PropTypes on Highlighter(aka: node). We also should rename separator for separatorComponent. For example in SearchBox all custom components are prefix with Component (ex: ResetComponent, SubmitComponent). And finally we need to replicate the props on the Snippet component.

<span key={`split-${i}-${hit[attributeName][i]}`}>
{item.map((element, index) => (
<Highlight
key={`split-${index}-${element.value}`}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can extract the key generation in a function since we use it tree times.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key generation is slightly different, since in one case we're accessing an element of an array (hit[attributeName][i]) and for the case where attributeName is a string, we do element.value. Do I do a function a maybe pass an attribute which will be a Boolean to specify whether it is an array and return either the first option or the second or leave it as is?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, you can simply create function that takes (index, value) as parameters. Then you called it with the according values (ex: element.value, hit[attributeName][i]).

@@ -14,7 +14,7 @@ import { get } from 'lodash';
* @param {string} highlightProperty - the property that contains the highlight structure in the results
* @param {string} attributeName - the highlighted attribute to look for
* @param {object} hit - the actual hit returned by Algolia.
* @return {object[]} - An array of {value: string, isDefined: boolean}.
* @return {object[]} - An array of {value: string, isDefined: boolean}.
Copy link
Collaborator

@samouss samouss Dec 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can update the documentation, it's isHighlighted instead of isDefined.

postTag,
highlightedValue: item.value,
})
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ternary complicate a bit the comprehension of the function. We can revert back to a simpler if statement.

return `split-${i}-${value}`;
}

export const Highlight = ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we export this as a component and then test the rendering out of it? So we freeze the implementation. Right now we are only testing that Highlight is called with some props, not the actual rendering of it (because it's shallow rendered in Highlighter.test.js)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by freezing the implementation? Highlight is tested separately so we don't need to do a full DOM rendering in Highlighter. We can just test that the the correct props are applied on the component. I think it's easier to reason about unit, rather than the all implementation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is that right no there's no test ensuring that the output of this single Highlight component is some specific DOM.

Which means that if we change the output without even touching the props being passed, nothing will break, while the public API contract will break (DOM will change).

If that's not clear still let me know

Copy link
Collaborator

@samouss samouss Dec 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope perfectly clear! But we already test the output of the Highlight component.

describe('Highlighter - Highlight', () => {
const defaultProps = {
value: 'test',
highlightedTagName: 'em',
isHighlighted: false,
nonHighlightedTagName: 'div',
};
it('renders a highlight', () => {
const props = {
...defaultProps,
isHighlighted: true,
};
const wrapper = shallow(<Highlight {...props} />);
expect(wrapper).toMatchSnapshot();
});
it('renders a nonhighlight', () => {
const props = {
...defaultProps,
};
const wrapper = shallow(<Highlight {...props} />);
expect(wrapper).toMatchSnapshot();
});
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

return `split-${i}-${value}`;
}

export const Highlight = ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Collaborator

@samouss samouss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last thing, we can update the connectHighlight documentation. First we can add attributeName, hit, highlightProperty to the section "Exposed Props". They are required since the provided prop highlight doesn't work without them. We can also rewrite the example because it's a bit complicated to understand how it works with the current code snippet.

Last, we can also precise that the highlight prop can now return a nested array depending on the shape of the highlighted property.

@samouss samouss merged commit 8e93c6a into master Dec 19, 2017
@samouss samouss deleted the feat/highlightarray branch December 19, 2017 07:49
samouss added a commit that referenced this pull request Dec 20, 2017
<a name="4.3.0"></a>

* reset page with multi index ([#665](#665)) ([865b7dc](865b7dc))
* **SearchBox:** use hidden over style to hide loader ([#714](#714)) ([ed5eb77](ed5eb77))
* test recipes ([#740](#740)) ([de2cc37](de2cc37))
* track all index in the manager ([#660](#660)) ([793502b](793502b))

* loading indicator ([#544](#544)) ([189659e](189659e))
* **Highlight:** support array of strings ([#715](#715)) ([8e93c6a](8e93c6a))
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Highlight: support arrays
5 participants