Fix broken tag filters in listings (#8086)

This commit is contained in:
rhymes 2020-05-28 10:24:50 +02:00 committed by GitHub
parent 58135879c8
commit eb355a6d4c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 125 additions and 180 deletions

View file

@ -49,6 +49,7 @@
}
}
.listing-filters-tags {
display: flex;
padding: 20px 0px;
position: relative;
input {

View file

@ -1,8 +1,7 @@
import PropTypes from 'prop-types';
import { tagPropTypes } from './tag-prop-types';
export const selectedTagsPropTypes = PropTypes.shape({
tags: PropTypes.arrayOf(tagPropTypes).isRequired,
tags: PropTypes.arrayOf(PropTypes.string).isRequired,
onClick: PropTypes.func.isRequired,
onKeyPress: PropTypes.func.isRequired,
});

View file

@ -3,20 +3,7 @@ import { deep } from 'preact-render-spy';
import ListingFiltersTags from '../components/ListingFiltersTags';
describe('<ListingFilterTags />', () => {
const firstTag = {
id: 1,
tag: 'clojure',
};
const secondTag = {
id: 2,
tag: 'java',
};
const thirdTag = {
id: 3,
tag: 'dotnet',
};
const getTags = () => [firstTag, secondTag, thirdTag];
const getTags = () => ['clojure', 'java', 'dotnet'];
const getProps = () => ({
message: 'Some message',
@ -78,9 +65,10 @@ describe('<ListingFilterTags />', () => {
it('Should render the selected Tags', () => {
const context = renderListingFilterTags();
getTags().forEach((tag) => {
const selectedTag = context.find(`#selected-tag-${tag.id}`);
const selectedTag = context.find(`#selected-tag-${tag}`);
expect(selectedTag.text()).toBe('×');
expect(selectedTag.text()).toEqual(expect.stringContaining(tag));
expect(selectedTag.text()).toEqual(expect.stringContaining('×'));
});
});
});

View file

@ -3,39 +3,23 @@ import render from 'preact-render-to-json';
import ListingFilters from '../components/ListingFilters';
describe('<ListingFilters />', () => {
const firstTag = {
id: 1,
tag: 'clojure',
};
const secondTag = {
id: 2,
tag: 'java',
};
const thirdTag = {
id: 3,
tag: 'dotnet',
};
const firstCategory = {
id: 20,
slug: 'clojure',
name: 'Clojure',
};
const secondCategory = {
id: 21,
slug: 'illa-iara-ques-htyashsayas-6kj8',
name: 'Go',
};
const thirdCategory = {
id: 22,
slug: 'alle-bece-tzehj-htyashsayas-7jh9',
name: 'csharp',
};
const getCategories = () => [firstCategory, secondCategory, thirdCategory];
const getTags = () => [firstTag, secondTag, thirdTag];
const getTags = () => ['clojure', 'java', 'dotnet'];
const getProps = () => ({
category: 'clojure',

View file

@ -4,19 +4,16 @@ import ListingFiltersCategories from '../components/ListingFiltersCategories';
describe('<ListingFiltersCategories />', () => {
const firstCategory = {
id: 20,
slug: 'clojure',
name: 'Clojure',
};
const secondCategory = {
id: 21,
slug: 'illa-iara-ques-htyashsayas-6kj8',
name: 'Go',
};
const thirdCategory = {
id: 22,
slug: 'alle-bece-tzehj-htyashsayas-7jh9',
name: 'csharp',
};
@ -76,7 +73,7 @@ describe('<ListingFiltersCategories />', () => {
const context = renderListingFilterCategories();
it('Should render the categories name and their respective links', () => {
categories.forEach((category) => {
const categoryLink = context.find(`#category-link-${category.id}`);
const categoryLink = context.find(`#category-link-${category.slug}`);
expect(categoryLink.attr('href')).toBe(`/listings/${category.slug}`);
expect(categoryLink.text()).toBe(category.name);
});
@ -85,7 +82,7 @@ describe('<ListingFiltersCategories />', () => {
it('Should set the class of the category link as "selected" when category slug matches the selected category name', () => {
const selectedCategoryLink = context.find(`.selected`);
expect(selectedCategoryLink.attr('id')).toBe(
`category-link-${firstCategory.id}`,
`category-link-${firstCategory.slug}`,
);
});
@ -95,7 +92,7 @@ describe('<ListingFiltersCategories />', () => {
);
unselectedCategories.forEach((unselectedCategory) => {
const unselectedCategoryLink = context.find(
`#category-link-${unselectedCategory.id}`,
`#category-link-${unselectedCategory.slug}`,
);
expect(unselectedCategoryLink.attr('className')).toBe('');
});

View file

@ -2,20 +2,7 @@ import { h } from 'preact';
import render from 'preact-render-to-json';
import SelectedTags from '../components/SelectedTags';
const firstTag = {
id: 1,
tag: 'clojure',
};
const secondTag = {
id: 2,
tag: 'java',
};
const thirdTag = {
id: 3,
tag: 'dotnet',
};
const tags = [firstTag, secondTag, thirdTag];
const tags = ['clojure', 'java', 'dotnet'];
const getProps = () => ({
tags,
onClick: () => {

View file

@ -18,29 +18,26 @@ exports[`<ListingFilters /> Should match the snapshot 1`] = `
</a>
<section>
<a
Key={20}
class="selected"
data-no-instant={true}
href="/listings/clojure"
id="category-link-20"
id="category-link-clojure"
onClick={[Function]}
>
Clojure
</a>
<a
Key={21}
data-no-instant={true}
href="/listings/illa-iara-ques-htyashsayas-6kj8"
id="category-link-21"
id="category-link-illa-iara-ques-htyashsayas-6kj8"
onClick={[Function]}
>
Go
</a>
<a
Key={22}
data-no-instant={true}
href="/listings/alle-bece-tzehj-htyashsayas-7jh9"
id="category-link-22"
id="category-link-alle-bece-tzehj-htyashsayas-7jh9"
onClick={[Function]}
>
csharp
@ -84,83 +81,77 @@ exports[`<ListingFilters /> Should match the snapshot 1`] = `
<section>
<span
class="listing-tag"
id="selected-tag-1"
id="selected-tag-clojure"
>
<a
class="tag-name"
data-no-instant={true}
href="/listings?tags="
onClick={[Function]}
href="/listings?t=clojure"
>
<span>
Object {
"id": 1,
"tag": "clojure",
}
<span
role="button"
tabIndex="0"
>
clojure
</span>
<button
class="tag-close"
data-no-instant={true}
<span
onClick={[Function]}
onKeyPress={[Function]}
t={true}
type="button"
role="button"
tabIndex="0"
>
×
</button>
</span>
</a>
</span>
<span
class="listing-tag"
id="selected-tag-2"
id="selected-tag-java"
>
<a
class="tag-name"
data-no-instant={true}
href="/listings?tags="
onClick={[Function]}
href="/listings?t=java"
>
<span>
Object {
"id": 2,
"tag": "java",
}
<span
role="button"
tabIndex="0"
>
java
</span>
<button
class="tag-close"
data-no-instant={true}
<span
onClick={[Function]}
onKeyPress={[Function]}
t={true}
type="button"
role="button"
tabIndex="0"
>
×
</button>
</span>
</a>
</span>
<span
class="listing-tag"
id="selected-tag-3"
id="selected-tag-dotnet"
>
<a
class="tag-name"
data-no-instant={true}
href="/listings?tags="
onClick={[Function]}
href="/listings?t=dotnet"
>
<span>
Object {
"id": 3,
"tag": "dotnet",
}
<span
role="button"
tabIndex="0"
>
dotnet
</span>
<button
class="tag-close"
data-no-instant={true}
<span
onClick={[Function]}
onKeyPress={[Function]}
t={true}
type="button"
role="button"
tabIndex="0"
>
×
</button>
</span>
</a>
</span>
</section>

View file

@ -4,83 +4,77 @@ exports[`<SelectedTags /> Should render all the tags 1`] = `
<section>
<span
class="listing-tag"
id="selected-tag-1"
id="selected-tag-clojure"
>
<a
class="tag-name"
data-no-instant={true}
href="/listings?tags="
onClick={[Function]}
href="/listings?t=clojure"
>
<span>
Object {
"id": 1,
"tag": "clojure",
}
<span
role="button"
tabIndex="0"
>
clojure
</span>
<button
class="tag-close"
data-no-instant={true}
<span
onClick={[Function]}
onKeyPress={[Function]}
t={true}
type="button"
role="button"
tabIndex="0"
>
×
</button>
</span>
</a>
</span>
<span
class="listing-tag"
id="selected-tag-2"
id="selected-tag-java"
>
<a
class="tag-name"
data-no-instant={true}
href="/listings?tags="
onClick={[Function]}
href="/listings?t=java"
>
<span>
Object {
"id": 2,
"tag": "java",
}
<span
role="button"
tabIndex="0"
>
java
</span>
<button
class="tag-close"
data-no-instant={true}
<span
onClick={[Function]}
onKeyPress={[Function]}
t={true}
type="button"
role="button"
tabIndex="0"
>
×
</button>
</span>
</a>
</span>
<span
class="listing-tag"
id="selected-tag-3"
id="selected-tag-dotnet"
>
<a
class="tag-name"
data-no-instant={true}
href="/listings?tags="
onClick={[Function]}
href="/listings?t=dotnet"
>
<span>
Object {
"id": 3,
"tag": "dotnet",
}
<span
role="button"
tabIndex="0"
>
dotnet
</span>
<button
class="tag-close"
data-no-instant={true}
<span
onClick={[Function]}
onKeyPress={[Function]}
t={true}
type="button"
role="button"
tabIndex="0"
>
×
</button>
</span>
</a>
</span>
</section>

View file

@ -7,13 +7,10 @@ const CategoryLinks = ({ categories, onClick, selectedCategory }) => {
{categories.map((category) => (
<a
href={`/listings/${category.slug}`}
id={`category-link-${category.id}`}
id={`category-link-${category.slug}`}
className={category.slug === selectedCategory ? 'selected' : ''}
onClick={(e) => {
onClick(e, category.slug);
}}
onClick={(e) => onClick(e, category.slug)}
data-no-instant
Key={category.id}
>
{category.name}
</a>
@ -23,7 +20,12 @@ const CategoryLinks = ({ categories, onClick, selectedCategory }) => {
};
CategoryLinks.propTypes = {
categories: PropTypes.isRequired,
categories: PropTypes.arrayOf(
PropTypes.shape({
slug: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
}),
).isRequired,
onClick: PropTypes.func.isRequired,
selectedCategory: PropTypes.string.isRequired,
};

View file

@ -2,7 +2,6 @@ import { h } from 'preact';
import PropTypes from 'prop-types';
import ListingFiltersCategories from './ListingFiltersCategories';
import ListingFiltersTags from './ListingFiltersTags';
import { tagPropTypes } from '../../common-prop-types';
const ListingFilters = ({
categories,
@ -37,14 +36,17 @@ const ListingFilters = ({
};
ListingFilters.propTypes = {
categories: PropTypes.isRequired,
category: PropTypes.isRequired,
categories: PropTypes.shape({
slug: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
}).isRequired,
category: PropTypes.string.isRequired,
onSelectCategory: PropTypes.func.isRequired,
message: PropTypes.isRequired,
onKeyUp: PropTypes.func.isRequired,
onClearQuery: PropTypes.func.isRequired,
onRemoveTag: PropTypes.func.isRequired,
tags: PropTypes.arrayOf(tagPropTypes).isRequired,
tags: PropTypes.arrayOf(PropTypes.string).isRequired,
onKeyPress: PropTypes.func.isRequired,
query: PropTypes.string.isRequired,
};

View file

@ -36,9 +36,14 @@ const ListingFiltersCategories = ({ categories, category, onClick }) => (
);
ListingFiltersCategories.propTypes = {
categories: PropTypes.isRequired,
categories: PropTypes.arrayOf(
PropTypes.shape({
slug: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
}),
).isRequired,
category: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired,
category: PropTypes.isRequired,
};
export default ListingFiltersCategories;

View file

@ -1,6 +1,5 @@
import { h } from 'preact';
import PropTypes from 'prop-types';
import { tagPropTypes } from '../../common-prop-types';
import ClearQueryButton from './ClearQueryButton';
import SelectedTags from './SelectedTags';
@ -28,7 +27,11 @@ const ListingFiltersTags = ({
{shouldRenderClearQueryButton && (
<ClearQueryButton onClick={onClearQuery} />
)}
<SelectedTags tags={tags} onClick={onRemoveTag} onKeyPress={onKeyPress} />
<SelectedTags
tags={tags}
onRemoveTag={onRemoveTag}
onKeyPress={onKeyPress}
/>
</div>
);
};
@ -39,7 +42,7 @@ ListingFiltersTags.propTypes = {
onClearQuery: PropTypes.func.isRequired,
onRemoveTag: PropTypes.func.isRequired,
onKeyPress: PropTypes.func.isRequired,
tags: PropTypes.arrayOf(tagPropTypes).isRequired,
tags: PropTypes.arrayOf(PropTypes.string).isRequired,
query: PropTypes.string.isRequired,
};

View file

@ -1,31 +1,23 @@
import { h } from 'preact';
import { selectedTagsPropTypes } from '../../common-prop-types';
const SelectedTags = ({ tags, onClick, onKeyPress }) => {
const SelectedTags = ({ tags, onRemoveTag, onKeyPress }) => {
return (
<section>
{tags.map((tag) => (
<span
className="listing-tag"
key={tag.id}
id={`selected-tag-${tag.id}`}
>
<a
href="/listings?tags="
className="tag-name"
onClick={onClick}
data-no-instant
>
<span>{tag}</span>
<button
className="tag-close"
t
type="button"
data-no-instant
onKeyPress={onKeyPress}
<span className="listing-tag" key={tag.id} id={`selected-tag-${tag}`}>
<a href={`/listings?t=${tag}`} className="tag-name" data-no-instant>
<span role="button" tabIndex="0">
{tag}
</span>
<span
role="button"
tabIndex="0"
onClick={(e) => onRemoveTag(e, tag)}
onKeyPress={(e) => onKeyPress(e, tag)}
>
×
</button>
</span>
</a>
</span>
))}